mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[WIN32K]
- Fix calculation of dest rect in IntSetDIBits - Rewrite NtGdiStretchDIBitsInternal. It now calls NtGdiSetDIBitsToDeviceInternal in case of SRCCOPY and no stretching and NtGdiCreateDIBitmapInternal + IntEngStretchBlt in the default case. This fixes RLE compressed dibs. - The code isn't yet perfect, Windows behaviour is pretty complex, especially in regard to topdown/bottomup DIBs and the whole code needs to be rewritten. It will cause one more failed bitmap test, but another one that was formerly only passing with legacy 9x behaviour now behaves correctly. See issue #5886 for more details. svn path=/trunk/; revision=51005
This commit is contained in:
parent
775a83cdf4
commit
2bbd8711a7
1 changed files with 132 additions and 108 deletions
|
@ -286,8 +286,7 @@ IntSetDIBits(
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcDst.top = bmi->bmiHeader.biHeight < 0 ?
|
rcDst.top = StartScan;
|
||||||
abs(bmi->bmiHeader.biHeight) - (ScanLines + StartScan) : StartScan;
|
|
||||||
rcDst.left = 0;
|
rcDst.left = 0;
|
||||||
rcDst.bottom = rcDst.top + ScanLines;
|
rcDst.bottom = rcDst.top + ScanLines;
|
||||||
rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
|
rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
|
||||||
|
@ -296,7 +295,7 @@ IntSetDIBits(
|
||||||
ptSrc.y = 0;
|
ptSrc.y = 0;
|
||||||
|
|
||||||
/* 1bpp bitmaps have 0 for white, 1 for black */
|
/* 1bpp bitmaps have 0 for white, 1 for black */
|
||||||
EXLATEOBJ_vInitialize(&exlo, psurfSrc->ppal, psurfDst->ppal, 0xFFFFFF, 0, 0);
|
EXLATEOBJ_vInitialize(&exlo, psurfSrc->ppal, psurfDst->ppal, 0xFFFFFF, 0xFFFFFF, 0);
|
||||||
|
|
||||||
result = IntEngCopyBits(&psurfDst->SurfObj,
|
result = IntEngCopyBits(&psurfDst->SurfObj,
|
||||||
&psurfSrc->SurfObj,
|
&psurfSrc->SurfObj,
|
||||||
|
@ -1030,133 +1029,158 @@ done:
|
||||||
return ScanLines;
|
return ScanLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ROP_TO_ROP4(Rop) ((Rop) >> 16)
|
||||||
|
|
||||||
|
W32KAPI
|
||||||
INT
|
INT
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtGdiStretchDIBitsInternal(
|
NtGdiStretchDIBitsInternal(
|
||||||
HDC hDC,
|
IN HDC hdc,
|
||||||
INT XDest,
|
IN INT xDst,
|
||||||
INT YDest,
|
IN INT yDst,
|
||||||
INT DestWidth,
|
IN INT cxDst,
|
||||||
INT DestHeight,
|
IN INT cyDst,
|
||||||
INT XSrc,
|
IN INT xSrc,
|
||||||
INT YSrc,
|
IN INT ySrc,
|
||||||
INT SrcWidth,
|
IN INT cxSrc,
|
||||||
INT SrcHeight,
|
IN INT cySrc,
|
||||||
LPBYTE Bits,
|
IN OPTIONAL LPBYTE pjInit,
|
||||||
LPBITMAPINFO BitsInfo,
|
IN LPBITMAPINFO pbmi,
|
||||||
DWORD Usage,
|
IN DWORD dwUsage,
|
||||||
DWORD ROP,
|
IN DWORD dwRop, // ms ntgdi.h says dwRop4(?)
|
||||||
UINT cjMaxInfo,
|
IN UINT cjMaxInfo,
|
||||||
UINT cjMaxBits,
|
IN UINT cjMaxBits,
|
||||||
HANDLE hcmXform)
|
IN HANDLE hcmXform)
|
||||||
{
|
{
|
||||||
|
BOOL bResult = FALSE;
|
||||||
|
SIZEL sizel;
|
||||||
|
RECTL rcSrc, rcDst;
|
||||||
PDC pdc;
|
PDC pdc;
|
||||||
INT ret = 0;
|
HBITMAP hbmTmp;
|
||||||
LONG height;
|
PSURFACE psurfTmp, psurfDst;
|
||||||
LONG width;
|
EXLATEOBJ exlo;
|
||||||
WORD planes, bpp;
|
|
||||||
DWORD compr, size;
|
|
||||||
HBITMAP hBitmap;
|
|
||||||
HBITMAP hOldBitmap;
|
|
||||||
HDC hdcMem;
|
|
||||||
PVOID pvBits;
|
|
||||||
PBYTE safeBits;
|
|
||||||
|
|
||||||
if (!Bits || !BitsInfo)
|
if (!(pdc = DC_LockDc(hdc)))
|
||||||
return 0;
|
|
||||||
|
|
||||||
safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
|
|
||||||
if(!safeBits)
|
|
||||||
{
|
{
|
||||||
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_SEH2_TRY
|
|
||||||
{
|
|
||||||
ProbeForRead(BitsInfo, cjMaxInfo, 1);
|
|
||||||
ProbeForRead(Bits, cjMaxBits, 1);
|
|
||||||
if (DIB_GetBitmapInfo(&BitsInfo->bmiHeader, &width, &height, &planes, &bpp, &compr, &size) == -1)
|
|
||||||
{
|
|
||||||
DPRINT1("Invalid bitmap\n");
|
|
||||||
_SEH2_YIELD(goto cleanup;)
|
|
||||||
}
|
|
||||||
RtlCopyMemory(safeBits, Bits, cjMaxBits);
|
|
||||||
}
|
|
||||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
||||||
{
|
|
||||||
DPRINT1("Error, failed to read the DIB bits\n");
|
|
||||||
_SEH2_YIELD(goto cleanup;)
|
|
||||||
}
|
|
||||||
_SEH2_END
|
|
||||||
|
|
||||||
if (width < 0)
|
|
||||||
{
|
|
||||||
DPRINT1("Bitmap has a negative width\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hBitmap = NtGdiGetDCObject(hDC, OBJ_BITMAP);
|
|
||||||
|
|
||||||
if (!(pdc = DC_LockDc(hDC)))
|
|
||||||
{
|
|
||||||
ExFreePoolWithTag(safeBits, TAG_DIB);
|
|
||||||
EngSetLastError(ERROR_INVALID_HANDLE);
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (XDest == 0 && YDest == 0 && XSrc == 0 && XSrc == 0 &&
|
/* Transform dest size */
|
||||||
DestWidth == SrcWidth && DestHeight == SrcHeight &&
|
sizel.cx = cxDst;
|
||||||
compr == BI_RGB &&
|
sizel.cy = cyDst;
|
||||||
ROP == SRCCOPY)
|
IntLPtoDP(pdc, (POINTL*)&sizel, 1);
|
||||||
{
|
|
||||||
BITMAP bmp;
|
|
||||||
ret = IntGdiGetObject(hBitmap, sizeof(bmp), &bmp) == sizeof(bmp);
|
|
||||||
if (ret &&
|
|
||||||
bmp.bmBitsPixel == bpp &&
|
|
||||||
bmp.bmWidth == SrcWidth &&
|
|
||||||
bmp.bmHeight == SrcHeight &&
|
|
||||||
bmp.bmPlanes == planes)
|
|
||||||
{
|
|
||||||
/* fast path */
|
|
||||||
ret = IntSetDIBits(pdc, hBitmap, 0, height, safeBits, BitsInfo, Usage);
|
|
||||||
DC_UnlockDc(pdc);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* slow path - need to use StretchBlt */
|
|
||||||
|
|
||||||
hBitmap = DIB_CreateDIBSection(pdc, BitsInfo, Usage, &pvBits, NULL, 0, 0);
|
|
||||||
DC_UnlockDc(pdc);
|
DC_UnlockDc(pdc);
|
||||||
|
|
||||||
if(!hBitmap)
|
/* Check if we can use NtGdiSetDIBitsToDeviceInternal */
|
||||||
|
if (sizel.cx == cxSrc && sizel.cy == cySrc && dwRop == SRCCOPY)
|
||||||
{
|
{
|
||||||
DPRINT1("Error, failed to create a DIB section\n");
|
/* Yes, we can! */
|
||||||
|
return NtGdiSetDIBitsToDeviceInternal(hdc,
|
||||||
|
xDst,
|
||||||
|
yDst,
|
||||||
|
cxDst,
|
||||||
|
cyDst,
|
||||||
|
xSrc,
|
||||||
|
ySrc,
|
||||||
|
0,
|
||||||
|
cySrc,
|
||||||
|
pjInit,
|
||||||
|
pbmi,
|
||||||
|
dwUsage,
|
||||||
|
cjMaxBits,
|
||||||
|
cjMaxInfo,
|
||||||
|
TRUE,
|
||||||
|
hcmXform);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create an intermediate bitmap from the DIB */
|
||||||
|
hbmTmp = NtGdiCreateDIBitmapInternal(hdc,
|
||||||
|
cxSrc,
|
||||||
|
cySrc,
|
||||||
|
CBM_INIT,
|
||||||
|
pjInit,
|
||||||
|
pbmi,
|
||||||
|
dwUsage,
|
||||||
|
cjMaxInfo,
|
||||||
|
cjMaxBits,
|
||||||
|
0,
|
||||||
|
hcmXform);
|
||||||
|
if (!hbmTmp)
|
||||||
|
{
|
||||||
|
DPRINT1("NtGdiCreateDIBitmapInternal failed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: locking twice is cheesy, coord tranlation in UM will fix it */
|
||||||
|
if (!(pdc = DC_LockDc(hdc)))
|
||||||
|
{
|
||||||
|
DPRINT1("Could not lock dc\n");
|
||||||
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
GreDeleteObject(hbmTmp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
psurfTmp = SURFACE_ShareLockSurface(hbmTmp);
|
||||||
|
if (!psurfTmp)
|
||||||
|
{
|
||||||
|
DPRINT1("Could not lock bitmap :-(\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdcMem = NtGdiCreateCompatibleDC(hDC);
|
psurfDst = pdc->dclevel.pSurface;
|
||||||
|
if (!psurfDst)
|
||||||
|
{
|
||||||
|
// CHECKME
|
||||||
|
bResult = TRUE;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
RtlCopyMemory(pvBits, safeBits, cjMaxBits);
|
/* Calculate source and destination rect */
|
||||||
hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
|
rcSrc.left = xSrc;
|
||||||
|
rcSrc.top = ySrc;
|
||||||
|
rcSrc.right = xSrc + abs(cxSrc);
|
||||||
|
rcSrc.bottom = ySrc + abs(cySrc);
|
||||||
|
rcDst.left = xDst;
|
||||||
|
rcDst.top = yDst;
|
||||||
|
rcDst.right = rcDst.left + cxDst;
|
||||||
|
rcDst.bottom = rcDst.top + cyDst;
|
||||||
|
IntLPtoDP(pdc, (POINTL*)&rcDst, 2);
|
||||||
|
RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
|
||||||
|
|
||||||
/* Origin for DIBitmap may be bottom left (positive biHeight) or top
|
/* Initialize XLATEOBJ */
|
||||||
left (negative biHeight) */
|
EXLATEOBJ_vInitialize(&exlo,
|
||||||
ret = NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
|
psurfTmp->ppal,
|
||||||
hdcMem, XSrc, abs(height) - SrcHeight - YSrc,
|
psurfDst->ppal,
|
||||||
SrcWidth, SrcHeight, ROP, 0);
|
RGB(0xff, 0xff, 0xff),
|
||||||
|
pdc->pdcattr->crBackgroundClr,
|
||||||
|
pdc->pdcattr->crForegroundClr);
|
||||||
|
|
||||||
if(ret)
|
/* Prepare DC for blit */
|
||||||
ret = SrcHeight;
|
DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcSrc);
|
||||||
NtGdiSelectBitmap(hdcMem, hOldBitmap);
|
|
||||||
NtGdiDeleteObjectApp(hdcMem);
|
|
||||||
GreDeleteObject(hBitmap);
|
|
||||||
|
|
||||||
|
/* Perform the stretch operation */
|
||||||
|
bResult = IntEngStretchBlt(&psurfDst->SurfObj,
|
||||||
|
&psurfTmp->SurfObj,
|
||||||
|
NULL,
|
||||||
|
pdc->rosdc.CombinedClip,
|
||||||
|
&exlo.xlo,
|
||||||
|
&rcDst,
|
||||||
|
&rcSrc,
|
||||||
|
NULL,
|
||||||
|
&pdc->eboFill.BrushObject,
|
||||||
|
NULL,
|
||||||
|
ROP_TO_ROP4(dwRop));
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
DC_vFinishBlit(pdc, NULL);
|
||||||
|
EXLATEOBJ_vCleanup(&exlo);
|
||||||
cleanup:
|
cleanup:
|
||||||
ExFreePoolWithTag(safeBits, TAG_DIB);
|
if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
|
||||||
return ret;
|
if (hbmTmp) GreDeleteObject(hbmTmp);
|
||||||
|
if (pdc) DC_UnlockDc(pdc);
|
||||||
|
|
||||||
|
return bResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1556,7 +1580,7 @@ DIB_CreateDIBSection(
|
||||||
bm.bmWidthBytes,
|
bm.bmWidthBytes,
|
||||||
BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
|
BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
|
||||||
BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
|
BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
|
||||||
(bi->biHeight < 0 ? BMF_TOPDOWN : 0),
|
((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
|
||||||
bi->biSizeImage,
|
bi->biSizeImage,
|
||||||
bm.bmBits,
|
bm.bmBits,
|
||||||
0);
|
0);
|
||||||
|
|
Loading…
Reference in a new issue