From 1ea8829ec1280cb242ed4c34f542b841df0c3278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 1 Mar 2011 01:03:58 +0000 Subject: [PATCH] [WIN32K] - Raster operations in user mode are on higher bytes, whereas they are on lower bytes for drivers. Try to clarify this situation. - Add sanity check about what was said previously. - Implement masking in EngBitBlt - Rewrite NtGdiMaskBlt accordingly - Realize the palette when selecting it into a device DC. - When applying raster operation, do so only on 24 bits, we don't support alpha channel in win32k This fixes VLC pink icons, Timo's MaskBlt tests and probably a lot of other things. [SHELL32] - Use correct (?) raster operations for drawing sjortcuts. Also note that now NtGdiMaskBlt locks the device contexts : this should avoid some race conditions, such as icons drawn on top of windows and the like. Win32k sucks less. So does reactos. Dedicated to Timo. Sleep well, mate. svn path=/trunk/; revision=50941 --- reactos/dll/win32/shell32/iconcache.c | 4 +- reactos/subsystems/win32/win32k/dib/dib.c | 44 +- reactos/subsystems/win32/win32k/dib/dib.h | 2 +- reactos/subsystems/win32/win32k/dib/dib1bpp.c | 2 +- .../subsystems/win32/win32k/dib/stretchblt.c | 8 +- reactos/subsystems/win32/win32k/eng/bitblt.c | 173 ++++--- .../subsystems/win32/win32k/eng/copybits.c | 4 +- reactos/subsystems/win32/win32k/eng/mouse.c | 14 +- .../subsystems/win32/win32k/eng/stretchblt.c | 36 +- .../subsystems/win32/win32k/include/color.h | 4 +- .../subsystems/win32/win32k/include/inteng.h | 41 +- .../subsystems/win32/win32k/ntuser/painting.c | 15 +- .../subsystems/win32/win32k/objects/bitblt.c | 484 +++++++----------- .../subsystems/win32/win32k/objects/dcobjs.c | 5 + .../subsystems/win32/win32k/objects/dibobj.c | 2 +- .../subsystems/win32/win32k/objects/drawing.c | 6 +- .../win32/win32k/objects/fillshap.c | 2 +- .../win32/win32k/objects/freetype.c | 4 +- .../subsystems/win32/win32k/objects/palette.c | 20 +- .../win32/win32k/objects/polyfill.c | 8 +- 20 files changed, 421 insertions(+), 457 deletions(-) diff --git a/reactos/dll/win32/shell32/iconcache.c b/reactos/dll/win32/shell32/iconcache.c index a57c33e52c6..01e84c99e75 100644 --- a/reactos/dll/win32/shell32/iconcache.c +++ b/reactos/dll/win32/shell32/iconcache.c @@ -180,8 +180,8 @@ static HICON SIC_OverlayShortcutImage(HICON SourceIcon, BOOL large) if (NULL == SelectObject(ShortcutDC, ShortcutIconInfo.hbmColor)) goto fail; if (!MaskBlt(TargetDC, 0, SourceBitmapInfo.bmHeight - ShortcutBitmapInfo.bmHeight, ShortcutBitmapInfo.bmWidth, ShortcutBitmapInfo.bmHeight, - ShortcutDC, 0, 0, ShortcutIconInfo.hbmMask, 0, 0, - MAKEROP4(SRCCOPY, 0xAA0000))) + ShortcutDC, 0, 0, ShortcutIconInfo.hbmMask, 0, 0, + MAKEROP4(0xAA0000, SRCCOPY))) { goto fail; } diff --git a/reactos/subsystems/win32/win32k/dib/dib.c b/reactos/subsystems/win32/win32k/dib/dib.c index 2066c9e0b72..37767877905 100644 --- a/reactos/subsystems/win32/win32k/dib/dib.c +++ b/reactos/subsystems/win32/win32k/dib/dib.c @@ -87,11 +87,12 @@ DIB_FUNCTIONS DibFunctionsForBitmapFormat[] = } }; + ULONG DIB_DoRop(ULONG Rop, ULONG Dest, ULONG Source, ULONG Pattern) { ULONG ResultNibble; - ULONG Result; + ULONG Result = 0; ULONG i; static const ULONG ExpandDest[16] = { @@ -151,31 +152,34 @@ static const ULONG ExpandDest[16] = 0xF0F0F0F0 /* 1111 */, }; - /* Optimized code for the various named rop codes. */ - switch (Rop) + Rop &=0xFF; + switch(Rop) { - case ROP3_TO_ROP4(BLACKNESS): return(0); - case ROP3_TO_ROP4(NOTSRCERASE): return(~(Dest | Source)); - case ROP3_TO_ROP4(NOTSRCCOPY): return(~Source); - case ROP3_TO_ROP4(SRCERASE): return((~Dest) & Source); - case ROP3_TO_ROP4(DSTINVERT): return(~Dest); - case ROP3_TO_ROP4(PATINVERT): return(Dest ^ Pattern); - case ROP3_TO_ROP4(SRCINVERT): return(Dest ^ Source); - case ROP3_TO_ROP4(SRCAND): return(Dest & Source); - case ROP3_TO_ROP4(MERGEPAINT): return(Dest | (~Source)); - case ROP3_TO_ROP4(SRCPAINT): return(Dest | Source); - case ROP3_TO_ROP4(MERGECOPY): return(Source & Pattern); - case ROP3_TO_ROP4(SRCCOPY): return(Source); - case ROP3_TO_ROP4(PATCOPY): return(Pattern); - case ROP3_TO_ROP4(PATPAINT): return(Dest | (~Source) | Pattern); - case ROP3_TO_ROP4(WHITENESS): return(0xFFFFFFFF); + + /* Optimized code for the various named rop codes. */ + case R3_OPINDEX_NOOP: return(Dest); + case R3_OPINDEX_BLACKNESS: return(0); + case R3_OPINDEX_NOTSRCERASE: return(~(Dest | Source)); + case R3_OPINDEX_NOTSRCCOPY: return(~Source); + case R3_OPINDEX_SRCERASE: return((~Dest) & Source); + case R3_OPINDEX_DSTINVERT: return(~Dest); + case R3_OPINDEX_PATINVERT: return(Dest ^ Pattern); + case R3_OPINDEX_SRCINVERT: return(Dest ^ Source); + case R3_OPINDEX_SRCAND: return(Dest & Source); + case R3_OPINDEX_MERGEPAINT: return(Dest | (~Source)); + case R3_OPINDEX_SRCPAINT: return(Dest | Source); + case R3_OPINDEX_MERGECOPY: return(Source & Pattern); + case R3_OPINDEX_SRCCOPY: return(Source); + case R3_OPINDEX_PATCOPY: return(Pattern); + case R3_OPINDEX_PATPAINT: return(Dest | (~Source) | Pattern); + case R3_OPINDEX_WHITENESS: return(0xFFFFFFFF); } + /* Expand the ROP operation to all four bytes */ - Rop &= 0xFF; Rop |= (Rop << 24) | (Rop << 16) | (Rop << 8); /* Do the operation on four bits simultaneously. */ Result = 0; - for (i = 0; i < 8; i++) + for (i = 0; i < 6; i++) { ResultNibble = Rop & ExpandDest[Dest & 0xF] & ExpandSource[Source & 0xF] & ExpandPattern[Pattern & 0xF]; Result |= (((ResultNibble & 0xFF000000) ? 0x8 : 0x0) | ((ResultNibble & 0x00FF0000) ? 0x4 : 0x0) | diff --git a/reactos/subsystems/win32/win32k/dib/dib.h b/reactos/subsystems/win32/win32k/dib/dib.h index 4ae455bc92b..5db2f042c7e 100644 --- a/reactos/subsystems/win32/win32k/dib/dib.h +++ b/reactos/subsystems/win32/win32k/dib/dib.h @@ -31,7 +31,7 @@ typedef struct _BLTINFO POINTL SourcePoint; BRUSHOBJ *Brush; POINTL BrushOrigin; - ULONG Rop4; + ROP4 Rop4; } BLTINFO, *PBLTINFO; typedef VOID (*PFN_DIB_PutPixel)(SURFOBJ*,LONG,LONG,ULONG); diff --git a/reactos/subsystems/win32/win32k/dib/dib1bpp.c b/reactos/subsystems/win32/win32k/dib/dib1bpp.c index b924112351c..b245c528611 100644 --- a/reactos/subsystems/win32/win32k/dib/dib1bpp.c +++ b/reactos/subsystems/win32/win32k/dib/dib1bpp.c @@ -380,7 +380,7 @@ DIB_1BPP_BitBlt(PBLTINFO BltInfo) Pattern |= (DIB_GetSourceIndex(PatternObj, (X + BrushOrigin.x + k) % PatternWidth, PatternY) << (31 - k)); } - Dest = DIB_DoRop(Rop4, Dest, Source, Pattern); + Dest = DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern); Dest &= ~((1 << (31 - NoBits)) - 1); Dest |= *((PBYTE)DestBits) & ((1 << (31 - NoBits)) - 1); diff --git a/reactos/subsystems/win32/win32k/dib/stretchblt.c b/reactos/subsystems/win32/win32k/dib/stretchblt.c index b6d479d8703..45a5b8f826b 100644 --- a/reactos/subsystems/win32/win32k/dib/stretchblt.c +++ b/reactos/subsystems/win32/win32k/dib/stretchblt.c @@ -43,6 +43,8 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma LONG PatternX = 0, PatternY = 0; + ASSERT(IS_VALID_ROP4(ROP)); + BOOL UsesSource = ROP4_USES_SOURCE(ROP); BOOL UsesPattern = ROP4_USES_PATTERN(ROP); @@ -122,7 +124,7 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma { sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth; if (sx < 0 || sy < 0 || - MaskSurf->sizlBitmap.cx < sx || MaskSurf->sizlBitmap.cy < sy || + MaskSurf->sizlBitmap.cx < sx || MaskSurf->sizlBitmap.cy < sy || fnMask_GetPixel(MaskSurf, sx, sy) != 0) { CanDraw = FALSE; @@ -137,10 +139,10 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma { Source = XLATEOBJ_iXlate(ColorTranslation, fnSource_GetPixel(SourceSurf, sx, sy)); } - else + else { Source = 0; - CanDraw = (ROP3_TO_ROP4(SRCCOPY) != ROP); + CanDraw = ((ROP & 0xFF) != R3_OPINDEX_SRCCOPY); } } diff --git a/reactos/subsystems/win32/win32k/eng/bitblt.c b/reactos/subsystems/win32/win32k/eng/bitblt.c index 029f55e1832..6b6ee51f9f1 100644 --- a/reactos/subsystems/win32/win32k/eng/bitblt.c +++ b/reactos/subsystems/win32/win32k/eng/bitblt.c @@ -27,11 +27,11 @@ typedef BOOLEAN (APIENTRY *PBLTRECTFUNC)(SURFOBJ* OutputObj, static BOOLEAN APIENTRY BltMask(SURFOBJ* psoDest, - SURFOBJ* psoSource, // unused + SURFOBJ* psoSource, SURFOBJ* psoMask, - XLATEOBJ* ColorTranslation, // unused + XLATEOBJ* ColorTranslation, RECTL* prclDest, - POINTL* pptlSource, // unused + POINTL* pptlSource, POINTL* pptlMask, BRUSHOBJ* pbo, POINTL* pptlBrush, @@ -46,19 +46,21 @@ BltMask(SURFOBJ* psoDest, PSURFACE psurfPattern; ULONG PatternWidth = 0, PatternHeight = 0; LONG PatternX0 = 0, PatternX = 0, PatternY = 0; + LONG SrcX = 0, SrcY = 0; PFN_DIB_PutPixel fnDest_PutPixel = NULL; - PFN_DIB_GetPixel fnPattern_GetPixel = NULL; - ULONG Pattern = 0; + PFN_DIB_GetPixel fnPattern_GetPixel = NULL, fnSrc_GetPixel = NULL, fnDest_GetPixel; + ULONG Pattern = 0, Source = 0, Dest = 0; HBITMAP hbmPattern; + DWORD fgndRop, bkgndRop; - ASSERT(psoSource == NULL); - ASSERT(pptlSource == NULL); + ASSERT(IS_VALID_ROP4(Rop4)); - if (psoMask == NULL) - { - return FALSE; - } + fgndRop = ROP4_FGND(Rop4); + bkgndRop = ROP4_BKGND(Rop4); + //DPRINT1("Rop4 : 0x%08x\n", Rop4); + + /* Determine pattern */ if (pbo && pbo->iSolidColor == 0xFFFFFFFF) { pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject); @@ -80,6 +82,18 @@ BltMask(SURFOBJ* psoDest, fjMaskBit0 = 0x80 >> (pptlMask->x & 0x07); fnDest_PutPixel = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_PutPixel; + fnDest_GetPixel = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_GetPixel; + + /* Do we have a source */ + if(psoSource) + { + /* Sanity check */ + ASSERT(ROP4_USES_SOURCE(Rop4)); + fnSrc_GetPixel = DibFunctionsForBitmapFormat[psoSource->iBitmapFormat].DIB_GetPixel; + SrcY = pptlSource->y; + SrcX = pptlSource->x; + } + if (psurfPattern) { PatternY = (prclDest->top - pptlBrush->y) % PatternHeight; @@ -92,48 +106,64 @@ BltMask(SURFOBJ* psoDest, { PatternX0 += PatternWidth; } - - for (y = prclDest->top; y < prclDest->bottom; y++) - { - pjMskCurrent = pjMskLine; - fjMaskBit = fjMaskBit0; - PatternX = PatternX0; - - for (x = prclDest->left; x < prclDest->right; x++) - { - if (*pjMskCurrent & fjMaskBit) - { - fnDest_PutPixel(psoDest, x, y, - fnPattern_GetPixel(psoPattern, PatternX, PatternY)); - } - fjMaskBit = _rotr8(fjMaskBit, 1); - pjMskCurrent += (fjMaskBit >> 7); - PatternX++; - PatternX %= PatternWidth; - } - pjMskLine += psoMask->lDelta; - PatternY++; - PatternY %= PatternHeight; - } + PatternX = PatternX0; } else { Pattern = pbo ? pbo->iSolidColor : 0; - for (y = prclDest->top; y < prclDest->bottom; y++) - { - pjMskCurrent = pjMskLine; - fjMaskBit = fjMaskBit0; + } - for (x = prclDest->left; x < prclDest->right; x++) + for (y = prclDest->top; y < prclDest->bottom; y++) + { + pjMskCurrent = pjMskLine; + fjMaskBit = fjMaskBit0; + + for (x = prclDest->left; x < prclDest->right; x++) + { + Rop4 = (*pjMskCurrent & fjMaskBit) ? fgndRop : bkgndRop; + + if(psurfPattern) { - if (*pjMskCurrent & fjMaskBit) - { - fnDest_PutPixel(psoDest, x, y, Pattern); - } - fjMaskBit = _rotr8(fjMaskBit, 1); - pjMskCurrent += (fjMaskBit >> 7); + if(ROP4_USES_PATTERN(Rop4)) + Pattern = fnPattern_GetPixel(psoPattern, PatternX, PatternY); + PatternX++; + PatternX %= PatternWidth; } - pjMskLine += psoMask->lDelta; + + if(psoSource) + { + if(ROP4_USES_SOURCE(Rop4)) + { + Source = XLATEOBJ_iXlate(ColorTranslation, + fnSrc_GetPixel(psoSource, SrcX, SrcY)); + } + SrcX++; + } + + if(ROP4_USES_DEST(Rop4)) + Dest = fnDest_GetPixel(psoDest, x, y); + + fnDest_PutPixel(psoDest, + x, + y, + DIB_DoRop(Rop4, + Dest, + Source, + Pattern)); + fjMaskBit = _rotr8(fjMaskBit, 1); + pjMskCurrent += (fjMaskBit >> 7); + } + pjMskLine += psoMask->lDelta; + if(psurfPattern) + { + PatternY++; + PatternY %= PatternHeight; + PatternX = PatternX0; + } + if(psoSource) + { + SrcY++; + SrcX = pptlSource->x; } } @@ -153,7 +183,7 @@ BltPatCopy(SURFOBJ* Dest, POINTL* MaskPoint, BRUSHOBJ* pbo, POINTL* BrushPoint, - ROP4 Rop4) + DWORD Rop4) { // These functions are assigned if we're working with a DIB // The assigned functions depend on the bitsPerPixel of the DIB @@ -188,7 +218,7 @@ CallDibBitBlt(SURFOBJ* OutputObj, BltInfo.DestRect = *OutputRect; BltInfo.SourcePoint = *InputPoint; - if (ROP3_TO_ROP4(SRCCOPY) == Rop4) + if ((Rop4 & 0xFF) == R3_OPINDEX_SRCCOPY) return DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo); BltInfo.Brush = pbo; @@ -244,7 +274,7 @@ NtGdiEngBitBlt( IN POINTL *pptlMask, IN BRUSHOBJ *pbo, IN POINTL *pptlBrush, - IN ROP4 rop4 ) + IN ROP4 Rop4) { RECTL rclTrg; POINTL ptlSrc; @@ -272,7 +302,7 @@ NtGdiEngBitBlt( } _SEH2_END; - return EngBitBlt(psoTrg, psoSrc, psoMask, pco, pxlo, &rclTrg, &ptlSrc, &ptlMask, pbo, &ptlBrush, rop4); + return EngBitBlt(psoTrg, psoSrc, psoMask, pco, pxlo, &rclTrg, &ptlSrc, &ptlMask, pbo, &ptlBrush, Rop4); } /* @@ -289,7 +319,7 @@ EngBitBlt(SURFOBJ *DestObj, POINTL *MaskOrigin, BRUSHOBJ *pbo, POINTL *BrushOrigin, - ROP4 rop4) + ROP4 Rop4) { BYTE clippingType; RECTL CombinedRect; @@ -306,16 +336,20 @@ EngBitBlt(SURFOBJ *DestObj, unsigned i; POINTL Pt; ULONG Direction; - BOOL UsesSource; + BOOL UsesSource, UsesMask; POINTL AdjustedBrushOrigin; - UsesSource = ROP4_USES_SOURCE(rop4); - if (R4_NOOP == rop4) + UsesSource = ROP4_USES_SOURCE(Rop4); + UsesMask = ROP4_USES_MASK(Rop4); + + if (Rop4 == ROP4_NOOP) { /* Copy destination onto itself: nop */ return TRUE; } + //DPRINT1("Rop4 : 0x%08x\n", Rop4); + OutputRect = *DestRect; if (OutputRect.right < OutputRect.left) { @@ -434,11 +468,11 @@ EngBitBlt(SURFOBJ *DestObj, clippingType = ClipRegion->iDComplexity; } - if (R4_MASK == rop4) + if (UsesMask) { BltRectFunc = BltMask; } - else if (ROP3_TO_ROP4(PATCOPY) == rop4) + else if ((Rop4 & 0xFF) == R3_OPINDEX_PATCOPY) { if (pbo && pbo->iSolidColor == 0xFFFFFFFF) BltRectFunc = CallDibBitBlt; @@ -456,7 +490,7 @@ EngBitBlt(SURFOBJ *DestObj, case DC_TRIVIAL: Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ColorTranslation, &OutputRect, &InputPoint, MaskOrigin, pbo, - &AdjustedBrushOrigin, rop4); + &AdjustedBrushOrigin, Rop4); break; case DC_RECT: /* Clip the blt to the clip rectangle */ @@ -470,7 +504,7 @@ EngBitBlt(SURFOBJ *DestObj, Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top; Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ColorTranslation, &CombinedRect, &Pt, MaskOrigin, pbo, - &AdjustedBrushOrigin, rop4); + &AdjustedBrushOrigin, Rop4); } break; case DC_COMPLEX: @@ -511,7 +545,7 @@ EngBitBlt(SURFOBJ *DestObj, Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ColorTranslation, &CombinedRect, &Pt, MaskOrigin, pbo, &AdjustedBrushOrigin, - rop4) && Ret; + Rop4) && Ret; } } } @@ -534,7 +568,7 @@ IntEngBitBlt( POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush, - ROP4 rop4) + ROP4 Rop4) { SURFACE *psurfTrg; SURFACE *psurfSrc = NULL; @@ -550,6 +584,11 @@ IntEngBitBlt( rclClipped = *prclTrg; RECTL_vMakeWellOrdered(&rclClipped); + //DPRINT1("Rop4 : 0x%08x\n", Rop4); + + /* Sanity check */ + ASSERT(IS_VALID_ROP4(Rop4)); + if (pco) { /* Clip target rect against the bounds of the clipping region */ @@ -564,7 +603,7 @@ IntEngBitBlt( pco = NULL; } - if (ROP4_USES_SOURCE(rop4)) + if (ROP4_USES_SOURCE(Rop4)) { ASSERT(psoSrc); psurfSrc = CONTAINING_RECORD(psoSrc, SURFACE, SurfObj); @@ -614,7 +653,7 @@ IntEngBitBlt( pptlMask, pbo, pptlBrush, - rop4); + Rop4); // FIXME: cleanup temp surface! @@ -820,7 +859,7 @@ EngMaskBitBlt(SURFOBJ *psoDest, else Ret = BltMask(psoOutput, NULL, psoInput, DestColorTranslation, &OutputRect, NULL, &InputPoint, pbo, &AdjustedBrushOrigin, - R4_MASK); + ROP4_MASK); break; case DC_RECT: // Clip the blt to the clip rectangle @@ -840,7 +879,7 @@ EngMaskBitBlt(SURFOBJ *psoDest, else { Ret = BltMask(psoOutput, NULL, psoInput, DestColorTranslation, - &CombinedRect, NULL, &Pt, pbo, &AdjustedBrushOrigin, R4_MASK); + &CombinedRect, NULL, &Pt, pbo, &AdjustedBrushOrigin, ROP4_MASK); } } break; @@ -889,7 +928,7 @@ EngMaskBitBlt(SURFOBJ *psoDest, Ret = BltMask(psoOutput, NULL, psoInput, DestColorTranslation, &CombinedRect, NULL, &Pt, pbo, &AdjustedBrushOrigin, - R4_MASK) && Ret; + ROP4_MASK) && Ret; } } } @@ -954,7 +993,7 @@ IntEngMaskBlt(SURFOBJ *psoDest, but the VMware driver doesn't hook that call. */ IntEngBitBlt(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation, DestRect, pptlMask, pptlMask, pbo, BrushOrigin, - R4_NOOP); + ROP4_NOOP); ret = EngMaskBitBlt(psoDest, psoMask, ClipRegion, DestColorTranslation, SourceColorTranslation, &OutputRect, &InputPoint, pbo, BrushOrigin); @@ -962,7 +1001,7 @@ IntEngMaskBlt(SURFOBJ *psoDest, /* Dummy BitBlt to let driver know that something has changed. */ IntEngBitBlt(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation, DestRect, pptlMask, pptlMask, pbo, BrushOrigin, - R4_NOOP); + ROP4_NOOP); return ret; } diff --git a/reactos/subsystems/win32/win32k/eng/copybits.c b/reactos/subsystems/win32/win32k/eng/copybits.c index afb2f16cc99..1200c1ce0fb 100644 --- a/reactos/subsystems/win32/win32k/eng/copybits.c +++ b/reactos/subsystems/win32/win32k/eng/copybits.c @@ -92,7 +92,7 @@ EngCopyBits(SURFOBJ *psoDest, // If CopyBits wasn't hooked, BitBlt must be ret = IntEngBitBlt(psoDest, psoSource, NULL, Clip, ColorTranslation, DestRect, SourcePoint, - NULL, NULL, NULL, ROP3_TO_ROP4(SRCCOPY)); + NULL, NULL, NULL, ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); goto cleanup; } @@ -111,7 +111,7 @@ EngCopyBits(SURFOBJ *psoDest, BltInfo.SourceSurface = psoSource; BltInfo.PatternSurface = NULL; BltInfo.XlateSourceToDest = ColorTranslation; - BltInfo.Rop4 = SRCCOPY; + BltInfo.Rop4 = ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY); switch (clippingType) { diff --git a/reactos/subsystems/win32/win32k/eng/mouse.c b/reactos/subsystems/win32/win32k/eng/mouse.c index b2db0e61af7..00dc0333ccb 100644 --- a/reactos/subsystems/win32/win32k/eng/mouse.c +++ b/reactos/subsystems/win32/win32k/eng/mouse.c @@ -175,7 +175,7 @@ IntHideMousePointer( &ptlSave, NULL, NULL, - ROP3_TO_ROP4(SRCCOPY)); + ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); } VOID @@ -228,7 +228,7 @@ IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest) NULL, NULL, NULL, - ROP3_TO_ROP4(SRCCOPY)); + ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); /* Blt the pointer on the screen. */ if (pgp->psurfColor) @@ -243,7 +243,7 @@ IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest) NULL, NULL, NULL, - ROP3_TO_ROP4(SRCAND)); + ROP4_FROM_INDEX(R3_OPINDEX_SRCAND)); IntEngBitBlt(psoDest, &pgp->psurfColor->SurfObj, @@ -255,7 +255,7 @@ IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest) NULL, NULL, NULL, - ROP3_TO_ROP4(SRCINVERT)); + ROP4_FROM_INDEX(R3_OPINDEX_SRCINVERT)); } else { @@ -269,7 +269,7 @@ IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest) NULL, NULL, NULL, - ROP3_TO_ROP4(SRCAND)); + ROP4_FROM_INDEX(R3_OPINDEX_SRCAND)); rclPointer.top += pgp->Size.cy; @@ -283,7 +283,7 @@ IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest) NULL, NULL, NULL, - ROP3_TO_ROP4(SRCINVERT)); + ROP4_FROM_INDEX(R3_OPINDEX_SRCINVERT)); } } @@ -337,7 +337,7 @@ EngSetPointerShape( rectl.bottom = sizel.cy; /* Calculate lDelta for our surfaces. */ - lDelta = WIDTH_BYTES_ALIGN32(sizel.cx, + lDelta = WIDTH_BYTES_ALIGN32(sizel.cx, BitsPerFormat(pso->iBitmapFormat)); /* Create a bitmap for saving the pixels under the cursor. */ diff --git a/reactos/subsystems/win32/win32k/eng/stretchblt.c b/reactos/subsystems/win32/win32k/eng/stretchblt.c index a6f3d4f4572..1b4a7f99ea6 100644 --- a/reactos/subsystems/win32/win32k/eng/stretchblt.c +++ b/reactos/subsystems/win32/win32k/eng/stretchblt.c @@ -104,7 +104,7 @@ EngStretchBltROP( IN POINTL *MaskOrigin, IN ULONG Mode, IN BRUSHOBJ *pbo, - IN DWORD ROP4) + IN ROP4 Rop4) { RECTL InputRect; RECTL OutputRect; @@ -116,7 +116,7 @@ EngStretchBltROP( PSTRETCHRECTFUNC BltRectFunc; BOOLEAN Ret = TRUE; POINTL AdjustedBrushOrigin; - BOOL UsesSource = ROP4_USES_SOURCE(ROP4); + BOOL UsesSource = ROP4_USES_SOURCE(Rop4); BYTE clippingType; RECTL ClipRect; @@ -132,6 +132,13 @@ EngStretchBltROP( LONG SrcHeight; LONG SrcWidth; + if (Rop4 == ROP4_NOOP) + { + /* Copy destination onto itself: nop */ + return TRUE; + } + + /* Determine clipping type */ if (ClipRegion == (CLIPOBJ *) NULL) { @@ -142,12 +149,6 @@ EngStretchBltROP( clippingType = ClipRegion->iDComplexity; } - if (ROP4 == R4_NOOP) - { - /* Copy destination onto itself: nop */ - return TRUE; - } - OutputRect = *prclDest; if (OutputRect.right < OutputRect.left) { @@ -257,7 +258,7 @@ EngStretchBltROP( case DC_TRIVIAL: Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, ColorTranslation, &OutputRect, &InputRect, MaskOrigin, - pbo, &AdjustedBrushOrigin, ROP4); + pbo, &AdjustedBrushOrigin, Rop4); break; case DC_RECT: // Clip the blt to the clip rectangle @@ -278,7 +279,7 @@ EngStretchBltROP( MaskOrigin, pbo, &AdjustedBrushOrigin, - ROP4); + Rop4); } break; case DC_COMPLEX: @@ -323,7 +324,7 @@ EngStretchBltROP( MaskOrigin, pbo, &AdjustedBrushOrigin, - ROP4); + Rop4); } } } @@ -371,7 +372,7 @@ EngStretchBlt( MaskOrigin, Mode, NULL, - ROP3_TO_ROP4(SRCCOPY)); + ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); } BOOL APIENTRY @@ -385,7 +386,7 @@ IntEngStretchBlt(SURFOBJ *psoDest, POINTL *pMaskOrigin, BRUSHOBJ *pbo, POINTL *BrushOrigin, - ROP4 ROP) + DWORD Rop4) { BOOLEAN ret; COLORADJUSTMENT ca; @@ -395,7 +396,7 @@ IntEngStretchBlt(SURFOBJ *psoDest, RECTL InputClippedRect; RECTL InputRect; RECTL OutputRect; - BOOL UsesSource = ROP4_USES_SOURCE(ROP); + BOOL UsesSource = ROP4_USES_SOURCE(Rop4); LONG InputClWidth, InputClHeight, InputWidth, InputHeight; ASSERT(psoDest); @@ -403,6 +404,9 @@ IntEngStretchBlt(SURFOBJ *psoDest, ASSERT(psurfDest); ASSERT(DestRect); + /* Sanity check */ + ASSERT(IS_VALID_ROP4(Rop4)); + InputClippedRect = *DestRect; if (InputClippedRect.right < InputClippedRect.left) { @@ -485,7 +489,7 @@ IntEngStretchBlt(SURFOBJ *psoDest, &MaskOrigin, COLORONCOLOR, pbo, - ROP); + Rop4); } if (! ret) @@ -502,7 +506,7 @@ IntEngStretchBlt(SURFOBJ *psoDest, &MaskOrigin, COLORONCOLOR, pbo, - ROP); + Rop4); } return ret; diff --git a/reactos/subsystems/win32/win32k/include/color.h b/reactos/subsystems/win32/win32k/include/color.h index 0972f2e8dd3..faf88a77eee 100644 --- a/reactos/subsystems/win32/win32k/include/color.h +++ b/reactos/subsystems/win32/win32k/include/color.h @@ -27,7 +27,7 @@ typedef struct _COLORSPACE typedef struct _COLORTRANSFORMOBJ { BASEOBJECT BaseObject; - HANDLE hColorTransform; + HANDLE hColorTransform; } GDICLRXFORM, COLORTRANSFORMOBJ, *PCOLORTRANSFORMOBJ; extern HCOLORSPACE hStockColorSpace; @@ -36,6 +36,6 @@ const PALETTEENTRY* FASTCALL COLOR_GetSystemPaletteTemplate (VOID); COLORREF APIENTRY COLOR_LookupNearestColor (PALETTEENTRY* palPalEntry, INT size, COLORREF color); INT APIENTRY COLOR_PaletteLookupExactIndex (PALETTEENTRY* palPalEntry, INT size, COLORREF col); INT APIENTRY COLOR_PaletteLookupPixel(PALETTEENTRY *palPalEntry, INT size, XLATEOBJ *XlateObj, COLORREF col, BOOL skipReserved); -UINT FASTCALL IntGdiRealizePalette (HDC); +UINT FASTCALL IntGdiRealizePalette (PDC); HCOLORSPACE FASTCALL IntGdiCreateColorSpace(PLOGCOLORSPACEEXW); BOOL FASTCALL IntGdiDeleteColorSpace(HCOLORSPACE); diff --git a/reactos/subsystems/win32/win32k/include/inteng.h b/reactos/subsystems/win32/win32k/include/inteng.h index 1d8610d2dac..4b360b0ce9b 100644 --- a/reactos/subsystems/win32/win32k/include/inteng.h +++ b/reactos/subsystems/win32/win32k/include/inteng.h @@ -17,19 +17,40 @@ typedef struct tagSPAN ULONG Width; } SPAN, *PSPAN; -#define R3_OPINDEX_SRCCOPY 0xcc -#define R3_OPINDEX_NOOP 0xaa -#define R4_NOOP ((R3_OPINDEX_NOOP << 8) | R3_OPINDEX_NOOP) -#define R4_MASK ((R3_OPINDEX_NOOP << 8) | R3_OPINDEX_SRCCOPY) +#define R3_OPINDEX_NOOP 0xAA + +#define R3_OPINDEX_BLACKNESS 0x00 +#define R3_OPINDEX_NOTSRCERASE 0x11 +#define R3_OPINDEX_NOTSRCCOPY 0x33 +#define R3_OPINDEX_SRCERASE 0x44 +#define R3_OPINDEX_DSTINVERT 0x55 +#define R3_OPINDEX_PATINVERT 0x5A +#define R3_OPINDEX_SRCINVERT 0x66 +#define R3_OPINDEX_SRCAND 0x88 +#define R3_OPINDEX_MERGEPAINT 0xBB +#define R3_OPINDEX_MERGECOPY 0xC0 +#define R3_OPINDEX_SRCCOPY 0xCC +#define R3_OPINDEX_SRCPAINT 0xEE +#define R3_OPINDEX_PATCOPY 0xF0 +#define R3_OPINDEX_PATPAINT 0xFB +#define R3_OPINDEX_WHITENESS 0xFF #define ROP2_TO_MIX(Rop2) (((Rop2) << 8) | (Rop2)) -#define ROP3_USES_DEST(Rop3) ((((Rop3) & 0xAA0000) >> 1) != ((Rop3) & 0x550000)) -#define ROP4_USES_DEST(Rop4) (((((Rop4) & 0xAA) >> 1) != ((Rop4) & 0x55)) || ((((Rop4) & 0xAA00) >> 1) != ((Rop4) & 0x5500))) -#define ROP3_USES_SOURCE(Rop3) ((((Rop3) & 0xCC0000) >> 2) != ((Rop3) & 0x330000)) -#define ROP4_USES_SOURCE(Rop4) (((((Rop4) & 0xCC) >> 2) != ((Rop4) & 0x33)) || ((((Rop4) & 0xCC00) >> 2) != ((Rop4) & 0x3300))) -#define ROP3_USES_PATTERN(Rop3) ((((Rop3) & 0xF00000) >> 4) != ((Rop3) & 0x0F0000)) + +#define ROP4_FROM_INDEX(index) ((index) | ((index) << 8)) + +#define ROP4_USES_SOURCE(Rop4) (((((Rop4) & 0xCC00) >> 2) != ((Rop4) & 0x3300)) || ((((Rop4) & 0xCC) >> 2) != ((Rop4) & 0x33))) +#define ROP4_USES_MASK(Rop4) (((Rop4) & 0xFF00) != (((Rop4) & 0xff) << 8)) +#define ROP4_USES_DEST(Rop4) (((((Rop4) & 0xAA) >> 1) != ((Rop4) & 0x55)) || ((((Rop4) & 0xAA00) >> 1) != ((Rop4) & 0x5500))) #define ROP4_USES_PATTERN(Rop4) (((((Rop4) & 0xF0) >> 4) != ((Rop4) & 0x0F)) || ((((Rop4) & 0xF000) >> 4) != ((Rop4) & 0x0F00))) -#define ROP3_TO_ROP4(Rop3) ((((Rop3) >> 8) & 0xff00) | (((Rop3) >> 16) & 0x00ff)) + +#define IS_VALID_ROP4(rop) (((rop) & 0xFFFF0000) == 0) + +#define ROP4_FGND(Rop4) ((Rop4) & 0x00FF) +#define ROP4_BKGND(Rop4) (((Rop4) & 0xFF00) >> 8) + +#define ROP4_NOOP (R3_OPINDEX_NOOP | (R3_OPINDEX_NOOP << 8)) +#define ROP4_MASK (R3_OPINDEX_SRCCOPY | (R3_OPINDEX_NOOP << 8)) /* Definitions of IntEngXxx functions */ diff --git a/reactos/subsystems/win32/win32k/ntuser/painting.c b/reactos/subsystems/win32/win32k/ntuser/painting.c index beedd93cfb8..8692a036a4b 100644 --- a/reactos/subsystems/win32/win32k/ntuser/painting.c +++ b/reactos/subsystems/win32/win32k/ntuser/painting.c @@ -307,7 +307,7 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse) /* * IntInvalidateWindows * - * Internal function used by IntRedrawWindow, UserRedrawDesktop, + * Internal function used by IntRedrawWindow, UserRedrawDesktop, * co_WinPosSetWindowPos, IntValidateParent, co_UserRedrawWindow. */ VOID FASTCALL @@ -759,7 +759,7 @@ IntPrintWindow( xSrc = 0; ySrc = 0; } - + // TODO: Setup Redirection for Print. return FALSE; @@ -1951,7 +1951,11 @@ UserRealizePalette(HDC hdc) HWND hWnd; DWORD Ret; - Ret = IntGdiRealizePalette(hdc); + PDC pdc = DC_LockDc(hdc); + if(!pdc) + return 0; + + Ret = IntGdiRealizePalette(pdc); if (Ret) // There was a change. { hWnd = IntWindowFromDC(hdc); @@ -1960,6 +1964,7 @@ UserRealizePalette(HDC hdc) UserSendNotifyMessage((HWND)HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM)hWnd, 0); } } + DC_UnlockDc(pdc); return Ret; } @@ -2065,7 +2070,7 @@ NtUserPrintWindow( HDC hdcBlt, UINT nFlags) { - PWND Window; + PWND Window; BOOL Ret = FALSE; UserEnterExclusive(); @@ -2075,7 +2080,7 @@ NtUserPrintWindow( Window = UserGetWindowObject(hwnd); // TODO: Add Desktop and MessageBox check via FNID's. if ( Window ) - { + { /* Validate flags and check it as a mask for 0 or 1. */ if ( (nFlags & PW_CLIENTONLY) == nFlags) Ret = IntPrintWindow( Window, hdcBlt, nFlags); diff --git a/reactos/subsystems/win32/win32k/objects/bitblt.c b/reactos/subsystems/win32/win32k/objects/bitblt.c index 0f7753728ba..1fa1d550027 100644 --- a/reactos/subsystems/win32/win32k/objects/bitblt.c +++ b/reactos/subsystems/win32/win32k/objects/bitblt.c @@ -23,7 +23,11 @@ #define NDEBUG #include +#define ROP_USES_SOURCE(Rop) (((((Rop) & 0xCC0000) >> 2) != ((Rop) & 0x330000)) || ((((Rop) & 0xCC000000) >> 2) != ((Rop) & 0x33000000))) +#define ROP_USES_MASK(Rop) (((Rop) & 0xFF000000) != (((Rop) & 0xff0000) << 8)) +#define FIXUP_ROP(Rop) if(((Rop) & 0xFF000000) == 0) Rop = MAKEROP4((Rop), (Rop)) +#define ROP_TO_ROP4(Rop) ((Rop) >> 16) BOOL APIENTRY NtGdiAlphaBlend( @@ -169,144 +173,21 @@ NtGdiBitBlt( IN DWORD crBackColor, IN FLONG fl) { - PDC DCDest; - PDC DCSrc = NULL; - HDC ahDC[2]; - PGDIOBJ apObj[2]; - PDC_ATTR pdcattr = NULL; - SURFACE *BitmapDest, *BitmapSrc = NULL; - RECTL DestRect, SourceRect; - POINTL SourcePoint; - BOOL Status = FALSE; - EXLATEOBJ exlo; - XLATEOBJ *XlateObj = NULL; - BOOL UsesSource = ROP3_USES_SOURCE(ROP); - - DPRINT("Locking DCs\n"); - ahDC[0] = hDCDest; - ahDC[1] = hDCSrc ; - GDIOBJ_LockMultipleObjs(2, ahDC, apObj); - DCDest = apObj[0]; - DCSrc = apObj[1]; - - if (NULL == DCDest) - { - if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject); - DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest); - return FALSE; - } - - if (DCDest->dctype == DC_TYPE_INFO) - { - if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject); - GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject); - /* Yes, Windows really returns TRUE in this case */ - return TRUE; - } - - if (UsesSource) - { - if (NULL == DCSrc) - { - GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject); - DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc); - return FALSE; - } - if (DCSrc->dctype == DC_TYPE_INFO) - { - GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject); - GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject); - /* Yes, Windows really returns TRUE in this case */ - return TRUE; - } - } - else if(DCSrc) - { - DPRINT1("Getting a valid Source handle without using source!!!\n"); - GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject); - DCSrc = NULL ; - } - - pdcattr = DCDest->pdcattr; - - DestRect.left = XDest; - DestRect.top = YDest; - DestRect.right = XDest+Width; - DestRect.bottom = YDest+Height; - IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); - - DestRect.left += DCDest->ptlDCOrig.x; - DestRect.top += DCDest->ptlDCOrig.y; - DestRect.right += DCDest->ptlDCOrig.x; - DestRect.bottom += DCDest->ptlDCOrig.y; - - SourcePoint.x = XSrc; - SourcePoint.y = YSrc; - - if (UsesSource) - { - IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1); - - SourcePoint.x += DCSrc->ptlDCOrig.x; - SourcePoint.y += DCSrc->ptlDCOrig.y; - /* Calculate Source Rect */ - SourceRect.left = SourcePoint.x; - SourceRect.top = SourcePoint.y; - SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left; - SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ; - } - - /* Prepare blit */ - DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect); - - if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) - DC_vUpdateFillBrush(DCDest); - - /* Determine surfaces to be used in the bitblt */ - BitmapDest = DCDest->dclevel.pSurface; - if (!BitmapDest) - goto cleanup; - - if (UsesSource) - { - { - BitmapSrc = DCSrc->dclevel.pSurface; - if (!BitmapSrc) - goto cleanup; - } - } - - /* Create the XLATEOBJ. */ - if (UsesSource) - { - EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); - XlateObj = &exlo.xlo; - } - - /* Perform the bitblt operation */ - Status = IntEngBitBlt(&BitmapDest->SurfObj, - BitmapSrc ? &BitmapSrc->SurfObj : NULL, - NULL, - DCDest->rosdc.CombinedClip, - XlateObj, - &DestRect, - &SourcePoint, - NULL, - &DCDest->eboFill.BrushObject, - &DCDest->dclevel.pbrFill->ptOrigin, - ROP3_TO_ROP4(ROP)); - - if (UsesSource) - EXLATEOBJ_vCleanup(&exlo); -cleanup: - DC_vFinishBlit(DCDest, DCSrc); - if (UsesSource) - { - GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject); - } - GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject); - - return Status; + /* Forward to NtGdiMaskBlt */ + // TODO : what's fl for? + return NtGdiMaskBlt(hDCDest, + XDest, + YDest, + Width, + Height, + hDCSrc, + XSrc, + YSrc, + NULL, + 0, + 0, + ROP, + crBackColor); } BOOL APIENTRY @@ -414,86 +295,6 @@ done: return Ret; } -/*********************************************************************** -* MaskBlt -* Ported from WINE by sedwards 11-4-03 -* -* Someone thought it would be faster to do it here and then switch back -* to GDI32. I dunno. Write a test and let me know. -* A. It should be in here! -*/ - -static const DWORD ROP3Table[256] = -{ - 0x000042, 0x010289, 0x020C89, 0x0300AA, 0x040C88, 0x0500A9, 0x060865, 0x0702C5, - 0x080F08, 0x090245, 0x0A0329, 0x0B0B2A, 0x0C0324, 0x0D0B25, 0x0E08A5, 0x0F0001, - 0x100C85, 0x1100A6, 0x120868, 0x1302C8, 0x140869, 0x1502C9, 0x165CCA, 0x171D54, - 0x180D59, 0x191CC8, 0x1A06C5, 0x1B0768, 0x1C06CA, 0x1D0766, 0x1E01A5, 0x1F0385, - 0x200F09, 0x210248, 0x220326, 0x230B24, 0x240D55, 0x251CC5, 0x2606C8, 0x271868, - 0x280369, 0x2916CA, 0x2A0CC9, 0x2B1D58, 0x2C0784, 0x2D060A, 0x2E064A, 0x2F0E2A, - 0x30032A, 0x310B28, 0x320688, 0x330008, 0x3406C4, 0x351864, 0x3601A8, 0x370388, - 0x38078A, 0x390604, 0x3A0644, 0x3B0E24, 0x3C004A, 0x3D18A4, 0x3E1B24, 0x3F00EA, - 0x400F0A, 0x410249, 0x420D5D, 0x431CC4, 0x440328, 0x450B29, 0x4606C6, 0x47076A, - 0x480368, 0x4916C5, 0x4A0789, 0x4B0605, 0x4C0CC8, 0x4D1954, 0x4E0645, 0x4F0E25, - 0x500325, 0x510B26, 0x5206C9, 0x530764, 0x5408A9, 0x550009, 0x5601A9, 0x570389, - 0x580785, 0x590609, 0x5A0049, 0x5B18A9, 0x5C0649, 0x5D0E29, 0x5E1B29, 0x5F00E9, - 0x600365, 0x6116C6, 0x620786, 0x630608, 0x640788, 0x650606, 0x660046, 0x6718A8, - 0x6858A6, 0x690145, 0x6A01E9, 0x6B178A, 0x6C01E8, 0x6D1785, 0x6E1E28, 0x6F0C65, - 0x700CC5, 0x711D5C, 0x720648, 0x730E28, 0x740646, 0x750E26, 0x761B28, 0x7700E6, - 0x7801E5, 0x791786, 0x7A1E29, 0x7B0C68, 0x7C1E24, 0x7D0C69, 0x7E0955, 0x7F03C9, - 0x8003E9, 0x810975, 0x820C49, 0x831E04, 0x840C48, 0x851E05, 0x8617A6, 0x8701C5, - 0x8800C6, 0x891B08, 0x8A0E06, 0x8B0666, 0x8C0E08, 0x8D0668, 0x8E1D7C, 0x8F0CE5, - 0x900C45, 0x911E08, 0x9217A9, 0x9301C4, 0x9417AA, 0x9501C9, 0x960169, 0x97588A, - 0x981888, 0x990066, 0x9A0709, 0x9B07A8, 0x9C0704, 0x9D07A6, 0x9E16E6, 0x9F0345, - 0xA000C9, 0xA11B05, 0xA20E09, 0xA30669, 0xA41885, 0xA50065, 0xA60706, 0xA707A5, - 0xA803A9, 0xA90189, 0xAA0029, 0xAB0889, 0xAC0744, 0xAD06E9, 0xAE0B06, 0xAF0229, - 0xB00E05, 0xB10665, 0xB21974, 0xB30CE8, 0xB4070A, 0xB507A9, 0xB616E9, 0xB70348, - 0xB8074A, 0xB906E6, 0xBA0B09, 0xBB0226, 0xBC1CE4, 0xBD0D7D, 0xBE0269, 0xBF08C9, - 0xC000CA, 0xC11B04, 0xC21884, 0xC3006A, 0xC40E04, 0xC50664, 0xC60708, 0xC707AA, - 0xC803A8, 0xC90184, 0xCA0749, 0xCB06E4, 0xCC0020, 0xCD0888, 0xCE0B08, 0xCF0224, - 0xD00E0A, 0xD1066A, 0xD20705, 0xD307A4, 0xD41D78, 0xD50CE9, 0xD616EA, 0xD70349, - 0xD80745, 0xD906E8, 0xDA1CE9, 0xDB0D75, 0xDC0B04, 0xDD0228, 0xDE0268, 0xDF08C8, - 0xE003A5, 0xE10185, 0xE20746, 0xE306EA, 0xE40748, 0xE506E5, 0xE61CE8, 0xE70D79, - 0xE81D74, 0xE95CE6, 0xEA02E9, 0xEB0849, 0xEC02E8, 0xED0848, 0xEE0086, 0xEF0A08, - 0xF00021, 0xF10885, 0xF20B05, 0xF3022A, 0xF40B0A, 0xF50225, 0xF60265, 0xF708C5, - 0xF802E5, 0xF90845, 0xFA0089, 0xFB0A09, 0xFC008A, 0xFD0A0A, 0xFE02A9, 0xFF0062, -}; - -static __inline BYTE -SwapROP3_SrcDst(BYTE bRop3) -{ - return (bRop3 & 0x99) | ((bRop3 & 0x22) << 1) | ((bRop3 & 0x44) >> 1); -} - -#define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF) -#define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF]) -#define DSTCOPY 0x00AA0029 -#define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */ - -/* NOTE: An alternative algorithm could use a pattern brush, created from - * the mask bitmap and then use raster operation 0xCA to combine the fore - * and background bitmaps. In this case erasing the bits beforehand would be - * unneccessary. On the other hand the Operation does not provide an optimized - * version in the DIB code, while SRCAND and SRCPAINT do. - * A fully correct implementation would call Eng/DrvBitBlt, but our - * EngBitBlt completely ignores the mask surface. - * - * Msk Fg Bk => x - * P S D DPSDxax - * ------------------------------------------ - * 0 0 0 0 0000xax = 000ax = 00x = 0 - * 0 0 1 1 1001xax = 101ax = 10x = 1 - * 0 1 0 0 0010xax = 001ax = 00x = 0 - * 0 1 1 1 1011xax = 100ax = 10x = 1 - * 1 0 0 0 0100xax = 010ax = 00x = 0 - * 1 0 1 0 1101xax = 111ax = 11x = 0 - * 1 1 0 1 0110xax = 011ax = 01x = 1 - * 1 1 1 1 1111xax = 110ax = 10x = 1 - * - * Operation index = 11001010 = 0xCA = PSaDPnao = DPSDxax - * ^ no, this is not random letters, its reverse Polish notation - */ - BOOL APIENTRY NtGdiMaskBlt( HDC hdcDest, @@ -510,97 +311,188 @@ NtGdiMaskBlt( DWORD dwRop, IN DWORD crBackColor) { - HBITMAP hbmFore, hbmBack; - HDC hdcMask, hdcFore, hdcBack; - PDC pdc; - HBRUSH hbr; - COLORREF crFore, crBack; + PDC DCDest; + PDC DCSrc = NULL; + HDC ahDC[2]; + PGDIOBJ apObj[2]; + PDC_ATTR pdcattr = NULL; + SURFACE *BitmapDest, *BitmapSrc = NULL, *psurfMask = NULL; + RECTL DestRect, SourceRect; + POINTL SourcePoint, MaskPoint; + BOOL Status = FALSE; + EXLATEOBJ exlo; + XLATEOBJ *XlateObj = NULL; + BOOL UsesSource = ROP_USES_SOURCE(dwRop); + BOOL UsesMask; - if (!hbmMask) - return NtGdiBitBlt(hdcDest, - nXDest, - nYDest, - nWidth, - nHeight, - hdcSrc, - nXSrc, - nYSrc, - FRGND_ROP3(dwRop), - crBackColor, - 0); + FIXUP_ROP(dwRop); - /* Lock the dest DC */ - pdc = DC_LockDc(hdcDest); - if (!pdc) return FALSE; + UsesMask = ROP_USES_MASK(dwRop); - /* Get brush and colors from dest dc */ - hbr = pdc->pdcattr->hbrush; - crFore = pdc->pdcattr->crForegroundClr; - crBack = pdc->pdcattr->crBackgroundClr; + //DPRINT1("dwRop : 0x%08x\n", dwRop); - /* Unlock the DC */ - DC_UnlockDc(pdc); + /* Take care of mask bitmap */ + if(hbmMask) + { + psurfMask = SURFACE_LockSurface(hbmMask); + if(!psurfMask) + { + EngSetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + } - /* 1. Create mask bitmap's dc */ - hdcMask = NtGdiCreateCompatibleDC(hdcDest); - NtGdiSelectBitmap(hdcMask, hbmMask); + if(UsesMask) + { + if(!psurfMask) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if(gajBitsPerFormat[psurfMask->SurfObj.iBitmapFormat] != 1) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + SURFACE_UnlockSurface(psurfMask); + return FALSE; + } + } + else if(psurfMask) + { + DPRINT1("Getting Mask bitmap without needing it?\n"); + SURFACE_UnlockSurface(psurfMask); + psurfMask = NULL; + } + MaskPoint.x = xMask; + MaskPoint.y = yMask; - /* 2. Create masked Background bitmap */ + /* Take care of source and destination bitmap */ + DPRINT("Locking DCs\n"); + ahDC[0] = hdcDest; + ahDC[1] = hdcSrc ; + GDIOBJ_LockMultipleObjs(2, ahDC, apObj); + DCDest = apObj[0]; + DCSrc = apObj[1]; - /* 2.1 Create bitmap */ - hdcBack = NtGdiCreateCompatibleDC(hdcDest); - hbmBack = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight); - NtGdiSelectBitmap(hdcBack, hbmBack); + if (NULL == DCDest) + { + if(DCSrc) DC_UnlockDc(DCSrc); + DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hdcDest); + return FALSE; + } - /* 2.2 Copy source bitmap */ - NtGdiSelectBrush(hdcBack, hbr); - IntGdiSetBkColor(hdcBack, crBack); - IntGdiSetTextColor(hdcBack, crFore); - NtGdiBitBlt(hdcBack, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY, 0, 0); + if (DCDest->dctype == DC_TYPE_INFO) + { + if(DCSrc) DC_UnlockDc(DCSrc); + DC_UnlockDc(DCDest); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } - /* 2.3 Do the background rop */ - NtGdiBitBlt(hdcBack, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop), 0, 0); + if (UsesSource) + { + if (NULL == DCSrc) + { + DC_UnlockDc(DCDest); + DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hdcSrc); + return FALSE; + } + if (DCSrc->dctype == DC_TYPE_INFO) + { + DC_UnlockDc(DCDest); + DC_UnlockDc(DCSrc); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + } + else if(DCSrc) + { + DPRINT("Getting a valid Source handle without using source!!!\n"); + DC_UnlockDc(DCSrc); + DCSrc = NULL ; + } - /* 2.4 Erase the foreground pixels */ - IntGdiSetBkColor(hdcBack, RGB(0xFF, 0xFF, 0xFF)); - IntGdiSetTextColor(hdcBack, RGB(0, 0, 0)); - NtGdiBitBlt(hdcBack, 0, 0, nWidth, nHeight, hdcMask, xMask, yMask, SRCAND, 0, 0); + pdcattr = DCDest->pdcattr; - /* 3. Create masked Foreground bitmap */ + DestRect.left = nXDest; + DestRect.top = nYDest; + DestRect.right = nXDest + nWidth; + DestRect.bottom = nYDest + nHeight; + IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); - /* 3.1 Create bitmap */ - hdcFore = NtGdiCreateCompatibleDC(hdcDest); - hbmFore = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight); - NtGdiSelectBitmap(hdcFore, hbmFore); + DestRect.left += DCDest->ptlDCOrig.x; + DestRect.top += DCDest->ptlDCOrig.y; + DestRect.right += DCDest->ptlDCOrig.x; + DestRect.bottom += DCDest->ptlDCOrig.y; - /* 3.2 Copy the dest bitmap */ - NtGdiSelectBrush(hdcFore, hbr); - IntGdiSetBkColor(hdcFore, crBack); - IntGdiSetTextColor(hdcFore, crFore); - NtGdiBitBlt(hdcFore, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY, 0, 0); + SourcePoint.x = nXSrc; + SourcePoint.y = nYSrc; - /* 2.3 Do the foreground rop */ - NtGdiBitBlt(hdcFore, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0,0); + if (UsesSource) + { + IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1); - /* 2.4 Erase the background pixels */ - IntGdiSetBkColor(hdcFore, RGB(0, 0, 0)); - IntGdiSetTextColor(hdcFore, RGB(0xFF, 0xFF, 0xFF)); - NtGdiBitBlt(hdcFore, 0, 0, nWidth, nHeight, hdcMask, xMask, yMask, SRCAND, 0, 0); + SourcePoint.x += DCSrc->ptlDCOrig.x; + SourcePoint.y += DCSrc->ptlDCOrig.y; + /* Calculate Source Rect */ + SourceRect.left = SourcePoint.x; + SourceRect.top = SourcePoint.y; + SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left; + SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ; + } - /* 3. Combine the fore and background into the background bitmap */ - NtGdiBitBlt(hdcBack, 0, 0, nWidth, nHeight, hdcFore, 0, 0, SRCPAINT, 0, 0); + /* Prepare blit */ + DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect); - /* 4. Copy the result to hdcDest */ - NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcBack, 0, 0, SRCCOPY, 0, 0); + if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) + DC_vUpdateFillBrush(DCDest); - /* 5. delete all temp objects */ - NtGdiDeleteObjectApp(hdcBack); - NtGdiDeleteObjectApp(hdcFore); - NtGdiDeleteObjectApp(hdcMask); - GreDeleteObject(hbmFore); - GreDeleteObject(hbmBack); + /* Determine surfaces to be used in the bitblt */ + BitmapDest = DCDest->dclevel.pSurface; + if (!BitmapDest) + goto cleanup; - return TRUE; + if (UsesSource) + { + { + BitmapSrc = DCSrc->dclevel.pSurface; + if (!BitmapSrc) + goto cleanup; + } + } + + /* Create the XLATEOBJ. */ + if (UsesSource) + { + EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); + XlateObj = &exlo.xlo; + } + + + /* Perform the bitblt operation */ + Status = IntEngBitBlt(&BitmapDest->SurfObj, + BitmapSrc ? &BitmapSrc->SurfObj : NULL, + psurfMask ? &psurfMask->SurfObj : NULL, + DCDest->rosdc.CombinedClip, + XlateObj, + &DestRect, + &SourcePoint, + &MaskPoint, + &DCDest->eboFill.BrushObject, + &DCDest->dclevel.pbrFill->ptOrigin, + ROP_TO_ROP4(dwRop)); + + if (UsesSource) + EXLATEOBJ_vCleanup(&exlo); +cleanup: + DC_vFinishBlit(DCDest, DCSrc); + if (UsesSource) + { + DC_UnlockDc(DCSrc); + } + DC_UnlockDc(DCDest); + if(psurfMask) SURFACE_UnlockSurface(psurfMask); + + return Status; } BOOL @@ -655,7 +547,9 @@ GreStretchBltMask( EXLATEOBJ exlo; XLATEOBJ *XlateObj = NULL; POINTL BrushOrigin; - BOOL UsesSource = ROP3_USES_SOURCE(ROP); + BOOL UsesSource = ROP_USES_SOURCE(ROP); + + FIXUP_ROP(ROP); if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc) { @@ -803,7 +697,7 @@ GreStretchBltMask( BitmapMask ? &MaskPoint : NULL, &DCDest->eboFill.BrushObject, &BrushOrigin, - ROP3_TO_ROP4(ROP)); + ROP_TO_ROP4(ROP)); if (UsesSource) { EXLATEOBJ_vCleanup(&exlo); @@ -877,6 +771,8 @@ IntPatBlt( ASSERT(pbrush); + FIXUP_ROP(dwRop); + if (pbrush->flAttrs & GDIBRUSH_IS_NULL) { return TRUE; @@ -934,7 +830,7 @@ IntPatBlt( NULL, &eboFill.BrushObject, &BrushOrigin, - ROP3_TO_ROP4(dwRop)); + ROP_TO_ROP4(dwRop)); DC_vFinishBlit(pdc, NULL); @@ -1007,7 +903,7 @@ NtGdiPatBlt( PDC_ATTR pdcattr; BOOL ret; - BOOL UsesSource = ROP3_USES_SOURCE(ROP); + BOOL UsesSource = ROP_USES_SOURCE(ROP); if (UsesSource) { /* in this case we call on GdiMaskBlt */ diff --git a/reactos/subsystems/win32/win32k/objects/dcobjs.c b/reactos/subsystems/win32/win32k/objects/dcobjs.c index 6975b60146f..7e6870be76f 100644 --- a/reactos/subsystems/win32/win32k/objects/dcobjs.c +++ b/reactos/subsystems/win32/win32k/objects/dcobjs.c @@ -179,6 +179,11 @@ GdiSelectPalette( DIRTY_BACKGROUND | DIRTY_TEXT; } + if(pdc->dctype == DCTYPE_MEMORY) + { + IntGdiRealizePalette(pdc); + } + PALETTE_ShareUnlockPalette(ppal); DC_UnlockDc(pdc); diff --git a/reactos/subsystems/win32/win32k/objects/dibobj.c b/reactos/subsystems/win32/win32k/objects/dibobj.c index 36c452f99f2..4a5ec9dd938 100644 --- a/reactos/subsystems/win32/win32k/objects/dibobj.c +++ b/reactos/subsystems/win32/win32k/objects/dibobj.c @@ -531,7 +531,7 @@ NtGdiSetDIBitsToDeviceInternal( NULL, NULL, NULL, - ROP3_TO_ROP4(SRCCOPY)); + ROP4_FROM_INDEX(R3_OPINDEX_SRCCOPY)); /* Cleanup EXLATEOBJ */ EXLATEOBJ_vCleanup(&exlo); diff --git a/reactos/subsystems/win32/win32k/objects/drawing.c b/reactos/subsystems/win32/win32k/objects/drawing.c index 86ab4c3a8c3..bac849ce9e9 100755 --- a/reactos/subsystems/win32/win32k/objects/drawing.c +++ b/reactos/subsystems/win32/win32k/objects/drawing.c @@ -1249,7 +1249,7 @@ IntFillRect( DC *dc, PBRUSH pbrush, BOOL Pen) { - DWORD ROP = PATCOPY; + DWORD ROP = ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY); RECTL DestRect; SURFACE *psurf; POINTL BrushOrigin; @@ -1291,7 +1291,7 @@ IntFillRect( DC *dc, BrushOrigin.y = pbrush->ptOrigin.y; if (pdcattr->jROP2 == R2_XORPEN) - ROP = PATINVERT; + ROP = ROP4_FROM_INDEX(R3_OPINDEX_PATINVERT); Ret = IntEngBitBlt( &psurf->SurfObj, @@ -1304,7 +1304,7 @@ IntFillRect( DC *dc, NULL, Pen ? &dc->eboLine.BrushObject : &dc->eboFill.BrushObject, &BrushOrigin, - ROP3_TO_ROP4(ROP)); + ROP); } return (int)Ret; diff --git a/reactos/subsystems/win32/win32k/objects/fillshap.c b/reactos/subsystems/win32/win32k/objects/fillshap.c index d5d6469ff6e..ae071d2cddf 100644 --- a/reactos/subsystems/win32/win32k/objects/fillshap.c +++ b/reactos/subsystems/win32/win32k/objects/fillshap.c @@ -604,7 +604,7 @@ IntRectangle(PDC dc, NULL, &dc->eboFill.BrushObject, &BrushOrigin, - ROP3_TO_ROP4(PATCOPY)); + ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY)); } } diff --git a/reactos/subsystems/win32/win32k/objects/freetype.c b/reactos/subsystems/win32/win32k/objects/freetype.c index d67405bc12c..4e941ee2047 100644 --- a/reactos/subsystems/win32/win32k/objects/freetype.c +++ b/reactos/subsystems/win32/win32k/objects/freetype.c @@ -3269,7 +3269,7 @@ GreExtTextOutW( &SourcePoint, &dc->eboBackground.BrushObject, &BrushOrigin, - ROP3_TO_ROP4(PATCOPY)); + ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY)); fuOptions &= ~ETO_OPAQUE; DC_vFinishBlit(dc, NULL); } @@ -3514,7 +3514,7 @@ GreExtTextOutW( &SourcePoint, &dc->eboBackground.BrushObject, &BrushOrigin, - ROP3_TO_ROP4(PATCOPY)); + ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY)); MouseSafetyOnDrawEnd(dc->ppdev); BackgroundLeft = DestRect.right; diff --git a/reactos/subsystems/win32/win32k/objects/palette.c b/reactos/subsystems/win32/win32k/objects/palette.c index c7656e03d1c..59b16430303 100644 --- a/reactos/subsystems/win32/win32k/objects/palette.c +++ b/reactos/subsystems/win32/win32k/objects/palette.c @@ -723,26 +723,18 @@ NtGdiGetNearestPaletteIndex( UINT FASTCALL -IntGdiRealizePalette(HDC hDC) +IntGdiRealizePalette(PDC pdc) { UINT i, realize = 0; - PDC pdc; PALETTE *ppalSurf, *ppalDC; - pdc = DC_LockDc(hDC); - if(!pdc) - { - EngSetLastError(ERROR_INVALID_HANDLE); - return 0; - } - ppalSurf = pdc->dclevel.pSurface->ppal; ppalDC = pdc->dclevel.ppal; if(!(ppalSurf->flFlags & PAL_INDEXED)) { // FIXME : set error? - goto cleanup; + return 0; } ASSERT(ppalDC->flFlags & PAL_INDEXED); @@ -755,8 +747,6 @@ IntGdiRealizePalette(HDC hDC) InterlockedExchange((LONG*)&ppalSurf->IndexedColors[i], *(LONG*)&ppalDC->IndexedColors[i]); } -cleanup: - DC_UnlockDc(pdc); return realize; } @@ -810,11 +800,9 @@ IntAnimatePalette(HPALETTE hPal, { if (dc->dclevel.hpal == hPal) { - DC_UnlockDc(dc); - IntGdiRealizePalette(hDC); + IntGdiRealizePalette(dc); } - else - DC_UnlockDc(dc); + DC_UnlockDc(dc); } UserReleaseDC(Wnd,hDC, FALSE); } diff --git a/reactos/subsystems/win32/win32k/objects/polyfill.c b/reactos/subsystems/win32/win32k/objects/polyfill.c index 1f6196a53af..e1b33802960 100644 --- a/reactos/subsystems/win32/win32k/objects/polyfill.c +++ b/reactos/subsystems/win32/win32k/objects/polyfill.c @@ -606,14 +606,14 @@ IntFillPolygon( BRUSHOBJ *BrushObj, CONST PPOINT Points, int Count, - RECTL DestRect, + RECTL DestRect, POINTL *BrushOrigin) { FILL_EDGE_LIST *list = 0; FILL_EDGE *ActiveHead = 0; FILL_EDGE *pLeft, *pRight; int ScanLine; - + //DPRINT("IntFillPolygon\n"); /* Create Edge List. */ @@ -657,11 +657,11 @@ IntFillPolygon( NULL, BrushObj, BrushOrigin, - ROP3_TO_ROP4(PATCOPY)); + ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY)); } pLeft = pRight->pNext; pRight = pLeft ? pLeft->pNext : NULL; - } + } } /* Free Edge List. If any are left. */