gdi32: Pass the source/dest visible rectangles to the AlphaBlend driver entry point.

This commit is contained in:
Alexandre Julliard 2011-07-11 14:17:04 +02:00
parent 1ac1d7c69b
commit bfc12c0c94
7 changed files with 40 additions and 154 deletions

View File

@ -607,22 +607,39 @@ BOOL WINAPI GdiAlphaBlend(HDC hdcDst, int xDst, int yDst, int widthDst, int heig
BOOL ret = FALSE;
DC *dcDst, *dcSrc;
TRACE( "%p %d,%d %dx%d -> %p %d,%d %dx%d op=%02x flags=%02x srcconstalpha=%02x alphafmt=%02x\n",
hdcSrc, xSrc, ySrc, widthSrc, heightSrc, hdcDst, xDst, yDst, widthDst, heightDst,
blendFunction.BlendOp, blendFunction.BlendFlags,
blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat );
dcSrc = get_dc_ptr( hdcSrc );
if (!dcSrc) return FALSE;
if ((dcDst = get_dc_ptr( hdcDst )))
{
struct bitblt_coords src, dst;
PHYSDEV src_dev = GET_DC_PHYSDEV( dcSrc, pAlphaBlend );
PHYSDEV dst_dev = GET_DC_PHYSDEV( dcDst, pAlphaBlend );
update_dc( dcSrc );
update_dc( dcDst );
ret = dst_dev->funcs->pAlphaBlend( dst_dev, xDst, yDst, widthDst, heightDst,
src_dev, xSrc, ySrc, widthSrc, heightSrc, blendFunction );
src.log_x = xSrc;
src.log_y = ySrc;
src.log_width = widthSrc;
src.log_height = heightSrc;
src.layout = GetLayout( src_dev->hdc );
dst.log_x = xDst;
dst.log_y = yDst;
dst.log_width = widthDst;
dst.log_height = heightDst;
dst.layout = GetLayout( dst_dev->hdc );
get_vis_rectangles( dcDst, &dst, dcSrc, &src );
TRACE("src %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s dst %p log=%d,%d %dx%d phys=%d,%d %dx%d vis=%s blend=%02x/%02x/%02x/%02x\n",
hdcSrc, src.log_x, src.log_y, src.log_width, src.log_height,
src.x, src.y, src.width, src.height, wine_dbgstr_rect(&src.visrect),
hdcDst, dst.log_x, dst.log_y, dst.log_width, dst.log_height,
dst.x, dst.y, dst.width, dst.height, wine_dbgstr_rect(&dst.visrect),
blendFunction.BlendOp, blendFunction.BlendFlags,
blendFunction.SourceConstantAlpha, blendFunction.AlphaFormat );
ret = dst_dev->funcs->pAlphaBlend( dst_dev, &dst, src_dev, &src, blendFunction );
release_dc_ptr( dcDst );
}
release_dc_ptr( dcSrc );

View File

@ -318,9 +318,8 @@ static INT CDECL nulldrv_AbortDoc( PHYSDEV dev )
return 0;
}
static BOOL CDECL nulldrv_AlphaBlend( PHYSDEV dst_dev, INT x_dst, INT y_dst, INT width_dst, INT height_dst,
PHYSDEV src_dev, INT x_src, INT y_src, INT width_src, INT height_src,
BLENDFUNCTION func)
static BOOL CDECL nulldrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION func)
{
return TRUE;
}

View File

@ -152,7 +152,7 @@ typedef struct gdi_dc_funcs
{
INT (CDECL *pAbortDoc)(PHYSDEV);
BOOL (CDECL *pAbortPath)(PHYSDEV);
BOOL (CDECL *pAlphaBlend)(PHYSDEV,INT,INT,INT,INT,PHYSDEV,INT,INT,INT,INT,BLENDFUNCTION);
BOOL (CDECL *pAlphaBlend)(PHYSDEV,struct bitblt_coords*,PHYSDEV,struct bitblt_coords*,BLENDFUNCTION);
BOOL (CDECL *pAngleArc)(PHYSDEV,INT,INT,DWORD,FLOAT,FLOAT);
BOOL (CDECL *pArc)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
BOOL (CDECL *pArcTo)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);

View File

@ -1165,116 +1165,6 @@ static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, RECT *visRe
}
/***********************************************************************
* BITBLT_GetVisRectangles
*
* Get the source and destination visible rectangles for StretchBlt().
* Return FALSE if one of the rectangles is empty.
*/
static BOOL BITBLT_GetVisRectangles( X11DRV_PDEVICE *physDevDst, X11DRV_PDEVICE *physDevSrc,
struct bitblt_coords *dst, struct bitblt_coords *src )
{
RECT rect, clipRect;
/* Get the destination visible rectangle */
rect.left = dst->x;
rect.top = dst->y;
rect.right = dst->x + dst->width;
rect.bottom = dst->y + dst->height;
LPtoDP( physDevDst->dev.hdc, (POINT *)&rect, 2 );
dst->x = rect.left;
dst->y = rect.top;
dst->width = rect.right - rect.left;
dst->height = rect.bottom - rect.top;
if (dst->layout & LAYOUT_RTL && dst->layout & LAYOUT_BITMAPORIENTATIONPRESERVED)
{
SWAP_INT32( &rect.left, &rect.right );
dst->x = rect.left;
dst->width = rect.right - rect.left;
}
if (rect.left > rect.right) { SWAP_INT32( &rect.left, &rect.right ); rect.left++; rect.right++; }
if (rect.top > rect.bottom) { SWAP_INT32( &rect.top, &rect.bottom ); rect.top++; rect.bottom++; }
GetRgnBox( physDevDst->region, &clipRect );
if (!IntersectRect( &dst->visrect, &rect, &clipRect )) return FALSE;
/* Get the source visible rectangle */
if (!physDevSrc) return TRUE;
rect.left = src->x;
rect.top = src->y;
rect.right = src->x + src->width;
rect.bottom = src->y + src->height;
LPtoDP( physDevSrc->dev.hdc, (POINT *)&rect, 2 );
src->x = rect.left;
src->y = rect.top;
src->width = rect.right - rect.left;
src->height = rect.bottom - rect.top;
if (src->layout & LAYOUT_RTL && src->layout & LAYOUT_BITMAPORIENTATIONPRESERVED)
{
SWAP_INT32( &rect.left, &rect.right );
src->x = rect.left;
src->width = rect.right - rect.left;
}
if (rect.left > rect.right) { SWAP_INT32( &rect.left, &rect.right ); rect.left++; rect.right++; }
if (rect.top > rect.bottom) { SWAP_INT32( &rect.top, &rect.bottom ); rect.top++; rect.bottom++; }
/* Apparently the clipping and visible regions are only for output,
so just check against dc extent here to avoid BadMatch errors */
clipRect = physDevSrc->drawable_rect;
OffsetRect( &clipRect, -(physDevSrc->drawable_rect.left + physDevSrc->dc_rect.left),
-(physDevSrc->drawable_rect.top + physDevSrc->dc_rect.top) );
if (!IntersectRect( &src->visrect, &rect, &clipRect ))
return FALSE;
/* Intersect the rectangles */
if ((src->width == dst->width) && (src->height == dst->height)) /* no stretching */
{
OffsetRect( &src->visrect, dst->x - src->x, dst->y - src->y );
if (!IntersectRect( &rect, &src->visrect, &dst->visrect )) return FALSE;
src->visrect = dst->visrect = rect;
OffsetRect( &src->visrect, src->x - dst->x, src->y - dst->y );
}
else /* stretching */
{
/* Map source rectangle into destination coordinates */
rect.left = dst->x + (src->visrect.left - src->x)*dst->width/src->width;
rect.top = dst->y + (src->visrect.top - src->y)*dst->height/src->height;
rect.right = dst->x + (src->visrect.right - src->x)*dst->width/src->width;
rect.bottom = dst->y + (src->visrect.bottom - src->y)*dst->height/src->height;
if (rect.left > rect.right) SWAP_INT32( &rect.left, &rect.right );
if (rect.top > rect.bottom) SWAP_INT32( &rect.top, &rect.bottom );
/* Avoid rounding errors */
rect.left--;
rect.top--;
rect.right++;
rect.bottom++;
if (!IntersectRect( &dst->visrect, &rect, &dst->visrect )) return FALSE;
/* Map destination rectangle back to source coordinates */
rect = dst->visrect;
rect.left = src->x + (dst->visrect.left - dst->x)*src->width/dst->width;
rect.top = src->y + (dst->visrect.top - dst->y)*src->height/dst->height;
rect.right = src->x + (dst->visrect.right - dst->x)*src->width/dst->width;
rect.bottom = src->y + (dst->visrect.bottom - dst->y)*src->height/dst->height;
if (rect.left > rect.right) SWAP_INT32( &rect.left, &rect.right );
if (rect.top > rect.bottom) SWAP_INT32( &rect.top, &rect.bottom );
/* Avoid rounding errors */
rect.left--;
rect.top--;
rect.right++;
rect.bottom++;
if (!IntersectRect( &src->visrect, &rect, &src->visrect )) return FALSE;
}
return TRUE;
}
/***********************************************************************
* client_side_dib_copy
*/
@ -1639,41 +1529,21 @@ done:
/***********************************************************************
* X11DRV_AlphaBlend
*/
BOOL CDECL X11DRV_AlphaBlend( PHYSDEV dst_dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
PHYSDEV src_dev, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
BLENDFUNCTION blendfn )
BOOL CDECL X11DRV_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION blendfn )
{
X11DRV_PDEVICE *physDevDst = get_x11drv_dev( dst_dev );
X11DRV_PDEVICE *physDevSrc = get_x11drv_dev( src_dev ); /* FIXME: check that it's really an x11 dev */
struct bitblt_coords src, dst;
src.x = xSrc;
src.y = ySrc;
src.width = widthSrc;
src.height = heightSrc;
src.layout = GetLayout( src_dev->hdc );
dst.x = xDst;
dst.y = yDst;
dst.width = widthDst;
dst.height = heightDst;
dst.layout = GetLayout( dst_dev->hdc );
if (!BITBLT_GetVisRectangles( physDevDst, physDevSrc, &dst, &src )) return TRUE;
TRACE( "format %x alpha %u rectdst=%d,%d %dx%d orgdst=%d,%d visdst=%s rectsrc=%d,%d %dx%d orgsrc=%d,%d vissrc=%s\n",
blendfn.AlphaFormat, blendfn.SourceConstantAlpha, dst.x, dst.y, dst.width, dst.height,
physDevDst->dc_rect.left, physDevDst->dc_rect.top, wine_dbgstr_rect( &dst.visrect ),
src.x, src.y, src.width, src.height,
physDevSrc->dc_rect.left, physDevSrc->dc_rect.top, wine_dbgstr_rect( &src.visrect ) );
if (src.x < 0 || src.y < 0 || src.width < 0 || src.height < 0 ||
src.width > physDevSrc->drawable_rect.right - physDevSrc->drawable_rect.left - src.x ||
src.height > physDevSrc->drawable_rect.bottom - physDevSrc->drawable_rect.top - src.y)
if (src->x < 0 || src->y < 0 || src->width < 0 || src->height < 0 ||
src->width > physDevSrc->drawable_rect.right - physDevSrc->drawable_rect.left - src->x ||
src->height > physDevSrc->drawable_rect.bottom - physDevSrc->drawable_rect.top - src->y)
{
WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src.x, src.y, src.width, src.height );
WARN( "Invalid src coords: (%d,%d), size %dx%d\n", src->x, src->y, src->width, src->height );
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
if (IsRectEmpty( &dst->visrect )) return TRUE;
return XRender_AlphaBlend( physDevDst, physDevSrc, &dst, &src, blendfn );
return XRender_AlphaBlend( physDevDst, dst, physDevSrc, src, blendfn );
}

View File

@ -1,6 +1,6 @@
# GDI driver
@ cdecl AlphaBlend(ptr long long long long ptr long long long long long) X11DRV_AlphaBlend
@ cdecl AlphaBlend(ptr ptr ptr ptr long) X11DRV_AlphaBlend
@ cdecl Arc(ptr long long long long long long long long) X11DRV_Arc
@ cdecl ChoosePixelFormat(ptr ptr) X11DRV_ChoosePixelFormat
@ cdecl Chord(ptr long long long long long long long long) X11DRV_Chord

View File

@ -290,8 +290,8 @@ BOOL X11DRV_XRender_GetSrcAreaStretch(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE
Pixmap pixmap, GC gc,
const struct bitblt_coords *src, const struct bitblt_coords *dst ) DECLSPEC_HIDDEN;
extern void X11DRV_XRender_UpdateDrawable(X11DRV_PDEVICE *physDev) DECLSPEC_HIDDEN;
extern BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
struct bitblt_coords *dst, struct bitblt_coords *src,
extern BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, struct bitblt_coords *dst,
X11DRV_PDEVICE *devSrc, struct bitblt_coords *src,
BLENDFUNCTION blendfn ) DECLSPEC_HIDDEN;
extern Drawable get_glxdrawable(X11DRV_PDEVICE *physDev) DECLSPEC_HIDDEN;

View File

@ -2208,8 +2208,8 @@ static void xrender_mono_blit( Picture src_pict, Picture mask_pict, Picture dst_
/******************************************************************************
* AlphaBlend
*/
BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, X11DRV_PDEVICE *devSrc,
struct bitblt_coords *dst, struct bitblt_coords *src, BLENDFUNCTION blendfn )
BOOL XRender_AlphaBlend( X11DRV_PDEVICE *devDst, struct bitblt_coords *dst,
X11DRV_PDEVICE *devSrc, struct bitblt_coords *src, BLENDFUNCTION blendfn )
{
Picture dst_pict, src_pict = 0, mask_pict = 0, tmp_pict = 0;
struct xrender_info *src_info = get_xrender_info( devSrc );