Commit 0d1ac4da authored by Chris Wilson's avatar Chris Wilson

uxa: Perform the xrgb -> argb conversion not inplace

After reports of segmentation faults caused by
d6b7f96f and vmware, the most obvious
cause would be illegally writing to the src data when performing the alpha
fill inline. So force the image upload to go via a fresh buffer whenever
we need to modify the incoming data.
Signed-off-by: Chris Wilson's avatarChris Wilson <chris@chris-wilson.co.uk>
Reported-and-tested-by: default avatarJeff Chua <jeff.chua.linux@gmail.com>
parent 0c47195c
......@@ -650,6 +650,54 @@ static void i830_uxa_finish_access(PixmapPtr pixmap)
pixmap->devPrivate.ptr = NULL;
}
static Bool i830_bo_put_image(PixmapPtr pixmap, dri_bo *bo, char *src, int src_pitch, int w, int h)
{
int stride = i830_pixmap_pitch(pixmap);
/* fill alpha channel */
if (pixmap->drawable.depth == 24) {
pixman_image_t *src_image, *dst_image;
src_image = pixman_image_create_bits (PIXMAN_x8r8g8b8,
w, h,
(uint32_t *) src, src_pitch);
dst_image = pixman_image_create_bits (PIXMAN_a8r8g8b8,
w, h,
(uint32_t *) bo->virtual, stride);
if (src_image && dst_image)
pixman_image_composite (PictOpSrc,
src_image, NULL, dst_image,
0, 0,
0, 0,
0, 0,
w, h);
if (src_image)
pixman_image_unref (src_image);
if (dst_image)
pixman_image_unref (dst_image);
if (src_image == NULL || dst_image == NULL)
return FALSE;
} else if (src_pitch == stride) {
memcpy (bo->virtual, src, stride * h);
} else {
char *dst = bo->virtual;
int row_length = w * pixmap->drawable.bitsPerPixel/8;
int num_rows = h;
while (num_rows--) {
memcpy (dst, src, row_length);
src += src_pitch;
dst += stride;
}
}
return TRUE;
}
static Bool
i830_uxa_pixmap_swap_bo_with_image(PixmapPtr pixmap,
char *src, int src_pitch)
......@@ -662,6 +710,7 @@ i830_uxa_pixmap_swap_bo_with_image(PixmapPtr pixmap,
int stride;
int w = pixmap->drawable.width;
int h = pixmap->drawable.height;
Bool ret;
priv = i830_get_pixmap_intel(pixmap);
......@@ -702,22 +751,11 @@ i830_uxa_pixmap_swap_bo_with_image(PixmapPtr pixmap,
return FALSE;
}
if (src_pitch == stride) {
memcpy (bo->virtual, src, src_pitch * h);
} else {
char *dst = bo->virtual;
w *= pixmap->drawable.bitsPerPixel/8;
while (h--) {
memcpy (dst, src, w);
src += src_pitch;
dst += stride;
}
}
ret = i830_bo_put_image(pixmap, bo, src, src_pitch, w, h);
drm_intel_gem_bo_unmap_gtt(bo);
return TRUE;
return ret;
}
static Bool i830_uxa_put_image(PixmapPtr pixmap,
......@@ -733,33 +771,6 @@ static Bool i830_uxa_put_image(PixmapPtr pixmap,
GCPtr gc;
Bool ret;
if (pixmap->drawable.depth == 24) {
/* fill alpha channel */
pixman_image_t *src_image, *dst_image;
src_image = pixman_image_create_bits (PIXMAN_x8r8g8b8,
w, h,
(uint32_t *) src, src_pitch);
dst_image = pixman_image_create_bits (PIXMAN_a8r8g8b8,
w, h,
(uint32_t *) src, src_pitch);
if (src_image && dst_image)
pixman_image_composite (PictOpSrc,
src_image, NULL, dst_image,
0, 0,
0, 0,
0, 0,
w, h);
if (src_image)
pixman_image_unref (src_image);
if (dst_image)
pixman_image_unref (dst_image);
}
if (x == 0 && y == 0 &&
w == pixmap->drawable.width &&
h == pixmap->drawable.height)
......@@ -770,9 +781,10 @@ static Bool i830_uxa_put_image(PixmapPtr pixmap,
}
priv = i830_get_pixmap_intel(pixmap);
if (priv->batch_read_domains || drm_intel_bo_busy(priv->bo)) {
if (priv->batch_read_domains ||
drm_intel_bo_busy(priv->bo) ||
pixmap->drawable.depth == 24) {
dri_bo *bo;
int stride;
/* Partial replacement, copy incoming image to a bo and blit. */
scratch = (*screen->CreatePixmap)(screen, w, h,
......@@ -789,22 +801,15 @@ static Bool i830_uxa_put_image(PixmapPtr pixmap,
return FALSE;
}
stride = i830_pixmap_pitch(scratch);
if (src_pitch == stride) {
memcpy (bo->virtual, src, stride * h);
} else {
char *dst = bo->virtual;
int row_length = w * pixmap->drawable.bitsPerPixel/8;
int num_rows = h;
while (num_rows--) {
memcpy (dst, src, row_length);
src += src_pitch;
dst += stride;
}
}
ret = i830_bo_put_image(scratch, bo, src, src_pitch, w, h);
drm_intel_gem_bo_unmap_gtt(bo);
scratch_pixmap = FALSE;
if (!ret) {
(*screen->DestroyPixmap) (scratch);
return FALSE;
}
} else {
/* bo is not busy so can be mapped without a stall, upload in-place. */
scratch = GetScratchPixmapHeader(screen, w, h,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment