📄 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 + -