diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-03-06 15:49:04 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-03-16 10:53:29 +0000 |
commit | d6b7f96fde1add92fd11f5a75869ae6fc688bf77 (patch) | |
tree | b1be185b912e456396850e0bacc4514e13f79785 | |
parent | 910fd171a00227025abc8bcc286a740f5bae895b (diff) |
Fill alpha on xrgb images.
Do not try to fixup the alpha in the ff/shaders as this has the
side-effect of overriding the alpha value of the border color, causing
images to be padded with black rather than transparent. This can
generate large and obnoxious visual artefacts.
Fixes:
Bug 17933 - x8r8g8b8 doesn't sample alpha=0 outside surface bounds
http://bugs.freedesktop.org/show_bug.cgi?id=17933
and many related cairo test suite failures.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/i830_render.c | 38 | ||||
-rw-r--r-- | src/i830_uxa.c | 29 | ||||
-rw-r--r-- | src/i915_render.c | 21 | ||||
-rw-r--r-- | uxa/uxa-render.c | 117 |
4 files changed, 88 insertions, 117 deletions
diff --git a/src/i830_render.c b/src/i830_render.c index 0d6a8034..71296d29 100644 --- a/src/i830_render.c +++ b/src/i830_render.c @@ -491,43 +491,23 @@ i830_prepare_composite(int op, PicturePtr source_picture, * is a8, in which case src.G is what's written, and the other * channels are ignored. */ - if (PICT_FORMAT_A(source_picture->format) != 0) { - ablend |= TB0A_ARG1_SEL_TEXEL0; - cblend |= - TB0C_ARG1_SEL_TEXEL0 | - TB0C_ARG1_REPLICATE_ALPHA; - } else { - ablend |= TB0A_ARG1_SEL_ONE; - cblend |= TB0C_ARG1_SEL_ONE; - } + ablend |= TB0A_ARG1_SEL_TEXEL0; + cblend |= TB0C_ARG1_SEL_TEXEL0 | TB0C_ARG1_REPLICATE_ALPHA; } else { - if (PICT_FORMAT_A(source_picture->format) != 0) { - ablend |= TB0A_ARG1_SEL_TEXEL0; - } else { - ablend |= TB0A_ARG1_SEL_ONE; - } if (PICT_FORMAT_RGB(source_picture->format) != 0) cblend |= TB0C_ARG1_SEL_TEXEL0; else cblend |= TB0C_ARG1_SEL_ONE | TB0C_ARG1_INVERT; /* 0.0 */ + ablend |= TB0A_ARG1_SEL_TEXEL0; } if (mask) { - if (dest_picture->format != PICT_a8 && - (mask_picture->componentAlpha && - PICT_FORMAT_RGB(mask_picture->format))) { - cblend |= TB0C_ARG2_SEL_TEXEL1; - } else { - if (PICT_FORMAT_A(mask_picture->format) != 0) - cblend |= TB0C_ARG2_SEL_TEXEL1 | - TB0C_ARG2_REPLICATE_ALPHA; - else - cblend |= TB0C_ARG2_SEL_ONE; - } - if (PICT_FORMAT_A(mask_picture->format) != 0) - ablend |= TB0A_ARG2_SEL_TEXEL1; - else - ablend |= TB0A_ARG2_SEL_ONE; + cblend |= TB0C_ARG2_SEL_TEXEL1; + if (dest_picture->format == PICT_a8 || + ! mask_picture->componentAlpha || + ! PICT_FORMAT_RGB(mask_picture->format)) + cblend |= TB0C_ARG2_REPLICATE_ALPHA; + ablend |= TB0A_ARG2_SEL_TEXEL1; } else { cblend |= TB0C_ARG2_SEL_ONE; ablend |= TB0A_ARG2_SEL_ONE; diff --git a/src/i830_uxa.c b/src/i830_uxa.c index 99043118..fec53782 100644 --- a/src/i830_uxa.c +++ b/src/i830_uxa.c @@ -237,6 +237,8 @@ i830_uxa_prepare_solid(PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg) case 32: /* RGB8888 */ intel->BR[13] |= ((1 << 24) | (1 << 25)); + if (pixmap->drawable.depth == 24) + fg |= 0xff000000; break; } intel->BR[16] = fg; @@ -710,6 +712,33 @@ 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) diff --git a/src/i915_render.c b/src/i915_render.c index 37af72b9..c4aa9a44 100644 --- a/src/i915_render.c +++ b/src/i915_render.c @@ -385,8 +385,9 @@ i915_prepare_composite(int op, PicturePtr source_picture, source_picture->format, PICT_a8r8g8b8, &intel->render_source_solid)) - return FALSE; - } else if (!intel_check_pitch_3d(source)) + intel->render_source_is_solid = FALSE; + } + if (!intel->render_source_is_solid && !intel_check_pitch_3d(source)) return FALSE; @@ -402,8 +403,9 @@ i915_prepare_composite(int op, PicturePtr source_picture, mask_picture->format, PICT_a8r8g8b8, &intel->render_mask_solid)) - return FALSE; - } else if (!intel_check_pitch_3d(mask)) + intel->render_mask_is_solid = FALSE; + } + if (!intel->render_mask_is_solid && !intel_check_pitch_3d(mask)) return FALSE; } @@ -475,7 +477,6 @@ static void i915_emit_composite_setup(ScrnInfoPtr scrn) { intel_screen_private *intel = intel_get_screen_private(scrn); int op = intel->i915_render_state.op; - PicturePtr source_picture = intel->render_source_picture; PicturePtr mask_picture = intel->render_mask_picture; PicturePtr dest_picture = intel->render_dest_picture; PixmapPtr mask = intel->render_mask; @@ -589,7 +590,6 @@ static void i915_emit_composite_setup(ScrnInfoPtr scrn) OUT_BATCH(0x00000000); } - OUT_BATCH(MI_NOOP); ADVANCE_BATCH(); { @@ -629,10 +629,6 @@ static void i915_emit_composite_setup(ScrnInfoPtr scrn) i915_fs_texldp(FS_R0, FS_S0, FS_T0); } - /* If the texture lacks an alpha channel, force the alpha to 1. */ - if (PICT_FORMAT_A(source_picture->format) == 0) - i915_fs_mov_masked(FS_R0, MASK_W, i915_fs_operand_one()); - src_reg = FS_R0; } @@ -647,11 +643,6 @@ static void i915_emit_composite_setup(ScrnInfoPtr scrn) } else { i915_fs_texldp(FS_R1, FS_S0 + t, FS_T0 + t); } - /* If the texture lacks an alpha channel, force the alpha to 1. - */ - if (PICT_FORMAT_A(mask_picture->format) == 0) - i915_fs_mov_masked(FS_R1, MASK_W, - i915_fs_operand_one()); mask_reg = FS_R1; } diff --git a/uxa/uxa-render.c b/uxa/uxa-render.c index e70a8450..ca46a2a9 100644 --- a/uxa/uxa-render.c +++ b/uxa/uxa-render.c @@ -262,13 +262,15 @@ uxa_get_color_for_pixmap (PixmapPtr pixmap, *pixel = uxa_get_pixmap_first_pixel(pixmap); - if (!uxa_get_rgba_from_pixel(*pixel, &red, &green, &blue, &alpha, - src_format)) + if (src_format != dst_format) { + if (!uxa_get_rgba_from_pixel(*pixel, &red, &green, &blue, &alpha, + src_format)) return FALSE; - if (!uxa_get_pixel_from_rgba(pixel, red, green, blue, alpha, - dst_format)) + if (!uxa_get_pixel_from_rgba(pixel, red, green, blue, alpha, + dst_format)) return FALSE; + } return TRUE; } @@ -364,6 +366,10 @@ uxa_picture_for_pixman_format(ScreenPtr pScreen, if (format == PIXMAN_a1) format = PIXMAN_a8; + /* fill alpha if unset */ + if (PIXMAN_FORMAT_A(format) == 0) + format = PIXMAN_a8r8g8b8; + pPixmap = (*pScreen->CreatePixmap)(pScreen, width, height, PIXMAN_FORMAT_DEPTH(format), UXA_CREATE_PIXMAP_FOR_MAP); @@ -384,64 +390,6 @@ uxa_picture_for_pixman_format(ScreenPtr pScreen, return pPicture; } -/* In order to avoid fallbacks when using an a1 source/mask, - * for example with non-antialiased trapezoids, we need to - * expand the bitmap into an a8 Picture. We do so by using the generic - * composition routines, which while may not be perfect is far faster - * than causing a fallback. - */ -static PicturePtr -uxa_picture_from_a1_pixman_image(ScreenPtr pScreen, pixman_image_t * image) -{ - PicturePtr pPicture; - PicturePtr pSrc; - PixmapPtr pPixmap; - int width, height; - int error; - - width = pixman_image_get_width(image); - height = pixman_image_get_height(image); - - pPicture = uxa_picture_for_pixman_format (pScreen, PIXMAN_a1, - width, height); - if (!pPicture) - return 0; - - pPixmap = GetScratchPixmapHeader(pScreen, width, height, 1, 1, - pixman_image_get_stride(image), - pixman_image_get_data(image)); - if (!pPixmap) { - FreePicture(pPicture, 0); - return 0; - } - - pSrc = CreatePicture(0, &pPixmap->drawable, - PictureMatchFormat(pScreen, 1, PICT_a1), - 0, 0, serverClient, &error); - if (!pSrc) { - FreeScratchPixmapHeader(pPixmap); - FreePicture(pPicture, 0); - return 0; - } - - ValidatePicture(pSrc); - - /* force the fallback path */ - if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) { - fbComposite(PictOpSrc, pSrc, NULL, pPicture, - 0, 0, 0, 0, 0, 0, width, height); - uxa_finish_access(pPicture->pDrawable); - } else { - FreePicture(pPicture, 0); - pPicture = 0; - } - - FreePicture(pSrc, 0); - FreeScratchPixmapHeader(pPixmap); - - return pPicture; -} - static PicturePtr uxa_picture_from_pixman_image(ScreenPtr pScreen, pixman_image_t * image, @@ -449,12 +397,8 @@ uxa_picture_from_pixman_image(ScreenPtr pScreen, { PicturePtr pPicture; PixmapPtr pPixmap; - GCPtr pGC; int width, height; - if (format == PICT_a1) - return uxa_picture_from_a1_pixman_image(pScreen, image); - width = pixman_image_get_width(image); height = pixman_image_get_height(image); @@ -473,18 +417,45 @@ uxa_picture_from_pixman_image(ScreenPtr pScreen, return 0; } - pGC = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), pScreen); - if (!pGC) { + if (((pPicture->pDrawable->depth << 24) | pPicture->format) == format) { + GCPtr pGC; + + pGC = GetScratchGC(PIXMAN_FORMAT_DEPTH(format), pScreen); + if (!pGC) { FreeScratchPixmapHeader(pPixmap); FreePicture(pPicture, 0); return 0; - } - ValidateGC(pPicture->pDrawable, pGC); + } + ValidateGC(pPicture->pDrawable, pGC); - (*pGC->ops->CopyArea) (&pPixmap->drawable, pPicture->pDrawable, - pGC, 0, 0, width, height, 0, 0); + (*pGC->ops->CopyArea) (&pPixmap->drawable, pPicture->pDrawable, + pGC, 0, 0, width, height, 0, 0); - FreeScratchGC(pGC); + FreeScratchGC(pGC); + } else { + PicturePtr pSrc; + int error; + + pSrc = CreatePicture(0, &pPixmap->drawable, + PictureMatchFormat(pScreen, + PIXMAN_FORMAT_DEPTH(format), + format), + 0, 0, serverClient, &error); + if (!pSrc) { + FreeScratchPixmapHeader(pPixmap); + FreePicture(pPicture, 0); + return 0; + } + ValidatePicture(pSrc); + + if (uxa_prepare_access(pPicture->pDrawable, UXA_ACCESS_RW)) { + fbComposite(PictOpSrc, pSrc, NULL, pPicture, + 0, 0, 0, 0, 0, 0, width, height); + uxa_finish_access(pPicture->pDrawable); + } + + FreePicture(pSrc, 0); + } FreeScratchPixmapHeader(pPixmap); return pPicture; |