From: jimtabor Date: Sat, 2 Mar 2019 17:30:21 +0000 (-0600) Subject: Use GDI Batch for PatBlt X-Git-Tag: 0.4.13-dev~305 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=b6262a25fd0a21de10af78ce84cdf0b6add2978f 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. --- diff --git a/win32ss/gdi/gdi32/include/gdi32p.h b/win32ss/gdi/gdi32/include/gdi32p.h index 9dc2ec4fb6b..67d3a68dbff 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 150040cc0d6..efc987e6cba 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 bd9306ae2eb..3c7d6c2ad00 100644 --- a/win32ss/gdi/ntgdi/gdibatch.c +++ b/win32ss/gdi/ntgdi/gdibatch.c @@ -4,6 +4,7 @@ #define NDEBUG #include +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: {