Alexandre Julliard : winex11: Force the alpha channel to zero for mono-> color blits.

Alexandre Julliard julliard at winehq.org
Mon Sep 26 16:15:10 CDT 2011


Module: wine
Branch: master
Commit: 922d9f5cf7520c7e4e9abd457da27e69f6d40138
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=922d9f5cf7520c7e4e9abd457da27e69f6d40138

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Sep 26 15:25:05 2011 +0200

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 deletions(-)

diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c
index 78c79c0..ccca315 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 e3fa09a..c8322ce 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,




More information about the wine-cvs mailing list