📄 swblt.cpp
字号:
/*Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.*/#include "precomp.h"unsigned long ProcessROP3( unsigned long dstValue, unsigned long srcValue, unsigned long brushValue, unsigned char rop3, unsigned char dstBitsPerPixel);class PixelIterator{public: // Fixed upon creation: unsigned char *RowPtr; int RowIncrement; unsigned long CacheStateNewDWord; unsigned long CacheStateNewRow; unsigned long CacheStateIncrement; unsigned long CacheStateIncrementDirty; int Is24Bit; unsigned long Mask; int BytesPerAccess; int Bpp; unsigned char MaskShiftXor; // IteratorState unsigned char *Ptr; unsigned long Cache; unsigned long Value; unsigned long CacheState; void InitPixelIterator( GPESurf *pSurf, int xPositive, int yPositive, RECTL *prcl, int xSkip, int ySkip );};class BrushPixelIterator : public PixelIterator{public: int PixelsRemaining; // Pixels still available this row of brush incl cache int PixelsPerRow; // Width of source surface int RowInitialPixelsRemaining; // PixelsRemaining at start of each Dst row int RowsRemaining; // Rows (incl this) left in pattern int Rows; // Total rows in pattern unsigned char *FirstRowPtr; // Pointer to first DWord to use in top/bottom row unsigned char *LeftRowPtr; // Ptr to *left* of pattern of current row // (RowPtr is *start* of next row) void InitBrushPixelIterator( GPESurf *pSurf, int xPositive, int yPositive, RECTL *prcl );};void BrushPixelIterator::InitBrushPixelIterator( GPESurf *pSurf, int xPositive, int yPositive, RECTL *prcl){ DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("BrushPixelIterator::InitBrushPixelIterator\r\n"))); InitPixelIterator( pSurf, xPositive, yPositive, prcl, 0, 0 ); PixelsPerRow = pSurf->Width(); Rows = pSurf->Height(); RowInitialPixelsRemaining = xPositive?PixelsPerRow-prcl->left:prcl->right; RowsRemaining = yPositive?Rows-prcl->top:prcl->bottom; FirstRowPtr = RowPtr - RowIncrement * ( Rows - RowsRemaining ); DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("PixelsPerRow=%d, Rows=%d, RowInitPixRem=%d, RowsRem=%d, FirstRowPtr=%08x\r\n"), PixelsPerRow, Rows, RowInitialPixelsRemaining, RowsRemaining, FirstRowPtr ));}void PixelIterator::InitPixelIterator( GPESurf *pSurf, int xPositive, int yPositive, RECTL *prcl, int xSkip, int ySkip ){ DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("PixelIterator::PixelIterator, prcl= l:%d,t:%d - r:%d,b:%d Bpp=%d\r\n"), prcl->left, prcl->top, prcl->right, prcl->bottom, EGPEFormatToBpp[pSurf->Format()] )); // Set pointer to start of first row to use RowPtr = (unsigned char *)(pSurf->Buffer()); if( yPositive ) { RowIncrement = pSurf->Stride(); RowPtr += pSurf->Stride() * (prcl->top + ySkip ); } else { RowIncrement = -pSurf->Stride(); RowPtr += pSurf->Stride() * (prcl->bottom-1-ySkip); } int StartX; Bpp = EGPEFormatToBpp[pSurf->Format()]; MaskShiftXor = (Bpp<8)?(8-Bpp):0; CacheStateNewDWord = (32/Bpp)<<8; // Initally 32/Bpp pixels in dword, 0 offset if( xPositive ) { StartX = prcl->left + xSkip; CacheStateIncrement = ((Bpp<<8) - 1)<<8; } else { StartX = prcl->right-1-xSkip; CacheStateIncrement = (((-Bpp)<<8) - 1)<<8; CacheStateNewDWord |= (32 - Bpp)<<16; // Initial offset points to last pixel in dword } CacheStateIncrementDirty = CacheStateIncrement+1; if( Is24Bit = ( pSurf->Format() == gpe24Bpp ) ) // deliberate assignment { RowPtr += 3 * StartX; BytesPerAccess = 3; } else { int StartBit = Bpp * StartX; RowPtr += (StartBit&~31) >> 3; // Since the first pixel on row in prcl may not be on dword alignment: CacheStateNewRow = CacheStateNewDWord; while( (( CacheStateNewRow >> 16 ) ^ StartBit ) & 31 ) CacheStateNewRow += CacheStateIncrement; BytesPerAccess = 4; } if( !xPositive ) BytesPerAccess = -BytesPerAccess; Mask = ( 2 << (Bpp - 1) ) - 1; DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("BytesPerAccess=%d,CacheStateNewRow=%06x,CacheStateIncrement=%06x\r\n"), BytesPerAccess, CacheStateNewRow, CacheStateIncrement )); DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Mask=%08x, CacheStateNewDWord=%08x, StartX=0x%04x(%d)\r\n"), Mask, CacheStateNewDWord, StartX, StartX )); DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Buffer=0x%08x\r\n"), (pSurf->Buffer()) ));}#undef SWAP#define SWAP(a,b,type) { type tmp=a; a=b; b=tmp; }SCODE GPE::EmulatedBlt( GPEBltParms *pParms ){ DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("New Blt. rop4=%04X\r\n"), pParms->rop4)); unsigned char rop3 = (unsigned char)pParms->rop4; unsigned char maskedROP3 = (unsigned char)( pParms->rop4 >> 8 ); unsigned char unmaskedROP3 = rop3; int complexBlt = 0; int quickWrite = 0; int width = pParms->prclDst->right - pParms->prclDst->left; int height = pParms->prclDst->bottom - pParms->prclDst->top; int x; RECTL rclBrush; int dstMatters = ((( pParms->rop4 >> 1 ) ^ pParms->rop4 ) & 0x5555 ) != 0; int dstXPositive = pParms->xPositive; // These differ from pParms->?Positive if flipping is being performed int dstYPositive = pParms->yPositive; RECTL *prclDst = pParms->prclDst; RECTL tmpRclDst; int xShrinkStretch = 0; int xShrink=0; int xStretch=0; int yShrinkStretch = 0; int yShrink=0; int yStretch=0; int srcWidth; int srcHeight; int rowXAccum, xAccum, xDMajor, xDMinor; // only valid if xShrinkStretch int yAccum, yDMajor, yDMinor; // only valid if yShrinkStretch int originalMaskRowInc, originalSrcRowInc; // Used if yShrinkStretch unsigned char *prevMaskPtr, *prevSrcPtr; unsigned long prevMaskCache, prevSrcCache; unsigned long prevMaskCacheState, prevSrcCacheState; unsigned long originalSrc; int dstXStartSkip = 0; // Number of dst pixels to not write (left if dstXPositive else right) int dstYStartSkip = 0; // Number of rows to ignore (top if dstYPositive) int srcXStartSkip = 0; int srcYStartSkip = 0; if( pParms->pDst->InVideoMemory() || ( pParms->pSrc && pParms->pSrc->InVideoMemory() ) || ( pParms->pMask && pParms->pMask->InVideoMemory() ) ) { // If we have a pending blt and now attempt a software operation using // video memory, the pipeline must be flushed. WaitForNotBusy(); }// DebugBreak(); // Handle improperly ordered prclDst resulting from stretch Blt // Note that only prclDst is ever improperly ordered if( width < 0 || height < 0 ) { tmpRclDst = *prclDst; prclDst = &tmpRclDst; if( width < 0 ) { SWAP( tmpRclDst.left, tmpRclDst.right, LONG ) width = -width; dstXPositive = !dstXPositive; } if( height < 0 ) { SWAP( tmpRclDst.top, tmpRclDst.bottom, LONG ) height = -height; dstYPositive = !dstYPositive; } } // prclDst is now properly ordered if( pParms->bltFlags & BLT_STRETCH ) // Check for stretching or shrinking vertically &/or horizontally { srcWidth = pParms->prclSrc->right - pParms->prclSrc->left; srcHeight = pParms->prclSrc->bottom - pParms->prclSrc->top; if( width > srcWidth ) { xStretch = 1; xDMajor = width; xDMinor = srcWidth; } if( width < srcWidth ) { xShrink = 1; xDMajor = srcWidth; xDMinor = width; } if( xStretch || xShrink) { xShrinkStretch = 1; // Convert to Bresenham parameters xDMinor *= 2; xDMajor = xDMinor - 2 * xDMajor; rowXAccum = xShrink?(2*width - srcWidth):(3*srcWidth - 2*width); // loaded into xAccum at start of each row } if( height > srcHeight ) { yStretch = 1; yDMajor = height; yDMinor = srcHeight; } if( height < srcHeight ) { yShrink = 1; yDMajor = srcHeight; yDMinor = height; } if( yStretch || yShrink) { yShrinkStretch = 1; // Convert to Bresenham parameters yDMinor *= 2; yDMajor = yDMinor - 2 * yDMajor; yAccum = yShrink?(2*height - srcHeight):(3*srcHeight - 2*height); } if( pParms->prclClip ) // ONLY happens if stretch blting { RECTL rclClipped = *prclDst; if( rclClipped.left < pParms->prclClip->left ) rclClipped.left = pParms->prclClip->left; if( rclClipped.top < pParms->prclClip->top ) rclClipped.top = pParms->prclClip->top; if( rclClipped.bottom > pParms->prclClip->bottom ) rclClipped.bottom = pParms->prclClip->bottom; if( rclClipped.right > pParms->prclClip->right ) rclClipped.right = pParms->prclClip->right; if( rclClipped.right <= rclClipped.left || rclClipped.bottom <= rclClipped.top ) return S_OK; // the clipping left nothing to do dstXStartSkip = dstXPositive?(rclClipped.left-prclDst->left):(prclDst->right-rclClipped.right); dstYStartSkip = dstYPositive?(rclClipped.top-prclDst->top):(prclDst->bottom-rclClipped.bottom); width = rclClipped.right - rclClipped.left; // Calculate fully clipped destination width height = rclClipped.bottom - rclClipped.top; // Fully clipped height } if( xShrink ) { while( rowXAccum < 0 ) { rowXAccum += xDMinor; srcXStartSkip++; } rowXAccum += xDMajor; } int skipCount; for( skipCount = dstXStartSkip; skipCount; skipCount-- ) { if( xShrink ) { while( rowXAccum < 0 ) { rowXAccum += xDMinor; srcXStartSkip++; } srcXStartSkip++; // <--- this is the srcSkip inherent with a dstSkip rowXAccum += xDMajor; } else if( xStretch ) { if( rowXAccum < 0 ) rowXAccum += xDMinor; else { rowXAccum += xDMajor; srcXStartSkip++; } } else srcXStartSkip++; } if( yShrink ) { yAccum += dstYStartSkip * yDMajor; srcYStartSkip += dstYStartSkip; // <--- this is the srcSkip inherent with a dstSkip } else if( yStretch ) { for( skipCount = dstYStartSkip; skipCount; skipCount-- ) { if( yAccum < 0 ) yAccum += yDMinor; else { yAccum += yDMajor; srcYStartSkip++; } } } else srcYStartSkip += dstYStartSkip; } int transparentBlt = pParms->bltFlags & BLT_TRANSPARENT; unsigned long transparentColor = pParms->solidColor; DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("pSrc=0x%08x, pDst=0x%08x, pBrush=%08x, pMask=%08x\r\n"), pParms->pSrc, pParms->pDst, pParms->pBrush, pParms->pMask )); if( pParms->pBrush ) { // Calculate an rclBrush so that the correct starting pixel is chosen for the brush iterator DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Pattern depth: %d Bpp\r\n"), EGPEFormatToBpp[pParms->pBrush->Format()] ) ); int topIndent = (pParms->pptlBrush)?pParms->pBrush->Height()-pParms->pptlBrush->y:0; int leftIndent = (pParms->pptlBrush)?pParms->pBrush->Width()-pParms->pptlBrush->x:0; rclBrush.left = ( leftIndent + prclDst->left ) % pParms->pBrush->Width(); rclBrush.right = ( rclBrush.left + pParms->pBrush->Width() - 1 ) % pParms->pBrush->Width(); rclBrush.top = ( topIndent + prclDst->top ) % pParms->pBrush->Height(); rclBrush.bottom = ( rclBrush.top + pParms->pBrush->Height() - 1 ) % pParms->pBrush->Height(); } PixelIterator src, dst, mask; BrushPixelIterator brush; src.Ptr = src.RowPtr = mask.Ptr = mask.RowPtr = brush.Ptr = brush.RowPtr = (unsigned char *)0; if( pParms->pSrc ) { DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("pSrc depth: %d Bpp\r\n"), EGPEFormatToBpp[pParms->pSrc->Format()] ) ); src.InitPixelIterator( pParms->pSrc, pParms->xPositive, pParms->yPositive, pParms->prclSrc, srcXStartSkip, srcYStartSkip ); } DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("pDst depth: %d Bpp\r\n"), EGPEFormatToBpp[pParms->pDst->Format()] ) ); if( pParms->pBrush ) { DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("pBrush depth: %d Bpp\r\n"), EGPEFormatToBpp[pParms->pBrush->Format()] ) ); brush.InitBrushPixelIterator( pParms->pBrush, pParms->xPositive, pParms->yPositive, &rclBrush ); } if( ( maskedROP3 != unmaskedROP3 ) && !(pParms->pMask) ) { DEBUGMSG(GPE_ZONE_ERROR,(TEXT("Rop4 = %04x but pMask is NULL\r\n"), pParms->rop4 )); return E_INVALIDARG; } if( pParms->pMask ) mask.InitPixelIterator( pParms->pMask, pParms->xPositive, pParms->yPositive, pParms->prclMask, srcXStartSkip, srcYStartSkip ); else mask.RowIncrement = 0; if( ( maskedROP3 != unmaskedROP3 ) && !(mask.RowPtr) ) { DEBUGMSG(GPE_ZONE_ERROR,(TEXT("Rop4 = %04x but mask.RowPtr is NULL\r\n"), pParms->rop4 )); return E_INVALIDARG; } if( ( dst.Bpp = EGPEFormatToBpp[pParms->pDst->Format()] ) >= 8 ) { quickWrite = 1; if( !dstYPositive ) { dst.RowIncrement = -pParms->pDst->Stride(); dst.RowPtr = (unsigned char *)pParms->pDst->Buffer() + pParms->pDst->Stride() * ( prclDst->bottom - 1 - dstYStartSkip ); } else { dst.RowIncrement = pParms->pDst->Stride(); dst.RowPtr = (unsigned char *)pParms->pDst->Buffer() + pParms->pDst->Stride() * ( dstYStartSkip + prclDst->top ); } if( !dstXPositive ) { dst.BytesPerAccess = -dst.Bpp/8; dst.RowPtr -= dst.BytesPerAccess * ( prclDst->right - 1 - dstXStartSkip ); } else { dst.BytesPerAccess = dst.Bpp/8; dst.RowPtr += dst.BytesPerAccess * ( dstXStartSkip + prclDst->left ); } dst.Mask = ( 2 << (dst.Bpp - 1) ) - 1; dst.CacheState=0; // so it is not marked as dirty } else dst.InitPixelIterator( pParms->pDst, dstXPositive, dstYPositive, prclDst, dstXStartSkip, dstYStartSkip ); if( yShrinkStretch )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -