📄 swblt.cpp
字号:
{
// Back up the source and mask row increments because they will be altered dynamically
originalMaskRowInc = mask.RowIncrement;
originalSrcRowInc = src.RowIncrement;
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("yStretch:%d yShrink:%d yDMinor:%d yDMajor:%d yAccum:%d\n"),
yStretch, yShrink, yDMinor, yDMajor, yAccum ));
}
if( pParms->rop4 == 0x0000 )
{
src.Value = 0;
}
else if( pParms->rop4 == 0xffff )
{
src.Value = dst.Mask;
}
else
{
src.Value = pParms->solidColor & dst.Mask;
if( ( maskedROP3 != unmaskedROP3 )
|| transparentBlt
|| xShrinkStretch
|| ( rop3 != 0xCC && ( rop3 != 0xF0 || pParms->pBrush ) ) )
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Complex Blt!\r\n")));
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("transparent:%d,masked:%2x,unmasked:%2x,rop3:%2x,mask.RowPtr:%08x\r\n"),
transparentBlt,maskedROP3, unmaskedROP3, rop3, mask.RowPtr ));
complexBlt = 1;
}
}
brush.Value = src.Value;
while( height-- )
{
// Handle y Shrinking or stretching
if( yShrinkStretch )
{
if( yShrink )
{
while( yAccum < 0 ) // skip source line(s) if shrinking
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("yShrink - skip line\r\n")));
src.RowPtr += src.RowIncrement;
mask.RowPtr += mask.RowIncrement;
yAccum += yDMinor;
}
yAccum += yDMajor;
}
else
{
if( yAccum < 0 )
{
// repeat source line if stretching
yAccum += yDMinor; // yDMinor is a small +ve number
if( yStretch )
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("yStretch - Repeat. Accum=%d\r\n"), yAccum));
src.RowIncrement = 0;
mask.RowIncrement = 0;
}
}
else
{
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("yStretch - Switch to next after this Accum=%d\r\n"), yAccum));
// Switch to next source line (after this row)
yAccum += yDMajor; // yDMajor is a large -ve value (i.e. |yDMajor| > |yDMinor| )
src.RowIncrement = originalSrcRowInc;
mask.RowIncrement = originalMaskRowInc;
}
}
}
// Move all iterators to next line
if( src.RowPtr )
{
src.Ptr = src.RowPtr;
src.RowPtr += src.RowIncrement;
if( ! src.Is24Bit )
{
src.Cache = *(unsigned long *)src.Ptr;
src.CacheState = src.CacheStateNewRow;
}
}
if( mask.RowPtr )
{
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Incrementing mask.RowPtr\r\n")));
mask.Ptr = mask.RowPtr;
mask.RowPtr += mask.RowIncrement;
mask.Cache = *(UNALIGNED unsigned long *)mask.Ptr;
mask.CacheState = mask.CacheStateNewRow;
}
if( brush.RowPtr )
{
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Incrementing brush.RowPtr\r\n")));
brush.Ptr = brush.RowPtr;
brush.LeftRowPtr = brush.Ptr - (brush.FirstRowPtr - (unsigned char *)(pParms->pBrush->Buffer()));
if( --brush.RowsRemaining )
brush.RowPtr += brush.RowIncrement;
else
{
brush.RowPtr = brush.FirstRowPtr;
brush.RowsRemaining = brush.Rows;
}
brush.Cache = *(unsigned long *)brush.Ptr;
brush.CacheState = brush.CacheStateNewRow;
brush.PixelsRemaining = brush.RowInitialPixelsRemaining;
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Brush Ptr = 0x%08x, next row:%08x\r\n"),
// brush.Ptr, brush.RowPtr));
}
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Incrementing dst.RowPtr\r\n")));
dst.Ptr = dst.RowPtr;
dst.RowPtr += dst.RowIncrement;
if( !quickWrite )
{
dst.Cache = *(unsigned long *)dst.Ptr;
dst.CacheState = dst.CacheStateNewRow;
}
if( xStretch )
{
prevMaskPtr = mask.Ptr;
prevMaskCache = mask.Cache;
prevMaskCacheState = mask.CacheState;
prevSrcPtr = src.Ptr;
prevSrcCache = src.Cache;
prevSrcCacheState = src.CacheState;
}
xAccum = rowXAccum;
for( x=0; x<width; x++ )
{
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("x=%d\r\n"), x));
if( src.Ptr )
{
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Reading source pixel\r\n")));
// Read the next pixel in and convert to same depth as destination
if( src.Is24Bit ) // Since 24-bit packed pixels cross dword boundaries:
{
src.Value = ( *src.Ptr ) + ( *(src.Ptr+1) << 8 ) + ( *(src.Ptr+2) << 16 );
src.Ptr += src.BytesPerAccess;
}
else
{
if( !(src.CacheState&0x00ff00) ) // Check bits remaining in src.Cache
{
src.Ptr += src.BytesPerAccess; // increment src.Ptr
src.CacheState = src.CacheStateNewDWord;
src.Cache = *(unsigned long *)src.Ptr; // reload src.Cache
}
src.Value = src.Cache >> ( (src.CacheState >> 16) ^ src.MaskShiftXor );
src.CacheState += src.CacheStateIncrement;
}
originalSrc = ( src.Value &= src.Mask );
if( pParms->pLookup )
src.Value = (pParms->pLookup)[src.Value];
if( pParms->pConvert )
{
src.Value = (pParms->pColorConverter->*(pParms->pConvert))( src.Value );
}
// pParms->pConvert( pParms->pColorConverter, src.Value );
}
if( complexBlt ) // brushed, masked, transparent, unusual rop3 etc
{
if( brush.Ptr )
{
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Reading brush pixel\r\n")));
// Note that the brush will already have been converted to the same
// depth as the destination (if they weren't the same).
// The exception is if the dest is 24Bpp. In this case, the brush
// will have been converted to 32Bpp for simplicity.
// See DrvRealizeBrush for details
if( !(brush.PixelsRemaining--) ) // Check for wrapping off right edge of pattern
{
brush.Ptr = brush.LeftRowPtr;
brush.PixelsRemaining = brush.PixelsPerRow-1;
brush.CacheState = brush.CacheStateNewDWord;
brush.Cache = *(unsigned long *)brush.Ptr; // reload brush.Cache
}
else if( !(brush.CacheState&0x00ff00) ) // Check bits remaining in brush.Cache
{
brush.Ptr += brush.BytesPerAccess; // increment brush.Ptr
brush.CacheState = brush.CacheStateNewDWord;
brush.Cache = *(unsigned long *)brush.Ptr; // reload brush.Cache
}
brush.Value = brush.Cache >> ( (brush.CacheState >> 16) ^ brush.MaskShiftXor );
brush.CacheState += brush.CacheStateIncrement;
}
if( mask.Ptr ) // This selects between two rop3's
{
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Reading mask pixel\r\n")));
if( !(mask.CacheState&0x00ff00) ) // check bits remaining in mask cache
{
mask.Ptr += mask.BytesPerAccess; // == +/- 4
mask.CacheState = mask.CacheStateNewDWord;
mask.Cache = *(UNALIGNED unsigned long *)mask.Ptr;
}
rop3 = ( mask.Cache & ( 1 << ( (mask.CacheState >> 16) ^ mask.MaskShiftXor ) ) ) ? unmaskedROP3 : maskedROP3;
mask.CacheState += mask.CacheStateIncrement;
}
if( xShrinkStretch )
{
// Handle x Stretching
if( xStretch )
{
if( xAccum < 0 ) // Repeat this pixel
{
xAccum += xDMinor;
mask.Ptr = prevMaskPtr;
mask.Cache = prevMaskCache;
mask.CacheState = prevMaskCacheState;
src.Ptr = prevSrcPtr;
src.Cache = prevSrcCache;
src.CacheState = prevSrcCacheState;
}
else // OK to move to next source pixel after this
{
xAccum += xDMajor;
prevMaskPtr = mask.Ptr;
prevMaskCache = mask.Cache;
prevMaskCacheState = mask.CacheState;
prevSrcPtr = src.Ptr;
prevSrcCache = src.Cache;
prevSrcCacheState = src.CacheState;
}
}
else // xShrink
{
while( xAccum < 0 ) // Skip pixel(s)
{
// Move to next src pixel
if( src.Is24Bit ) // Since 24-bit packed pixels cross dword boundaries:
src.Ptr += src.BytesPerAccess;
else
{
if( !(src.CacheState&0x00ff00) ) // Check bits remaining in src.Cache
{
src.Ptr += src.BytesPerAccess; // increment src.Ptr
src.CacheState = src.CacheStateNewDWord;
if (x != width - 1 )
src.Cache = *(unsigned long *)src.Ptr; // reload src.Cache
}
src.CacheState += src.CacheStateIncrement;
}
// Move to next mask pixel
if( pParms->pMask )
{
if( !(mask.CacheState&0x00ff00) ) // check bits remaining in mask cache
{
mask.Ptr += mask.BytesPerAccess; // == +/- 4
mask.CacheState = mask.CacheStateNewDWord;
mask.Cache = *(UNALIGNED unsigned long *)mask.Ptr;
}
mask.CacheState += mask.CacheStateIncrement;
}
xAccum += xDMinor;
}
xAccum += xDMajor;
}
}
if( dstMatters ) // The underlying rop4 utilizes the dst.
{
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Reading dst pixel\r\n")));
// We maintain dst.Cache valid at all times if not doing quickWrite
if( quickWrite )
{
switch(dst.Bpp)
{
case 8:
*(unsigned char *)&dst.Value = *(unsigned char *)dst.Ptr;
break;
case 16:
*(unsigned short *)&dst.Value = *(unsigned short *)dst.Ptr;
break;
case 32:
*(unsigned long *)&dst.Value = *(unsigned long *)dst.Ptr;
break;
case 24:
dst.Value = ( *dst.Ptr ) + ( *(dst.Ptr+1) << 8 ) + ( *(dst.Ptr+2) << 16 );
}
}
else
dst.Value = dst.Cache >> ( ( dst.CacheState >> 16 ) ^ dst.MaskShiftXor );
}
switch( rop3 )
{
// The compiler sorts these and creates a binary search set of tests to
// get to an entry quickly. Branch "prediction" helps this a lot.
// Remember that masked rop4s makes NOP and SRCCOPY quite a likely rop3
case 0xAA: break; // NOP
case 0xCC: break; // SRCCOPY
case 0x00: src.Value = 0; break; // BLACKNESS
case 0x22: src.Value = (~src.Value) & dst.Value; break; // no-name
case 0xB8: src.Value = (brush.Value & ~src.Value)|(src.Value & dst.Value); break; // no-name
case 0x11: src.Value = ~(src.Value | dst.Value); break; // NOTSRCERASE
case 0x33: src.Value = ~src.Value; break; // NOTSRCCOPY
case 0x44: src.Value &= ~dst.Value; break; // SRCERASE
case 0x55: src.Value = ~dst.Value; break; // DSTINVERT
case 0x5A: src.Value = brush.Value ^ dst.Value; break; // PATINVERT
case 0x66: src.Value ^= dst.Value; break; // SRCINVERT
case 0x88: src.Value &= dst.Value; break; // SRCAND
case 0xBB: src.Value = ~src.Value | dst.Value; break; // MERGEPAINT
case 0xC0: src.Value &= brush.Value; break; // MERGECOPY
case 0xEE: src.Value |= dst.Value; break; // SRCPAINT
case 0xF0: src.Value = brush.Value; break; // PATCOPY
case 0xFB: src.Value = brush.Value | ~src.Value | dst.Value; break; // PATPAINT
case 0xFF: src.Value = 0xFFFFFFFF; break; // WHITENESS
case 0xE2: src.Value = ( dst.Value & ~src.Value ) | ( brush.Value & src.Value ); break;
case 0xAC: src.Value = ((src.Value^dst.Value)&brush.Value)^src.Value; break;
default: src.Value = ProcessROP3(dst.Value,src.Value,brush.Value,rop3,dst.Bpp);
}
src.Value &= dst.Mask;
if( rop3 == 0xAA || ( transparentBlt && ( originalSrc == transparentColor ) ) )
{
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("NOT writing pixel\r\n")));
// we won't write this pixel
if( quickWrite )
dst.Ptr += dst.BytesPerAccess;
else
{
dst.CacheState += dst.CacheStateIncrement; // leave dirty flag as-is
if( !(dst.CacheState&0x00ff00) ) // Check bits remaining in dst cache
{
if( dst.CacheState & 0x0000ff )
*(unsigned long *)dst.Ptr = dst.Cache; // flush cache
dst.CacheState = dst.CacheStateNewDWord; // clears dirty flag
dst.Ptr += dst.BytesPerAccess; // +/- 4
dst.Cache = *(unsigned long *)dst.Ptr;
}
}
continue;
}
}
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Writing pixel\r\n")));
// Now, we are ready to write the value from src.Value into the dst pixel
if( quickWrite )
{
switch(dst.Bpp)
{
case 8:
*(unsigned char *)dst.Ptr = (unsigned char)src.Value;
break;
case 16:
*(unsigned short *)dst.Ptr = (unsigned short)src.Value;
break;
case 32:
*(unsigned long *)dst.Ptr = (unsigned long)src.Value;
break;
case 24:
*dst.Ptr = (unsigned char)(src.Value);
*(dst.Ptr+1) = (unsigned char)(src.Value>>8);
*(dst.Ptr+2) = (unsigned char)(src.Value>>16);
}
dst.Ptr += dst.BytesPerAccess;
}
else
{
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Old Cache: 0x%08x, Cache State: 0x%08x, Ptr: 0x%08x\r\n"),
// dst.Cache, dst.CacheState, dst.Ptr));
unsigned char tmpShift = (unsigned char)(( dst.CacheState >> 16 ) ^ dst.MaskShiftXor);
dst.Cache &= ~( dst.Mask << tmpShift);
dst.Cache |= src.Value << tmpShift;
dst.CacheState += dst.CacheStateIncrementDirty; // sets dirty flag
if( !(dst.CacheState&0x00ff00) ) // Check bits remaining in dst cache
{
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Writing 0x%08x to Ptr: 0x%08x\r\n"),
// dst.Cache, dst.Ptr ));
*(unsigned long *)dst.Ptr = dst.Cache; // flush cache (we know it was dirty)
dst.CacheState = dst.CacheStateNewDWord; // clears dirty flag
dst.Ptr += dst.BytesPerAccess; // +/- 4
if (x != width - 1 )
dst.Cache = *(unsigned long *)dst.Ptr;
}
// DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("New Cache: 0x%08x, Cache State: 0x%08x, Ptr: 0x%08x\r\n"),
// dst.Cache, dst.CacheState, dst.Ptr));
}
} // next column
if( dst.CacheState & 0x0000ff )
*(unsigned long *)dst.Ptr = dst.Cache; // flush cache
} // next row
return S_OK;
}
unsigned long ProcessROP3(
unsigned long dstValue,
unsigned long srcValue,
unsigned long brushValue,
unsigned char rop3,
unsigned char dstBitsPerPixel)
{
if( dstBitsPerPixel > 24 )
{
// Break into two halves, otherwise the brushValue<<=2 below will overflow
return ProcessROP3(dstValue,srcValue,brushValue,rop3,16) |
( ProcessROP3(dstValue>>16,srcValue>>16,brushValue>>16,rop3,dstBitsPerPixel-16) << 16);
}
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("Process rop3=%02x, numbits=%d, pattern=%04x, source=%04x, dest=%04x, "),
rop3,dstBitsPerPixel,brushValue,srcValue,dstValue ));
unsigned long result = 0;
unsigned long rsltBit = 1;
brushValue <<= 2;
srcValue <<= 1;
while( dstBitsPerPixel-- )
{
if( ( 1<< ( brushValue&4 | srcValue&2 | dstValue&1 ) ) & rop3 )
result |= rsltBit;
brushValue >>= 1;
srcValue >>= 1;
dstValue >>= 1;
rsltBit <<=1;
}
DEBUGMSG(GPE_ZONE_BLT_LO,(TEXT("resuult=%04x\r\n"), result));
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -