GDI: implement AlphaBlend

Mike McCormack mike at codeweavers.com
Mon Aug 2 09:32:44 CDT 2004


This is the work of Huw Davies.

Mike


ChangeLog:
<huw at codeweavers.com>
* implement AlphaBlend using the XRENDER extension

-------------- next part --------------
Index: dlls/gdi/bitblt.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/bitblt.c,v
retrieving revision 1.2
diff -u -r1.2 bitblt.c
--- dlls/gdi/bitblt.c	14 Apr 2004 19:35:25 -0000	1.2
+++ dlls/gdi/bitblt.c	2 Aug 2004 13:11:37 -0000
@@ -398,14 +398,30 @@
 /******************************************************************************
  *           GdiAlphaBlend [GDI32.@]
  */
-BOOL WINAPI GdiAlphaBlend(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
-                          HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
+BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heightDst,
+                          HDC hdcSrc, int xSrc, int ySrc, int widthSrc, int heightSrc,
                           BLENDFUNCTION blendFunction)
 {
-    FIXME("partial stub - using StretchBlt\n");
-    return StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
-                      hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
-                      SRCCOPY);
+    BOOL ret = FALSE;
+    DC *dcDst, *dcSrc;
+    DWORD bfn = 0;
+
+    if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
+    /* FIXME: there is a race condition here */
+    if ((dcDst = DC_GetDCUpdate( hdcDst )))
+    {
+        dcSrc = DC_GetDCPtr( hdcSrc );
+        TRACE("%p %d,%d %dx%d -> %p %d,%d %dx%d blend=%08lx\n",
+              hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
+              hdcDst, xDst, yDst, widthDst, heightDst, bfn );
+        if (dcDst->funcs->pAlphaBlend)
+            ret = dcDst->funcs->pAlphaBlend( dcDst->physDev, xDst, yDst, widthDst, heightDst,
+                                             dcSrc ? dcSrc->physDev : NULL,
+                                             xSrc, ySrc, widthSrc, heightSrc, bfn );
+        if (dcSrc) GDI_ReleaseObj( hdcSrc );
+        GDI_ReleaseObj( hdcDst );
+    }
+    return ret;
 }
 
 /*********************************************************************
Index: dlls/gdi/driver.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/driver.c,v
retrieving revision 1.32
diff -u -r1.32 driver.c
--- dlls/gdi/driver.c	13 Jul 2004 03:53:55 -0000	1.32
+++ dlls/gdi/driver.c	2 Aug 2004 13:11:38 -0000
@@ -77,6 +77,7 @@
 
     GET_FUNC(AbortDoc);
     GET_FUNC(AbortPath);
+    GET_FUNC(AlphaBlend);
     GET_FUNC(AngleArc);
     GET_FUNC(Arc);
     GET_FUNC(ArcTo);
Index: dlls/gdi/gdi_private.h
===================================================================
RCS file: /home/wine/wine/dlls/gdi/gdi_private.h,v
retrieving revision 1.12
diff -u -r1.12 gdi_private.h
--- dlls/gdi/gdi_private.h	21 Jul 2004 04:07:28 -0000	1.12
+++ dlls/gdi/gdi_private.h	2 Aug 2004 13:11:38 -0000
@@ -52,6 +52,7 @@
 {
     INT      (*pAbortDoc)(PHYSDEV);
     BOOL     (*pAbortPath)(PHYSDEV);
+    BOOL     (*pAlphaBlend)(PHYSDEV,INT,INT,INT,INT,PHYSDEV,INT,INT,INT,INT,DWORD);
     BOOL     (*pAngleArc)(PHYSDEV,INT,INT,DWORD,FLOAT,FLOAT);
     BOOL     (*pArc)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
     BOOL     (*pArcTo)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
Index: dlls/gdi/enhmfdrv/init.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/enhmfdrv/init.c,v
retrieving revision 1.30
diff -u -r1.30 init.c
--- dlls/gdi/enhmfdrv/init.c	18 Jun 2004 19:33:41 -0000	1.30
+++ dlls/gdi/enhmfdrv/init.c	2 Aug 2004 13:11:38 -0000
@@ -36,6 +36,7 @@
 {
     NULL,                            /* pAbortDoc */
     EMFDRV_AbortPath,                /* pAbortPath */
+    NULL,                            /* pAlphaBlend */
     NULL,                            /* pAngleArc */
     EMFDRV_Arc,                      /* pArc */
     NULL,                            /* pArcTo */
