https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0c13ff2a4b3673cac8e70…
commit 0c13ff2a4b3673cac8e70ca45139febc4114f568
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Mon Mar 22 15:59:15 2021 +0100
Commit: Jérôme Gardou <jerome.gardou(a)reactos.org>
CommitDate: Mon Mar 22 22:40:33 2021 +0100
[WIN32K] Rewrite DIB1BPP -> DIB1BPP copy
Simpler is sometimes better.
Fixes some crashes & memory corruptions happening because of all those broken
loops.
---
win32ss/gdi/dib/dib1bpp.c | 230 ++++++----------------------------------------
win32ss/gdi/ntgdi/rect.h | 14 +++
2 files changed, 43 insertions(+), 201 deletions(-)
diff --git a/win32ss/gdi/dib/dib1bpp.c b/win32ss/gdi/dib/dib1bpp.c
index 034570e9cad..6a90282808d 100644
--- a/win32ss/gdi/dib/dib1bpp.c
+++ b/win32ss/gdi/dib/dib1bpp.c
@@ -65,207 +65,35 @@ DIB_1BPP_BitBltSrcCopy_From1BPP (
BOOLEAN bTopToBottom,
BOOLEAN bLeftToRight )
{
+ LONG Height = RECTL_lGetHeight(DestRect);
+ BOOLEAN XorBit = !!XLATEOBJ_iXlate(pxlo, 0);
- DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n",
bLeftToRight, bTopToBottom);
+ /* Make sure this is as expected */
+ ASSERT(DestRect->left >= 0);
+ ASSERT(DestRect->top >= 0);
+ ASSERT(Height > 0);
+ ASSERT(RECTL_lGetWidth(DestRect) > 0);
- // The 'window' in this sense is the x-position that corresponds
- // to the left-edge of the 8-pixel byte we are currently working with.
- // dwx is current x-window, dwx2 is the 'last' window we need to process.
- int dwx, dwx2; // Destination window x-position
- int swx; // Source window x-position
-
- // Left and right edges of source and dest rectangles
- int dl = DestRect->left; // dest left
- int dr = DestRect->right-1; // dest right (inclusive)
- int sl = SourcePoint->x; // source left
- int sr = sl + dr - dl; // source right (inclusive)
-
- // Which direction are we going?
- int xinc;
- int yinc;
- int ySrcDelta, yDstDelta;
-
- // The following 4 variables are used for the y-sweep
- int dy; // dest y
- int dy1; // dest y start
- int dy2; // dest y end
- int sy1; // src y start
-
- int shift;
- BYTE srcmask, dstmask, xormask;
-
- // 'd' and 's' are the dest & src buffer pointers that I use on my
x-sweep
- // 'pd' and 'ps' are the dest & src buffer pointers used on the
inner y-sweep
- PBYTE d, pd; // dest ptrs
- PBYTE s, ps; // src ptrs
-
- shift = (dl-sl)&7;
-
- xormask = 0xFF * (BYTE)XLATEOBJ_iXlate(pxlo, 0);
-
- if ( DestRect->top <= SourcePoint->y )
- {
- DPRINT("Moving up (scan top -> bottom).\n");
- // Moving up (scan top -> bottom)
- dy1 = DestRect->top;
- dy2 = DestRect->bottom - 1;
- if (bTopToBottom)
- {
- sy1 = SourcePoint->y + dy2 - dy1;
- ySrcDelta = -SourceSurf->lDelta;
- }
- else
- {
- sy1 = SourcePoint->y;
- ySrcDelta = SourceSurf->lDelta;
- }
- yinc = 1;
- yDstDelta = DestSurf->lDelta;
- }
- else
- {
- DPRINT("Moving down (scan bottom -> top).\n");
- // Moving down (scan bottom -> top)
- dy1 = DestRect->bottom - 1;
- dy2 = DestRect->top;
- if (bTopToBottom)
- {
- sy1 = SourcePoint->y;
- ySrcDelta = SourceSurf->lDelta;
- }
- else
- {
- sy1 = SourcePoint->y + dy1 - dy2;
- ySrcDelta = -SourceSurf->lDelta;
- }
- yinc = -1;
- yDstDelta = -DestSurf->lDelta;
- }
- if ( DestRect->left <= SourcePoint->x )
- {
- DPRINT("Moving left (scan left->right).\n");
- // Moving left (scan left->right)
- dwx = dl&~7;
- dwx2 = dr&~7;
- if (bLeftToRight)
- {
- swx = (sr - (dr & 7)) & ~7;
- xinc = -1;
- }
- else
- {
- swx = (sl-(dl&7))&~7;
- xinc = 1;
- }
- }
- else
- {
- DPRINT("Moving right (scan right->left).\n");
- // Moving right (scan right->left)
- dwx = dr & ~7;
- dwx2 = dl & ~7;
- if (bLeftToRight)
- {
- swx = (sl-(dl&7))&~7;
- xinc = 1;
- }
- else
- {
- swx = (sr - (dr & 7)) & ~7; // (sr - 7) & ~7; // We need the left edge
of this block. Thus the -7
- xinc = -1;
- }
- }
- d = &(((PBYTE)DestSurf->pvScan0)[dy1*DestSurf->lDelta + (dwx>>3)]);
- s = &(((PBYTE)SourceSurf->pvScan0)[sy1*SourceSurf->lDelta +
(swx>>3)]);
- for ( ;; )
- {
- dy = dy1;
- pd = d;
- ps = s;
- srcmask = 0xff;
- if ( dwx < dl )
- {
- int diff = dl-dwx;
- srcmask &= (1<<(8-diff))-1;
- }
- if ( dwx+7 > dr )
+ while (Height--)
{
- int diff = dr-dwx+1;
- srcmask &= ~((1<<(8-diff))-1);
- }
- dstmask = ~srcmask;
+ LONG yDst = DestRect->top + Height;
+ LONG ySrc = bTopToBottom ?
+ SourcePoint->y + RECTL_lGetHeight(DestRect) - Height
+ : SourcePoint->y + Height;
+ LONG Width = RECTL_lGetWidth(DestRect);
- // We unfortunately *must* have 5 different versions of the inner
- // loop to be certain we don't try to read from memory that is not
- // needed and may in fact be invalid.
- if ( !shift )
- {
- for ( ;; )
- {
- *pd = (BYTE)((*pd & dstmask) | ((ps[0]^xormask) & srcmask));
-
- // This *must* be here, because we could be going up *or* down...
- if ( dy == dy2 )
- break;
- dy += yinc;
- pd += yDstDelta;
- ps += ySrcDelta;
- }
- }
- else if ( !(0xFF00 & (srcmask<<shift) ) ) // Check if ps[0] not needed...
- {
- for ( ;; )
- {
- *pd = (BYTE)((*pd & dstmask)
- | ( ( (ps[1]^xormask) >> shift ) & srcmask ));
-
- // This *must* be here, because we could be going up *or* down...
- if ( dy == dy2 )
- break;
- dy += yinc;
- pd += yDstDelta;
- ps += ySrcDelta;
- }
- }
- else if ( !(0xFF & (srcmask<<shift) ) ) // Check if ps[1] not needed...
- {
- for ( ;; )
- {
- *pd = (*pd & dstmask)
- | ( ( (ps[0]^xormask) << ( 8 - shift ) ) & srcmask );
-
- // This *must* be here, because we could be going up *or* down...
- if ( dy == dy2 )
- break;
- dy += yinc;
- pd += yDstDelta;
- ps += ySrcDelta;
- }
- }
- else // Both ps[0] and ps[1] are needed
- {
- for ( ;; )
- {
- *pd = (*pd & dstmask)
- | ( ( ( ((ps[1]^xormask))|((ps[0]^xormask)<<8) ) >> shift ) &
srcmask );
-
- // This *must* be here, because we could be going up *or* down...
- if ( dy == dy2 )
- break;
- dy += yinc;
- pd += yDstDelta;
- ps += ySrcDelta;
- }
+ while (Width--)
+ {
+ LONG xDst = DestRect->left + Width;
+ LONG xSrc = bLeftToRight ?
+ SourcePoint->x + RECTL_lGetWidth(DestRect) - Width
+ : SourcePoint->x + Width;
+ ULONG PixelPut = DIB_1BPP_GetPixel(SourceSurf, xSrc, ySrc);
+ if (XorBit)
+ PixelPut = !PixelPut;
+ DIB_1BPP_PutPixel(DestSurf, xDst, yDst, PixelPut);
+ }
}
-
- // This *must* be here, because we could be going right *or* left...
- if ( dwx == dwx2 )
- break;
- d += xinc;
- s += xinc;
- dwx += xinc<<3;
- swx += xinc<<3;
- }
}
BOOLEAN
@@ -338,11 +166,11 @@ DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo)
break;
case BMF_8BPP:
- DPRINT("8BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
+ DPRINT("8BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
BltInfo->DestRect.left, BltInfo->DestRect.top,
BltInfo->DestRect.right, BltInfo->DestRect.bottom,
BltInfo->DestRect.right - BltInfo->DestRect.left);
-
+
if (bTopToBottom)
{
// This sets sy to the bottom line
@@ -371,7 +199,7 @@ DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo)
break;
case BMF_16BPP:
- DPRINT("16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
+ DPRINT("16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
BltInfo->DestRect.left, BltInfo->DestRect.top,
BltInfo->DestRect.right, BltInfo->DestRect.bottom,
BltInfo->DestRect.right - BltInfo->DestRect.left);
@@ -404,7 +232,7 @@ DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo)
case BMF_24BPP:
- DPRINT("24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
+ DPRINT("24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
BltInfo->DestRect.left, BltInfo->DestRect.top,
BltInfo->DestRect.right, BltInfo->DestRect.bottom,
BltInfo->DestRect.right - BltInfo->DestRect.left);
@@ -437,7 +265,7 @@ DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo)
case BMF_32BPP:
- DPRINT("32BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
+ DPRINT("32BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
BltInfo->DestRect.left, BltInfo->DestRect.top,
BltInfo->DestRect.right, BltInfo->DestRect.bottom,
BltInfo->DestRect.right - BltInfo->DestRect.left);
diff --git a/win32ss/gdi/ntgdi/rect.h b/win32ss/gdi/ntgdi/rect.h
index a268311ad27..fadae970f0a 100644
--- a/win32ss/gdi/ntgdi/rect.h
+++ b/win32ss/gdi/ntgdi/rect.h
@@ -81,6 +81,20 @@ RECTL_bClipRectBySize(
return !RECTL_bIsEmptyRect(prclDst);
}
+FORCEINLINE
+LONG
+RECTL_lGetHeight(_In_ const RECTL* prcl)
+{
+ return prcl->bottom - prcl->top;
+}
+
+FORCEINLINE
+LONG
+RECTL_lGetWidth(_In_ const RECTL* prcl)
+{
+ return prcl->right - prcl->left;
+}
+
BOOL
FASTCALL
RECTL_bUnionRect(