[WIN32K] Add StretchBlt function ability to flip images (#3458)

Modify dib\dibxxbpp.c programs to understand flipped images. See Videos at CORE-16642

1. Mirroring Horizontally works.
2. Mirroring Vertically works.
3. Rotation 180° works.

CORE-16642, CORE-14408, CORE-16634
This commit is contained in:
Doug Lyons 2021-02-20 17:28:36 -06:00 committed by GitHub
parent 89843bec56
commit ce7836c6d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 2307 additions and 168 deletions

View File

@ -6,6 +6,7 @@
* PROGRAMMERS: Jason Filby
* Thomas Bluemel
* Gregor Anich
* Doug Lyons
*/
#include <win32k.h>
@ -13,6 +14,9 @@
#define NDEBUG
#include <debug.h>
#define DEC_OR_INC(var, decTrue, amount) \
((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
VOID
DIB_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
{
@ -142,17 +146,66 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
LONG i, j, sx, sy, xColor, f1;
PBYTE SourceBits, DestBits, SourceLine, DestLine;
PBYTE SourceBits_4BPP, SourceLine_4BPP;
PWORD Source32, Dest32;
DWORD Index, StartLeft, EndRight;
BOOLEAN bTopToBottom, bLeftToRight;
DPRINT("DIB_16BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
/* Get back left to right flip here */
bLeftToRight = BltInfo->DestRect.left > BltInfo->DestRect.right;
/* Check for top to bottom flip needed. */
bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
DPRINT("BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
/* Make WellOrdered with top < bottom and left < right */
RECTL_vMakeWellOrdered(&BltInfo->DestRect);
DPRINT("BPP is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
switch(BltInfo->SourceSurface->iBitmapFormat)
{
case BMF_1BPP:
DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
sx = BltInfo->SourcePoint.x;
/* This sets sy to the top line */
sy = BltInfo->SourcePoint.y;
if (bTopToBottom)
{
/* This sets sy to the bottom line */
sy += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
if (bLeftToRight)
{
/* This sets the sx to the rightmost pixel */
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
StartLeft = BltInfo->DestRect.left + 1;
EndRight = BltInfo->DestRect.right + 1;
}
else
{
StartLeft = BltInfo->DestRect.left;
EndRight = BltInfo->DestRect.right;
}
for (i = StartLeft; i < EndRight; i++)
{
if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
{
@ -164,21 +217,37 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
}
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
case BMF_4BPP:
DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
/* This sets SourceBits_4BPP to the top line */
SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
(BltInfo->SourcePoint.x >> 1);
if (bTopToBottom)
{
/* This sets SourceBits_4BPP to the bottom line */
SourceBits_4BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
SourceLine_4BPP = SourceBits_4BPP;
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
/* This sets sx to the rightmost pixel */
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
f1 = sx & 1;
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
@ -188,49 +257,76 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
if(f1 == 1)
{
SourceLine_4BPP++;
DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
f1 = 0;
}
else
{
f1 = 1;
}
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
}
break;
case BMF_8BPP:
DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
/* This sets SourceLine to the top line */
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
BltInfo->SourcePoint.x;
DestLine = DestBits;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->SourceSurface->lDelta
* (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
}
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
*((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
BltInfo->XlateSourceToDest, *SourceBits);
SourceBits += 1;
DEC_OR_INC(SourceBits, bLeftToRight, 1);
DestBits += 2;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
case BMF_16BPP:
if (NULL == BltInfo->XlateSourceToDest || 0 !=
(BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
DPRINT("BMF_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);
if ((BltInfo->XlateSourceToDest == NULL ||
(BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
(!bTopToBottom && !bLeftToRight))
{
DPRINT("XO_TRIVIAL is TRUE.\n");
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
{
/* This sets SourceBits to the top line */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
(BltInfo->SourcePoint.y *
BltInfo->SourceSurface->lDelta) + 2 *
@ -248,6 +344,7 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
}
else
{
/* This sets SourceBits to the bottom line */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom -
BltInfo->DestRect.top - 1) *
@ -273,6 +370,11 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
}
else
{
DPRINT("XO_TRIVIAL is NOT TRUE.\n");
if (!bTopToBottom && !bLeftToRight)
/* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */
{
DPRINT("Flip is None.\n");
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
{
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
@ -330,14 +432,165 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
DestLine -= BltInfo->DestSurface->lDelta;
}
}
}
else
{
/* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
BOOL TopToBottomDone = FALSE;
if (bLeftToRight)
{
DPRINT("Flip is bLeftToRight.\n");
/* Allocate enough pixels for a row in WORD's */
WORD *store = ExAllocatePoolWithTag(NonPagedPool,
(BltInfo->DestRect.right - BltInfo->DestRect.left + 1) * 2, TAG_DIB);
if (store == NULL)
{
DPRINT1("Storage Allocation Failed.\n");
return FALSE;
}
WORD Index;
/* This sets SourceBits to the bottom line */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
* BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
/* Sets DestBits to the bottom line */
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+ (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta
+ 2 * BltInfo->DestRect.left + 2;
for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
{
/* Set Dest32 to right pixel */
Dest32 = (WORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
Source32 = (WORD *) SourceBits;
Index = 0;
/* Store pixels from left to right */
for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
{
store[Index] = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *(WORD *)Source32++);
Index++;
}
Index = 0;
/* Copy stored data to pixels from right to left */
for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
{
*(WORD *)Dest32-- = store[Index];
Index++;
}
SourceBits -= BltInfo->SourceSurface->lDelta;
DestBits -= BltInfo->DestSurface->lDelta;
}
ExFreePoolWithTag(store, TAG_DIB);
TopToBottomDone = TRUE;
}
if (bTopToBottom)
{
DPRINT("Flip is bTopToBottom.\n");
/* Allocate enough pixels for a column in WORD's */
WORD *store = ExAllocatePoolWithTag(NonPagedPool,
(BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1) * 2, TAG_DIB);
if (store == NULL)
{
DPRINT1("Storage Allocation Failed.\n");
return FALSE;
}
/* This set SourceBits to the top line */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ 2 * BltInfo->SourcePoint.x;
/* This sets DestBits to the top line */
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+ ((BltInfo->DestRect.top) * BltInfo->DestSurface->lDelta)
+ 2 * BltInfo->DestRect.left;
if ((BltInfo->SourceSurface->fjBitmap & BMF_TOPDOWN) == 0)
{
DestBits += BltInfo->DestSurface->lDelta;
}
if (bLeftToRight)
{
DPRINT("Adjusting DestBits for bLeftToRight.\n");
DestBits += 2;
}
/* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
* and have already completed the bLeftToRight. So we will lose our first flip output
* unless we work with its output which is at the destination site. So in this case
* our new Source becomes the previous outputs Destination. */
if (TopToBottomDone)
{
/* This sets SourceBits to the top line */
SourceBits = DestBits;
}
for (j = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= j ; j--)
{
/* Set Dest32 to bottom pixel */
Dest32 = (WORD *) DestBits + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
* BltInfo->DestSurface->lDelta / 2;
Source32 = (WORD *) SourceBits;
Index = 0;
/* Store pixels from top to bottom */
for (i = BltInfo->DestRect.top; i <= BltInfo->DestRect.bottom - 1; i++)
{
store[Index] = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32);
Source32 += BltInfo->SourceSurface->lDelta / 2;
Index++;
}
Index = 0;
/* Copy stored data to pixels from bottom to top */
for (i = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= i; i--)
{
*Dest32 = store[Index];
Dest32 -= BltInfo->DestSurface->lDelta / 2;
Index++;
}
SourceBits += 2;
DestBits += 2;
}
ExFreePoolWithTag(store, TAG_DIB);
}
}
}
break;
case BMF_24BPP:
DPRINT("BMF_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);
/* This sets SourceLine to the top line */
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
3 * BltInfo->SourcePoint.x;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
}
DestLine = DestBits;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@ -345,6 +598,11 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets the SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 3;
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
xColor = (*(SourceBits + 2) << 0x10) +
@ -353,19 +611,27 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
*((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
BltInfo->XlateSourceToDest, xColor);
SourceBits += 3;
DEC_OR_INC(SourceBits, bLeftToRight, 3);
DestBits += 2;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
case BMF_32BPP:
DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
4 * BltInfo->SourcePoint.x;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
}
DestLine = DestBits;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@ -373,23 +639,29 @@ DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
*((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
BltInfo->XlateSourceToDest,
*((PDWORD) SourceBits));
SourceBits += 4;
DEC_OR_INC(SourceBits, bLeftToRight, 4);
DestBits += 2;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
default:
DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n",
BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
DPRINT1("DIB_16BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n",
BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
return FALSE;
}
@ -402,6 +674,9 @@ DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
{
LONG DestY;
/* Make WellOrdered with top < bottom and left < right */
RECTL_vMakeWellOrdered(DestRect);
#if defined(_M_IX86) && !defined(_MSC_VER)
/* This is about 10% faster than the generic C code below */
ULONG delta = DestSurface->lDelta;

View File

@ -4,6 +4,7 @@
* FILE: win32ss/gdi/dib/dib1bpp.c
* PURPOSE: Device Independant Bitmap functions, 1bpp
* PROGRAMMERS: Jason Filby
* Doug Lyons
*/
#include <win32k.h>
@ -11,6 +12,9 @@
#define NDEBUG
#include <debug.h>
#define DEC_OR_INC(var, decTrue, amount) \
((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
VOID
DIB_1BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
{
@ -57,13 +61,18 @@ DIB_1BPP_BitBltSrcCopy_From1BPP (
SURFOBJ* SourceSurf,
XLATEOBJ* pxlo,
PRECTL DestRect,
POINTL *SourcePoint )
POINTL *SourcePoint,
BOOLEAN bTopToBottom,
BOOLEAN bLeftToRight )
{
DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
// 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 y-position
int swx; // Source window x-position
// Left and right edges of source and dest rectangles
int dl = DestRect->left; // dest left
@ -96,39 +105,75 @@ DIB_1BPP_BitBltSrcCopy_From1BPP (
if ( DestRect->top <= SourcePoint->y )
{
DPRINT("Moving up (scan top -> bottom).\n");
// Moving up (scan top -> bottom)
dy1 = DestRect->top;
dy2 = DestRect->bottom - 1;
sy1 = SourcePoint->y;
if (bTopToBottom)
{
sy1 = SourcePoint->y + dy2 - dy1;
ySrcDelta = -SourceSurf->lDelta;
}
else
{
sy1 = SourcePoint->y;
ySrcDelta = SourceSurf->lDelta;
}
yinc = 1;
ySrcDelta = SourceSurf->lDelta;
yDstDelta = DestSurf->lDelta;
}
else
{
DPRINT("Moving down (scan bottom -> top).\n");
// Moving down (scan bottom -> top)
dy1 = DestRect->bottom - 1;
dy2 = DestRect->top;
sy1 = SourcePoint->y + dy1 - dy2;
if (bTopToBottom)
{
sy1 = SourcePoint->y;
ySrcDelta = SourceSurf->lDelta;
}
else
{
sy1 = SourcePoint->y + dy1 - dy2;
ySrcDelta = -SourceSurf->lDelta;
}
yinc = -1;
ySrcDelta = -SourceSurf->lDelta;
yDstDelta = -DestSurf->lDelta;
}
if ( DestRect->left <= SourcePoint->x )
{
DPRINT("Moving left (scan left->right).\n");
// Moving left (scan left->right)
dwx = dl&~7;
swx = (sl-(dl&7))&~7;
dwx2 = dr&~7;
xinc = 1;
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;
swx = (sr - (dr & 7)) & ~7; // (sr - 7) & ~7; // We need the left edge of this block. Thus the -7
dwx2 = dl & ~7;
xinc = -1;
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)]);
@ -227,81 +272,199 @@ BOOLEAN
DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo)
{
ULONG Color;
LONG i, j, sx, sy = BltInfo->SourcePoint.y;
LONG i, j, sx, sy;
BOOLEAN bTopToBottom, bLeftToRight;
// This sets sy to the top line
sy = BltInfo->SourcePoint.y;
DPRINT("DIB_1BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
/* Get back left to right flip here */
bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
/* Check for top to bottom flip needed. */
bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
// Make WellOrdered with top < bottom and left < right
RECTL_vMakeWellOrdered(&BltInfo->DestRect);
DPRINT("BPP is '%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
switch ( BltInfo->SourceSurface->iBitmapFormat )
{
case BMF_1BPP:
DIB_1BPP_BitBltSrcCopy_From1BPP ( BltInfo->DestSurface, BltInfo->SourceSurface, BltInfo->XlateSourceToDest, &BltInfo->DestRect, &BltInfo->SourcePoint );
DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
DIB_1BPP_BitBltSrcCopy_From1BPP ( BltInfo->DestSurface, BltInfo->SourceSurface,
BltInfo->XlateSourceToDest, &BltInfo->DestRect, &BltInfo->SourcePoint,
bTopToBottom, bLeftToRight );
break;
case BMF_4BPP:
DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
if (bTopToBottom)
{
// This sets sy to the bottom line
sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
// This sets the sx to the rightmost pixel
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
case BMF_8BPP:
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
sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
// This sets sx to the rightmost pixel
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_8BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
case BMF_16BPP:
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);
if (bTopToBottom)
{
// This sets sy to the bottom line
sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
// This sets the sx to the rightmost pixel
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_16BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
case BMF_24BPP:
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);
if (bTopToBottom)
{
// This sets sy to the bottom line
sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
// This sets the sx to the rightmost pixel
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
case BMF_32BPP:
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);
if (bTopToBottom)
{
// This sets sy to the bottom line
sy += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
// This sets the sx to the rightmost pixel
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_32BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
@ -460,6 +623,9 @@ DIB_1BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
{
LONG DestY;
/* Make WellOrdered with top < bottom and left < right */
RECTL_vMakeWellOrdered(DestRect);
for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
{
DIB_1BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);

View File

@ -6,6 +6,7 @@
* PROGRAMMERS: Jason Filby
* Thomas Bluemel
* Gregor Anich
* Doug Lyons
*/
#include <win32k.h>
@ -13,6 +14,9 @@
#define NDEBUG
#include <debug.h>
#define DEC_OR_INC(var, decTrue, amount) \
((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
VOID
DIB_24BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
{
@ -53,6 +57,24 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
PBYTE SourceBits, DestBits, SourceLine, DestLine;
PBYTE SourceBits_4BPP, SourceLine_4BPP;
PWORD SourceBits_16BPP, SourceLine_16BPP;
BOOLEAN bTopToBottom, bLeftToRight;
DPRINT("DIB_24BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
/* Get back left to right flip here */
bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
/* Check for top to bottom flip needed. */
bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
DPRINT("BltInfo->SourcePoint.x is '%d' and BltInfo->SourcePoint.y is '%d'.\n",
BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
/* Make WellOrdered by making top < bottom and left < right */
RECTL_vMakeWellOrdered(&BltInfo->DestRect);
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left * 3;
@ -60,11 +82,26 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
{
case BMF_1BPP:
sx = BltInfo->SourcePoint.x;
/* This sets sy to the top line */
sy = BltInfo->SourcePoint.y;
if (bTopToBottom)
{
/* This sets sy to the bottom line */
sy += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
/* This sets sx to the rightmost pixel */
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
@ -73,20 +110,37 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
} else {
DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
}
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
case BMF_4BPP:
DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
/* This sets SourceBits_4BPP to the top line */
SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
if (bTopToBottom)
{
/* This sets SourceBits_4BPP to the bottom line */
SourceBits_4BPP += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
SourceLine_4BPP = SourceBits_4BPP;
DestLine = DestBits;
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
/* This sets sx to the rightmost pixel */
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
f1 = sx & 1;
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
@ -96,17 +150,33 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
*DestLine++ = xColor & 0xff;
*(PWORD)DestLine = (WORD)(xColor >> 8);
DestLine += 2;
if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
sx++;
if(f1 == 1) {
DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
f1 = 0;
}
else
{
f1 = 1;
}
DEC_OR_INC(sx, bLeftToRight, 1);
}
SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestBits += BltInfo->DestSurface->lDelta;
}
break;
case BMF_8BPP:
DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
/* This sets SourceLine to the top line */
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
}
DestLine = DestBits;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@ -114,47 +184,83 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets the SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits);
*DestBits = xColor & 0xff;
*(PWORD)(DestBits + 1) = (WORD)(xColor >> 8);
SourceBits += 1;
DEC_OR_INC(SourceBits, bLeftToRight, 1);
DestBits += 3;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
case BMF_16BPP:
DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
/* This sets SourceBits_16BPP to the top line */
SourceBits_16BPP = (PWORD)((PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x);
if (bTopToBottom)
{
/* This sets SourceBits_16BPP to the bottom line */
SourceBits_16BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
SourceLine_16BPP = SourceBits_16BPP;
DestLine = DestBits;
if (bLeftToRight)
{
/* This sets the SourceLine_16BPP to the rightmost pixel */
SourceLine_16BPP += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceLine_16BPP);
*DestLine++ = xColor & 0xff;
*(PWORD)DestLine = (WORD)(xColor >> 8);
DestLine += 2;
SourceLine_16BPP++;
DEC_OR_INC(SourceLine_16BPP, bLeftToRight, 1);
}
if (bTopToBottom)
{
SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP - BltInfo->SourceSurface->lDelta);
}
else
{
SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP + BltInfo->SourceSurface->lDelta);
}
SourceBits_16BPP = (PWORD)((PBYTE)SourceBits_16BPP + BltInfo->SourceSurface->lDelta);
DestBits += BltInfo->DestSurface->lDelta;
}
break;
case BMF_24BPP:
if (NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
DPRINT("24BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
/* Check for no flips here because we are about to use RtlMoveMemory and it can only do increasing src & dst */
if ((BltInfo->XlateSourceToDest == NULL ||
(BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
(!bTopToBottom && !bLeftToRight))
{
DPRINT("XO_TRIVIAL is TRUE.\n");
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
{
/* This sets SourceBits to the top line */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
@ -176,6 +282,11 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
}
}
else
{
DPRINT("XO_TRIVIAL is NOT TRUE.\n");
if (!bTopToBottom && !bLeftToRight)
/* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */
{
sx = BltInfo->SourcePoint.x;
sy = BltInfo->SourcePoint.y;
@ -191,11 +302,151 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
}
sy++;
}
}
else
{
/* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
BOOL TopToBottomDone = FALSE;
if (bLeftToRight)
{
DPRINT("Flip is bLeftToRight.\n");
DWORD Index;
/* Allocate enough pixels for a row in DWORD's */
DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
(BltInfo->DestRect.right - BltInfo->DestRect.left + 1) * 4, TAG_DIB);
if (store == NULL)
{
DPRINT1("Storage Allocation Failed.\n");
return FALSE;
}
sx = BltInfo->SourcePoint.x;
/* This sets sy to the top line */
sy = BltInfo->SourcePoint.y;
/* This sets sx to the rightmost pixel */
sx = BltInfo->SourcePoint.x + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
/* This sets sx to the rightmost pixel */
sx = BltInfo->SourcePoint.x + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
Index = 0;
// Read right to left and store
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
store[Index] = DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy);
Index++;
sx--;
}
Index = 0;
// Write left to right to pixel
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, store[Index]));
Index++;
}
sy++;
}
ExFreePoolWithTag(store, TAG_DIB);
TopToBottomDone = TRUE;
}
if (bTopToBottom)
{
DPRINT("Flip is bTopToBottom.\n");
DWORD Index;
/* Allocate enough pixels for a column in DWORD's */
DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
(BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1) * 4, TAG_DIB);
if (store == NULL)
{
DPRINT1("Storage Allocation Failed.\n");
return FALSE;
}
/* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
* and have already completed the bLeftToRight. So we will lose our first flip output
* unless we work with its output which is at the destination site. So in this case
* our new Source becomes the previous outputs Destination.
*/
if (TopToBottomDone)
{
sx = BltInfo->DestRect.left;
sy = BltInfo->DestRect.top;
/* This sets sy to the bottom line */
sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
}
else
{
sx = BltInfo->SourcePoint.x;
/* This sets sy to the top line */
sy = BltInfo->SourcePoint.y;
/* This sets sy to the bottom line */
sy = BltInfo->SourcePoint.y + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
/* This sets sy to the bottom line */
sy = BltInfo->SourcePoint.y + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
Index = 0;
/* Read bottom to top and store */
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
if (TopToBottomDone)
{
store[Index] = DIB_24BPP_GetPixel(BltInfo->DestSurface, sx, sy);
}
else
{
store[Index] = DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy);
}
Index++;
sy--;
}
Index = 0;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
DIB_24BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, store[Index]));
Index++;
}
sx++;
}
ExFreePoolWithTag(store, TAG_DIB);
}
}
}
break;
case BMF_32BPP:
DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
}
DestLine = DestBits;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@ -203,16 +454,21 @@ DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo)
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((PDWORD) SourceBits));
*DestBits = xColor & 0xff;
*(PWORD)(DestBits + 1) = (WORD)(xColor >> 8);
SourceBits += 4;
DEC_OR_INC(SourceBits, bLeftToRight, 4);
DestBits += 3;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
@ -255,7 +511,9 @@ DIB_24BPP_BitBlt(PBLTINFO BltInfo)
else
{
if (BltInfo->Brush)
{
Pattern = BltInfo->Brush->iSolidColor;
}
}
}
@ -301,6 +559,9 @@ DIB_24BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
{
LONG DestY;
/* Make WellOrdered by making top < bottom and left < right */
RECTL_vMakeWellOrdered(DestRect);
#if defined(_M_IX86) && !defined(_MSC_VER)
PBYTE xaddr = (PBYTE)DestSurface->pvScan0 + DestRect->top * DestSurface->lDelta + (DestRect->left << 1) + DestRect->left;
PBYTE addr;

View File

@ -6,6 +6,7 @@
* PROGRAMMERS: Jason Filby
* Thomas Bluemel
* Gregor Anich
* Doug Lyons
*/
#include <win32k.h>
@ -13,6 +14,9 @@
#define NDEBUG
#include <debug.h>
#define DEC_OR_INC(var, decTrue, amount) \
((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
VOID
DIB_32BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
{
@ -51,46 +55,137 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)
{
LONG i, j, sx, sy, xColor, f1;
PBYTE SourceBits, DestBits, SourceLine, DestLine;
PBYTE SourceBitsT, SourceBitsB, DestBitsT, DestBitsB;
PBYTE SourceBits_4BPP, SourceLine_4BPP;
PDWORD Source32, Dest32;
DWORD Index, DestWidth, DestHeight;
BOOLEAN bTopToBottom, bLeftToRight;
BOOLEAN blDeltaSrcNeg, blDeltaDestNeg;
BOOLEAN blDeltaAdjustDone = FALSE;
DPRINT("DIB_32BPP_BitBltSrcCopy: SourcePoint (%d, %d), SourceSurface cx/cy (%d/%d), "
"DestSurface cx/cy (%d/%d) DestRect: (%d,%d)-(%d,%d)\n",
BltInfo->SourcePoint.x, BltInfo->SourcePoint.y,
BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
DPRINT("BltInfo->DestSurface->lDelta is '%d' and BltInfo->SourceSurface->lDelta is '%d'.\n",
BltInfo->DestSurface->lDelta, BltInfo->SourceSurface->lDelta);
DPRINT("iBitmapFormat is %d and width,height is (%d,%d).\n", BltInfo->SourceSurface->iBitmapFormat,
BltInfo->DestRect.right - BltInfo->DestRect.left, BltInfo->DestRect.bottom - BltInfo->DestRect.top);
DPRINT("BltInfo->SourcePoint.x is '%d' and BltInfo->SourcePoint.y is '%d'.\n",
BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
/* Do not deal with negative numbers for these values */
if ((BltInfo->DestRect.left < 0) || (BltInfo->DestRect.top < 0) ||
(BltInfo->DestRect.right < 0) || (BltInfo->DestRect.bottom < 0))
return FALSE;
/* Detect negative lDelta's meaning Bottom-Up bitmaps */
blDeltaSrcNeg = BltInfo->SourceSurface->lDelta < 0;
blDeltaDestNeg = BltInfo->DestSurface->lDelta < 0;
/* Get back left to right flip here */
bLeftToRight = BltInfo->DestRect.left > BltInfo->DestRect.right;
/* Check for top to bottom flip needed. */
bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
DPRINT("bTopToBottom is '%d' and DestSurface->lDelta < 0 is '%d' and SourceSurface->lDelta < 0 is '%d'.\n",
bTopToBottom, BltInfo->DestSurface->lDelta < 0 ? 1 : 0, BltInfo->SourceSurface->lDelta < 0 ? 1 : 0);
/* Make WellOrdered with top < bottom and left < right */
RECTL_vMakeWellOrdered(&BltInfo->DestRect);
DestWidth = BltInfo->DestRect.right - BltInfo->DestRect.left;
DestHeight = BltInfo->DestRect.bottom - BltInfo->DestRect.top;
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+ (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta)
+ 4 * BltInfo->DestRect.left;
DPRINT("iBitmapFormat is %d and width,height is (%d,%d).\n", BltInfo->SourceSurface->iBitmapFormat,
DestWidth, DestHeight);
switch (BltInfo->SourceSurface->iBitmapFormat)
{
case BMF_1BPP:
DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
DestWidth);
if (bLeftToRight || bTopToBottom)
DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
sx = BltInfo->SourcePoint.x;
/* This sets sy to the top line */
sy = BltInfo->SourcePoint.y;
if (bTopToBottom)
{
/* This sets sy to the bottom line */
sy += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
if (bLeftToRight)
{
/* This sets the sx to the rightmost pixel */
sx += (DestWidth - 1);
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
if (DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
{
DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
} else {
}
else
{
DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
}
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
case BMF_4BPP:
DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
DestWidth);
if (bLeftToRight || bTopToBottom)
DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
/* This sets SourceBits_4BPP to the top line */
SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0
+ (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ (BltInfo->SourcePoint.x >> 1);
if (bTopToBottom)
{
/* This sets SourceBits_4BPP to the bottom line */
SourceBits_4BPP += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
SourceLine_4BPP = SourceBits_4BPP;
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
/* This sets sx to the rightmost pixel */
sx += (DestWidth - 1);
}
f1 = sx & 1;
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
@ -99,66 +194,120 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)
(*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
if (f1 == 1) {
SourceLine_4BPP++;
DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
f1 = 0;
} else {
f1 = 1;
}
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
}
break;
case BMF_8BPP:
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n",
DestWidth);
if (bLeftToRight || bTopToBottom)
DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
/* This sets SourceLine to the top line */
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
+ (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ BltInfo->SourcePoint.x;
DestLine = DestBits;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
}
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets the SourceBits to the rightmost pixel */
SourceBits += (DestWidth - 1);
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
xColor = *SourceBits;
*((PDWORD) DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
SourceBits += 1;
DEC_OR_INC(SourceBits, bLeftToRight, 1);
DestBits += 4;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
case BMF_16BPP:
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
DestWidth);
if (bLeftToRight || bTopToBottom)
DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
/* This sets SourceLine to the top line */
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
+ (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ 2 * BltInfo->SourcePoint.x;
DestLine = DestBits;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
}
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets the SourceBits to the rightmost pixel */
SourceBits += (DestWidth - 1) * 2;
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
xColor = *((PWORD) SourceBits);
*((PDWORD) DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
SourceBits += 2;
DEC_OR_INC(SourceBits, bLeftToRight, 2);
DestBits += 4;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
case BMF_24BPP:
DPRINT("24BPP Case Selected with DestRect Width of '%d'.\n",
DestWidth);
if (bLeftToRight || bTopToBottom)
DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
/* This sets SourceLine to the top line */
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
+ (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ 3 * BltInfo->SourcePoint.x;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->SourceSurface->lDelta * (DestHeight - 1);
}
DestLine = DestBits;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@ -166,46 +315,109 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets the SourceBits to the rightmost pixel */
SourceBits += (DestWidth - 1) * 3;
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
xColor = (*(SourceBits + 2) << 0x10) +
(*(SourceBits + 1) << 0x08) +
(*(SourceBits));
*((PDWORD)DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
SourceBits += 3;
DEC_OR_INC(SourceBits, bLeftToRight, 3);
DestBits += 4;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
case BMF_32BPP:
if (NULL == BltInfo->XlateSourceToDest ||
0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
DPRINT("32BPP Case Selected with SourcePoint (%d,%d) and DestRect Width/height of '%d/%d' DestRect: (%d,%d)-(%d,%d).\n",
BltInfo->SourcePoint.x, BltInfo->SourcePoint.y, DestWidth, DestHeight,
BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
if (bLeftToRight || bTopToBottom)
DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
/* This handles the negative lDelta's which represent Top-to-Bottom bitmaps */
if (((blDeltaSrcNeg || blDeltaDestNeg) && !(blDeltaSrcNeg && blDeltaDestNeg)) && bTopToBottom)
{
DPRINT("Adjusting for lDelta's here.\n");
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
{
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
/* SourceBits points to top-left pixel for lDelta < 0 and bottom-left for lDelta > 0 */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ 4 * BltInfo->SourcePoint.x;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
RtlMoveMemory(DestBits, SourceBits, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
SourceBits += BltInfo->SourceSurface->lDelta;
DestBits += BltInfo->DestSurface->lDelta;
}
}
else
{
/* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ ((BltInfo->SourcePoint.y
+ BltInfo->DestRect.bottom
- BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta)
+ DestHeight - 1) * BltInfo->SourceSurface->lDelta)
+ 4 * BltInfo->SourcePoint.x;
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 4 * BltInfo->DestRect.left;
/* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+ ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
+ 4 * BltInfo->DestRect.left;
for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
{
RtlMoveMemory(DestBits, SourceBits, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
SourceBits -= BltInfo->SourceSurface->lDelta;
DestBits -= BltInfo->DestSurface->lDelta;
}
}
blDeltaAdjustDone = TRUE;
}
/* This tests for whether we can use simplified/quicker code below.
* It works for increasing source and destination areas only and there is no overlap and no flip.
*/
if ((BltInfo->XlateSourceToDest == NULL ||
(BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
(!bTopToBottom && !bLeftToRight))
{
DPRINT("XO_TRIVIAL is TRUE.\n");
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
{
/* SourceBits points to top-left pixel for lDelta < 0 and bottom-left for lDelta > 0 */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ 4 * BltInfo->SourcePoint.x;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
SourceBits += BltInfo->SourceSurface->lDelta;
DestBits += BltInfo->DestSurface->lDelta;
}
}
else
{
/* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ ((BltInfo->SourcePoint.y
+ DestHeight - 1) * BltInfo->SourceSurface->lDelta)
+ 4 * BltInfo->SourcePoint.x;
/* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+ ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
+ 4 * BltInfo->DestRect.left;
for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
{
RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
SourceBits -= BltInfo->SourceSurface->lDelta;
DestBits -= BltInfo->DestSurface->lDelta;
}
@ -213,66 +425,272 @@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)
}
else
{
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
DPRINT("XO_TRIVIAL is NOT TRUE.\n");
if (!bTopToBottom && !bLeftToRight)
{
SourceBits = ((PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x);
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
{
if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
SourceBits = ((PBYTE)BltInfo->SourceSurface->pvScan0
+ (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ 4 * BltInfo->SourcePoint.x);
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
Dest32 = (DWORD *) DestBits;
Source32 = (DWORD *) SourceBits;
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
{
*Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
Dest32 = (DWORD *) DestBits;
Source32 = (DWORD *) SourceBits;
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
*Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
}
}
else
{
Dest32 = (DWORD *) DestBits + (DestWidth - 1);
Source32 = (DWORD *) SourceBits + (DestWidth - 1);
for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
{
*Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
}
}
SourceBits += BltInfo->SourceSurface->lDelta;
DestBits += BltInfo->DestSurface->lDelta;
}
else
}
else
{
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ ((BltInfo->SourcePoint.y
+ DestHeight - 1) * BltInfo->SourceSurface->lDelta)
+ 4 * BltInfo->SourcePoint.x;
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+ ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
+ 4 * BltInfo->DestRect.left;
for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
{
Dest32 = (DWORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
Source32 = (DWORD *) SourceBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
{
*Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
Dest32 = (DWORD *) DestBits;
Source32 = (DWORD *) SourceBits;
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
*Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
}
}
else
{
Dest32 = (DWORD *) DestBits + (DestWidth - 1);
Source32 = (DWORD *) SourceBits + (DestWidth - 1);
for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
{
*Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
}
}
SourceBits -= BltInfo->SourceSurface->lDelta;
DestBits -= BltInfo->DestSurface->lDelta;
}
SourceBits += BltInfo->SourceSurface->lDelta;
DestBits += BltInfo->DestSurface->lDelta;
}
}
else
{
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 4 * BltInfo->DestRect.left;
for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
/* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
BOOL TopToBottomDone = FALSE;
/* No need to flip a LeftToRight bitmap only one pixel wide */
if ((bLeftToRight) && (DestWidth > 1))
{
if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
DPRINT("Flip is bLeftToRight.\n");
/* Allocate enough pixels for a row in DWORD's */
DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
(DestWidth + 1) * 4, TAG_DIB);
if (store == NULL)
{
Dest32 = (DWORD *) DestBits;
Source32 = (DWORD *) SourceBits;
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
*Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
}
DPRINT1("Storage Allocation Failed.\n");
return FALSE;
}
/* This sets SourceBits to the bottom line */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ ((BltInfo->SourcePoint.y + DestHeight - 1)
* BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
/* This sets DestBits to the bottom line */
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+ (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta
+ 4 * BltInfo->DestRect.left;
for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
{
/* Set Dest32 to right pixel */
Dest32 = (DWORD *) DestBits + (DestWidth - 1);
Source32 = (DWORD *) SourceBits;
Index = 0;
/* Store pixels from left to right */
for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
{
store[Index] = *Source32++;
Index++;
}
Index = 0;
/* Copy stored dat to pixels from right to left */
for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
{
*Dest32-- = store[Index];
Index++;
}
SourceBits -= BltInfo->SourceSurface->lDelta;
DestBits -= BltInfo->DestSurface->lDelta;
}
ExFreePoolWithTag(store, TAG_DIB);
TopToBottomDone = TRUE;
}
/* Top to Botoom Handling if bitmap more than one pixel high */
if ((bTopToBottom) && (DestHeight > 1))
{
/* Note: It is very important that this code remain optimized for time used.
* Otherwise you will have random crashes in ReactOS that are undesirable.
* For an example of this just try executing the code here two times.
*/
DPRINT("Flip is bTopToBottom.\n");
/* Allocate enough pixels for a row in DWORD's */
DWORD *store = ExAllocatePoolWithTag(NonPagedPool,
(DestWidth + 1) * 4, TAG_DIB);
if (store == NULL)
{
DPRINT1("Storage Allocation Failed.\n");
return FALSE;
}
/* This set DestBitsT to the top line */
DestBitsT = (PBYTE)BltInfo->DestSurface->pvScan0
+ ((BltInfo->DestRect.top) * BltInfo->DestSurface->lDelta)
+ 4 * BltInfo->DestRect.left;
/* This sets DestBitsB to the bottom line */
DestBitsB = (PBYTE)BltInfo->DestSurface->pvScan0
+ (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta
+ 4 * BltInfo->DestRect.left;
/* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
* and have already completed the bLeftToRight. So we will lose our first flip output
* unless we work with its output which is at the destination site. So in this case
* our new Source becomes the previous outputs Destination.
* Also in we use the same logic when we have corrected for negative lDelta's above
* and already completed a flip from Source to Destination for the first step
*/
if (TopToBottomDone || blDeltaAdjustDone)
{
/* This sets SourceBitsB to the bottom line */
SourceBitsB = DestBitsB;
/* This sets SourceBitsT to the top line */
SourceBitsT = DestBitsT;
}
else
{
Dest32 = (DWORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
Source32 = (DWORD *) SourceBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
{
*Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
}
/* This sets SourceBitsB to the bottom line */
SourceBitsB = (PBYTE)BltInfo->SourceSurface->pvScan0
+ ((BltInfo->SourcePoint.y + DestHeight - 1)
* BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
/* This sets SourceBitsT to the top line */
SourceBitsT = (PBYTE)BltInfo->SourceSurface->pvScan0
+ (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
}
SourceBits -= BltInfo->SourceSurface->lDelta;
DestBits -= BltInfo->DestSurface->lDelta;
/* Overlaps and Vertical flips do not mix well. So we test for this and handle it
* by using two operations. First we just do a copy of the source to the destination.
* Then we do a flip in place at the destination location and we are done.
*/
if ((BltInfo->SourcePoint.y != BltInfo->DestRect.top) && // The values are not equal and
(abs(BltInfo->SourcePoint.y - BltInfo->DestRect.top) < (DestHeight + 2)) && // they are NOT seperated by > DestHeight
(BltInfo->SourceSurface->pvScan0 == BltInfo->DestSurface->pvScan0)) // and same surface (probably screen)
{
DPRINT("Flips Need Adjustments, so do move here.\n");
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
{
/* SourceBits points to top-left pixel for lDelta < 0 and bottom-left for lDelta > 0 */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
+ 4 * BltInfo->SourcePoint.x;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
SourceBits += BltInfo->SourceSurface->lDelta;
DestBits += BltInfo->DestSurface->lDelta;
}
}
else
{
/* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+ ((BltInfo->SourcePoint.y
+ DestHeight - 1) * BltInfo->SourceSurface->lDelta)
+ 4 * BltInfo->SourcePoint.x;
/* SourceBits points to bottom-left pixel for lDelta < 0 and top-left for lDelta > 0 */
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+ ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta)
+ 4 * BltInfo->DestRect.left;
for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
{
RtlMoveMemory(DestBits, SourceBits, 4 * DestWidth);
SourceBits -= BltInfo->SourceSurface->lDelta;
DestBits -= BltInfo->DestSurface->lDelta;
}
}
/* This sets SourceBitsB to the bottom line */
SourceBitsB = DestBitsB;
/* This sets SourceBitsT to the top line */
SourceBitsT = DestBitsT;
}
/* Vertical Flip code starts here */
for (j = 0; j < DestHeight / 2 ; j++)
{
/* Store bottom row of Source pixels */
RtlMoveMemory(store, SourceBitsB, 4 * DestWidth);
/* Copy top Source row to bottom Destination row overwriting it */
RtlMoveMemory(DestBitsB, SourceBitsT, 4 * DestWidth);
/* Copy stored bottom row of Source pixels to Destination top row of pixels */
RtlMoveMemory(DestBitsT, store, 4 * DestWidth);
/* Index top rows down and bottom rows up */
SourceBitsT += BltInfo->SourceSurface->lDelta;
SourceBitsB -= BltInfo->SourceSurface->lDelta;
DestBitsT += BltInfo->DestSurface->lDelta;
DestBitsB -= BltInfo->DestSurface->lDelta;
}
if (DestHeight % 2)
{
/* If we had an odd number of lines we handle the center one here */
DPRINT("Handling Top To Bottom with Odd Number of lines.\n");
RtlMoveMemory(DestBitsB, SourceBitsT, 4 * DestWidth);
}
ExFreePoolWithTag(store, TAG_DIB);
}
}
}
break;
default:
DPRINT1("DIB_32BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
DPRINT1("DIB_32BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
return FALSE;
}
@ -352,7 +770,7 @@ DIB_32BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
register NICEPIXEL32 DstPixel, SrcPixel;
UCHAR Alpha, SrcBpp;
DPRINT("DIB_32BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
DPRINT("DIB_32BPP_AlphaBlend: SourceRect: (%d,%d)-(%d,%d), DestRect: (%d,%d)-(%d,%d)\n",
SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);

View File

@ -32,6 +32,9 @@ DIB_32BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
{
ULONG DestY;
/* Make WellOrdered by making top < bottom and left < right */
RECTL_vMakeWellOrdered(DestRect);
for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
{
DIB_32BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color);

View File

@ -4,14 +4,17 @@
* FILE: win32ss/gdi/dib/dib4bpp.c
* PURPOSE: Device Independant Bitmap functions, 4bpp
* PROGRAMMERS: Jason Filby
* Doug Lyons
*/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
#define DEC_OR_INC(var, decTrue, amount) \
((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
VOID
DIB_4BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
{
@ -63,6 +66,24 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
PBYTE SourceBits_24BPP, SourceLine_24BPP;
PBYTE DestBits, DestLine, SourceBits_8BPP, SourceLine_8BPP;
PBYTE SourceBits, SourceLine;
BOOLEAN bTopToBottom, bLeftToRight;
DPRINT("DIB_4BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
/* Get back left to right flip here */
bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
/* Check for top to bottom flip needed. */
bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
/* Make WellOrdered with top < bottom and left < right */
RECTL_vMakeWellOrdered(&BltInfo->DestRect);
DPRINT("BPP is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 +
(BltInfo->DestRect.left >> 1) +
@ -71,12 +92,30 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
switch (BltInfo->SourceSurface->iBitmapFormat)
{
case BMF_1BPP:
DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
sx = BltInfo->SourcePoint.x;
/* This sets sy to the top line */
sy = BltInfo->SourcePoint.y;
if (bTopToBottom)
{
/* This sets sy to the bottom line */
sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
/* This sets the sx to the rightmost pixel */
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
@ -87,64 +126,129 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
{
DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
}
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
case BMF_4BPP:
DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
/* This sets sy to the top line */
sy = BltInfo->SourcePoint.y;
if (bTopToBottom)
{
/* This sets sy to the bottom line */
sy += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
* BltInfo->SourceSurface->lDelta;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
/* This sets the sx to the rightmost pixel */
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
if (NULL != BltInfo->XlateSourceToDest)
{
DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy)));
DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j,
XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy)));
}
else
{
DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j,
DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
}
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
case BMF_8BPP:
SourceBits_8BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
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);
SourceBits_8BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
if (bTopToBottom)
{
/* This sets SourceBits to the bottom line */
SourceBits_8BPP = (PBYTE)((LONG_PTR)SourceBits_8BPP +
((BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) *
BltInfo->SourceSurface->lDelta));
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
SourceLine_8BPP = SourceBits_8BPP;
DestLine = DestBits;
if (bLeftToRight)
{
/* This sets SourceBits_8BPP to the rightmost pixel */
SourceBits_8BPP += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
f2 = BltInfo->DestRect.left & 1;
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
*DestLine = (*DestLine & notmask[f2]) |
(BYTE)((XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceLine_8BPP)) << ((4 * (1 - f2))));
if(f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; }
SourceLine_8BPP++;
if (f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; }
DEC_OR_INC(SourceLine_8BPP, bLeftToRight, 1);
}
SourceBits_8BPP += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceBits_8BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestBits += BltInfo->DestSurface->lDelta;
}
break;
case BMF_16BPP:
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
DPRINT("BMF_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);
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
2 * BltInfo->SourcePoint.x;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) *
BltInfo->SourceSurface->lDelta;;
}
DestLine = DestBits;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
SourceBits = SourceLine;
if (bLeftToRight)
{
/* This sets SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 2;
}
DestBits = DestLine;
f2 = BltInfo->DestRect.left & 1;
@ -154,16 +258,32 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
*DestBits = (*DestBits & notmask[f2]) |
(BYTE)((XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor)) << ((4 * (1 - f2))));
if(f2 == 1) { DestBits++; f2 = 0; } else { f2 = 1; }
SourceBits += 2;
DEC_OR_INC(SourceBits, bLeftToRight, 2);
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
case BMF_24BPP:
SourceBits_24BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x * 3;
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);
SourceBits_24BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
BltInfo->SourcePoint.x * 3;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceBits_24BPP += BltInfo->SourceSurface->lDelta *
(BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
@ -171,6 +291,12 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
DestLine = DestBits;
f2 = BltInfo->DestRect.left & 1;
if (bLeftToRight)
{
/* This sets the SourceBits_24BPP to the rightmost pixel */
SourceLine_24BPP += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 3;
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
xColor = (*(SourceLine_24BPP + 2) << 0x10) +
@ -179,22 +305,40 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
*DestLine = (*DestLine & notmask[f2]) |
(BYTE)((XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor)) << ((4 * (1 - f2))));
if(f2 == 1) { DestLine++; f2 = 0; } else { f2 = 1; }
SourceLine_24BPP+=3;
DEC_OR_INC(SourceLine_24BPP, bLeftToRight, 3);
}
SourceBits_24BPP += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceBits_24BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestBits += BltInfo->DestSurface->lDelta;
}
break;
case BMF_32BPP:
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
4 * BltInfo->SourcePoint.x;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
}
DestLine = DestBits;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
}
f2 = BltInfo->DestRect.left & 1;
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
@ -203,16 +347,18 @@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo)
*DestBits = (*DestBits & notmask[f2]) |
(BYTE)((XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor)) << ((4 * (1 - f2))));
if(f2 == 1) { DestBits++; f2 = 0; } else { f2 = 1; }
SourceBits += 4;
DEC_OR_INC(SourceBits, bLeftToRight, 4);
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
default:
DbgPrint("DIB_4BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
DbgPrint("DIB_4BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n",
BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
return FALSE;
}
return(TRUE);
@ -290,7 +436,8 @@ DIB_4BPP_BitBlt(PBLTINFO BltInfo)
if (BltInfo->PatternSurface)
{
Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface,
(DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
}
DIB_4BPP_PutPixel(BltInfo->DestSurface, DestX, DestY, DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xF);
@ -339,7 +486,8 @@ DIB_4BPP_BitBlt(PBLTINFO BltInfo)
}
if (BltInfo->PatternSurface)
{
Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface,
(DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY);
}
DIB_4BPP_PutPixel(BltInfo->DestSurface, DestX, DestY, DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xF);
}
@ -361,6 +509,9 @@ DIB_4BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
{
LONG DestY;
/* Make WellOrdered by making top < bottom and left < right */
RECTL_vMakeWellOrdered(DestRect);
for (DestY = DestRect->top; DestY < DestRect->bottom; DestY++)
{
DIB_4BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);

View File

@ -6,6 +6,7 @@
* PROGRAMMERS: Jason Filby
* Thomas Bluemel
* Gregor Anich
* Doug Lyons
*/
#include <win32k.h>
@ -13,6 +14,9 @@
#define NDEBUG
#include <debug.h>
#define DEC_OR_INC(var, decTrue, amount) \
((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
VOID
DIB_8BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
{
@ -57,18 +61,56 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
LONG i, j, sx, sy, xColor, f1;
PBYTE SourceBits, DestBits, SourceLine, DestLine;
PBYTE SourceBits_4BPP, SourceLine_4BPP;
BOOLEAN bTopToBottom, bLeftToRight;
DPRINT("DIB_8BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
/* Get back left to right flip here */
bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
/* Check for top to bottom flip needed. */
bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
DPRINT("bTopToBottom is '%d' and bLeftToRight is '%d'.\n", bTopToBottom, bLeftToRight);
/* Make WellOrdered by making top < bottom and left < right */
RECTL_vMakeWellOrdered(&BltInfo->DestRect);
DPRINT("BPP is '%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
switch(BltInfo->SourceSurface->iBitmapFormat)
{
case BMF_1BPP:
DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
sx = BltInfo->SourcePoint.x;
/* This sets sy to the top line */
sy = BltInfo->SourcePoint.y;
if (bTopToBottom)
{
/* This sets sy to the bottom line */
sy += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
/* This sets the sx to the rightmost pixel */
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
{
if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
@ -79,19 +121,36 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
{
DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
}
sx++;
DEC_OR_INC(sx, bLeftToRight, 1);
}
sy++;
DEC_OR_INC(sy, bTopToBottom, 1);
}
break;
case BMF_4BPP:
DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
/* This sets SourceBits_4BPP to the top line */
SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
if (bTopToBottom)
{
/* This sets SourceBits_4BPP to the bottom line */
SourceBits_4BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
}
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
{
SourceLine_4BPP = SourceBits_4BPP;
sx = BltInfo->SourcePoint.x;
if (bLeftToRight)
{
/* This sets sx to the rightmost pixel */
sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
}
f1 = sx & 1;
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
@ -99,19 +158,35 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
(*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
sx++;
}
if(f1 == 1)
{
DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
f1 = 0;
}
else
{
f1 = 1;
}
SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(sx, bLeftToRight, 1);
}
DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
}
break;
case BMF_8BPP:
if (NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
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 ((BltInfo->XlateSourceToDest == NULL ||
(BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
(!bTopToBottom && !bLeftToRight))
{
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
{
DPRINT("BltInfo->DestRect.top < BltInfo->SourcePoint.y.\n");
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
@ -122,6 +197,7 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
}
else
{
DPRINT("BltInfo->DestRect.top >= BltInfo->SourcePoint.y.\n");
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
@ -134,8 +210,14 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
}
else
{
DPRINT("XO_TRIVIAL is NOT TRUE or we have flips.\n");
if (!bTopToBottom && !bLeftToRight)
/* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */
{
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
{
DPRINT("Dest.top < SourcePoint.y.\n");
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
DestLine = DestBits;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@ -152,6 +234,7 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
}
else
{
DPRINT("Dest.top >= SourcePoint.y.\n");
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
@ -167,56 +250,244 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
}
}
}
else
{
/* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
BOOL OneDone = FALSE;
if (bLeftToRight)
{
DPRINT("Flip is bLeftToRight.\n");
/* Allocate enough pixels for a row in BYTE's */
BYTE *store = ExAllocatePoolWithTag(NonPagedPool,
BltInfo->DestRect.right - BltInfo->DestRect.left + 1, TAG_DIB);
if (store == NULL)
{
DPRINT1("Storage Allocation Failed.\n");
return FALSE;
}
WORD Index;
/* This sets SourceLine to the top line */
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
(BltInfo->SourcePoint.y *
BltInfo->SourceSurface->lDelta) +
BltInfo->SourcePoint.x;
/* This set the DestLine to the top line */
DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
(BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) +
BltInfo->DestRect.left;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
SourceBits = SourceLine;
DestBits = DestLine;
/* This sets SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
Index = 0;
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
store[Index] = (BYTE)XLATEOBJ_iXlate(
BltInfo->XlateSourceToDest,
*SourceBits);
SourceBits--;
Index++;
}
Index = 0;
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
*DestBits = store[Index];
DestBits++;
Index++;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DestLine += BltInfo->DestSurface->lDelta;
}
ExFreePoolWithTag(store, TAG_DIB);
OneDone = TRUE;
}
if (bTopToBottom)
{
DPRINT("Flip is bTopToBottom.\n");
DWORD Index;
/* Allocate enough pixels for a column in BYTE's */
BYTE *store = ExAllocatePoolWithTag(NonPagedPool,
BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1, TAG_DIB);
if (store == NULL)
{
DPRINT1("Storage Allocation Failed.\n");
return FALSE;
}
/* The OneDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
* and have already completed the bLeftToRight. So we will lose our first flip output
* unless we work with its output which is at the destination site. So in this case
* our new Source becomes the previous outputs Destination. */
if (OneDone)
{
/* This sets SourceLine to the bottom line of our previous destination */
SourceLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
(BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left +
(BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->DestSurface->lDelta;
}
else
{
/* This sets SourceLine to the bottom line */
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
* BltInfo->SourceSurface->lDelta) +
BltInfo->SourcePoint.x;
}
/* This set the DestLine to the top line */
DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
(BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) +
BltInfo->DestRect.left;
/* Read columns */
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
DestBits = DestLine;
SourceBits = SourceLine;
Index = 0;
/* Read up the column and store the pixels */
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
store[Index] = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits);
/* Go up a line */
SourceBits -= BltInfo->SourceSurface->lDelta;
Index++;
}
Index = 0;
/* Get the stored pixel and copy then down the column */
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
*DestBits = store[Index];
/* Go down a line */
DestBits += BltInfo->SourceSurface->lDelta;
Index++;
}
/* Index to next column */
SourceLine += 1;
DestLine += 1;
}
ExFreePoolWithTag(store, TAG_DIB);
}
}
}
break;
case BMF_16BPP:
DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
DPRINT("BMF_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);
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;;
}
DestLine = DestBits;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
SourceBits = SourceLine;
if (bLeftToRight)
{
/* This sets SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 2;
}
DestBits = DestLine;
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
xColor = *((PWORD) SourceBits);
*DestBits = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
SourceBits += 2;
DEC_OR_INC(SourceBits, bLeftToRight, 2);
DestBits += 1;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
case BMF_24BPP:
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);
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
DestLine = DestBits;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
}
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
{
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets the SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 3;
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
xColor = (*(SourceBits + 2) << 0x10) +
(*(SourceBits + 1) << 0x08) +
(*(SourceBits));
*DestBits = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
SourceBits += 3;
DEC_OR_INC(SourceBits, bLeftToRight, 3);
DestBits += 1;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
case BMF_32BPP:
DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
BltInfo->DestRect.right - BltInfo->DestRect.left);
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
if (bTopToBottom)
{
/* This sets SourceLine to the bottom line */
SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
}
DestLine = DestBits;
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
@ -224,15 +495,21 @@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
SourceBits = SourceLine;
DestBits = DestLine;
if (bLeftToRight)
{
/* This sets SourceBits to the rightmost pixel */
SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
}
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
{
xColor = *((PDWORD) SourceBits);
*DestBits = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
SourceBits += 4;
DEC_OR_INC(SourceBits, bLeftToRight, 4);
DestBits += 1;
}
SourceLine += BltInfo->SourceSurface->lDelta;
DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
DestLine += BltInfo->DestSurface->lDelta;
}
break;
@ -250,6 +527,10 @@ BOOLEAN
DIB_8BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
{
LONG DestY;
/* Make WellOrdered by making top < bottom and left < right */
RECTL_vMakeWellOrdered(DestRect);
for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
{
DIB_8BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);

View File

@ -6,6 +6,7 @@
* PROGRAMMERS: Magnus Olsen
* Evgeniy Boltik
* Gregor Schneider
* Doug Lyons
*/
#include <win32k.h>
@ -47,25 +48,46 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
BOOL UsesSource = ROP4_USES_SOURCE(ROP);
BOOL UsesPattern = ROP4_USES_PATTERN(ROP);
BOOLEAN bTopToBottom, bLeftToRight;
ASSERT(IS_VALID_ROP4(ROP));
fnDest_GetPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_GetPixel;
fnDest_PutPixel = DibFunctionsForBitmapFormat[DestSurf->iBitmapFormat].DIB_PutPixel;
DPRINT("Dest BPP: %u, dstRect: (%d,%d)-(%d,%d)\n",
DPRINT("Dest BPP: %u, DestRect: (%d,%d)-(%d,%d)\n",
BitsPerFormat(DestSurf->iBitmapFormat), DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
DstHeight = DestRect->bottom - DestRect->top;
DstWidth = DestRect->right - DestRect->left;
SrcHeight = SourceRect->bottom - SourceRect->top;
SrcWidth = SourceRect->right - SourceRect->left;
/* Here we do the tests and set our conditions */
if (((SrcWidth < 0) && (DstWidth < 0)) || ((SrcWidth >= 0) && (DstWidth >= 0)))
bLeftToRight = FALSE;
else
bLeftToRight = TRUE;
if (((SrcHeight < 0) && (DstHeight < 0)) || ((SrcHeight >= 0) && (DstHeight >= 0)))
bTopToBottom = FALSE;
else
bTopToBottom = TRUE;
/* Make Well Ordered to start */
RECTL_vMakeWellOrdered(DestRect);
if (UsesSource)
{
SourceCy = SourceSurf->sizlBitmap.cy;
fnSource_GetPixel = DibFunctionsForBitmapFormat[SourceSurf->iBitmapFormat].DIB_GetPixel;
DPRINT("Source BPP: %u, srcRect: (%d,%d)-(%d,%d)\n",
DPRINT("Source BPP: %u, SourceRect: (%d,%d)-(%d,%d)\n",
BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom);
}
if (MaskSurf)
{
DPRINT("MaskSurf is not NULL.\n");
fnMask_GetPixel = DibFunctionsForBitmapFormat[MaskSurf->iBitmapFormat].DIB_GetPixel;
MaskCy = MaskSurf->sizlBitmap.cy;
}
@ -87,9 +109,11 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
default:
xxBPPMask = 0xFFFFFFFF;
}
DPRINT("xxBPPMask is 0x%x.\n", xxBPPMask);
if (UsesPattern)
{
DPRINT("UsesPattern is not NULL.\n");
if (PatternSurface)
{
PatternY = (DestRect->top - BrushOrigin->y) % PatternSurface->sizlBitmap.cy;
@ -106,6 +130,12 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
}
}
if (PatternSurface)
{
DPRINT("PatternSurface is not NULL.\n");
}
DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
for (DesY = DestRect->top; DesY < DestRect->bottom; DesY++)
{
@ -118,7 +148,16 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
}
}
if (UsesSource)
sy = SourceRect->top+(DesY - DestRect->top) * SrcHeight / DstHeight;
{
if (bTopToBottom)
{
sy = SourceRect->bottom-(DesY - DestRect->top) * SrcHeight / DstHeight; // flips about the x-axis
}
else
{
sy = SourceRect->top+(DesY - DestRect->top) * SrcHeight / DstHeight;
}
}
for (DesX = DestRect->left; DesX < DestRect->right; DesX++)
{
@ -126,7 +165,14 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
if (fnMask_GetPixel)
{
sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth;
if (bLeftToRight)
{
sx = SourceRect->right - (DesX - DestRect->left) * SrcWidth / DstWidth; // flips about the y-axis
}
else
{
sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth;
}
if (sx < 0 || sy < 0 ||
MaskSurf->sizlBitmap.cx < sx || MaskCy < sy ||
fnMask_GetPixel(MaskSurf, sx, sy) != 0)
@ -137,7 +183,14 @@ BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFOBJ *Ma
if (UsesSource && CanDraw)
{
sx = SourceRect->left+(DesX - DestRect->left) * SrcWidth / DstWidth;
if (bLeftToRight)
{
sx = SourceRect->right-(DesX - DestRect->left) * SrcWidth / DstWidth; // flips about the y-axis
}
else
{
sx = SourceRect->left + (DesX - DestRect->left) * SrcWidth / DstWidth;
}
if (sx >= 0 && sy >= 0 &&
SourceSurf->sizlBitmap.cx > sx && SourceCy > sy)
{

View File

@ -3,8 +3,13 @@
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: GDI BitBlt Functions
* FILE: win32ss/gdi/eng/bitblt.c
* PROGRAMER: Jason Filby
* PROGRAMERS: Jason Filby
* Timo Kreuzer
* Doug Lyons
*
* WARNING: Modify this file with extreme caution. It is very sensitive to timing changes.
* Adding code can cause the system to show a Fatal Exception Error and fail to boot!.
* This is especially true in CallDibBitBlt, IntEngBitBlt and EngBitBlt (even DPRINT's).
*/
#include <win32k.h>
@ -255,6 +260,12 @@ CallDibBitBlt(SURFOBJ* OutputObj,
psoPattern = NULL;
}
/* Make WellOrdered with top < bottom and left < right */
RECTL_vMakeWellOrdered(&BltInfo.DestRect);
DPRINT("CallDibBitBlt: BltInfo.DestRect: (%d,%d)-(%d,%d)\n",
BltInfo.DestRect.left, BltInfo.DestRect.top, BltInfo.DestRect.right, BltInfo.DestRect.bottom);
Result = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBlt(&BltInfo);
return Result;
@ -344,10 +355,30 @@ EngBitBlt(
ULONG Direction;
BOOL UsesSource, UsesMask;
POINTL AdjustedBrushOrigin;
LONG lTmp;
BOOLEAN bTopToBottom, bLeftToRight;
UsesSource = ROP4_USES_SOURCE(rop4);
UsesMask = ROP4_USES_MASK(rop4);
if (prclTrg->left > prclTrg->right)
{
bLeftToRight = TRUE;
}
else
{
bLeftToRight = FALSE;
}
if (prclTrg->top > prclTrg->bottom)
{
bTopToBottom = TRUE;
}
else
{
bTopToBottom = FALSE;
}
if (rop4 == ROP4_NOOP)
{
/* Copy destination onto itself: nop */
@ -359,6 +390,12 @@ EngBitBlt(
OutputRect = *prclTrg;
RECTL_vMakeWellOrdered(&OutputRect);
DPRINT("EngBitBlt: prclTrg: (%d,%d)-(%d,%d)\n",
prclTrg->left, prclTrg->top, prclTrg->right, prclTrg->bottom);
DPRINT("EngBitBlt: OutputRect: (%d,%d)-(%d,%d)\n",
OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
if (UsesSource)
{
if (!psoSrc || !pptlSrc)
@ -498,6 +535,21 @@ EngBitBlt(
switch (clippingType)
{
case DC_TRIVIAL:
/* Fix up OutputRect here */
if (bLeftToRight)
{
lTmp = OutputRect.left;
OutputRect.left = OutputRect.right;
OutputRect.right = lTmp;
}
if (bTopToBottom)
{
lTmp = OutputRect.top;
OutputRect.top = OutputRect.bottom;
OutputRect.bottom = lTmp;
}
Ret = (*BltRectFunc)(OutputObj,
InputObj,
psoMask,
@ -622,6 +674,8 @@ IntEngBitBlt(
RECTL rclSrcClipped;
POINTL ptlBrush;
PFN_DrvBitBlt pfnBitBlt;
LONG lTmp;
BOOLEAN bTopToBottom, bLeftToRight;
/* Sanity checks */
ASSERT(IS_VALID_ROP4(Rop4));
@ -629,6 +683,9 @@ IntEngBitBlt(
psurfTrg = CONTAINING_RECORD(psoTrg, SURFACE, SurfObj);
bLeftToRight = prclTrg->left > prclTrg->right;
bTopToBottom = prclTrg->top > prclTrg->bottom;
/* Get the target rect and make it well ordered */
rclClipped = *prclTrg;
RECTL_vMakeWellOrdered(&rclClipped);
@ -721,6 +778,24 @@ IntEngBitBlt(
pfnBitBlt = EngBitBlt;
}
/* rclClipped needs to be modified in accordance with flips here */
if (bLeftToRight)
{
lTmp = rclClipped.left;
rclClipped.left = rclClipped.right;
rclClipped.right = lTmp;
}
if (bTopToBottom)
{
lTmp = rclClipped.top;
rclClipped.top = rclClipped.bottom;
rclClipped.bottom = lTmp;
}
DPRINT("About to call EngBitBlt: rclClipped: (%d,%d)-(%d,%d)\n",
rclClipped.left, rclClipped.top, rclClipped.right, rclClipped.bottom);
bResult = pfnBitBlt(psoTrg,
psoSrc,
psoMask,

View File

@ -3,7 +3,8 @@
* PROJECT: ReactOS kernel
* PURPOSE: GDI EngCopyBits Function
* FILE: win32ss/gdi/eng/copybits.c
* PROGRAMER: Jason Filby
* PROGRAMERS: Jason Filby
* Doug Lyons
*/
#include <win32k.h>
@ -32,6 +33,30 @@ EngCopyBits(
SURFACE *psurfSource;
RECTL rclDest = *DestRect;
POINTL ptlSrc = *SourcePoint;
LONG lTmp;
BOOL bTopToBottom;
DPRINT("Entering EngCopyBits with SourcePoint (%d,%d) and DestRect (%d,%d)-(%d,%d).\n",
SourcePoint->x, SourcePoint->y, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
DPRINT("psoSource cx/cy is %d/%d and psoDest cx/cy is %d/%d.\n",
psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy, psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy);
/* Retrieve Top Down/flip here and then make Well-Ordered again */
if (DestRect->top > DestRect->bottom)
{
bTopToBottom = TRUE;
lTmp = DestRect->top;
DestRect->top = DestRect->bottom;
DestRect->bottom = lTmp;
rclDest = *DestRect;
}
else
{
bTopToBottom = FALSE;
}
DPRINT("bTopToBottom is '%d'.\n", bTopToBottom);
ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL);
@ -113,24 +138,42 @@ EngCopyBits(
switch (clippingType)
{
case DC_TRIVIAL:
DPRINT("DC_TRIVIAL.\n");
BltInfo.DestRect = *DestRect;
BltInfo.SourcePoint = *SourcePoint;
/* Now we set the Dest Rect top and bottom based on Top Down/flip */
if (bTopToBottom)
{
lTmp = BltInfo.DestRect.top;
BltInfo.DestRect.top = BltInfo.DestRect.bottom;
BltInfo.DestRect.bottom = lTmp;
}
ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
break;
case DC_RECT:
DPRINT("DC_RECT.\n");
// Clip the blt to the clip rectangle
RECTL_bIntersectRect(&BltInfo.DestRect, DestRect, &Clip->rclBounds);
BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top;
/* Now we set the Dest Rect top and bottom based on Top Down/flip */
if (bTopToBottom)
{
lTmp = BltInfo.DestRect.top;
BltInfo.DestRect.top = BltInfo.DestRect.bottom;
BltInfo.DestRect.bottom = lTmp;
}
ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
break;
case DC_COMPLEX:
DPRINT("DC_COMPLEX.\n");
CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_ANY, 0);
do
@ -149,6 +192,14 @@ EngCopyBits(
BltInfo.SourcePoint.x = SourcePoint->x + BltInfo.DestRect.left - DestRect->left;
BltInfo.SourcePoint.y = SourcePoint->y + BltInfo.DestRect.top - DestRect->top;
/* Now we set the Dest Rect top and bottom based on Top Down/flip */
if (bTopToBottom)
{
lTmp = BltInfo.DestRect.top;
BltInfo.DestRect.top = BltInfo.DestRect.bottom;
BltInfo.DestRect.bottom = lTmp;
}
if (!DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo))
{
ret = FALSE;

View File

@ -3,7 +3,8 @@
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: GDI stretch blt functions
* FILE: win32ss/gdi/eng/stretchblt.c
* PROGRAMER: Jason Filby
* PROGRAMERS: Jason Filby
* Doug Lyons
*/
#include <win32k.h>
@ -11,6 +12,21 @@
#define NDEBUG
#include <debug.h>
/***************************************************************************************************************************
We want to receive and send the flip state along to existing functions without changing their parameter lists.
So a way that we can do this is to use the DestRect to carry this information along with it.
Since there are four values, we can use their relative positions (coordinates) to indicate the four flip conditions.
if delta-x == 0 then there can be no Left-to-Right flip. If delta-y == 0 there can be no Top-to-Bottom flip.
So we can set the four flip conditions based on BOOLEAN flags as follows:
We will use internal bits bTopToBottom and bLeftToRight as follows:
!bTopToBottom && !bLeftToRight means no flips therefore left < right and top < bottom (normal well-formed rectangle)
bTopToBottom means there is a Top-To-Bottom flip therefore left < right and top > bottom
bLeftToRight means there is a Left-To-Right flip therefore left > right and top < bottom
bLeftToRight && bTopToBottom means both flips therefore left > right and top > bottom
****************************************************************************************************************************/
typedef BOOLEAN (APIENTRY *PSTRETCHRECTFUNC)(SURFOBJ* OutputObj,
SURFOBJ* InputObj,
SURFOBJ* Mask,
@ -38,6 +54,11 @@ CallDibStretchBlt(SURFOBJ* psoDest,
SURFOBJ* psoPattern;
BOOL bResult;
DPRINT("Entering CallDibStretchBlt: psoSource cx/cy (%d/%d), psoDest cx/cy (%d/%d) OutputRect: (%d,%d)-(%d,%d)\n",
psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy,
psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy,
OutputRect->left, OutputRect->top, OutputRect->right, OutputRect->bottom);
if (BrushOrigin == NULL)
{
RealBrushOrigin.x = RealBrushOrigin.y = 0;
@ -115,6 +136,35 @@ EngStretchBltROP(
LONG SrcHeight;
LONG SrcWidth;
LONG cxSrc, cySrc, cxDest, cyDest;
BOOLEAN bLeftToRight, bTopToBottom;
LONG lTmp;
DPRINT("Entering EngStretchBltROP: prclSrc: (%d/%d)-(%d/%d) prclDest: (%d,%d)-(%d,%d)\n",
prclSrc->left, prclSrc->top, prclSrc->right, prclSrc->bottom,
prclDest->left, prclDest->top, prclDest->right, prclDest->bottom);
cxSrc = prclSrc->right - prclSrc->left;
cySrc = prclSrc->bottom - prclSrc->top;
cxDest = prclDest->right - prclDest->left;
cyDest = prclDest->bottom - prclDest->top;
/* Here we do the tests and set our conditions */
if (((cxSrc < 0) && (cxDest < 0)) || ((cxSrc >= 0) && (cxDest >= 0)))
bLeftToRight = FALSE;
else
bLeftToRight = TRUE;
if (((cySrc < 0) && (cyDest < 0)) || ((cySrc >= 0) && (cyDest >= 0)))
bTopToBottom = FALSE;
else
bTopToBottom = TRUE;
/* Make Well Ordered to start */
OutputRect = *prclDest;
RECTL_vMakeWellOrdered(&OutputRect);
*prclDest = OutputRect;
if (Rop4 == ROP4_NOOP)
{
/* Copy destination onto itself: nop */
@ -237,9 +287,29 @@ EngStretchBltROP(
DstWidth = OutputRect.right - OutputRect.left;
SrcHeight = InputRect.bottom - InputRect.top;
SrcWidth = InputRect.right - InputRect.left;
DPRINT("bLeftToRight is '%d' and bTopToBottom is '%d'.\n", bLeftToRight, bTopToBottom);
switch (clippingType)
{
case DC_TRIVIAL:
if (bLeftToRight)
{
lTmp = OutputRect.left;
OutputRect.left = OutputRect.right;
OutputRect.right = lTmp;
}
if (bTopToBottom)
{
lTmp = OutputRect.top;
OutputRect.top = OutputRect.bottom;
OutputRect.bottom = lTmp;
}
DPRINT("About to call CallDibStretchBlt: OutputRect: (%d,%d)-(%d,%d)\n",
OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
ColorTranslation, &OutputRect, &InputRect, MaskOrigin,
pbo, &AdjustedBrushOrigin, Rop4);
@ -256,6 +326,24 @@ EngStretchBltROP(
InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth;
InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth;
if (bLeftToRight)
{
lTmp = CombinedRect.left;
CombinedRect.left = CombinedRect.right;
CombinedRect.right = lTmp;
}
if (bTopToBottom)
{
lTmp = CombinedRect.top;
CombinedRect.top = CombinedRect.bottom;
CombinedRect.bottom = lTmp;
}
DPRINT("About to call CallDibStretchBlt: CombinedRect: (%d,%d)-(%d,%d)\n",
CombinedRect.left, CombinedRect.top, CombinedRect.right, CombinedRect.bottom);
Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
ColorTranslation,
&CombinedRect,
@ -301,6 +389,24 @@ EngStretchBltROP(
InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth;
InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth;
if (bLeftToRight)
{
lTmp = CombinedRect.left;
CombinedRect.left = CombinedRect.right;
CombinedRect.right = lTmp;
}
if (bTopToBottom)
{
lTmp = CombinedRect.top;
CombinedRect.top = CombinedRect.bottom;
CombinedRect.bottom = lTmp;
}
DPRINT("About to call CallDibStretchBlt: CombinedRect: (%d,%d)-(%d,%d)\n",
CombinedRect.left, CombinedRect.top, CombinedRect.right, CombinedRect.bottom);
Ret = (*BltRectFunc)(psoOutput, psoInput, Mask,
ColorTranslation,
&CombinedRect,
@ -382,6 +488,18 @@ IntEngStretchBlt(SURFOBJ *psoDest,
RECTL OutputRect;
BOOL UsesSource = ROP4_USES_SOURCE(Rop4);
LONG InputClWidth, InputClHeight, InputWidth, InputHeight;
LONG lTmp, cxSrc, cySrc, cxDest, cyDest;
BOOLEAN bTopToBottom, bLeftToRight;
INT Case0000, Case0001, Case0010, Case0011;
INT Case0100, Case0101, Case0110, Case0111;
INT Case1000, Case1001, Case1010, Case1011;
INT Case1100, Case1101, Case1110;
DPRINT("Source cx/cy (%d/%d) and Destination cx/cy (%d/%d).\n",
psoSource->sizlBitmap.cx, psoSource->sizlBitmap.cy, psoDest->sizlBitmap.cx, psoDest->sizlBitmap.cy);
DPRINT("Source lDelta is '%d' and Destination lDelta is '%d'.\n",
psoSource->lDelta, psoDest->lDelta);
ASSERT(psoDest);
//ASSERT(psoSource); // FIXME!
@ -390,17 +508,113 @@ IntEngStretchBlt(SURFOBJ *psoDest,
//ASSERT(!RECTL_bIsEmptyRect(SourceRect)); // FIXME!
/* If no clip object is given, use trivial one */
if (!ClipRegion) ClipRegion = (CLIPOBJ *)&gxcoTrivial;
if (!ClipRegion)
{
DPRINT("Using trivial clip region.\n");
ClipRegion = (CLIPOBJ *)&gxcoTrivial;
}
else
{
DPRINT("ClipRegion->rclBounds is (%d,%d)-(%d,%d).\n",
ClipRegion->rclBounds.left, ClipRegion->rclBounds.top,
ClipRegion->rclBounds.right, ClipRegion->rclBounds.bottom);
}
psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
/* Sanity check */
ASSERT(IS_VALID_ROP4(Rop4));
cxSrc = SourceRect->right - SourceRect->left;
cySrc = SourceRect->bottom - SourceRect->top;
cxDest = DestRect->right - DestRect->left;
cyDest = DestRect->bottom - DestRect->top;
Case1110 = ((cxDest > 0) && (cyDest > 0) && (cxSrc > 0) && (cySrc < 0));
Case1101 = ((cxDest > 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc > 0));
Case1100 = ((cxDest > 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc < 0));
Case1011 = ((cxDest > 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc > 0));
Case1010 = ((cxDest > 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc < 0));
Case1001 = ((cxDest > 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc > 0));
Case1000 = ((cxDest > 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc < 0));
Case0111 = ((cxDest < 0) && (cyDest > 0) && (cxSrc > 0) && (cySrc > 0));
Case0110 = ((cxDest < 0) && (cyDest > 0) && (cxSrc > 0) && (cySrc < 0));
Case0101 = ((cxDest < 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc > 0));
Case0100 = ((cxDest < 0) && (cyDest > 0) && (cxSrc < 0) && (cySrc < 0));
Case0011 = ((cxDest < 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc > 0));
Case0010 = ((cxDest < 0) && (cyDest < 0) && (cxSrc > 0) && (cySrc < 0));
Case0001 = ((cxDest < 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc > 0));
Case0000 = ((cxDest < 0) && (cyDest < 0) && (cxSrc < 0) && (cySrc < 0));
/* Make DestRect & OutputRect Well Ordered to start */
RECTL_vMakeWellOrdered(DestRect);
OutputRect = *DestRect;
/* Here we do the tests and set our conditions */
if (((cxSrc < 0) && (cxDest < 0)) || ((cxSrc >= 0) && (cxDest >= 0)))
bLeftToRight = FALSE;
else
bLeftToRight = TRUE;
if (((cySrc < 0) && (cyDest < 0)) || ((cySrc >= 0) && (cyDest >= 0)))
bTopToBottom = FALSE;
else
bTopToBottom = TRUE;
DPRINT("bTopToBottom is '%d' and bLeftToRight is '%d'.\n", bTopToBottom, bLeftToRight);
/* Check if source and dest size are equal */
if (((DestRect->right - DestRect->left) == (SourceRect->right - SourceRect->left)) &&
((DestRect->bottom - DestRect->top) == (SourceRect->bottom - SourceRect->top)))
if ((abs(DestRect->right - DestRect->left) == abs(SourceRect->right - SourceRect->left)) &&
(abs(DestRect->bottom - DestRect->top) == abs(SourceRect->bottom - SourceRect->top)))
{
DPRINT("source and dest size are equal.\n");
DPRINT("IntEngStretchBlt: dstRect: (%d,%d)-(%d,%d)\n",
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
if (Case0000 || Case0001 || Case0010 || Case0011) // Destinations X & Y are both negative
{
lTmp = SourceRect->left;
SourceRect->left = SourceRect->right;
SourceRect->right = lTmp;
lTmp = SourceRect->top;
SourceRect->top = SourceRect->bottom;
SourceRect->bottom = lTmp;
}
if (Case0100 || Case0101 || Case0110 || Case0111) // Destination X is negative and Y is positive
{
lTmp = SourceRect->left;
SourceRect->left = SourceRect->right;
SourceRect->right = lTmp;
}
if (Case1000 || Case1001 || Case1010 || Case1011) // Destination X is positive and Y is negative
{
lTmp = SourceRect->top;
SourceRect->top = SourceRect->bottom;
SourceRect->bottom = lTmp;
}
if (bLeftToRight)
{
lTmp = DestRect->left;
DestRect->left = DestRect->right;
DestRect->right = lTmp;
}
if (bTopToBottom)
{
lTmp = DestRect->top;
DestRect->top = DestRect->bottom;
DestRect->bottom = lTmp;
}
DPRINT("Calling IntEngBitBlt: SourceRect (%d,%d)-(%d,%d) DestRect: (%d,%d)-(%d,%d)\n",
SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
/* Pass the request to IntEngBitBlt */
return IntEngBitBlt(psoDest,
psoSource,
@ -415,6 +629,90 @@ IntEngStretchBlt(SURFOBJ *psoDest,
Rop4);
}
DPRINT("source and dest size are NOT equal.\n");
DPRINT("SourceRect: (%d,%d)-(%d,%d) and DestRect: (%d,%d)-(%d,%d)\n",
SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
/* if cxSrc < 0 then we change the signs for both cxSrc and cxDest and
* we reverse their coordinates, because these outcomes are the same.
*/
if (cxSrc < 0)
{
lTmp = SourceRect->left;
SourceRect->left = SourceRect->right;
SourceRect->right = lTmp;
lTmp = DestRect->left;
DestRect->left = DestRect->right;
DestRect->right = lTmp;
cxSrc = -cxSrc;
cxDest = -cxDest;
}
/* if cySrc < 0 then we change the signs for both cySrc and cyDest and
* we reverse their coordinates, because these outcomes are the same.
*/
if (cySrc < 0)
{
lTmp = DestRect->top;
DestRect->top = DestRect->bottom;
DestRect->bottom = lTmp;
lTmp = SourceRect->top;
SourceRect->top = SourceRect->bottom;
SourceRect->bottom = lTmp;
cySrc = -cySrc;
cyDest = -cyDest;
}
if (Case0010 || Case0111) // Horizontal Flips
{
DestRect->left--;
}
if (Case0010 || Case0111 || Case1000 || Case1101) // Horizontal Flips
{
SourceRect->left--;
SourceRect->right--;
}
if (Case0001 || Case0100 || Case1011 || Case1110) // Vertical Flips
{
SourceRect->top--;
SourceRect->bottom--;
}
if (Case0011 || Case0110 || Case1001 || Case1100) // Horizontal and Vertical Flips
{
SourceRect->left--;
SourceRect->right--;
SourceRect->top--;
SourceRect->bottom--;
}
if (Case0000 || Case1010) // No Flip - Just Copy
{
SourceRect->top++;
SourceRect->bottom++;
DestRect->top++;
DestRect->bottom++;
}
if (Case0000 || Case0101) // No Flip - Just Copy
{
SourceRect->left++;
SourceRect->right++;
DestRect->left++;
DestRect->right++;
}
DPRINT("SourceRect: (%d,%d)-(%d,%d) and DestRect: (%d,%d)-(%d,%d)\n",
SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
InputClippedRect = *DestRect;
if (InputClippedRect.right < InputClippedRect.left)
{
@ -429,6 +727,7 @@ IntEngStretchBlt(SURFOBJ *psoDest,
if (NULL == psoSource)
{
DPRINT("Returning FALSE.\n");
return FALSE;
}
InputRect = *SourceRect;
@ -436,17 +735,28 @@ IntEngStretchBlt(SURFOBJ *psoDest,
if (InputRect.right < InputRect.left ||
InputRect.bottom < InputRect.top)
{
DPRINT("Returning TRUE.\n");
/* Everything clipped away, nothing to do */
return TRUE;
}
DPRINT("InputRect: (%d,%d)-(%d,%d) and InputClippedRect: (%d,%d)-(%d,%d)\n",
InputRect.left, InputRect.top, InputRect.right, InputRect.bottom,
InputClippedRect.left, InputClippedRect.top, InputClippedRect.right, InputClippedRect.bottom);
if (ClipRegion->iDComplexity != DC_TRIVIAL)
{
if (!RECTL_bIntersectRect(&OutputRect, &InputClippedRect,
&ClipRegion->rclBounds))
{
DPRINT("Returning TRUE.\n");
return TRUE;
}
DPRINT("InputClippedRect: (%d,%d)-(%d,%d) and OutputRect: (%d,%d)-(%d,%d)\n",
InputClippedRect.left, InputClippedRect.top, InputClippedRect.right, InputClippedRect.bottom,
OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
/* Update source rect */
InputClWidth = InputClippedRect.right - InputClippedRect.left;
InputClHeight = InputClippedRect.bottom - InputClippedRect.top;
@ -460,9 +770,15 @@ IntEngStretchBlt(SURFOBJ *psoDest,
}
else
{
DPRINT("Complexity = DC_TRIVIAL.\n");
OutputRect = InputClippedRect;
}
DPRINT("InputRect: (%d,%d)-(%d,%d) and OutputRect: (%d,%d)-(%d,%d)\n",
InputRect.left, InputRect.top, InputRect.right, InputRect.bottom,
OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
if (pMaskOrigin != NULL)
{
MaskOrigin.x = pMaskOrigin->x;
@ -480,6 +796,7 @@ IntEngStretchBlt(SURFOBJ *psoDest,
/* Call the driver's DrvStretchBlt if available */
if (psurfDest->flags & HOOK_STRETCHBLTROP)
{
DPRINT("About to call GDIDEVFUNCS(psoDest).StretchBltROP.\n");
/* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */
ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest,
psoSource,
@ -498,6 +815,25 @@ IntEngStretchBlt(SURFOBJ *psoDest,
if (! ret)
{
/* set OutputRect to follow flip */
if (bLeftToRight)
{
lTmp = OutputRect.left;
OutputRect.left = OutputRect.right;
OutputRect.right = lTmp;
}
if (bTopToBottom)
{
lTmp = OutputRect.top;
OutputRect.top = OutputRect.bottom;
OutputRect.bottom = lTmp;
}
DPRINT("Calling EngStretchBltROP: InputRect: (%d,%d)-(%d,%d) and OutputRect: (%d,%d)-(%d,%d)\n",
InputRect.left, InputRect.top, InputRect.right, InputRect.bottom,
OutputRect.left, OutputRect.top, OutputRect.right, OutputRect.bottom);
ret = EngStretchBltROP(psoDest,
psoSource,
MaskSurf,

View File

@ -7,6 +7,8 @@
*/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
DBG_DEFAULT_CHANNEL(GdiBlt);
BOOL APIENTRY
@ -480,6 +482,29 @@ NtGdiMaskBlt(
XlateObj = &exlo.xlo;
}
DPRINT("DestRect: (%d,%d)-(%d,%d) and SourcePoint is (%d,%d)\n",
DestRect.left, DestRect.top, DestRect.right, DestRect.bottom,
SourcePoint.x, SourcePoint.y);
DPRINT("nWidth is '%d' and nHeight is '%d'.\n", nWidth, nHeight);
/* Fix BitBlt so that it will not flip left to right */
if ((DestRect.left > DestRect.right) && (nWidth < 0))
{
SourcePoint.x += nWidth;
nWidth = -nWidth;
}
/* Fix BitBlt so that it will not flip top to bottom */
if ((DestRect.top > DestRect.bottom) && (nHeight < 0))
{
SourcePoint.y += nHeight;
nHeight = -nHeight;
}
/* Make Well Ordered so that we don't flip either way */
RECTL_vMakeWellOrdered(&DestRect);
/* Perform the bitblt operation */
Status = IntEngBitBlt(&BitmapDest->SurfObj,
BitmapSrc ? &BitmapSrc->SurfObj : NULL,
@ -563,6 +588,7 @@ GreStretchBltMask(
BOOL UsesSource;
BOOL UsesMask;
ROP4 rop4;
BOOL Case0000, Case0101, Case1010, CaseExcept;
rop4 = WIN32_ROP4_TO_ENG_ROP4(dwRop4);
@ -615,12 +641,31 @@ GreStretchBltMask(
}
}
Case0000 = ((WidthDest < 0) && (HeightDest < 0) && (WidthSrc < 0) && (HeightSrc < 0));
Case0101 = ((WidthDest < 0) && (HeightDest > 0) && (WidthSrc < 0) && (HeightSrc > 0));
Case1010 = ((WidthDest > 0) && (HeightDest < 0) && (WidthSrc > 0) && (HeightSrc < 0));
CaseExcept = (Case0000 || Case0101 || Case1010);
pdcattr = DCDest->pdcattr;
DestRect.left = XOriginDest;
DestRect.top = YOriginDest;
DestRect.right = XOriginDest+WidthDest;
DestRect.bottom = YOriginDest+HeightDest;
/* Account for possible negative span values */
if ((WidthDest < 0) && !CaseExcept)
{
DestRect.left++;
DestRect.right++;
}
if ((HeightDest < 0) && !CaseExcept)
{
DestRect.top++;
DestRect.bottom++;
}
IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
DestRect.left += DCDest->ptlDCOrig.x;
@ -638,6 +683,18 @@ GreStretchBltMask(
SourceRect.right = XOriginSrc+WidthSrc;
SourceRect.bottom = YOriginSrc+HeightSrc;
/* Account for possible negative span values */
if ((WidthSrc < 0) && !CaseExcept)
{
SourceRect.left++;
SourceRect.right++;
}
if ((HeightSrc < 0) && !CaseExcept)
{
SourceRect.top++;
SourceRect.bottom++;
}
if (UsesSource)
{
IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
@ -698,6 +755,10 @@ GreStretchBltMask(
MaskPoint.y += DCMask->ptlDCOrig.y;
}
DPRINT("Calling IntEngStrethBlt SourceRect: (%d,%d)-(%d,%d) and DestRect: (%d,%d)-(%d,%d).\n",
SourceRect.left, SourceRect.top, SourceRect.right, SourceRect.bottom,
DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
/* Perform the bitblt operation */
Status = IntEngStretchBlt(&BitmapDest->SurfObj,
BitmapSrc ? &BitmapSrc->SurfObj : NULL,

View File

@ -628,9 +628,17 @@ NtGdiSetDIBitsToDeviceInternal(
pDestSurf = &pSurf->SurfObj;
/* Copy the bits */
DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
DPRINT("BitsToDev with rcDest=(%d|%d) (%d|%d), ptSource=(%d|%d) w=%d h=%d\n",
rcDest.left, rcDest.top, rcDest.right, rcDest.bottom,
ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy);
/* This fixes the large Google text on Google.com from being upside down */
if (rcDest.top > rcDest.bottom)
{
RECTL_vMakeWellOrdered(&rcDest);
ptSource.y -= SourceSize.cy;
}
bResult = IntEngBitBlt(pDestSurf,
pSourceSurf,
pMaskSurf,
@ -722,7 +730,7 @@ GreGetDIBitsInternal(
&size);
if(bitmap_type == -1)
{
DPRINT("Wrong bitmap format\n");
DPRINT1("Wrong bitmap format\n");
EngSetLastError(ERROR_INVALID_PARAMETER);
ScanLines = 0;
goto done;