From 54fd8b3d14a199084119488f20036bc6362e6cef Mon Sep 17 00:00:00 2001 From: Damjan Jovanovic Date: Sat, 4 Nov 2006 09:54:59 +0200 Subject: [PATCH] winex11.drv: Added a basic client-side DIB copy optimization. --- dlls/winex11.drv/bitblt.c | 95 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 61a3ad6963..953e8a15b5 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -2,6 +2,7 @@ * GDI bit-blit operations * * Copyright 1993, 1994 Alexandre Julliard + * Copyright 2006 Damjan Jovanovic * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -1525,6 +1526,93 @@ BOOL X11DRV_PatBlt( X11DRV_PDEVICE *physDev, INT left, INT top, INT width, INT h } +/*********************************************************************** + * X11DRV_ClientSideDIBCopy + */ +static BOOL X11DRV_ClientSideDIBCopy( X11DRV_PDEVICE *physDevSrc, INT xSrc, INT ySrc, + X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst, + INT width, INT height ) +{ + DIBSECTION srcDib, dstDib; + BYTE *srcPtr, *dstPtr; + INT bytesPerPixel; + INT bytesToCopy; + INT y; + static RECT unusedRect; + + if (GetObjectW(physDevSrc->bitmap->hbitmap, sizeof(srcDib), &srcDib) != sizeof(srcDib)) + return FALSE; + if (GetObjectW(physDevDst->bitmap->hbitmap, sizeof(dstDib), &dstDib) != sizeof(dstDib)) + return FALSE; + + /* check for oversized values, just like X11DRV_DIB_CopyDIBSection() */ + if (xSrc > srcDib.dsBm.bmWidth || ySrc > srcDib.dsBm.bmHeight) + return FALSE; + if (xSrc + width > srcDib.dsBm.bmWidth) + width = srcDib.dsBm.bmWidth - xSrc; + if (ySrc + height > srcDib.dsBm.bmHeight) + height = srcDib.dsBm.bmHeight - ySrc; + + if (GetRgnBox(physDevSrc->region, &unusedRect) == COMPLEXREGION || + GetRgnBox(physDevDst->region, &unusedRect) == COMPLEXREGION) + { + /* for simple regions, the clipping was already done by BITBLT_GetVisRectangles */ + FIXME("potential optimization: client-side complex region clipping\n"); + return FALSE; + } + if (dstDib.dsBm.bmBitsPixel <= 8) + { + FIXME("potential optimization: client-side color-index mode DIB copy\n"); + return FALSE; + } + if (!(srcDib.dsBmih.biCompression == BI_BITFIELDS && + dstDib.dsBmih.biCompression == BI_BITFIELDS && + !memcmp(srcDib.dsBitfields, dstDib.dsBitfields, 3*sizeof(DWORD))) + && !(srcDib.dsBmih.biCompression == BI_RGB && + dstDib.dsBmih.biCompression == BI_RGB)) + { + FIXME("potential optimization: client-side compressed DIB copy\n"); + return FALSE; + } + if (srcDib.dsBm.bmHeight < 0 || dstDib.dsBm.bmHeight < 0) + { + FIXME("potential optimization: client-side bottom-up DIB copy\n"); + return FALSE; + } + + switch (dstDib.dsBm.bmBitsPixel) + { + case 15: + case 16: + bytesPerPixel = 2; + break; + case 24: + bytesPerPixel = 3; + break; + case 32: + bytesPerPixel = 4; + break; + default: + FIXME("don't know how to work with a depth of %d\n", physDevSrc->depth); + return FALSE; + } + + bytesToCopy = width * bytesPerPixel; + + srcPtr = &physDevSrc->bitmap->base[ySrc*srcDib.dsBm.bmWidthBytes + xSrc*bytesPerPixel]; + dstPtr = &physDevDst->bitmap->base[yDst*dstDib.dsBm.bmWidthBytes + xDst*bytesPerPixel]; + + for (y = yDst; y < yDst + height; ++y) + { + memcpy(dstPtr, srcPtr, bytesToCopy); + srcPtr += srcDib.dsBm.bmWidthBytes; + dstPtr += dstDib.dsBm.bmWidthBytes; + } + + return TRUE; +} + + /*********************************************************************** * X11DRV_BitBlt */ @@ -1587,7 +1675,12 @@ BOOL X11DRV_BitBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst, height = visRectDst.bottom - visRectDst.top; if (sDst == DIB_Status_AppMod) { - FIXME("potential optimization - client-side DIB copy\n"); + result = X11DRV_ClientSideDIBCopy( physDevSrc, xSrc, ySrc, + physDevDst, xDst, yDst, + width, height ); + if (result) + goto END; + /* fall back to X server copying */ } X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod, FALSE );