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

📄 blit.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************
<module>
* Name         : Blit.c
* Title        : Presentation and blitting functions
* Author(s)    : Imagination Technologies
* Created      : 2 March 2004
*
* Copyright    : 2004 by Imagination Technologies Limited.
*                All rights reserved.  No part of this software, either
*                material or conceptual may be copied or distributed,
*                transmitted, transcribed, stored in a retrieval system
*                or translated into any human or computer language in any
*                form by any means, electronic, mechanical, manual or
*                other-wise, or disclosed to third parties without the
*                express written permission of Imagination Technologies
*                Limited, Unit 8, HomePark Industrial Estate,
*                King's Langley, Hertfordshire, WD4 8LZ, U.K.
*
* Description  : Functions for blitting, flipping and colourfilling.
*
* Platform     : Windows CE
*
</module>
********************************************************************************/

#include "context.h"
#include "twiddle.h"

/*
	Size of the largest Blt in DWORDs. Used in HardwareBlt and
	GetBltStatus to check for room in the HWQ.
*/
#define MAX_BLT_SIZE	56
/*----------------------------------------------------------------------------
<function>
 FUNCTION	:	ScaleRectAndClamp	
    
 PURPOSE	:	Scales a blit rect accordingly if the surface is a texture,
				then clamps any negative values to 0

 PARAMETERS	:	In :psRect		- Rect to be scaled
				In :psSurface	- Surface to which rect applies
  
</function>
------------------------------------------------------------------------------*/
IMG_VOID ScaleRectAndClamp(RECT* psRect, LPD3DM_SURFACE psSurface)
{
	if(psSurface->eSurfaceType == D3DMRTYPE_TEXTURE)
	{
		psRect->left   *= psSurface->sDescription.sTexture.psMapDetails->dwUScale;
		psRect->right  *= psSurface->sDescription.sTexture.psMapDetails->dwUScale;
		psRect->top    *= psSurface->sDescription.sTexture.psMapDetails->dwVScale;
		psRect->bottom *= psSurface->sDescription.sTexture.psMapDetails->dwVScale;
	}

	psRect->left   = (psRect->left   < 0) ? 0 : psRect->left;
	psRect->top    = (psRect->top    < 0) ? 0 : psRect->top;
	psRect->right  = (psRect->right  < 0) ? 0 : psRect->right;
	psRect->bottom = (psRect->bottom < 0) ? 0 : psRect->bottom;
}

