⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swblt.cpp

📁 windows ce 3.00 嵌入式操作系统源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*

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