Implement AlphaBlend using the XRENDER extension.

This commit is contained in:
Huw Davies 2004-08-02 18:54:54 +00:00 committed by Alexandre Julliard
parent c09881d51c
commit dd5b23fddb
8 changed files with 168 additions and 6 deletions

View File

@ -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;
}
/*********************************************************************

View File

@ -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);

View File

@ -36,6 +36,7 @@ static const DC_FUNCTIONS EMFDRV_Funcs =
{
NULL, /* pAbortDoc */
EMFDRV_AbortPath, /* pAbortPath */
NULL, /* pAlphaBlend */
NULL, /* pAngleArc */
EMFDRV_Arc, /* pArc */
NULL, /* pArcTo */

View File

@ -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);

View File

@ -36,6 +36,7 @@ static const DC_FUNCTIONS MFDRV_Funcs =
{
NULL, /* pAbortDoc */
MFDRV_AbortPath, /* pAbortPath */
NULL, /* pAlphaBlend */
NULL, /* pAngleArc */
MFDRV_Arc, /* pArc */
NULL, /* pArcTo */

View File

@ -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 );

View File

@ -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

View File

@ -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 */