/*----------------------------------------------------------------------------
<function>
 FUNCTION	:	GetTextureCopyOrder	
    
 PURPOSE	:	Calculate texture copy order from source and dest dimensions.

 PARAMETERS	:	In :psSourceRect - Source dimensions
				In :psDestRect	- Destination dimensions
  
 RETURNS	:	DWORD     dwCopyOrder	- Copy order as defined in mbx12ddef.h
</function>
------------------------------------------------------------------------------*/
DWORD GetTextureCopyOrder(RECT *psSourceRect, RECT *psDestRect)
{
    /* Default to left-down blitting */
    DWORD dwCopyOrder   = MBX2D_TEXTCOPY_TL2BR;
    BOOL  ScanXPositive = TRUE;
    BOOL  ScanYPositive = TRUE;

    /* Check for an overlap */
	if (psSourceRect->bottom > psDestRect->top    &&
		psSourceRect->top    < psDestRect->bottom &&
		psSourceRect->right  > psDestRect->left   &&
		psSourceRect->left   < psDestRect->right) 
	{
	    /* Work out ScanX/ScanY flags */
		if (psSourceRect->top == psDestRect->top) 
		{
			/* Horizontal blt, just set ScanXPositive appropriately */
			ScanXPositive = (BOOL)(psSourceRect->left >= psDestRect->left);
		}
		else 
		{
			/* Non horizontal blts, just set ScanYPositive appropriately */
			ScanYPositive = (BOOL)(psSourceRect->top >= psDestRect->top);
		}	

        /* Work out copy order from ScanX/ScanY flags */
        if (ScanXPositive) 
        {
			/* X+ */
			if(ScanYPositive) 
            {
				/* Y+ */
				dwCopyOrder = MBX2D_TEXTCOPY_TL2BR;
			}
			else 
            {
				/* Y- */
				dwCopyOrder = MBX2D_TEXTCOPY_BL2TR;
			}			
		}
		else 
        {
			/* X- */	
			if (ScanYPositive) 
            {
				/* Y+ */
				dwCopyOrder = MBX2D_TEXTCOPY_TR2BL;
			}
			else
            {
				/* Y- */
				dwCopyOrder = MBX2D_TEXTCOPY_BR2TL;
			}			
		}
	}
	return dwCopyOrder;
}
/*----------------------------------------------------------------------------
<function>
 FUNCTION	:	WriteStretchBlock	
    
 PURPOSE	:	Calculate stretch from source and dest dimensions and write to
                2D hardware.

 PARAMETERS	:	In: psSourceRect - Source dimensions
				In: psDestRect - Destination dimensions
				In: ppdwCmd - Command under construction
  
 RETURNS	:	BOOL      bHandled      - False means punt the blit
</function>
------------------------------------------------------------------------------*/
BOOL WriteStretchBlock(RECT *psSourceRect, RECT *psDestRect, DWORD **ppdwCmd)
{
    ULONG uXFPStretch;
    ULONG uYFPStretch;

	ULONG uDW = psDestRect->right - psDestRect->left;
	ULONG uDH = psDestRect->bottom - psDestRect->top;
	ULONG uSW = psSourceRect->right - psSourceRect->left;
	ULONG uSH = psSourceRect->bottom - psSourceRect->top;

    /* 
		Check the scale factor falls within our range by centering
		it and making sure that none overlaps our 10 bit range
	*/
    ULONG uXCheck = (uSW << 16) / uDW;
    ULONG uYCheck = (uSH << 16) / uDH;
    if ((uXCheck & 0xFFE007FF) || (0 == uXCheck) ||
        (uYCheck & 0xFFE007FF) || (0 == uYCheck))
    {
        return FALSE;
    }
	
    /* Calculate X and Y stretch in 5.5 fixed point format */
	uXFPStretch = (uDW == uSW)
				? MBX2D_NO_STRETCH
				: uXCheck >> (16 - MBX2D_STRETCH_FPSHIFT);
	uYFPStretch = (uDH == uSH)
				? MBX2D_NO_STRETCH
				: uYCheck >> (16 - MBX2D_STRETCH_FPSHIFT);

	*(*ppdwCmd)++ = MBX2D_STRETCH_BH 
					| (uXFPStretch<<MBX2D_X_STRETCH_SHIFT)
					| (uYFPStretch<<MBX2D_Y_STRETCH_SHIFT);
    return TRUE;
}
/*----------------------------------------------------------------------------
<function>
 FUNCTION	:	WriteSrcSurf	
    
 PURPOSE	:	Write 2D Source Surface data to the 2D hardware.

 PARAMETERS	:	In: psData - Surface data
				In: psRect - Surface dimensions
				In: ppdwCmd - Command under construction
  
 RETURNS	:	BOOL            		- TRUE if successful	
</function>
------------------------------------------------------------------------------*/
BOOL WriteSrcSurf(LPD3DM_SURFACE psData, RECT *psRect, DWORD **ppdwCmd)
{	
	ULONG uHWFormat;
    
    /* Select a hardware format based on the D3DM surface format */
    switch(psData->eFormat)
    {
		case D3DMFMT_R3G3B2:	uHWFormat = MBX2D_SRC_332RGB;	break;
		case D3DMFMT_R5G6B5:	uHWFormat = MBX2D_SRC_565RGB;	break;
		case D3DMFMT_R8G8B8:	uHWFormat = MBX2D_SRC_888RGB;	break;
		case D3DMFMT_A1R5G5B5:	uHWFormat = MBX2D_SRC_1555ARGB;	break;
		case D3DMFMT_A4R4G4B4:	uHWFormat = MBX2D_SRC_4444ARGB;	break;
		case D3DMFMT_X8R8G8B8:
		case D3DMFMT_A8R8G8B8:	uHWFormat = MBX2D_SRC_8888ARGB;	break;
        default:
			D3DM_DPF((DPF_ERROR, "WriteSrcSurf:Unsupported blit format"));
			return FALSE;
    }
        
    /* Write block header */
    *(*ppdwCmd)++ = 	MBX2D_SRC_CTRL_BH
                    |	MBX2D_SRC_FBMEM
                    |	uHWFormat
                    |	((psData->dwStrideByte << MBX2D_SRC_STRIDE_SHIFT) & MBX2D_SRC_STRIDE_MASK);

	if(psData->eSurfaceType == D3DMRTYPE_TEXTURE)
	{
		/* Write base address */   
		*(*ppdwCmd)++ = (((psData->psMemInfo->uiDevAddr.uiAddr + psData->sDescription.sTexture.dwLevelOffset)
						>>	MBX2D_SRC_ADDR_ALIGNSHIFT)
						<<	MBX2D_SRC_ADDR_SHIFT)
						&	MBX2D_SRC_ADDR_MASK;

		D3DM_DPF((DPF_BLIT_MESSAGE, "***** Queueing Blit from 0x%8.8X",psData->psMemInfo->uiDevAddr.uiAddr + psData->sDescription.sTexture.dwLevelOffset));

	}
	else
	{
		/* Write base address */   
		*(*ppdwCmd)++ = ((psData->psMemInfo->uiDevAddr.uiAddr
						>>	MBX2D_SRC_ADDR_ALIGNSHIFT)
						<<	MBX2D_SRC_ADDR_SHIFT)
						&	MBX2D_SRC_ADDR_MASK;

		D3DM_DPF((DPF_BLIT_MESSAGE, "***** Queueing Blit from 0x%8.8X",psData->psMemInfo->uiDevAddr.uiAddr));
	}
                    
    /* Write the starting pixel coordinate */
    *(*ppdwCmd)++ = MBX2D_SRC_OFF_BH
                    | ((psRect->left << MBX2D_SRCOFF_XSTART_SHIFT) & MBX2D_SRCOFF_XSTART_MASK)
                    | ((psRect->top  << MBX2D_SRCOFF_YSTART_SHIFT) & MBX2D_SRCOFF_YSTART_MASK);
    
	return TRUE;
}
/*----------------------------------------------------------------------------
<function>
 FUNCTION	:	WriteDstSurf	
    
 PURPOSE	:	Write 2D Destination Surface data to the 2D hardware.

 PARAMETERS	:	In:	psData	- Surface data
				In: ppdwCmd - Command under construction
  
 RETURNS	:	BOOL            		- TRUE if successful	
</function>
------------------------------------------------------------------------------*/
BOOL WriteDstSurf(LPD3DM_SURFACE psData, DWORD **ppdwCmd)
{	
	ULONG uHWFormat;
    
    /* Select a hardware format based on the D3DM surface format */
    switch(psData->eFormat)
    {
		case D3DMFMT_R3G3B2:	uHWFormat = MBX2D_SRC_332RGB;	break;
		case D3DMFMT_R5G6B5:	uHWFormat = MBX2D_SRC_565RGB;	break;
		case D3DMFMT_R8G8B8:	uHWFormat = MBX2D_SRC_888RGB;	break;
		case D3DMFMT_A1R5G5B5:	uHWFormat = MBX2D_SRC_1555ARGB;	break;
		case D3DMFMT_A4R4G4B4:	uHWFormat = MBX2D_SRC_4444ARGB;	break;
		case D3DMFMT_X8R8G8B8:
		case D3DMFMT_A8R8G8B8:	uHWFormat = MBX2D_SRC_8888ARGB;	break;
        default:
			D3DM_DPF((DPF_ERROR, "WriteSrcSurf:Unsupported blit format"));
			return FALSE;
    }
      
    /* Write block header */
    *(*ppdwCmd)++ = MBX2D_DST_CTRL_BH
                    |	uHWFormat
                    |	((psData->dwStrideByte << MBX2D_DST_STRIDE_SHIFT) & MBX2D_DST_STRIDE_MASK);


	if(psData->eSurfaceType == D3DMRTYPE_TEXTURE)
	{
		/* Write base address */ 
		*(*ppdwCmd)++ = (((psData->psMemInfo->uiDevAddr.uiAddr + psData->sDescription.sTexture.dwLevelOffset)
						>>	MBX2D_DST_ADDR_ALIGNSHIFT)
						<<	MBX2D_DST_ADDR_SHIFT)
						&	MBX2D_DST_ADDR_MASK;

		D3DM_DPF((DPF_BLIT_MESSAGE, "***** Queueing Blit to 0x%8.8X",psData->psMemInfo->uiDevAddr.uiAddr + psData->sDescription.sTexture.dwLevelOffset));

	}
	else
	{
		/* Write base address */ 
		*(*ppdwCmd)++ = ((psData->psMemInfo->uiDevAddr.uiAddr
						>>	MBX2D_DST_ADDR_ALIGNSHIFT)
						<<	MBX2D_DST_ADDR_SHIFT)
						&	MBX2D_DST_ADDR_MASK;

		D3DM_DPF((DPF_BLIT_MESSAGE, "***** Queueing Blit to 0x%8.8X",psData->psMemInfo->uiDevAddr.uiAddr));
	}


    return TRUE;
}
/*----------------------------------------------------------------------------
<function>
 FUNCTION	:	WriteBlitBlock	
    
 PURPOSE	:	Write blit data to the 2D hardware.

 PARAMETERS	:	In: dwHeader  	    - Block header
                In: dwFillColor     - Fill colour
				In: psRect		    - Destination surface dimensions
    			In: ppdwCmd - Command under construction

 RETURNS	:	void	
</function>
------------------------------------------------------------------------------*/
void WriteBlitBlock(DWORD dwHeader, DWORD dwFillColor, RECT *psRect, DWORD **ppdwCmd)
{	
    DWORD           dwDstXStart        = 0;
    DWORD           dwDstXEnd          = 0;
    DWORD           dwDstYStart        = 0;
    DWORD           dwDstYEnd          = 0;

    /* Write block header */
	*(*ppdwCmd)++ = dwHeader;

    /* 
		Write the fill colour if MBX2D_USE_FILL is specified.
		??? Check format of this - should be same as dest ??? 
	*/
	if ((dwHeader & MBX2D_PAT_MASK)	== MBX2D_USE_FILL)
    {
        *(*ppdwCmd)++ = dwFillColor;
    }
    /* 
		Build the destination size control words.For each word, cast it to 
		SHORT (maintaining sign), shift appropriately,then mask out unnecessary bits.
	*/
    dwDstXStart = (((SHORT)psRect->left  ) << MBX2D_DST_XSTART_SHIFT) & MBX2D_DST_XSTART_MASK;
    dwDstYStart = (((SHORT)psRect->top   ) << MBX2D_DST_YSTART_SHIFT) & MBX2D_DST_YSTART_MASK;
    dwDstXEnd   = (((SHORT)psRect->right ) << MBX2D_DST_XEND_SHIFT  ) & MBX2D_DST_XEND_MASK;
    dwDstYEnd   = (((SHORT)psRect->bottom) << MBX2D_DST_YEND_SHIFT  ) & MBX2D_DST_YEND_MASK;
    
    // Write the Dst control words.
    *(*ppdwCmd)++ = dwDstXStart | dwDstYStart;
    *(*ppdwCmd)++ = dwDstXEnd   | dwDstYEnd;
}
/*----------------------------------------------------------------------------
<function>
 FUNCTION	:	WriteClipBlock	
    
 PURPOSE	:	Write clip data to the 2D hardware.

 PARAMETERS	:	In: dwRectCnt       - Number of clip rectangles
                In: prDestRects	    - List of clip rectangles
    			In: ppdwCmd - Command under construction
  
 RETURNS	:	void	
</function>
------------------------------------------------------------------------------*/
void WriteClipBlock(DWORD dwRectCnt, RECT *psDestRects, DWORD **ppdwCmd)
{
    DWORD dwClipCount = (dwRectCnt << MBX2D_CLIPCOUNT_SHIFT) & MBX2D_CLIPCOUNT_MASK;
    DWORD i           = 0;

	/* 
		Hardware only supports 4 rectangles. 
		FIXME - TODO: split blit up if >4 clip rectangles.
	*/
	ASSERT(dwRectCnt <= 4);

    /* Write block header */
	*(*ppdwCmd)++ = MBX2D_CLIP_BH | dwClipCount;

    /* Write each clip rectangle */
	for(i = 0; i < dwRectCnt; i++, psDestRects++)
	{
		/* Need to check for massive clips??? FIXME */
        DWORD dwClipXMax = ((SHORT)psDestRects->right  << MBX2D_CLIP_XMAX_SHIFT) & MBX2D_CLIP_XMAX_MASK;
        DWORD dwClipXMin = ((SHORT)psDestRects->left   << MBX2D_CLIP_XMIN_SHIFT) & MBX2D_CLIP_XMIN_MASK;
        DWORD dwClipYMax = ((SHORT)psDestRects->bottom << MBX2D_CLIP_YMAX_SHIFT) & MBX2D_CLIP_YMAX_MASK;
        DWORD dwClipYMin = ((SHORT)psDestRects->top    << MBX2D_CLIP_YMIN_SHIFT) & MBX2D_CLIP_YMIN_MASK;

		*(*ppdwCmd)++ = dwClipXMax | dwClipXMin;
		*(*ppdwCmd)++ = dwClipYMax | dwClipYMin;
	}
}


