From 922d9f5cf7520c7e4e9abd457da27e69f6d40138 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 26 Sep 2011 15:25:05 +0200 Subject: [PATCH] winex11: Force the alpha channel to zero for mono->color blits. --- dlls/gdi32/tests/bitmap.c | 43 ++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/xrender.c | 38 ++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c index 78c79c02475..ccca315ebf4 100644 --- a/dlls/gdi32/tests/bitmap.c +++ b/dlls/gdi32/tests/bitmap.c @@ -2761,6 +2761,7 @@ static void test_StretchBlt(void) HBRUSH hBrush, hOldBrush; BITMAPINFO biDst, biSrc; UINT32 expected[256]; + RGBQUAD colors[2]; memset(&biDst, 0, sizeof(BITMAPINFO)); biDst.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); @@ -3007,6 +3008,48 @@ todo_wine SelectObject(hdcSrc, oldSrc); DeleteObject(bmpSrc); + + biSrc.bmiHeader.biBitCount = 1; + bmpSrc = CreateDIBSection(hdcScreen, &biSrc, DIB_RGB_COLORS, (void**)&srcBuffer, NULL, 0); + oldSrc = SelectObject(hdcSrc, bmpSrc); + *((DWORD *)colors + 0) = 0x123456; + *((DWORD *)colors + 1) = 0x335577; + SetDIBColorTable( hdcSrc, 0, 2, colors ); + srcBuffer[0] = 0x55555555; + memset(dstBuffer, 0xcc, 4 * sizeof(*dstBuffer)); + SetTextColor( hdcDst, 0 ); + SetBkColor( hdcDst, 0 ); + StretchBlt(hdcDst, 0, 0, 4, 1, hdcSrc, 0, 0, 4, 1, SRCCOPY ); + expected[0] = expected[2] = 0x00123456; + expected[1] = expected[3] = 0x00335577; + ok(!memcmp(dstBuffer, expected, 16), + "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X }\n", + expected[0], expected[1], expected[2], expected[3], + dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3] ); + + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + + bmpSrc = CreateBitmap( 16, 16, 1, 1, 0 ); + oldSrc = SelectObject(hdcSrc, bmpSrc); + SetPixel( hdcSrc, 0, 0, 0 ); + SetPixel( hdcSrc, 1, 0, 0xffffff ); + SetPixel( hdcSrc, 2, 0, 0xffffff ); + SetPixel( hdcSrc, 3, 0, 0 ); + memset(dstBuffer, 0xcc, 4 * sizeof(*dstBuffer)); + SetTextColor( hdcDst, RGB(0x22,0x44,0x66) ); + SetBkColor( hdcDst, RGB(0x65,0x43,0x21) ); + StretchBlt(hdcDst, 0, 0, 4, 1, hdcSrc, 0, 0, 4, 1, SRCCOPY ); + expected[0] = expected[3] = 0x00224466; + expected[1] = expected[2] = 0x00654321; + ok(!memcmp(dstBuffer, expected, 16), + "StretchBlt expected { %08X, %08X, %08X, %08X } got { %08X, %08X, %08X, %08X }\n", + expected[0], expected[1], expected[2], expected[3], + dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3] ); + + SelectObject(hdcSrc, oldSrc); + DeleteObject(bmpSrc); + DeleteDC(hdcSrc); SelectObject(hdcDst, oldDst); diff --git a/dlls/winex11.drv/xrender.c b/dlls/winex11.drv/xrender.c index e3fa09a5ebe..c8322ce755f 100644 --- a/dlls/winex11.drv/xrender.c +++ b/dlls/winex11.drv/xrender.c @@ -2278,6 +2278,35 @@ done_unlock: return retv; } +/* multiply the alpha channel of a picture */ +static void multiply_alpha( Picture pict, XRenderPictFormat *format, int alpha, + int x, int y, int width, int height ) +{ + XRenderPictureAttributes pa; + Pixmap src_pixmap, mask_pixmap; + Picture src_pict, mask_pict; + XRenderColor color; + + wine_tsx11_lock(); + src_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, format->depth ); + mask_pixmap = XCreatePixmap( gdi_display, root_window, 1, 1, format->depth ); + pa.repeat = RepeatNormal; + src_pict = pXRenderCreatePicture( gdi_display, src_pixmap, format, CPRepeat, &pa ); + pa.component_alpha = True; + mask_pict = pXRenderCreatePicture( gdi_display, mask_pixmap, format, CPRepeat|CPComponentAlpha, &pa ); + color.red = color.green = color.blue = color.alpha = 0xffff; + pXRenderFillRectangle( gdi_display, PictOpSrc, src_pict, &color, 0, 0, 1, 1 ); + color.alpha = alpha; + pXRenderFillRectangle( gdi_display, PictOpSrc, mask_pict, &color, 0, 0, 1, 1 ); + pXRenderComposite( gdi_display, PictOpInReverse, src_pict, mask_pict, pict, + 0, 0, 0, 0, x, y, width, height ); + pXRenderFreePicture( gdi_display, src_pict ); + pXRenderFreePicture( gdi_display, mask_pict ); + XFreePixmap( gdi_display, src_pixmap ); + XFreePixmap( gdi_display, mask_pixmap ); + wine_tsx11_unlock(); +} + /* Helper function for (stretched) blitting using xrender */ static void xrender_blit( int op, Picture src_pict, Picture mask_pict, Picture dst_pict, int x_src, int y_src, int x_dst, int y_dst, @@ -2317,13 +2346,16 @@ static void xrender_mono_blit( Picture src_pict, Picture dst_pict, { Picture tile_pict; int x_offset, y_offset; + XRenderColor color; /* When doing a mono->color blit, the source data is used as mask, and the source picture * contains a 1x1 picture for tiling. The source data effectively acts as an alpha channel to * the tile data. */ EnterCriticalSection( &xrender_cs ); - tile_pict = get_tile_pict( dst_format, bg ); + color = *bg; + color.alpha = 0xffff; /* tile pict needs 100% alpha */ + tile_pict = get_tile_pict( dst_format, &color ); wine_tsx11_lock(); pXRenderFillRectangle( gdi_display, PictOpSrc, dst_pict, fg, x_dst, y_dst, width, height ); @@ -2347,6 +2379,10 @@ static void xrender_mono_blit( Picture src_pict, Picture dst_pict, 0, 0, x_offset, y_offset, x_dst, y_dst, width, height ); wine_tsx11_unlock(); LeaveCriticalSection( &xrender_cs ); + + /* force the alpha channel for background pixels, it has been set to 100% by the tile */ + if (bg->alpha != 0xffff && (dst_format == WXR_FORMAT_A8R8G8B8 || dst_format == WXR_FORMAT_B8G8R8A8)) + multiply_alpha( dst_pict, pict_formats[dst_format], bg->alpha, x_dst, y_dst, width, height ); } static void get_colors( struct xrender_physdev *physdev_src, struct xrender_physdev *physdev_dst,