winex11: Use the DIB engine for client-side DIB copy optimizations.
This commit is contained in:
parent
c819e4bdea
commit
0f9dfb932e
|
@ -1186,128 +1186,6 @@ static int BITBLT_PutDstArea(X11DRV_PDEVICE *physDev, Pixmap pixmap, const RECT
|
|||
return exposures;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* client_side_dib_copy
|
||||
*/
|
||||
static BOOL client_side_dib_copy( 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 srcRowOffset, dstRowOffset;
|
||||
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(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)
|
||||
{
|
||||
static BOOL fixme_once;
|
||||
if(!fixme_once++) 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.bmBitsPixel != dstDib.dsBm.bmBitsPixel)
|
||||
{
|
||||
FIXME("potential optimization: pixel format conversion\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (srcDib.dsBmih.biWidth < 0 || dstDib.dsBmih.biWidth < 0)
|
||||
{
|
||||
FIXME("negative widths not yet implemented\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;
|
||||
|
||||
if (physDevSrc->bitmap->topdown)
|
||||
{
|
||||
srcPtr = &physDevSrc->bitmap->base[ySrc*srcDib.dsBm.bmWidthBytes + xSrc*bytesPerPixel];
|
||||
srcRowOffset = srcDib.dsBm.bmWidthBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcPtr = &physDevSrc->bitmap->base[(srcDib.dsBm.bmHeight-ySrc-1)*srcDib.dsBm.bmWidthBytes
|
||||
+ xSrc*bytesPerPixel];
|
||||
srcRowOffset = -srcDib.dsBm.bmWidthBytes;
|
||||
}
|
||||
if (physDevDst->bitmap->topdown)
|
||||
{
|
||||
dstPtr = &physDevDst->bitmap->base[yDst*dstDib.dsBm.bmWidthBytes + xDst*bytesPerPixel];
|
||||
dstRowOffset = dstDib.dsBm.bmWidthBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
dstPtr = &physDevDst->bitmap->base[(dstDib.dsBm.bmHeight-yDst-1)*dstDib.dsBm.bmWidthBytes
|
||||
+ xDst*bytesPerPixel];
|
||||
dstRowOffset = -dstDib.dsBm.bmWidthBytes;
|
||||
}
|
||||
|
||||
/* Handle overlapping regions on the same DIB */
|
||||
if (physDevSrc == physDevDst && ySrc < yDst)
|
||||
{
|
||||
srcPtr += srcRowOffset * (height - 1);
|
||||
srcRowOffset = -srcRowOffset;
|
||||
dstPtr += dstRowOffset * (height - 1);
|
||||
dstRowOffset = -dstRowOffset;
|
||||
}
|
||||
|
||||
for (y = yDst; y < yDst + height; ++y)
|
||||
{
|
||||
memmove(dstPtr, srcPtr, bytesToCopy);
|
||||
srcPtr += srcRowOffset;
|
||||
dstPtr += dstRowOffset;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL same_format(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst)
|
||||
{
|
||||
if (physDevSrc->depth != physDevDst->depth) return FALSE;
|
||||
|
@ -1455,13 +1333,12 @@ BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
|
|||
if (physDevDst == physDevSrc) sSrc = sDst;
|
||||
|
||||
/* try client-side DIB copy */
|
||||
if (!fStretch && rop == SRCCOPY &&
|
||||
sSrc == DIB_Status_AppMod && sDst == DIB_Status_AppMod &&
|
||||
same_format(physDevSrc, physDevDst))
|
||||
if (!fStretch && sSrc == DIB_Status_AppMod)
|
||||
{
|
||||
if (client_side_dib_copy( physDevSrc, src->visrect.left, src->visrect.top,
|
||||
physDevDst, dst->visrect.left, dst->visrect.top, width, height ))
|
||||
goto done;
|
||||
if (physDevDst != physDevSrc) X11DRV_UnlockDIBSection( physDevSrc, FALSE );
|
||||
X11DRV_UnlockDIBSection( physDevDst, FALSE );
|
||||
dst_dev = GET_NEXT_PHYSDEV( dst_dev, pStretchBlt );
|
||||
return dst_dev->funcs->pStretchBlt( dst_dev, dst, src_dev, src, rop );
|
||||
}
|
||||
|
||||
X11DRV_CoerceDIBSection( physDevDst, DIB_Status_GdiMod );
|
||||
|
@ -1477,16 +1354,7 @@ BOOL X11DRV_StretchBlt( PHYSDEV dst_dev, struct bitblt_coords *dst,
|
|||
XSetFunction( gdi_display, physDevDst->gc, OP_ROP(*opcode) );
|
||||
wine_tsx11_unlock();
|
||||
|
||||
if (physDevSrc != physDevDst)
|
||||
{
|
||||
if (sSrc == DIB_Status_AppMod)
|
||||
{
|
||||
X11DRV_DIB_CopyDIBSection( physDevSrc, physDevDst, src->visrect.left, src->visrect.top,
|
||||
dst->visrect.left, dst->visrect.top, width, height );
|
||||
goto done;
|
||||
}
|
||||
X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
|
||||
}
|
||||
if (physDevSrc != physDevDst) X11DRV_CoerceDIBSection( physDevSrc, DIB_Status_GdiMod );
|
||||
wine_tsx11_lock();
|
||||
XCopyArea( gdi_display, physDevSrc->drawable,
|
||||
physDevDst->drawable, physDevDst->gc,
|
||||
|
|
|
@ -3555,77 +3555,6 @@ static void X11DRV_DIB_DoCopyDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB,
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* X11DRV_DIB_CopyDIBSection
|
||||
*/
|
||||
void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
|
||||
DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
|
||||
DWORD width, DWORD height)
|
||||
{
|
||||
DIBSECTION dib;
|
||||
X_PHYSBITMAP *physBitmap;
|
||||
unsigned int nColorMap;
|
||||
int* x11ColorMap;
|
||||
int freeColorMap;
|
||||
|
||||
TRACE("(%p,%p,%d,%d,%d,%d,%d,%d)\n", physDevSrc->dev.hdc, physDevDst->dev.hdc,
|
||||
xSrc, ySrc, xDest, yDest, width, height);
|
||||
/* this function is meant as an optimization for BitBlt,
|
||||
* not to be called otherwise */
|
||||
physBitmap = physDevSrc->bitmap;
|
||||
if (!physBitmap || GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib ) != sizeof(dib))
|
||||
{
|
||||
ERR("called for non-DIBSection!?\n");
|
||||
return;
|
||||
}
|
||||
/* while BitBlt should already have made sure we only get
|
||||
* positive values, we should check for oversize values */
|
||||
if ((xSrc < dib.dsBm.bmWidth) &&
|
||||
(ySrc < dib.dsBm.bmHeight)) {
|
||||
if (xSrc + width > dib.dsBm.bmWidth)
|
||||
width = dib.dsBm.bmWidth - xSrc;
|
||||
if (ySrc + height > dib.dsBm.bmHeight)
|
||||
height = dib.dsBm.bmHeight - ySrc;
|
||||
/* if the source bitmap is 8bpp or less, we're supposed to use the
|
||||
* DC's palette for color conversion (not the DIB color table) */
|
||||
if (dib.dsBm.bmBitsPixel <= 8) {
|
||||
HPALETTE hPalette = GetCurrentObject( physDevSrc->dev.hdc, OBJ_PAL );
|
||||
if (!hPalette || (hPalette == GetStockObject(DEFAULT_PALETTE))) {
|
||||
/* HACK: no palette has been set in the source DC,
|
||||
* use the DIB colormap instead - this is necessary in some
|
||||
* cases since we need to do depth conversion in some places
|
||||
* where real Windows can just copy data straight over */
|
||||
x11ColorMap = physBitmap->colorMap;
|
||||
nColorMap = physBitmap->nColorMap;
|
||||
freeColorMap = FALSE;
|
||||
} else {
|
||||
const BITMAPINFO* info = (BITMAPINFO*)&dib.dsBmih;
|
||||
unsigned int i;
|
||||
|
||||
nColorMap = X11DRV_DIB_GetColorCount(info);
|
||||
x11ColorMap = HeapAlloc(GetProcessHeap(), 0, nColorMap * sizeof(int));
|
||||
for (i = 0; i < nColorMap; i++)
|
||||
x11ColorMap[i] = X11DRV_PALETTE_ToPhysical(physDevSrc, PALETTEINDEX(i));
|
||||
freeColorMap = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nColorMap = 0;
|
||||
x11ColorMap = NULL;
|
||||
freeColorMap = FALSE;
|
||||
}
|
||||
/* perform the copy */
|
||||
X11DRV_DIB_DoCopyDIBSection(physBitmap, FALSE, x11ColorMap, nColorMap,
|
||||
physDevDst->drawable, physDevDst->gc, xSrc, ySrc,
|
||||
physDevDst->dc_rect.left + xDest, physDevDst->dc_rect.top + yDest,
|
||||
width, height);
|
||||
/* free color mapping */
|
||||
if (freeColorMap)
|
||||
HeapFree(GetProcessHeap(), 0, x11ColorMap);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* X11DRV_DIB_DoUpdateDIBSection
|
||||
*/
|
||||
|
|
|
@ -468,9 +468,6 @@ extern INT X11DRV_DIB_Lock(X_PHYSBITMAP *,INT) DECLSPEC_HIDDEN;
|
|||
extern void X11DRV_DIB_Unlock(X_PHYSBITMAP *,BOOL) DECLSPEC_HIDDEN;
|
||||
|
||||
extern void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib) DECLSPEC_HIDDEN;
|
||||
extern void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
|
||||
DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
|
||||
DWORD width, DWORD height) DECLSPEC_HIDDEN;
|
||||
|
||||
/**************************************************************************
|
||||
* X11 GDI driver
|
||||
|
|
Loading…
Reference in New Issue