https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b6262a25fd0a21de10af7…
commit b6262a25fd0a21de10af78ce84cdf0b6add2978f
Author: jimtabor <james.tabor(a)reactos.org>
AuthorDate: Sat Mar 2 11:30:21 2019 -0600
Commit: jimtabor <james.tabor(a)reactos.org>
CommitDate: Sat Mar 2 11:30:21 2019 -0600
Use GDI Batch for PatBlt
This should increase speed a bit. Makes a good argument to use
PolyPatBlt for more than one call.
PolyPatBlt is not fully tested yet.
---
win32ss/gdi/gdi32/include/gdi32p.h | 4 +-
win32ss/gdi/gdi32/objects/painting.c | 61 +++++++++++++-
win32ss/gdi/ntgdi/gdibatch.c | 158 ++++++++++++++++++++++++++++++++++-
3 files changed, 218 insertions(+), 5 deletions(-)
diff --git a/win32ss/gdi/gdi32/include/gdi32p.h b/win32ss/gdi/gdi32/include/gdi32p.h
index 9dc2ec4fb6..67d3a68dbf 100644
--- a/win32ss/gdi/gdi32/include/gdi32p.h
+++ b/win32ss/gdi/gdi32/include/gdi32p.h
@@ -388,8 +388,8 @@ GdiAllocBatchCommand(
}
/* Get the size of the entry */
- if (Cmd == GdiBCPatBlt) cjSize = 0;
- else if (Cmd == GdiBCPolyPatBlt) cjSize = 0;
+ if (Cmd == GdiBCPatBlt) cjSize = sizeof(GDIBSPATBLT);
+ else if (Cmd == GdiBCPolyPatBlt) cjSize = sizeof(GDIBSPPATBLT);
else if (Cmd == GdiBCTextOut) cjSize = 0;
else if (Cmd == GdiBCExtTextOut) cjSize = 0;
else if (Cmd == GdiBCSetBrushOrg) cjSize = sizeof(GDIBSSETBRHORG);
diff --git a/win32ss/gdi/gdi32/objects/painting.c b/win32ss/gdi/gdi32/objects/painting.c
index 150040cc0d..efc987e6cb 100644
--- a/win32ss/gdi/gdi32/objects/painting.c
+++ b/win32ss/gdi/gdi32/objects/painting.c
@@ -456,9 +456,35 @@ PatBlt(
_In_ INT nHeight,
_In_ DWORD dwRop)
{
+ PDC_ATTR pdcattr;
+
HANDLE_METADC(BOOL, PatBlt, FALSE, hdc, nXLeft, nYLeft, nWidth, nHeight, dwRop);
- /* FIXME some part need be done in user mode */
+ /* Get the DC attribute */
+ pdcattr = GdiGetDcAttr(hdc);
+ if (pdcattr && !(pdcattr->ulDirty_ & DC_DIBSECTION))
+ {
+ PGDIBSPATBLT pgO;
+
+ pgO = GdiAllocBatchCommand(hdc, GdiBCPatBlt);
+ if (pgO)
+ {
+ pgO->nXLeft = nXLeft;
+ pgO->nYLeft = nYLeft;
+ pgO->nWidth = nWidth;
+ pgO->nHeight = nHeight;
+ pgO->dwRop = dwRop;
+ /* Snapshot attributes */
+ pgO->hbrush = pdcattr->hbrush;
+ pgO->crForegroundClr = pdcattr->crForegroundClr;
+ pgO->crBackgroundClr = pdcattr->crBackgroundClr;
+ pgO->crBrushClr = pdcattr->crBrushClr;
+ pgO->ulForegroundClr = pdcattr->ulForegroundClr;
+ pgO->ulBackgroundClr = pdcattr->ulBackgroundClr;
+ pgO->ulBrushClr = pdcattr->ulBrushClr;
+ return TRUE;
+ }
+ }
return NtGdiPatBlt( hdc, nXLeft, nYLeft, nWidth, nHeight, dwRop);
}
@@ -474,6 +500,7 @@ PolyPatBlt(
UINT i;
BOOL bResult;
HBRUSH hbrOld;
+ PDC_ATTR pdcattr;
/* Handle meta DCs */
if ((GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) ||
@@ -511,7 +538,37 @@ PolyPatBlt(
return bResult;
}
- /* FIXME some part need be done in user mode */
+ /* Get the DC attribute */
+ pdcattr = GdiGetDcAttr(hdc);
+ if (nCount && pdcattr && !(pdcattr->ulDirty_ &
DC_DIBSECTION))
+ {
+ PGDIBSPPATBLT pgO;
+ PTEB pTeb = NtCurrentTeb();
+
+ pgO = GdiAllocBatchCommand(hdc, GdiBCPolyPatBlt);
+ if (pgO)
+ {
+ USHORT cjSize = sizeof(GDIBSPPATBLT) + (nCount-1) * sizeof(PATRECT);
+
+ if ((pTeb->GdiTebBatch.Offset + cjSize) <= GDIBATCHBUFSIZE)
+ {
+ pgO->Count = nCount;
+ pgO->Mode = dwMode;
+ pgO->rop4 = dwRop;
+ /* Snapshot attributes */
+ pgO->crForegroundClr = pdcattr->crForegroundClr;
+ pgO->crBackgroundClr = pdcattr->crBackgroundClr;
+ pgO->crBrushClr = pdcattr->crBrushClr;
+ pgO->ulForegroundClr = pdcattr->ulForegroundClr;
+ pgO->ulBackgroundClr = pdcattr->ulBackgroundClr;
+ pgO->ulBrushClr = pdcattr->ulBrushClr;
+ RtlCopyMemory(pgO->pRect, pPoly, nCount * sizeof(PATRECT));
+ // Recompute offset, remember one is already accounted for in the
structure.
+ pTeb->GdiTebBatch.Offset += (nCount-1) * sizeof(PATRECT);
+ return TRUE;
+ }
+ }
+ }
return NtGdiPolyPatBlt(hdc, dwRop, pPoly, nCount, dwMode);
}
diff --git a/win32ss/gdi/ntgdi/gdibatch.c b/win32ss/gdi/ntgdi/gdibatch.c
index bd9306ae2e..3c7d6c2ad0 100644
--- a/win32ss/gdi/ntgdi/gdibatch.c
+++ b/win32ss/gdi/ntgdi/gdibatch.c
@@ -4,6 +4,7 @@
#define NDEBUG
#include <debug.h>
+BOOL FASTCALL IntPatBlt( PDC,INT,INT,INT,INT,DWORD,PEBRUSHOBJ);
//
// Gdi Batch Flush support functions.
@@ -89,16 +90,171 @@ GdiFlushUserBatch(PDC dc, PGDIBATCHHDR pHdr)
switch(Cmd)
{
case GdiBCPatBlt:
+ {
+ PGDIBSPATBLT pgDPB;
+ DWORD dwRop, flags;
+ HBRUSH hOrgBrush;
+ COLORREF crColor, crBkColor, crBrushClr;
+ ULONG ulForegroundClr, ulBackgroundClr, ulBrushClr;
+ if (!dc) break;
+ pgDPB = (PGDIBSPATBLT) pHdr;
+ /* Convert the ROP3 to a ROP4 */
+ dwRop = pgDPB->dwRop;
+ dwRop = MAKEROP4(dwRop & 0xFF0000, dwRop);
+ /* Check if the rop uses a source */
+ if (WIN32_ROP4_USES_SOURCE(dwRop))
+ {
+ /* This is not possible */
+ break;
+ }
+ /* Check if the DC has no surface (empty mem or info DC) */
+ if (dc->dclevel.pSurface == NULL)
+ {
+ /* Nothing to do */
+ break;
+ }
+ // Save current attributes and flags
+ crColor = dc->pdcattr->crForegroundClr;
+ crBkColor = dc->pdcattr->ulBackgroundClr;
+ crBrushClr = dc->pdcattr->crBrushClr;
+ ulForegroundClr = dc->pdcattr->ulForegroundClr;
+ ulBackgroundClr = dc->pdcattr->ulBackgroundClr;
+ ulBrushClr = dc->pdcattr->ulBrushClr;
+ hOrgBrush = dc->pdcattr->hbrush;
+ flags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND | DIRTY_TEXT |
DIRTY_FILL | DC_BRUSH_DIRTY);
+ // Set the attribute snapshot
+ dc->pdcattr->hbrush = pgDPB->hbrush;
+ dc->pdcattr->crForegroundClr = pgDPB->crForegroundClr;
+ dc->pdcattr->crBackgroundClr = pgDPB->crBackgroundClr;
+ dc->pdcattr->crBrushClr = pgDPB->crBrushClr;
+ dc->pdcattr->ulForegroundClr = pgDPB->ulForegroundClr;
+ dc->pdcattr->ulBackgroundClr = pgDPB->ulBackgroundClr;
+ dc->pdcattr->ulBrushClr = pgDPB->ulBrushClr;
+ // Process dirty attributes if any
+ if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+ DC_vUpdateFillBrush(dc);
+ if (dc->pdcattr->ulDirty_ & DIRTY_TEXT)
+ DC_vUpdateTextBrush(dc);
+ if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
+ DC_vUpdateBackgroundBrush(dc);
+ /* Call the internal function */
+ IntPatBlt(dc, pgDPB->nXLeft, pgDPB->nYLeft, pgDPB->nWidth,
pgDPB->nHeight, dwRop, &dc->eboFill);
+ // Restore attributes and flags
+ dc->pdcattr->hbrush = hOrgBrush;
+ dc->pdcattr->crForegroundClr = crColor;
+ dc->pdcattr->crBackgroundClr = crBkColor;
+ dc->pdcattr->crBrushClr = crBrushClr;
+ dc->pdcattr->ulForegroundClr = ulForegroundClr;
+ dc->pdcattr->ulBackgroundClr = ulBackgroundClr;
+ dc->pdcattr->ulBrushClr = ulBrushClr;
+ dc->pdcattr->ulDirty_ |= flags;
break;
+ }
case GdiBCPolyPatBlt:
+ {
+ PGDIBSPPATBLT pgDPB;
+ EBRUSHOBJ eboFill;
+ PBRUSH pbrush;
+ PPATRECT pRects;
+ INT cRects, i;
+ DWORD dwRop, flags;
+ COLORREF crColor, crBkColor, crBrushClr;
+ ULONG ulForegroundClr, ulBackgroundClr, ulBrushClr;
+ if (!dc) break;
+ pgDPB = (PGDIBSPPATBLT) pHdr;
+ /* Convert the ROP3 to a ROP4 */
+ dwRop = pgDPB->rop4;
+ dwRop = MAKEROP4(dwRop & 0xFF0000, dwRop);
+ /* Check if the rop uses a source */
+ if (WIN32_ROP4_USES_SOURCE(dwRop))
+ {
+ /* This is not possible */
+ break;
+ }
+ /* Check if the DC has no surface (empty mem or info DC) */
+ if (dc->dclevel.pSurface == NULL)
+ {
+ /* Nothing to do */
+ break;
+ }
+ // Save current attributes and flags
+ crColor = dc->pdcattr->crForegroundClr;
+ crBkColor = dc->pdcattr->ulBackgroundClr;
+ crBrushClr = dc->pdcattr->crBrushClr;
+ ulForegroundClr = dc->pdcattr->ulForegroundClr;
+ ulBackgroundClr = dc->pdcattr->ulBackgroundClr;
+ ulBrushClr = dc->pdcattr->ulBrushClr;
+ flags = dc->pdcattr->ulDirty_ & (DIRTY_BACKGROUND | DIRTY_TEXT |
DIRTY_FILL | DC_BRUSH_DIRTY);
+ // Set the attribute snapshot
+ dc->pdcattr->crForegroundClr = pgDPB->crForegroundClr;
+ dc->pdcattr->crBackgroundClr = pgDPB->crBackgroundClr;
+ dc->pdcattr->crBrushClr = pgDPB->crBrushClr;
+ dc->pdcattr->ulForegroundClr = pgDPB->ulForegroundClr;
+ dc->pdcattr->ulBackgroundClr = pgDPB->ulBackgroundClr;
+ dc->pdcattr->ulBrushClr = pgDPB->ulBrushClr;
+ // Process dirty attributes if any
+ if (dc->pdcattr->ulDirty_ & DIRTY_TEXT)
+ DC_vUpdateTextBrush(dc);
+ if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
+ DC_vUpdateBackgroundBrush(dc);
+
+ DPRINT1("GdiBCPolyPatBlt Testing\n");
+ pRects = pgDPB->pRect;
+ cRects = pgDPB->Count;
+
+ for (i = 0; i < cRects; i++)
+ {
+ pbrush = BRUSH_ShareLockBrush(pRects->hBrush);
+
+ /* Check if we could lock the brush */
+ if (pbrush != NULL)
+ {
+ /* Initialize a brush object */
+ EBRUSHOBJ_vInitFromDC(&eboFill, pbrush, dc);
+
+ IntPatBlt(
+ dc,
+ pRects->r.left,
+ pRects->r.top,
+ pRects->r.right,
+ pRects->r.bottom,
+ dwRop,
+ &eboFill);
+
+ /* Cleanup the brush object and unlock the brush */
+ EBRUSHOBJ_vCleanup(&eboFill);
+ BRUSH_ShareUnlockBrush(pbrush);
+ }
+ pRects++;
+ }
+
+ // Restore attributes and flags
+ dc->pdcattr->crForegroundClr = crColor;
+ dc->pdcattr->crBackgroundClr = crBkColor;
+ dc->pdcattr->crBrushClr = crBrushClr;
+ dc->pdcattr->ulForegroundClr = ulForegroundClr;
+ dc->pdcattr->ulBackgroundClr = ulBackgroundClr;
+ dc->pdcattr->ulBrushClr = ulBrushClr;
+ dc->pdcattr->ulDirty_ |= flags;
break;
-
+ }
case GdiBCTextOut:
break;
case GdiBCExtTextOut:
+ {
+ //GreExtTextOutW( hDC,
+ // XStart,
+ // YStart,
+ // fuOptions,
+ // &SafeRect,
+ // SafeString,
+ // Count,
+ // SafeDx,
+ // dwCodePage );
break;
+ }
case GdiBCSetBrushOrg:
{