📄 blitsw.c
字号:
/******************************************************************************
<module>
* Name : Blitsw.c
* Title : Software 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 software blitting and colourfilling.
*
* Platform : Windows CE
*
</module>
********************************************************************************/
#include "context.h"
/*----------------------------------------------------------------------------
<function>
FUNCTION : RotatePixelCoords
PURPOSE : Takes a pixel location and gives its equivalent rotated coords
</function>
------------------------------------------------------------------------------*/
IMG_VOID RotatePixelCoords(IMG_UINT32 ui32Xin,
IMG_UINT32 ui32Yin,
IMG_UINT32 *pui32Xout,
IMG_UINT32 *pui32Yout,
IMG_UINT32 ui32TargetWidth,
IMG_UINT32 ui32TargetHeight,
IMG_UINT32 ui32RotationAngle)
{
switch(ui32RotationAngle)
{
case 0:
{
*pui32Xout = ui32Xin;
*pui32Yout = ui32Yin;
break;
}
case 90:
{
*pui32Xout = ui32Yin;
*pui32Yout = ui32TargetHeight - ui32Xin - 1;
break;
}
case 180:
{
*pui32Xout = ui32TargetWidth - ui32Xin - 1;
*pui32Yout = ui32TargetHeight - ui32Yin - 1;
break;
}
case 270:
{
*pui32Xout = ui32TargetWidth - ui32Yin - 1;
*pui32Yout = ui32Xin;
break;
}
}
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : PixelIsClipped
PURPOSE : Checks to see if a point is clipped out or not
</function>
------------------------------------------------------------------------------*/
IMG_BOOL PixelIsClipped(RECT *psClipRects,
IMG_UINT32 ui32NumClipRects,
LPD3DM_SURFACE psDestSurface,
RECT *psDestRect,
IMG_UINT32 ui32X,
IMG_UINT32 ui32Y)
{
IMG_INT32 i32XSurfaceValue, i32YSurfaceValue;
IMG_UINT32 i;
i32XSurfaceValue = (IMG_INT32) ui32X + psDestRect->left;
i32YSurfaceValue = (IMG_INT32) ui32Y + psDestRect->top;
for(i=0; i< ui32NumClipRects; i++, psClipRects++)
{
if(i32XSurfaceValue > psClipRects->left &&
i32XSurfaceValue < psClipRects->right &&
i32YSurfaceValue > psClipRects->top &&
i32YSurfaceValue < psClipRects->bottom)
{
/* Pixel isn't clipped */
return FALSE;
}
}
return TRUE;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : GetPixelFromBuffer
PURPOSE : Grabs a pixel from a buffer
</function>
------------------------------------------------------------------------------*/
IMG_UINT32 GetPixelFromBuffer(IMG_UINT8 *pui8Pixels,
IMG_UINT32 ui32StrideByte,
IMG_UINT32 ui32X,
IMG_UINT32 ui32Y,
IMG_UINT32 ui32BytesPerPixel)
{
IMG_UINT32 ui32TargetColour;
switch(ui32BytesPerPixel)
{
case 1:
{
ui32TargetColour = (IMG_UINT32) *(pui8Pixels +
(ui32Y * ui32StrideByte) +
(ui32X * ui32BytesPerPixel));
break;
}
case 2:
{
ui32TargetColour = (IMG_UINT32) *((IMG_UINT16*) (pui8Pixels +
(ui32Y * ui32StrideByte) +
(ui32X * ui32BytesPerPixel)));
break;
}
case 4:
{
ui32TargetColour = *((IMG_UINT32*) (pui8Pixels +
(ui32Y * ui32StrideByte) +
(ui32X * ui32BytesPerPixel)));
break;
}
}
return ui32TargetColour;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : WritePixelToBuffer
PURPOSE : Writes a pixel to a buffer
</function>
------------------------------------------------------------------------------*/
IMG_VOID WritePixelToBuffer(IMG_UINT8 *pui8Pixels,
IMG_UINT32 ui32PixelValue,
IMG_UINT32 ui32StrideByte,
IMG_UINT32 ui32X,
IMG_UINT32 ui32Y,
IMG_UINT32 ui32BytesPerPixel)
{
/* Copy pixel to buffer */
switch(ui32BytesPerPixel)
{
case 1:
{
*(pui8Pixels + (ui32Y * ui32StrideByte) +
(ui32X * ui32BytesPerPixel))
= ((IMG_UINT8) ui32PixelValue);
break;
}
case 2:
{
*((IMG_UINT16*)(pui8Pixels +
(ui32Y * ui32StrideByte) +
(ui32X * ui32BytesPerPixel)))
= ((IMG_UINT16) ui32PixelValue);
break;
}
case 4:
{
*((IMG_UINT32*)(pui8Pixels +
(ui32Y * ui32StrideByte) +
(ui32X * ui32BytesPerPixel)))
= ui32PixelValue;
break;
}
}
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : ScaleColour
PURPOSE : Scales a colour value
</function>
------------------------------------------------------------------------------*/
IMG_VOID ScaleColour(IMG_UINT32 *pui32ColourVal, IMG_UINT32 ui32MaxSource, IMG_UINT32 ui32MaxDest)
{
IMG_UINT8 ui8Shift = 0;
if(ui32MaxSource > ui32MaxDest)
{
/* Dest value has smaller headroom (fewer bits) */
while(ui32MaxSource != ui32MaxDest)
{
ui32MaxSource = ui32MaxSource >> 1;
ui8Shift++;
}
*pui32ColourVal = *pui32ColourVal >> ui8Shift;
}
else if(ui32MaxDest > ui32MaxSource)
{
/* Dest value has greater headroom (more bits) */
while(ui32MaxDest != ui32MaxSource)
{
ui32MaxSource = (ui32MaxSource << 1) | 0x1;
ui8Shift++;
}
*pui32ColourVal = *pui32ColourVal << ui8Shift;
}
else return; /* No change */
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : CopyConvertPixel
PURPOSE : Copys and converts the given pixel
</function>
------------------------------------------------------------------------------*/
IMG_VOID CopyConvertPixel(PVR_DEVFORMAT *psSourceFMT,
IMG_UINT8 *pui8Src,
IMG_UINT32 ui32SrcStrideByte,
IMG_UINT32 ui32SrcBytesPerPixel,
PVR_DEVFORMAT *psDestFMT,
IMG_UINT8 *pui8Dest,
IMG_UINT32 ui32DestStrideByte,
IMG_UINT32 ui32DestBytesPerPixel,
IMG_UINT32 ui32X,
IMG_UINT32 ui32Y,
IMG_UINT32 ui32RotationAngle,
IMG_UINT32 ui32TargetWidth,
IMG_UINT32 ui32TargetHeight)
{
IMG_UINT32 ui32Pixel;
IMG_UINT32 ui32Alpha, ui32Red, ui32Green, ui32Blue;
IMG_UINT32 ui32XRotate, ui32YRotate;
/* Grab source pixel */
ui32Pixel = GetPixelFromBuffer(pui8Src, ui32SrcStrideByte, ui32X, ui32Y, ui32SrcBytesPerPixel);
/* Unpack Source pixel */
ui32Alpha = ((ui32Pixel & psSourceFMT->ui32AMask) >> psSourceFMT->ui32AShift);
ui32Red = ((ui32Pixel & psSourceFMT->ui32RMask) >> psSourceFMT->ui32RShift);
ui32Green = ((ui32Pixel & psSourceFMT->ui32GMask) >> psSourceFMT->ui32GShift);
ui32Blue = ((ui32Pixel & psSourceFMT->ui32BMask) >> psSourceFMT->ui32BShift);
/* Scale Colour Values */
ScaleColour(&ui32Alpha, psSourceFMT->ui32AMask >> psSourceFMT->ui32AShift, psDestFMT->ui32AMask >> psDestFMT->ui32AShift);
ScaleColour(&ui32Red, psSourceFMT->ui32RMask >> psSourceFMT->ui32RShift, psDestFMT->ui32RMask >> psDestFMT->ui32RShift);
ScaleColour(&ui32Green, psSourceFMT->ui32GMask >> psSourceFMT->ui32GShift, psDestFMT->ui32GMask >> psDestFMT->ui32GShift);
ScaleColour(&ui32Blue, psSourceFMT->ui32BMask >> psSourceFMT->ui32BShift, psDestFMT->ui32BMask >> psDestFMT->ui32BShift);
/* Repack pixel */
ui32Pixel = (ui32Alpha << psDestFMT->ui32AShift)
| (ui32Red << psDestFMT->ui32RShift)
| (ui32Green << psDestFMT->ui32GShift)
| (ui32Blue << psDestFMT->ui32BShift);
switch(ui32RotationAngle)
{
case 0:
{
ui32XRotate = ui32X;
ui32YRotate = ui32Y;
break;
}
case 90:
case 180:
case 270:
{
RotatePixelCoords(ui32X, ui32Y, &ui32XRotate, &ui32YRotate, ui32TargetWidth, ui32TargetHeight, ui32RotationAngle);
break;
}
}
/* Write new pixel to dest */
WritePixelToBuffer(pui8Dest, ui32Pixel, ui32DestStrideByte, ui32XRotate, ui32YRotate, ui32DestBytesPerPixel);
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : InterpolatePixels
PURPOSE : Interpolates between 2 pixel values
</function>
------------------------------------------------------------------------------*/
IMG_UINT32 InterpolatePixels(PVR_DEVFORMAT *psPixelFormat,
IMG_UINT32 ui32PixValA,
IMG_FLOAT fPixScaleA,
IMG_UINT32 ui32PixValB,
IMG_FLOAT fPixScaleB)
{
IMG_FLOAT fPixAAlpha, fPixARed, fPixAGreen, fPixABlue;
IMG_FLOAT fPixBAlpha, fPixBRed, fPixBGreen, fPixBBlue;
IMG_FLOAT fPixOutAlpha, fPixOutRed, fPixOutGreen, fPixOutBlue;
/* Unpack Pixel A */
fPixAAlpha = (IMG_FLOAT) ((ui32PixValA & psPixelFormat->ui32AMask) >> psPixelFormat->ui32AShift);
fPixARed = (IMG_FLOAT) ((ui32PixValA & psPixelFormat->ui32RMask) >> psPixelFormat->ui32RShift);
fPixAGreen = (IMG_FLOAT) ((ui32PixValA & psPixelFormat->ui32GMask) >> psPixelFormat->ui32GShift);
fPixABlue = (IMG_FLOAT) ((ui32PixValA & psPixelFormat->ui32BMask) >> psPixelFormat->ui32BShift);
/* Unpack Pixel B */
fPixBAlpha = (IMG_FLOAT) ((ui32PixValB & psPixelFormat->ui32AMask) >> psPixelFormat->ui32AShift);
fPixBRed = (IMG_FLOAT) ((ui32PixValB & psPixelFormat->ui32RMask) >> psPixelFormat->ui32RShift);
fPixBGreen = (IMG_FLOAT) ((ui32PixValB & psPixelFormat->ui32GMask) >> psPixelFormat->ui32GShift);
fPixBBlue = (IMG_FLOAT) ((ui32PixValB & psPixelFormat->ui32BMask) >> psPixelFormat->ui32BShift);
/* Scale and accumulate */
fPixOutAlpha = (fPixAAlpha * fPixScaleA) + (fPixBAlpha * fPixScaleB);
fPixOutRed = (fPixARed * fPixScaleA) + (fPixBRed * fPixScaleB);
fPixOutGreen = (fPixAGreen * fPixScaleA) + (fPixBGreen * fPixScaleB);
fPixOutBlue = (fPixABlue * fPixScaleA) + (fPixBBlue * fPixScaleB);
/* Repack and return */
return (((IMG_UINT32) (fPixOutAlpha + 0.5f)) << psPixelFormat->ui32AShift)
| (((IMG_UINT32) (fPixOutRed + 0.5f)) << psPixelFormat->ui32RShift)
| (((IMG_UINT32) (fPixOutGreen + 0.5f)) << psPixelFormat->ui32GShift)
| (((IMG_UINT32) (fPixOutBlue + 0.5f)) << psPixelFormat->ui32BShift);
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : RoundPixel
PURPOSE : Rounds floating point pixel to nearest pixel
</function>
------------------------------------------------------------------------------*/
IMG_VOID RoundPixel(IMG_FLOAT fX, IMG_FLOAT fY, IMG_UINT32 *pui32X1, IMG_UINT32 *pui32Y1)
{
*pui32X1 = (IMG_UINT32) (fX + 0.5f);
*pui32Y1 = (IMG_UINT32) (fY + 0.5f);
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : GetNearestPixels
PURPOSE : Finds the 4 nearest pixels to given floating point pixel values
</function>
------------------------------------------------------------------------------*/
IMG_VOID GetNearestPixels(IMG_FLOAT fX,
IMG_FLOAT fY,
IMG_UINT32 *pui32X1,
IMG_UINT32 *pui32Y1,
IMG_UINT32 *pui32X2,
IMG_UINT32 *pui32Y2,
IMG_UINT32 *pui32X3,
IMG_UINT32 *pui32Y3,
IMG_UINT32 *pui32X4,
IMG_UINT32 *pui32Y4)
{
*pui32X1 = (IMG_UINT32) fX;
*pui32Y1 = (IMG_UINT32) fY;
*pui32X2 = (IMG_UINT32) (fX + 1.0f);
*pui32Y2 = (IMG_UINT32) fY;
*pui32X3 = (IMG_UINT32) fX;
*pui32Y3 = (IMG_UINT32) (fY + 1.0f);
*pui32X4 = (IMG_UINT32) (fX + 1.0f);
*pui32Y4 = (IMG_UINT32) (fY + 1.0f);
}
/*----------------------------------------------------------------------------
<function>
FUNCTION : SoftwareBlit
PURPOSE : Performs software blits - last chance blitting - will be slow
RETURNS : DDHAL return code.
</function>
------------------------------------------------------------------------------*/
BOOL SoftwareBlit(LPD3DM_SURFACE psSourceSurface,
RECT *psSourceRect,
LPD3DM_SURFACE psDestSurface,
RECT *psDestRect,
D3DMTEXTUREFILTERTYPE Filter,
DWORD dwFillColour,
RECT *psClipRects,
DWORD dwNumClipRects,
DWORD dwRotationAngle)
{
/* TODO -
Verify supported Format
Scale Source To temp with Filtering
Copy convert with clipping
If dest is texture see if we can twiddle ?
*/
PVR_DEVFORMAT *psSourceFMT = IMG_NULL, *psDestFMT = IMG_NULL;
IMG_UINT8 *pui8Dest, *pui8Src;
IMG_UINT32 ui32TargetWidth, ui32TargetHeight, ui32SourceWidth, ui32SourceHeight;
IMG_BOOL bStretch;
IMG_BOOL bFilter;
IMG_UINT32 i, j;
IMG_UINT32 ui32TargetColour;
IMG_UINT32 ui32SrcBytesPerPixel, ui32DestBytesPerPixel;
IMG_UINT32 ui32SrcStrideBytes, ui32DestStrideBytes;
IMG_UINT32 ui32SourceSurfaceWidth, ui32SourceSurfaceHeight;
IMG_UINT32 ui32DestSurfaceWidth, ui32DestSurfaceHeight;
IMG_UINT32 ui32SrcNextWriteOpVal = 0, ui32DstNextWriteOpVal = 0, ui32DstReadOpsPending = 0;
PVRSRV_MEM_INFO *psSourceMemInfo, *psDestMemInfo = psDestSurface->psMemInfo;
IMG_BOOL bTimeout = IMG_TRUE;
IMG_BOOL bStart = IMG_FALSE;
IMG_UINT32 uiStart = 0;
PROFILE_START_FUNC(SOFTWARE_BLIT);
/* Surface Synchronisation */
ui32DstReadOpsPending = PVRSRVGetReadOpsPending(psDestMemInfo->psSyncInfo, IMG_FALSE);
if(psSourceSurface != IMG_NULL)
{
psSourceMemInfo = psSourceSurface->psMemInfo;
ui32SrcNextWriteOpVal = PVRSRVGetNextWriteOp(psSourceMemInfo->psSyncInfo, IMG_TRUE);
PVRSRVGetReadOpsPending(psSourceMemInfo->psSyncInfo, IMG_TRUE);
}
ui32DstNextWriteOpVal = PVRSRVGetNextWriteOp(psDestSurface->psMemInfo->psSyncInfo, IMG_FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -