linamh/app-emulation/wine/files/0006-dib-engine-add-clipping-on-xxx.patch

561 lines
21 KiB
Diff
Raw Normal View History

DIB Engine: Add clipping on xxxBlt and AlphaBlend
From: Massimo Del Fedele <max@veneto.com>
---
dlls/winedib.drv/bitblt.c | 332 +++++++++++++++++++++++++++++++++++++------
dlls/winedib.drv/clipping.c | 42 +++++
dlls/winedib.drv/dc.c | 14 ++
dlls/winedib.drv/dibdrv.h | 6 +
4 files changed, 341 insertions(+), 53 deletions(-)
diff --git a/dlls/winedib.drv/bitblt.c b/dlls/winedib.drv/bitblt.c
index c0227a0..05c9392 100644
--- a/dlls/winedib.drv/bitblt.c
+++ b/dlls/winedib.drv/bitblt.c
@@ -33,6 +33,26 @@ static inline void intSwap(int *a, int *b)
*b = tmp;
}
+static inline void setRect(RECT *r, int x1, int y1, int x2, int y2)
+{
+ r->left = x1;
+ r->top = y1;
+ r->right = x2;
+ r->bottom = y2;
+}
+
+static inline void setPoint(POINT *p, int x, int y)
+{
+ p->x = x;
+ p->y = y;
+}
+
+static inline void setSize(SIZE *sz, int cx, int cy)
+{
+ sz->cx = cx;
+ sz->cy = cy;
+}
+
/* clips a source and destination areas to their respective clip rectangles
returning both source and dest modified; result is TRUE if clipping
leads to a non null rectangle, FALSE otherwise */
@@ -130,13 +150,158 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT*
leads to a non null rectangle, FALSE otherwise */
static BOOL StretchBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *szSrc, SIZE *szDst, RECT*srcClip, RECT*dstClip)
{
- ONCE(FIXME("TO DO\n"));
+ int xs1, ys1, xs2, ys2;
+ int xsc1, ysc1, xsc2, ysc2;
+ int xd1, yd1, xd2, yd2;
+ int xdc1, ydc1, xdc2, ydc2;
+ int ws, hs, wd, hd, dx, dy;
+ int mulh, divh, mulv, divv;
+
+ /* extract sizes */
+ ws = szSrc->cx; hs = szSrc->cy;
+ wd = szDst->cx; hd = szDst->cy;
+
+ /* if sizes null or negative, just return false */
+ /* FIXME : add support for mirror stretch */
+ if(ws <= 0 || hs <= 0 || wd <= 0 || hd <= 0)
+ return FALSE;
+
+ /* stores scaling factors from source rect to dest one */
+ mulh = wd; divh = ws;
+ mulv = hd; divv = hs;
+
+ /* extract dest area data */
+ xd1 = pd->x;
+ yd1 = pd->y;
+ xd2 = xd1 + wd;
+ yd2 = yd1 + hd;
+
+ /* extract source data */
+ xs1 = ps->x;
+ ys1 = ps->y;
+ xs2 = xs1 + ws;
+ ys2 = ys1 + hs;
+
+ /* if source clip area is not null, do first clipping on it */
+ if(srcClip)
+ {
+ /* extract source clipping area */
+ xsc1 = srcClip->left;
+ ysc1 = srcClip->top;
+ xsc2 = srcClip->right;
+ ysc2 = srcClip->bottom;
+
+ /* order clip area rectangle points */
+ if(xsc1 > xsc2) intSwap(&xsc1, &xsc2);
+ if(ysc1 > ysc2) intSwap(&ysc1, &ysc2);
+
+ /* clip on source clipping start point */
+ if(xs1 < xsc1) { dx = xsc1 - xs1; ws -= dx; xd1 += MulDiv(dx, mulh, divh); xs1 = xsc1; }
+ if(ys1 < ysc1) { dy = ysc1 - ys1; hs -= dy; yd1 += MulDiv(dy, mulv, divv); ys1 = ysc1; }
+
+ /* clip on source clipping end point */
+ if(xs2 > xsc2) { dx = xs2 - xsc2; ws -= dx; xd2 -= MulDiv(dx, mulh, divh); xs2 = xsc2; }
+ if(ys2 > ysc2) { dy = ys2 - ysc2; hs -= dy; yd2 -= MulDiv(dy, mulv, divv); ys2 = ysc2; }
+
+ /* if already zero area, return false */
+ if(ws <= 0 || hs <= 0)
+ return FALSE;
+ wd = xd2 - xd1;
+ hd = yd2 - yd1;
+ }
+ /* now do clipping on destination area */
+ if(dstClip)
+ {
+ /* extract destination clipping area */
+ xdc1 = dstClip->left;
+ ydc1 = dstClip->top;
+ xdc2 = dstClip->right;
+ ydc2 = dstClip->bottom;
+
+ /* order clip area rectangle points */
+ if(xdc1 > xdc2) intSwap(&xdc1, &xdc2);
+ if(ydc1 > ydc2) intSwap(&ydc1, &ydc2);
+
+ /* clip on dest clipping start point */
+ if(xd1 < xdc1) { dx = xdc1 - xd1; wd -= dx; xs1 += MulDiv(dx, divh, mulh); xd1 = xdc1; }
+ if(yd1 < ydc1) { dy = ydc1 - yd1; hd -= dy; ys1 += MulDiv(dy, divv, mulv); yd1 = ydc1; }
+
+ /* clip on dest clipping end point */
+ if(xd2 > xdc2) { dx = xd2 - xdc2; wd -= dx; xs2 -= MulDiv(dx, divh, mulh); xd2 = xdc2; }
+ if(yd2 > ydc2) { dy = yd2 - ydc2; hd -= dy; ys2 -= MulDiv(dy, divv, mulv); yd2 = ydc2; }
+
+ /* if already zero area, return false */
+ if(wd <= 0 || hd <= 0)
+ return FALSE;
+
+ ws = xs2 - xs1;
+ hs = ys2 - ys1;
+ }
+
+ /* sets clipped/translated points and sizes and returns TRUE */
+ ps->x = xs1; ps->y = ys1;
+ pd->x = xd1; pd->y = yd1;
+ szSrc->cx = ws; szSrc->cy = hs;
+ szDst->cx = wd; szDst->cy = hd;
+
return TRUE;
}
/***********************************************************************
+ * _DIBDRV_InternalAlphaBlend
+ */
+BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
+ DIBDRVPHYSDEV *physDevSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc,
+ BLENDFUNCTION blendfn)
+{
+ BOOL res;
+ POINT pd, ps;
+ SIZE szSrc, szDst;
+ int iRec;
+ RECT dstClip, srcClip;
+
+ /* first clip on physical DC sizes */
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&szDst, widthDst, heightDst);
+ setSize(&szSrc, widthSrc, heightSrc);
+ setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
+ if(physDevSrc)
+ {
+ setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
+ }
+ else
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
+ if(!res)
+ return FALSE;
+ xDst = pd.x; yDst = pd.y;
+ xSrc = ps.x; ySrc = ps.y;
+ widthDst = szDst.cx; heightDst = szDst.cy;
+ widthSrc = szSrc.cx; heightSrc = szSrc.cy;
+
+ /* then, do blitting for each dest clip area (no clipping on source) */
+ res = FALSE;
+ for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
+ {
+ RECT *r = physDevDst->regionRects + iRec;
+ setRect(&dstClip, r->left, r->top, r->right, r->bottom);
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&szDst, widthDst, heightDst);
+ setSize(&szSrc, widthSrc, heightSrc);
+ if(!StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip))
+ continue;
+ if(physDevDst->physBitmap.funcs->AlphaBlend(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
+ physDevSrc, ps.x, ps.y, szSrc.cx, szSrc.cy, blendfn))
+ res = TRUE;
+ }
+ return res;
+}
+
+/***********************************************************************
* DIBDRV_AlphaBlend
*/
BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT widthDst, INT heightDst,
@@ -145,6 +310,11 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
{
BOOL res;
+ POINT pd = {xDst, yDst};
+ POINT ps = {xSrc, ySrc};
+ SIZE szDst = {widthDst, heightDst};
+ SIZE szSrc = {widthSrc, heightSrc};
+
MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d\n",
physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevDst->physBitmap) : "",
xDst, yDst, widthDst, heightDst,
@@ -177,16 +347,24 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
{
/* DIB section selected in dest DC, use DIB Engine */
MAYBE(TRACE("Blending DIB->DIB\n"));
- res = physDevDst->physBitmap.funcs->AlphaBlend(physDevDst, xDst, yDst, widthDst, heightDst,
- physDevSrc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
+ res = _DIBDRV_InternalAlphaBlend(physDevDst, xDst, yDst, widthDst, heightDst,
+ physDevSrc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
}
else
{
/* DDB selected on dest DC -- must double-convert */
HBITMAP tmpDIB, stock;
HDC tmpDC;
+ RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
MAYBE(TRACE("Blending DIB->DDB\n"));
+ /* clip blit area */
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, 0);
+ if(!res)
+ goto fin;
+ xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy;
+ xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
+
/* converts dest DDB onto a temporary DIB -- just the needed part */
tmpDIB = _DIBDRV_ConvertDevDDBtoDIB(physDevDst->hdc, physDevSrc->hdc, xDst, yDst, widthDst, heightDst);
if(!tmpDIB)
@@ -232,8 +410,55 @@ fin:
}
/***********************************************************************
- * DIBDRV_BitBlt
+ * _DIBDRV_InternalBitBlt
*/
+BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+ INT width, INT height, DIBDRVPHYSDEV *physDevSrc,
+ INT xSrc, INT ySrc, DWORD rop )
+{
+ BOOL res;
+ POINT pd, ps;
+ SIZE sz;
+ int iRec;
+ RECT dstClip, srcClip;
+
+ /* first clip on physical DC sizes */
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&sz, width, height);
+ setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
+ if(physDevSrc)
+ {
+ setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
+ res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, &dstClip);
+ }
+ else
+ res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip);
+ if(!res)
+ return FALSE;
+ xDst = pd.x; yDst = pd.y;
+ xSrc = ps.x; ySrc = ps.y;
+ width = sz.cx; height = sz.cy;
+
+ /* then, do blitting for each dest clip area (no clipping on source) */
+ res = FALSE;
+ for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
+ {
+ RECT *r = physDevDst->regionRects + iRec;
+ setRect(&dstClip, r->left, r->top, r->right, r->bottom);
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&sz, width, height);
+ if(!BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip))
+ continue;
+ if(physDevDst->physBitmap.funcs->BitBlt(physDevDst, pd.x, pd.y, sz.cx, sz.cy, physDevSrc, ps.x, ps.y, rop))
+ res = TRUE;
+ }
+ return res;
+}
+
+/***********************************************************************
+ * DIBDRV_BitBlt */
BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
INT width, INT height, DIBDRVPHYSDEV *physDevSrc,
INT xSrc, INT ySrc, DWORD rop )
@@ -254,26 +479,13 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
if(physDevDst->hasDIB)
{
/* DIB section selected in dest DC, use DIB Engine */
-
/* clip blit area */
RECT dstClip = {0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height};
if(!physDevSrc || physDevSrc->hasDIB)
{
- /* clip blit area */
- if(physDevSrc)
- {
- RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
- res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, &dstClip);
- }
- else
- res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip);
- if(!res)
- goto noBlt2;
- xDst = pd.x; yDst = pd.y; width = sz.cx; height = sz.cy; xSrc = ps.x; ySrc = ps.y;
-
/* source is null or has a DIB, no need to convert anyting */
- res = physDevDst->physBitmap.funcs->BitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, ySrc, rop);
+ res = _DIBDRV_InternalBitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, ySrc, rop);
}
else
{
@@ -309,8 +521,7 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
goto noBlt1;
}
SelectObject(physDevSrc->hdc, dib);
- res = physDevDst->physBitmap.funcs->BitBlt(physDevDst, xDst, yDst, width, height,
- physDevSrc, xSrc, 0, rop);
+ res = _DIBDRV_InternalBitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, 0, rop);
SelectObject(physDevSrc->hdc, ddb);
DeleteObject(dib);
noBlt1:
@@ -410,6 +621,58 @@ noBlt3:
}
/***********************************************************************
+ * _DIBDRV_InternalStretchBlt
+ */
+BOOL _DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+ INT widthDst, INT heightDst, DIBDRVPHYSDEV *physDevSrc,
+ INT xSrc, INT ySrc, int widthSrc, int heightSrc, DWORD rop )
+{
+ BOOL res;
+ POINT pd, ps;
+ SIZE szSrc, szDst;
+ int iRec;
+ RECT dstClip, srcClip;
+
+ /* first clip on physical DC sizes */
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&szDst, widthDst, heightDst);
+ setSize(&szSrc, widthSrc, heightSrc);
+ setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
+ if(physDevSrc)
+ {
+ setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
+ }
+ else
+ res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
+ if(!res)
+ return FALSE;
+ xDst = pd.x; yDst = pd.y;
+ xSrc = ps.x; ySrc = ps.y;
+ widthDst = szDst.cx; heightDst = szDst.cy;
+ widthSrc = szSrc.cx; heightSrc = szSrc.cy;
+
+ /* then, do blitting for each dest clip area (no clipping on source) */
+ res = FALSE;
+ for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
+ {
+ RECT *r = physDevDst->regionRects + iRec;
+ setRect(&dstClip, r->left, r->top, r->right, r->bottom);
+ setPoint(&pd, xDst, yDst);
+ setPoint(&ps, xSrc, ySrc);
+ setSize(&szDst, widthDst, heightDst);
+ setSize(&szSrc, widthSrc, heightSrc);
+ if(!StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip))
+ continue;
+ if(physDevDst->physBitmap.funcs->StretchBlt(physDevDst, pd.x, pd.y, szDst.cx, szDst.cy,
+ physDevSrc, ps.x, ps.y, szSrc.cx, szSrc.cy, rop))
+ res = TRUE;
+ }
+ return res;
+}
+
+/***********************************************************************
* DIBDRV_StretchBlt
*/
BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
@@ -439,38 +702,15 @@ BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
{
/* DIB section selected in dest DC, use DIB Engine */
- /* clip blit area */
- RECT dstClip = {0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height};
-
if(!physDevSrc || physDevSrc->hasDIB)
{
- /* clip blit area */
- if(physDevSrc)
- {
- RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
- res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
- }
- else
- res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
- if(!res)
- goto noBlt2;
- xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy;
- xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
-
/* source is null or has a DIB, no need to convert anyting */
- res = physDevDst->physBitmap.funcs->StretchBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop);
+ res = _DIBDRV_InternalStretchBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop);
}
else
{
/* source is a DDB, must convert it to DIB */
- /* don't clip on source */
- res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
- if(!res)
- goto noBlt2;
- xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy;
- xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
-
/* we must differentiate from 2 cases :
1) source DC is a memory DC
2) source DC is a device DC */
@@ -495,8 +735,8 @@ BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
goto noBlt1;
}
SelectObject(physDevSrc->hdc, dib);
- res = physDevDst->physBitmap.funcs->StretchBlt(physDevDst, xDst, yDst, widthDst, heightDst,
- physDevSrc, xSrc, 0, widthSrc, heightSrc, rop);
+ res = _DIBDRV_InternalStretchBlt(physDevDst, xDst, yDst, widthDst, heightDst,
+ physDevSrc, xSrc, 0, widthSrc, heightSrc, rop);
SelectObject(physDevSrc->hdc, ddb);
DeleteObject(dib);
noBlt1:
diff --git a/dlls/winedib.drv/clipping.c b/dlls/winedib.drv/clipping.c
index 81dec25..ed10b92 100644
--- a/dlls/winedib.drv/clipping.c
+++ b/dlls/winedib.drv/clipping.c
@@ -25,22 +25,50 @@
WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
-
/***********************************************************************
* DIBDRV_SetDeviceClipping
*/
void DIBDRV_SetDeviceClipping( DIBDRVPHYSDEV *physDev, HRGN vis_rgn, HRGN clip_rgn )
{
+ RGNDATA *data;
+ DWORD size;
+ int iRect;
+
MAYBE(TRACE("physDev:%p, vis_rgn:%p, clip_rgn:%p\n", physDev, vis_rgn, clip_rgn));
- if(physDev->hasDIB)
+ /* sets the region for X11 driver anyways... we may change bitmap later on */
+ _DIBDRV_GetDisplayDriver()->pSetDeviceClipping(physDev->X11PhysDev, vis_rgn, clip_rgn);
+
+ /* then we set the region for DIB engine, same reason */
+
+ CombineRgn( physDev->region, vis_rgn, clip_rgn, clip_rgn ? RGN_AND : RGN_COPY );
+
+ /* get region rectangles */
+ if(!(size = GetRegionData(physDev->region, 0, NULL)))
+ return;
+ data = HeapAlloc(GetProcessHeap(), 0, size);
+ if (!GetRegionData(physDev->region, size, data))
{
- /* DIB section selected in, use DIB Engine */
- ONCE(FIXME("STUB\n"));
+ HeapFree( GetProcessHeap(), 0, data );
+ return;
}
- else
+
+ /* frees any previous regions rectangles in DC */
+ if(physDev->regionData)
+ HeapFree(GetProcessHeap(), 0, physDev->regionData);
+
+ /* sets the rectangles on physDev */
+ physDev->regionData = data;
+ physDev->regionRects = (RECT *)data->Buffer;
+ physDev->regionRectCount = data->rdh.nCount;
+
+ if(TRACE_ON(dibdrv))
{
- /* DDB selected in, use X11 driver */
- _DIBDRV_GetDisplayDriver()->pSetDeviceClipping(physDev->X11PhysDev, vis_rgn, clip_rgn);
+ TRACE("Region dump : %d rectangles\n", physDev->regionRectCount);
+ for(iRect = 0; iRect < physDev->regionRectCount; iRect++)
+ {
+ RECT *r = physDev->regionRects + iRect;
+ TRACE("Rect #%03d, x1:%4d, y1:%4d, x2:%4d, y2:%4d\n", iRect, r->left, r->top, r->right, r->bottom);
+ }
}
}
diff --git a/dlls/winedib.drv/dc.c b/dlls/winedib.drv/dc.c
index 6184677..8212d42 100644
--- a/dlls/winedib.drv/dc.c
+++ b/dlls/winedib.drv/dc.c
@@ -165,6 +165,12 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev
/* clears pen and brush */
physDev->rop2 = R2_COPYPEN;
+
+ /* clipping region */
+ physDev->region = CreateRectRgn( 0, 0, 0, 0 );
+ physDev->regionData = NULL;
+ physDev->regionRects = NULL;
+ physDev->regionRectCount = 0;
physDev->backgroundColor = 0;
_DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->backgroundAnd, &physDev->backgroundXor);
@@ -228,6 +234,14 @@ BOOL DIBDRV_DeleteDC( DIBDRVPHYSDEV *physDev )
physDev->brushAnds = NULL;
physDev->brushXors = NULL;
+ /* frees clipping region */
+ DeleteObject(physDev->region);
+ if(physDev->regionData)
+ HeapFree(GetProcessHeap(), 0, physDev->regionData);
+ physDev->regionData = NULL;
+ physDev->regionRects = NULL;
+ physDev->regionRectCount = 0;
+
/* frees DIB Engine device */
HeapFree(GetProcessHeap(), 0, physDev);
diff --git a/dlls/winedib.drv/dibdrv.h b/dlls/winedib.drv/dibdrv.h
index c801d96..b0f128e 100644
--- a/dlls/winedib.drv/dibdrv.h
+++ b/dlls/winedib.drv/dibdrv.h
@@ -204,6 +204,12 @@ typedef struct _DIBDRVPHYSDEV
/* active ROP2 */
INT rop2;
+
+ /* clipping region and its rectangles */
+ HRGN region;
+ RGNDATA *regionData;
+ RECT *regionRects;
+ int regionRectCount;
/* background color and active ROP2 precalculated
AND and XOR values for it */