From dd5b23fddbf05c02d1ad8a46663345edf441fff7 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Mon, 2 Aug 2004 18:54:54 +0000 Subject: [PATCH] Implement AlphaBlend using the XRENDER extension. --- dlls/gdi/bitblt.c | 28 ++++++-- dlls/gdi/driver.c | 1 + dlls/gdi/enhmfdrv/init.c | 1 + dlls/gdi/gdi_private.h | 1 + dlls/gdi/mfdrv/init.c | 1 + dlls/x11drv/x11drv.h | 4 ++ dlls/x11drv/x11drv.spec | 1 + dlls/x11drv/xrender.c | 137 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 168 insertions(+), 6 deletions(-) diff --git a/dlls/gdi/bitblt.c b/dlls/gdi/bitblt.c index ef39099a7f8..8b114eb6af3 100644 --- a/dlls/gdi/bitblt.c +++ b/dlls/gdi/bitblt.c @@ -398,14 +398,30 @@ error: /****************************************************************************** * 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 388f859b358..e2a8bb7c6ec 100644 --- a/dlls/gdi/driver.c +++ b/dlls/gdi/driver.c @@ -77,6 +77,7 @@ static struct graphics_driver *create_driver( HMODULE module ) 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 7e037aa3d1a..94fe611289c 100644 --- a/dlls/gdi/enhmfdrv/init.c +++ b/dlls/gdi/enhmfdrv/init.c @@ -36,6 +36,7 @@ static const DC_FUNCTIONS EMFDRV_Funcs = { 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 4bae5eda184..5d9ff3d9714 100644 --- a/dlls/gdi/gdi_private.h +++ b/dlls/gdi/gdi_private.h @@ -52,6 +52,7 @@ typedef struct tagDC_FUNCS { 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 239628d476e..c76025db3b1 100644 --- a/dlls/gdi/mfdrv/init.c +++ b/dlls/gdi/mfdrv/init.c @@ -36,6 +36,7 @@ static const DC_FUNCTIONS MFDRV_Funcs = { 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 d80bce2356c..58261f14ad6 100644 --- a/dlls/x11drv/x11drv.h +++ b/dlls/x11drv/x11drv.h @@ -117,6 +117,10 @@ extern unsigned int X11DRV_server_startticks; /* 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 b35c913a3ba..97d2d0d2ff1 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 98fb2f34dc2..cbbe61951ac 100644 --- a/dlls/x11drv/xrender.c +++ b/dlls/x11drv/xrender.c @@ -47,6 +47,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(xrender); #include #include +/* 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 @@ static void *xrender_handle; #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(XRenderCreateGlyphSet) 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 @@ void X11DRV_XRender_Init(void) #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(XRenderCreateGlyphSet) 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 @@ done: 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 @@ void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev) 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 */