- Rewrite NtGdiStretchDIBitsInternal : clearer, faster, stronger (+1 wine test)

svn path=/branches/reactos-yarotows/; revision=48465
This commit is contained in:
Jérôme Gardou 2010-08-05 21:12:57 +00:00
parent 96444b43c2
commit 3f5d90a47a

View file

@ -290,7 +290,7 @@ IntSetDIBits(
if(!(psurfSrc && psurfDst)) if(!(psurfSrc && psurfDst))
{ {
DPRINT1("Error, could not lock surfaces.\n"); DPRINT1("Error, could not lock surfaces\n");
goto cleanup; goto cleanup;
} }
@ -1021,42 +1021,32 @@ NtGdiStretchDIBitsInternal(
UINT cjMaxBits, UINT cjMaxBits,
HANDLE hcmXform) HANDLE hcmXform)
{ {
HBITMAP hBitmap, hOldBitmap = NULL; PDC pdc;
HDC hdcMem = NULL; INT ret = 0;
LONG height;
LONG width;
WORD planes, bpp;
DWORD compr, size;
HBITMAP hBitmap;
BOOL fastpath = FALSE;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PVOID pvDIBits;
INT Ret = 0;
if (!Bits || !BitsInfo) if (!Bits || !BitsInfo)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0; return 0;
}
/* Create a DIB Section, data will be probed there */ if (!(pdc = DC_LockDc(hDC))) return 0;
hBitmap = NtGdiCreateDIBSection(hDC,
NULL,
0,
BitsInfo,
Usage,
0,
0,
0,
&pvDIBits);
if(!hBitmap)
{
DPRINT1("Failed to create a DIB.\n");
return 0;
}
/* Set bits */
_SEH2_TRY _SEH2_TRY
{ {
ProbeForRead(BitsInfo, cjMaxInfo, 1);
ProbeForRead(Bits, cjMaxBits, 1); ProbeForRead(Bits, cjMaxBits, 1);
RtlCopyMemory(pvDIBits, Bits, DIB_GetDIBImageBytes(BitsInfo->bmiHeader.biWidth, if (DIB_GetBitmapInfo( &BitsInfo->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
BitsInfo->bmiHeader.biHeight, {
BitsInfo->bmiHeader.biBitCount)); DPRINT1("Invalid bitmap\n");
Status = STATUS_INVALID_PARAMETER;
}
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -1066,50 +1056,69 @@ NtGdiStretchDIBitsInternal(
if(!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
DPRINT1("Error : Could not read DIB bits\n"); DPRINT1("Error, failed to read the DIB bits\n");
SetLastNtError(Status);
goto cleanup; goto cleanup;
} }
hdcMem = NtGdiCreateCompatibleDC(0); if (width < 0)
if(!hdcMem)
{ {
DPRINT1("Failed to create a memory DC!"); DPRINT1("Bitmap has a negative width\n");
goto cleanup; return 0;
} }
hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap); hBitmap = NtGdiGetDCObject(hDC, OBJ_BITMAP);
if(!hOldBitmap)
if (XDest == 0 && YDest == 0 && XSrc == 0 && XSrc == 0 &&
DestWidth == SrcWidth && DestHeight == SrcHeight &&
compr == BI_RGB &&
ROP == SRCCOPY)
{ {
DPRINT1("Could not select the DIB into the memory DC\n"); BITMAP bmp;
goto cleanup; if (IntGdiGetObject(hBitmap, sizeof(bmp), &bmp) == sizeof(bmp))
{
if (bmp.bmBitsPixel == bpp &&
bmp.bmWidth == SrcWidth &&
bmp.bmHeight == SrcHeight &&
bmp.bmPlanes == planes)
fastpath = TRUE;
}
} }
/* Do we want to stretch ? */ if (fastpath)
if((SrcWidth == DestWidth) && (SrcHeight == DestHeight))
{ {
Ret = NtGdiBitBlt(hDC, XDest, YDest, XDest + DestWidth, YDest + DestHeight, /* fast path */
hdcMem, XSrc, YSrc, ROP, 0, 0); DPRINT1("using fast path\n");
ret = IntSetDIBits( pdc, hBitmap, 0, height, Bits, BitsInfo, Usage);
} }
else else
{ {
Ret = NtGdiStretchBlt(hDC, XDest, YDest, XDest + DestWidth, YDest + DestHeight, /* slow path - need to use StretchBlt */
hdcMem, XSrc, YSrc, XSrc + SrcWidth, YSrc + SrcHeight, HBITMAP hOldBitmap;
ROP, 0); HPALETTE hpal = NULL;
} HDC hdcMem;
PVOID pvBits;
if(Ret) hdcMem = NtGdiCreateCompatibleDC( hDC );
Ret = SrcHeight ; hBitmap = DIB_CreateDIBSection(pdc, BitsInfo, Usage, &pvBits, NULL, 0, 0);
RtlCopyMemory(pvBits, Bits, cjMaxBits);
hOldBitmap = NtGdiSelectBitmap( hdcMem, hBitmap );
cleanup: /* Origin for DIBitmap may be bottom left (positive biHeight) or top
if(hdcMem) left (negative biHeight) */
{ ret = NtGdiStretchBlt( hDC, XDest, YDest, DestWidth, DestHeight,
if(hOldBitmap) NtGdiSelectBitmap(hdcMem, hOldBitmap); hdcMem, XSrc, abs(height) - SrcHeight - YSrc,
SrcWidth, SrcHeight, ROP, 0 );
if(hpal)
GdiSelectPalette(hdcMem, hpal, FALSE);
if(ret)
ret = SrcHeight;
NtGdiSelectBitmap( hdcMem, hOldBitmap );
NtGdiDeleteObjectApp( hdcMem ); NtGdiDeleteObjectApp( hdcMem );
}
GreDeleteObject( hBitmap ); GreDeleteObject( hBitmap );
}
return Ret; cleanup:
DC_UnlockDc(pdc);
return ret;
} }
@ -1575,7 +1584,7 @@ DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
*height = core->bcHeight; *height = core->bcHeight;
*planes = core->bcPlanes; *planes = core->bcPlanes;
*bpp = core->bcBitCount; *bpp = core->bcBitCount;
*compr = 0; *compr = BI_RGB;
*size = 0; *size = 0;
return 0; return 0;
} }