Index: dlls/gdi/mfdrv/init.c
===================================================================
RCS file: /home/wine/wine/dlls/gdi/mfdrv/init.c,v
retrieving revision 1.30
diff -u -r1.30 init.c
--- dlls/gdi/mfdrv/init.c	29 Mar 2004 20:27:18 -0000	1.30
+++ dlls/gdi/mfdrv/init.c	2 Aug 2004 13:11:38 -0000
@@ -36,6 +36,7 @@
 {
     NULL,                            /* pAbortDoc */
     MFDRV_AbortPath,                 /* pAbortPath */
+    NULL,                            /* pAlphaBlend */
     NULL,                            /* pAngleArc */
     MFDRV_Arc,                       /* pArc */
     NULL,                            /* pArcTo */
Index: dlls/x11drv/x11drv.h
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/x11drv.h,v
retrieving revision 1.30
diff -u -r1.30 x11drv.h
--- dlls/x11drv/x11drv.h	13 Jul 2004 03:49:52 -0000	1.30
+++ dlls/x11drv/x11drv.h	2 Aug 2004 13:11:38 -0000
@@ -117,6 +117,10 @@
 
 /* Wine driver X11 functions */
 
+extern BOOL X11DRV_AlphaBlend( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
+                               INT widthDst, INT heightDst,
+                               X11DRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc,
+                               INT widthSrc, INT heightSrc, DWORD blendfn );
 extern BOOL X11DRV_BitBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
                              INT width, INT height, X11DRV_PDEVICE *physDevSrc,
                              INT xSrc, INT ySrc, DWORD rop );
Index: dlls/x11drv/x11drv.spec
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/x11drv.spec,v
retrieving revision 1.59
diff -u -r1.59 x11drv.spec
--- dlls/x11drv/x11drv.spec	15 Jun 2004 17:04:02 -0000	1.59
+++ dlls/x11drv/x11drv.spec	2 Aug 2004 13:11:38 -0000
@@ -1,5 +1,6 @@
 # GDI driver
 
+@ cdecl AlphaBlend(ptr long long long long ptr long long long long long) X11DRV_AlphaBlend
 @ cdecl Arc(ptr long long long long long long long long) X11DRV_Arc
 @ cdecl BitBlt(ptr long long long long ptr long long long) X11DRV_BitBlt
 @ cdecl ChoosePixelFormat(ptr ptr) X11DRV_ChoosePixelFormat
Index: dlls/x11drv/xrender.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/xrender.c,v
retrieving revision 1.42
diff -u -r1.42 xrender.c
--- dlls/x11drv/xrender.c	22 Jul 2004 19:44:10 -0000	1.42
+++ dlls/x11drv/xrender.c	2 Aug 2004 13:11:38 -0000
@@ -109,6 +109,7 @@
 
 #define MAKE_FUNCPTR(f) static typeof(f) * p##f;
 MAKE_FUNCPTR(XRenderAddGlyphs)
+MAKE_FUNCPTR(XRenderComposite)
 MAKE_FUNCPTR(XRenderCompositeString8)
 MAKE_FUNCPTR(XRenderCompositeString16)
 MAKE_FUNCPTR(XRenderCompositeString32)
@@ -116,6 +117,7 @@
 MAKE_FUNCPTR(XRenderCreatePicture)
 MAKE_FUNCPTR(XRenderFillRectangle)
 MAKE_FUNCPTR(XRenderFindFormat)
+MAKE_FUNCPTR(XRenderFindStandardFormat)
 MAKE_FUNCPTR(XRenderFindVisualFormat)
 MAKE_FUNCPTR(XRenderFreeGlyphSet)
 MAKE_FUNCPTR(XRenderFreePicture)
@@ -152,6 +154,7 @@
 
 #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(xrender_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
 LOAD_FUNCPTR(XRenderAddGlyphs)
+LOAD_FUNCPTR(XRenderComposite)
 LOAD_FUNCPTR(XRenderCompositeString8)
 LOAD_FUNCPTR(XRenderCompositeString16)
 LOAD_FUNCPTR(XRenderCompositeString32)
@@ -159,6 +162,7 @@
 LOAD_FUNCPTR(XRenderCreatePicture)
 LOAD_FUNCPTR(XRenderFillRectangle)
 LOAD_FUNCPTR(XRenderFindFormat)
+LOAD_FUNCPTR(XRenderFindStandardFormat)
 LOAD_FUNCPTR(XRenderFindVisualFormat)
 LOAD_FUNCPTR(XRenderFreeGlyphSet)
 LOAD_FUNCPTR(XRenderFreePicture)
@@ -1504,6 +1508,123 @@
     return retv;
 }
 
+BOOL X11DRV_AlphaBlend(X11DRV_PDEVICE *devDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
+                       X11DRV_PDEVICE *devSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
+                       DWORD blendfn)
+{
+    XRenderPictureAttributes pa;
+    XRenderPictFormat *src_format;
+    Picture dst_pict, src_pict;
+    Pixmap xpm;
+    HBITMAP hBitmap;
+    BITMAPOBJ *bmp;
+    XImage *image;
+    GC gc;
+    XGCValues gcv;
+    char *dstbits, *data;
+    int y;
+    POINT pts[2];
+
+    if(!X11DRV_XRender_Installed) {
+        FIXME("Unable to AlphaBlend without Xrender\n");
+        return FALSE;
+    }
+    pts[0].x = xDst;
+    pts[0].y = yDst;
+    pts[1].x = xDst + widthDst;
+    pts[1].y = yDst + heightDst;
+    LPtoDP(devDst->hdc, pts, 2);
+    xDst      = pts[0].x;
+    yDst      = pts[0].y;
+    widthDst  = pts[1].x - pts[0].x;
+    heightDst = pts[1].y - pts[0].y;
+
+    pts[0].x = xSrc;
+    pts[0].y = ySrc;
+    pts[1].x = xSrc + widthSrc;
+    pts[1].y = ySrc + heightSrc;
+    LPtoDP(devSrc->hdc, pts, 2);
+    xSrc      = pts[0].x;
+    ySrc      = pts[0].y;
+    widthSrc  = pts[1].x - pts[0].x;
+    heightSrc = pts[1].y - pts[0].y;
+
+
+    if(widthDst != widthSrc || heightDst != heightSrc) {
+        FIXME("Unable to Stretch\n");
+        return FALSE;
+    }
+
+    hBitmap = GetCurrentObject( devSrc->hdc, OBJ_BITMAP );
+    bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBitmap, BITMAP_MAGIC );
+    if(!bmp || !bmp->dib) {
+        FIXME("not a dibsection\n");
+        GDI_ReleaseObj( hBitmap );
+        return FALSE;
+    }
+
+    if(bmp->dib->dsBm.bmBitsPixel != 32) {
+        FIXME("not a 32 bpp dibsection\n");
+        GDI_ReleaseObj( hBitmap );
+        return FALSE;
+    }
+    dstbits = data = HeapAlloc(GetProcessHeap(), 0, heightSrc * widthSrc * 4);
+    for(y = ySrc + heightSrc - 1; y >= ySrc; y--) {
+        memcpy(dstbits, (char *)bmp->dib->dsBm.bmBits + y * bmp->dib->dsBm.bmWidthBytes + xSrc * 4,
+               widthSrc * 4);
+        dstbits += widthSrc * 4;
+    }
+
+    wine_tsx11_lock();
+    image = XCreateImage(gdi_display, visual, 32, ZPixmap, 0,
+                         data, widthSrc, heightSrc, 32, widthSrc * 4);
+
+    src_format = pXRenderFindStandardFormat(gdi_display, PictStandardARGB32);
+
+
+    TRACE("src_format %p\n", src_format);
+
+    pa.subwindow_mode = IncludeInferiors;
+
+    /* FIXME use devDst->xrender->pict ? */
+    dst_pict = pXRenderCreatePicture(gdi_display,
+                                     devDst->drawable,
+                                     (devDst->depth == 1) ?
+                                     mono_format : screen_format,
+                                     CPSubwindowMode, &pa);
+    TRACE("dst_pict %08lx\n", dst_pict);
+    TRACE("src_drawable = %08lx\n", devSrc->drawable);
+    xpm = XCreatePixmap(gdi_display,
+                        devSrc->drawable,
+                        widthSrc, heightSrc, 32);
+    gcv.graphics_exposures = False;
+    gc = XCreateGC(gdi_display, xpm, GCGraphicsExposures, &gcv);
+    TRACE("xpm = %08lx\n", xpm);
+    XPutImage(gdi_display, xpm, gc, image, 0, 0, 0, 0, widthSrc, heightSrc);
+
+    src_pict = pXRenderCreatePicture(gdi_display,
+                                     xpm, src_format,
+                                     CPSubwindowMode, &pa);
+    TRACE("src_pict %08lx\n", src_pict);
+
+    pXRenderComposite(gdi_display, PictOpOver, src_pict, 0, dst_pict,
+                      xSrc, ySrc, 0, 0,
+                      xDst + devDst->org.x, yDst + devDst->org.y, widthSrc, heightSrc);
+
+
+    pXRenderFreePicture(gdi_display, src_pict);
+    XFreePixmap(gdi_display, xpm);
+    XFreeGC(gdi_display, gc);
+    pXRenderFreePicture(gdi_display, dst_pict);
+    image->data = NULL;
+    XDestroyImage(image);
+
+    wine_tsx11_unlock();
+    HeapFree(GetProcessHeap(), 0, data);
+    GDI_ReleaseObj( hBitmap );
+    return TRUE;
+}
+
 #else /* HAVE_X11_EXTENSIONS_XRENDER_H */
 
 void X11DRV_XRender_Init(void)
@@ -1540,6 +1661,14 @@
 {
   assert(0);
   return;
+}
+
+BOOL X11DRV_AlphaBlend(X11DRV_PDEVICE *devDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
+                       X11DRV_PDEVICE *devSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
+                       DWORD blendfn)
+{
+  FIXME("not supported - XRENDER headers were missing at compile time\n");
+  return FALSE;
 }
 
 #endif /* HAVE_X11_EXTENSIONS_XRENDER_H */


More information about the wine-patches mailing list