Implement AlphaBlend using the XRENDER extension.
diff --git a/dlls/gdi/bitblt.c b/dlls/gdi/bitblt.c
index ef39099..8b114eb 100644
--- a/dlls/gdi/bitblt.c
+++ b/dlls/gdi/bitblt.c
@@ -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;
}
/*********************************************************************
diff --git a/dlls/gdi/driver.c b/dlls/gdi/driver.c
index 388f859..e2a8bb7 100644
--- a/dlls/gdi/driver.c
+++ b/dlls/gdi/driver.c
@@ -77,6 +77,7 @@
GET_FUNC(AbortDoc);
GET_FUNC(AbortPath);
+ GET_FUNC(AlphaBlend);
GET_FUNC(AngleArc);
GET_FUNC(Arc);
GET_FUNC(ArcTo);
diff --git a/dlls/gdi/enhmfdrv/init.c b/dlls/gdi/enhmfdrv/init.c
index 7e037aa..94fe611 100644
--- a/dlls/gdi/enhmfdrv/init.c
+++ b/dlls/gdi/enhmfdrv/init.c
@@ -36,6 +36,7 @@
{
NULL, /* pAbortDoc */
EMFDRV_AbortPath, /* pAbortPath */
+ NULL, /* pAlphaBlend */
NULL, /* pAngleArc */
EMFDRV_Arc, /* pArc */
NULL, /* pArcTo */
diff --git a/dlls/gdi/gdi_private.h b/dlls/gdi/gdi_private.h
index 4bae5ed..5d9ff3d 100644
--- a/dlls/gdi/gdi_private.h
+++ b/dlls/gdi/gdi_private.h
@@ -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);
diff --git a/dlls/gdi/mfdrv/init.c b/dlls/gdi/mfdrv/init.c
index 239628d..c76025d 100644
--- a/dlls/gdi/mfdrv/init.c
+++ b/dlls/gdi/mfdrv/init.c
@@ -36,6 +36,7 @@
{
NULL, /* pAbortDoc */
MFDRV_AbortPath, /* pAbortPath */
+ NULL, /* pAlphaBlend */
NULL, /* pAngleArc */
MFDRV_Arc, /* pArc */
NULL, /* pArcTo */
diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h
index d80bce2..58261f1 100644
--- a/dlls/x11drv/x11drv.h
+++ b/dlls/x11drv/x11drv.h
@@ -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 );
diff --git a/dlls/x11drv/x11drv.spec b/dlls/x11drv/x11drv.spec
index b35c913..97d2d0d 100644
--- a/dlls/x11drv/x11drv.spec
+++ b/dlls/x11drv/x11drv.spec
@@ -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
diff --git a/dlls/x11drv/xrender.c b/dlls/x11drv/xrender.c
index 98fb2f3..cbbe619 100644
--- a/dlls/x11drv/xrender.c
+++ b/dlls/x11drv/xrender.c
@@ -47,6 +47,14 @@
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
+/* Older version of the Xrender headers don't define these */
+#ifndef PictStandardARGB32
+
+#define PictStandardARGB32 0
+XRenderPictFormat * XRenderFindStandardFormat (Display *dpy, int format);
+
+#endif
+
static XRenderPictFormat *screen_format; /* format of screen */
static XRenderPictFormat *mono_format; /* format of mono bitmap */
@@ -109,6 +117,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 +125,7 @@
MAKE_FUNCPTR(XRenderCreatePicture)
MAKE_FUNCPTR(XRenderFillRectangle)
MAKE_FUNCPTR(XRenderFindFormat)
+MAKE_FUNCPTR(XRenderFindStandardFormat)
MAKE_FUNCPTR(XRenderFindVisualFormat)
MAKE_FUNCPTR(XRenderFreeGlyphSet)
MAKE_FUNCPTR(XRenderFreePicture)
@@ -152,6 +162,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 +170,7 @@
LOAD_FUNCPTR(XRenderCreatePicture)
LOAD_FUNCPTR(XRenderFillRectangle)
LOAD_FUNCPTR(XRenderFindFormat)
+LOAD_FUNCPTR(XRenderFindStandardFormat)
LOAD_FUNCPTR(XRenderFindVisualFormat)
LOAD_FUNCPTR(XRenderFreeGlyphSet)
LOAD_FUNCPTR(XRenderFreePicture)
@@ -1504,6 +1516,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)
@@ -1542,4 +1671,12 @@
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 */