📄 blit.c
字号:
/******************************************************************************
<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 + -