summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-03-25 09:12:09 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2010-03-25 13:33:55 +0000
commit0d1ac4da5288a621d0493cb109fcd1e040e6c5a7 (patch)
treea779fbe661ab79d4184360ad64090270046f9cd8
parent0c47195ca805881e3fbd5b9224be5c930feeeb8c (diff)
uxa: Perform the xrgb -> argb conversion not inplace
After reports of segmentation faults caused by d6b7f96fde1add92fd11f5a75869ae6fc688bf77 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 <chris@chris-wilson.co.uk> Reported-and-tested-by: Jeff Chua <jeff.chua.linux@gmail.com>
-rw-r--r--src/i830_uxa.c115
1 files changed, 60 insertions, 55 deletions
diff --git a/src/i830_uxa.c b/src/i830_uxa.c
index 3af4042d..589e16d4 100644
--- a/src/i830_uxa.c
+++ b/src/i830_uxa.c
@@ -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,