/*----------------------------------------------------------------------------
<function>
 FUNCTION	: Hardware3DBlit
    
 PURPOSE	: Performs hardware blits using the	3D hardware if possible

 PARAMETERS	:  
			  
 RETURNS	: DDHAL return code.
</function>
------------------------------------------------------------------------------*/
BOOL  Hardware3DBlit(LPD3DM_SURFACE			psSourceSurface,
				     RECT					*psSourceRect,
					 LPD3DM_SURFACE			psDestSurface,
				     RECT					*psDestRect,
				     D3DMTEXTUREFILTERTYPE	Filter,
				     DWORD					dwFillColour,
				     RECT					*psClipRects,
				     DWORD					dwNumClipRects,
					 DWORD					dwSourceRotationAngle)
{
#ifdef SUPPORT_3D_BLIT

	MBX_3DBLIT_PARAMS	s3DParams;
	IMG_UINT32			ui32FBFormat;
	IMG_UINT32			ui32Width, ui32Height;

	PROFILE_START_FUNC(HARDWARE_3D_BLIT);

	/* We can't do 3D blits to any surfaces larger than the primary display mode */
	if(psDestSurface->eSurfaceType == D3DMRTYPE_TEXTURE)
	{
		ui32Width  = psDestSurface->sDescription.sTexture.dwScaledWidth;
		ui32Height = psDestSurface->sDescription.sTexture.dwScaledHeight;
	}
	else
	{
		ui32Width  = psDestSurface->dwWidth;
		ui32Height = psDestSurface->dwHeight;
	}

	if(dwSourceRotationAngle == 90 || dwSourceRotationAngle == 270)
	{
		IMG_UINT32 ui32Tmp	= ui32Width;
		ui32Width			= ui32Height;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -