Commit dd5b23fd authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

Implement AlphaBlend using the XRENDER extension.

parent c09881d5
......@@ -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;
}
/*********************************************************************
......
......@@ -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);
......
......@@ -36,6 +36,7 @@ static const DC_FUNCTIONS EMFDRV_Funcs =
{
NULL, /* pAbortDoc */
EMFDRV_AbortPath, /* pAbortPath */
NULL, /* pAlphaBlend */
NULL, /* pAngleArc */
EMFDRV_Arc, /* pArc */
NULL, /* pArcTo */
......
......@@ -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);
......
......@@ -36,6 +36,7 @@ static const DC_FUNCTIONS MFDRV_Funcs =
{
NULL, /* pAbortDoc */
MFDRV_AbortPath, /* pAbortPath */
NULL, /* pAlphaBlend */
NULL, /* pAngleArc */
MFDRV_Arc, /* pArc */
NULL, /* pArcTo */
......
......@@ -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 );
......
# 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
......
......@@ -47,6 +47,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(xrender);
#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 @@ 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 */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment