📄 blit.c
字号:
PURPOSE : Performs copy blit between PVR Textures
</function>
------------------------------------------------------------------------------*/
void PVRTCCopy(LPD3DM_SURFACE psSourceSurface,
LPD3DM_SURFACE psDestSurface)
{
DWORD dwBitsPerPixel = (psDestSurface->eFormat == MBXFOURCC_PVRTC4) ? 4 : 2;
DWORD dwWidthPsuedoPixel = (psDestSurface->eSurfaceType == D3DMRTYPE_TEXTURE) ?
(psDestSurface->sDescription.sTexture.dwScaledWidth * dwBitsPerPixel)/16:
(psDestSurface->dwWidth * dwBitsPerPixel)/16;
DWORD dwHeight = (psDestSurface->eSurfaceType == D3DMRTYPE_TEXTURE) ?
psDestSurface->sDescription.sTexture.dwScaledHeight:
(psDestSurface->dwHeight * dwBitsPerPixel)/16;
#ifdef SOFTWARE_PVRTC_COPY
PVOID pvSourceAddress = (PVOID)(psSourceSurface->eSurfaceType == D3DMRTYPE_TEXTURE) ?
(((PBYTE)psSourceSurface->psMemInfo->pvLinAddr) + psSourceSurface->sDescription.sTexture.dwLevelOffset):
(psSourceSurface->psMemInfo->pvLinAddr);
PVOID pvDestAddress = (PVOID)(psDestSurface->eSurfaceType == D3DMRTYPE_TEXTURE) ?
(((PBYTE)psDestSurface->psMemInfo->pvLinAddr) + psDestSurface->sDescription.sTexture.dwLevelOffset):
(psDestSurface->psMemInfo->pvLinAddr);
memcpy(pvDestAddress, pvSourceAddress, dwWidthPsuedoPixel * dwHeight * 2);
#else
DWORD dwCommandPacket[10];
DWORD dwSourceAddress = (psSourceSurface->eSurfaceType == D3DMRTYPE_TEXTURE) ?
(psSourceSurface->psMemInfo->uiDevAddr.uiAddr + psSourceSurface->sDescription.sTexture.dwLevelOffset):
(psSourceSurface->psMemInfo->uiDevAddr.uiAddr);
DWORD dwDestAddress = (psDestSurface->eSurfaceType == D3DMRTYPE_TEXTURE) ?
(psDestSurface->psMemInfo->uiDevAddr.uiAddr + psDestSurface->sDescription.sTexture.dwLevelOffset):
(psDestSurface->psMemInfo->uiDevAddr.uiAddr);
dwCommandPacket[0] = MBX2D_DST_CTRL_BH
| MBX2D_SRC_4444ARGB
| (((dwWidthPsuedoPixel * 2/* 2 bytes per psuedo pixel*/)
<< MBX2D_DST_STRIDE_SHIFT)
& MBX2D_DST_STRIDE_MASK);
dwCommandPacket[1] = ((dwDestAddress
>> MBX2D_DST_ADDR_ALIGNSHIFT)
<< MBX2D_DST_ADDR_SHIFT)
& MBX2D_DST_ADDR_MASK;
dwCommandPacket[2] = MBX2D_SRC_CTRL_BH
| MBX2D_SRC_FBMEM
| MBX2D_SRC_4444ARGB
| ((dwWidthPsuedoPixel * 2
<< MBX2D_SRC_STRIDE_SHIFT)
& MBX2D_SRC_STRIDE_MASK);
dwCommandPacket[3] = (( dwSourceAddress
>> MBX2D_SRC_ADDR_ALIGNSHIFT)
<< MBX2D_SRC_ADDR_SHIFT)
& MBX2D_SRC_ADDR_MASK;
/* Write the starting pixel coordinate */
dwCommandPacket[4] = MBX2D_SRC_OFF_BH
| ((0 << MBX2D_SRCOFF_XSTART_SHIFT) & MBX2D_SRCOFF_XSTART_MASK)
| ((0 << MBX2D_SRCOFF_YSTART_SHIFT) & MBX2D_SRCOFF_YSTART_MASK);
dwCommandPacket[5] = MBX2D_STRETCH_BH
| (MBX2D_NO_STRETCH<<MBX2D_X_STRETCH_SHIFT)
| (MBX2D_NO_STRETCH<<MBX2D_Y_STRETCH_SHIFT);
dwCommandPacket[6] = MBX2D_BLIT_BH | MBX2D_ROP3_SRCCOPY;
dwCommandPacket[7] = 0;/* colour */
dwCommandPacket[8] = 0;/* Starting point */
dwCommandPacket[9] = (dwWidthPsuedoPixel << MBX2D_DST_XEND_SHIFT)
| (dwHeight << MBX2D_DST_YEND_SHIFT);
/* Queue the blit */
if(PVRSRVQueueBlt( psSourceSurface->psContext->psContextQueue,
psDestSurface->psMemInfo->psSyncInfo,
1,
&psSourceSurface->psMemInfo->psSyncInfo ,
10,
dwCommandPacket)!= PVRSRV_OK)
{
D3DM_DPF((DPF_ERROR, "PVRTCCopy:Couldn't queue the blit. Failing"));
psSourceSurface->psContext->hrLastError = D3DMERR_DRIVERINTERNALERROR;
return;
}
PROFILE_STOP_FUNC(TWIDDLE_COPY);
#endif
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: PresentFlip
PURPOSE: Performs a presentation flip from one surface to another
PARAMETERS: In: psTargetSurface - Surface to flip to
In: dwSyncInterval - Interval between flips
RETURNS:
</function>
------------------------------------------------------------------------------*/
VOID PresentFlip(LPD3DM_SURFACE psTargetSurface, DWORD dwSyncInterval)
{
LPD3DM_SURFACE psCurrentDisplay;
LPD3DM_CONTEXT psContext;
psContext = psTargetSurface->psContext;
psCurrentDisplay = psContext->psCurrentDisplay;
/* Queue the flip */
if(PVRSRVQueueFlip(psContext->psContextQueue,
psTargetSurface->psMemInfo->psSyncInfo,
psCurrentDisplay->psMemInfo->psSyncInfo,
psTargetSurface->psMemInfo,
(dwSyncInterval == 0) ? FALSE : TRUE,
dwSyncInterval) != PVRSRV_OK)
{
D3DM_DPF((DPF_ERROR, "Flip:Couldn't queue the flip"));
psContext->hrLastError = D3DM_GENERICFAILURE;
return;
}
psContext->psCurrentDisplay = psTargetSurface;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: Copy
PURPOSE: Calculates and waits for VSync, then performs the necessary blit
PARAMETERS: In: ppd - Presentation data
RETURNS:
</function>
------------------------------------------------------------------------------*/
VOID Copy(LPD3DM_PRESENT ppd)
{
DWORD dwSyncVal;
LPD3DM_SURFACE psPresentSurface;
LPD3DM_CONTEXT psContext;
RECT sNewRects[2];
RECT *psNewClipRects, *psSourceRect, *psDestRect;
psPresentSurface = (LPD3DM_SURFACE) ppd->PresentSurface;
psContext = psPresentSurface->psContext;
/* Determine vsync interval */
switch(psContext->SwapEffect)
{
case D3DMSWAPEFFECT_DISCARD:
{
dwSyncVal = 1;
break;
}
case D3DMSWAPEFFECT_COPY_VSYNC:
{
dwSyncVal = psContext->nVSyncInterval;
break;
}
case D3DMSWAPEFFECT_COPY:
{
dwSyncVal = 0;
break;
}
}
/* FIXME - TODO - VSYNC BLITS - CURRENTLY UNSUPPORTED*/
if(psContext->dwRotationAngle != 0)
{
/* Rotate rects as required */
RotateRects(psContext,
(LPD3DMRECT)sNewRects,
(LPD3DMRECT)&ppd->SourceRect,
1,
psPresentSurface->dwWidth,
psPresentSurface->dwHeight);
RotateRects(psContext,
(LPD3DMRECT)&sNewRects[1],
(LPD3DMRECT)&ppd->DestinationRect,
1,
psContext->psCurrentDisplay->dwWidth,
psContext->psCurrentDisplay->dwHeight);
if(ppd->NumClippingRects > 0)
{
/* Rotate rects as required */
psNewClipRects = D3DMAllocate(sizeof(D3DMRECT) * ppd->NumClippingRects);
RotateRects(psContext,
(LPD3DMRECT)psNewClipRects,
(LPD3DMRECT)&ppd->ClippingRects,
ppd->NumClippingRects,
psContext->psCurrentDisplay->dwWidth,
psContext->psCurrentDisplay->dwHeight);
}
else
{
psNewClipRects = ppd->ClippingRects;
}
psSourceRect = &sNewRects[0];
psDestRect = &sNewRects[1];
}
else
{
psNewClipRects = ppd->ClippingRects;
psSourceRect = &ppd->SourceRect;
psDestRect = &ppd->DestinationRect;
}
/* Perform the blit */
if(!Hardware2DBlit(psPresentSurface,
psSourceRect,
psContext->psCurrentDisplay,
psDestRect,
D3DMTEXF_NONE,
0,
psNewClipRects,
ppd->NumClippingRects,
0))
{
/* Hardware can't do it so try a software blit */
if(!SoftwareBlit(psPresentSurface,
psSourceRect,
psContext->psCurrentDisplay,
psDestRect,
D3DMTEXF_NONE,
0,
psNewClipRects,
ppd->NumClippingRects,
0))
{
D3DM_DPF((DPF_ERROR, "Copy:Couldn't do the presentation blit. Failing"));
psContext->hrLastError = D3DMERR_DRIVERINTERNALERROR;
return;
}
}
if(psContext->dwRotationAngle != 0 && ppd->NumClippingRects > 0)
{
D3DMFree(psNewClipRects);
}
#if defined (DEBUG)
/* Queue a cornflower blue colourfill for the D3DMSWAPEFFECT_DISCARD swap effect */
if(psContext->SwapEffect == D3DMSWAPEFFECT_DISCARD)
{
D3DM_COLORFILL sColourFill;
sColourFill.Rect = ppd->SourceRect;
sColourFill.SurfaceId = (ULONG) psPresentSurface;
sColourFill.Color = 0xFF6595ED;
ColourFill(&sColourFill);
}
#endif
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: CopyRectangle
PURPOSE: Copies a rectangle from one surface to another
PARAMETERS: In: pcrd - Copy rect data
RETURNS:
</function>
------------------------------------------------------------------------------*/
VOID CopyRectangle(LPD3DM_COPYRECT pcrd)
{
LPD3DM_SURFACE psSourceSurface;
LPD3DM_SURFACE psDestSurface;
RECT sDest, *psSourceRect, *psDestRect;
DWORD dwTargetWidth, dwTargetHeight;
DWORD dwSourceRectWidth, dwSourceRectHeight;
D3DMRECT sNewRects[2];
LPD3DM_CONTEXT psContext;
psSourceSurface = (LPD3DM_SURFACE) pcrd->SourceSurf;
psDestSurface = (LPD3DM_SURFACE) pcrd->DestSurf;
dwSourceRectWidth = pcrd->SourceRect.right - pcrd->SourceRect.left;
dwSourceRectHeight = pcrd->SourceRect.bottom - pcrd->SourceRect.top;
psContext = psSourceSurface->psContext;
/* Flush any outstanding geometry */
FlushGeometryOnSurface(psDestSurface);
/* Check for PVRTC */
if(psDestSurface->eFormat == MBXFOURCC_PVRTC4 ||
psDestSurface->eFormat == MBXFOURCC_PVRTC2 ||
psSourceSurface->eFormat == MBXFOURCC_PVRTC4 ||
psSourceSurface->eFormat == MBXFOURCC_PVRTC2)
{
/*
Test against the middleware assigned surface sizes to determine if we are blitting
whole surface as the actual texture size may be scaled in some manner
*/
if(psDestSurface->eFormat != psSourceSurface->eFormat ||
(dwSourceRectWidth != psDestSurface->dwWidth && dwSourceRectHeight != psDestSurface->dwHeight))
{
/* FIXME Can we do partial copies of PVRTC? */
/* Unsupported */
D3DM_DPF((DPF_ERROR, "CopyRectangle:Unsupported PVRTC Blit. Failing"));
psSourceSurface->psContext->hrLastError = D3DMERR_DRIVERINTERNALERROR;
return;
}
else
{
PVRTCCopy(psSourceSurface, psDestSurface);
return;
}
}
/* Obtain relevant target dimensions */
if(psDestSurface->eSurfaceType == D3DMRTYPE_TEXTURE)
{
dwTargetWidth = psDestSurface->sDescription.sTexture.dwScaledWidth;
dwTargetHeight = psDestSurface->sDescription.sTexture.dwScaledHeight;
}
else if(psDestSurface->eSurfaceType == D3DMRTYPE_SURFACE)
{
dwTargetWidth = psDestSurface->dwWidth;
dwTargetHeight = psDestSurface->dwHeight;
}
else
{
/* We need to ensure target dimensions are swapped if we're rotated */
switch(psContext->dwRotationAngle)
{
case 0:
case 180:
{
dwTargetWidth = psDestSurface->dwWidth;
dwTargetHeight = psDestSurface->dwHeight;
break;
}
case 90:
case 270:
{
dwTargetHeight = psDestSurface->dwWidth;
dwTargetWidth = psDestSurface->dwHeight;
break;
}
}
}
*((POINT*)&sDest) = pcrd->DestPoint;
/* Calculate target rect width */
if(sDest.left + dwSourceRectWidth > dwTargetWidth)
{
/* Clip dest rect to right edge */
sDest.right = dwTargetWidth;
/* Modify source width so copy occurs, rather than a stretch */
pcrd->SourceRect.right = pcrd->SourceRect.left + (sDest.right - sDest.left);
}
else
{
sDest.right = sDest.left + dwSourceRectWidth;
}
/* Calculate target rect Height */
if(sDest.top + dwSourceRectHeight > dwTargetHeight)
{
/* Clip dest rect to bottom edge */
sDest.bottom = dwTargetHeight;
/* Modify source width so copy occurs, rather than a stretch */
pcrd->SourceRect.bottom = pcrd->SourceRect.top + (sDest.bottom - sDest.top);
}
else
{
sDest.bottom = sDest.top + dwSourceRectHeight;
}
/* Scale rects as required */
ScaleRectAndClamp(&pcrd->SourceRect, psSourceSurface);
ScaleRectAndClamp(&sDest, psDestSurface);
/* Check rotation status */
if(psContext->dwRotationAngle != 0 &&
(psSourceSurface->eSurfaceType == D3DMRTYPE_BACKBUFFER ||
psSourceSurface->eSurfaceType == D3DMRTYPE_FRONTBUFFER ||
psDestSurface->eSurfaceType == D3DMRTYPE_BACKBUFFER ||
psDestSurface->eSurfaceType == D3DMRTYPE_FRONTBUFFER))
{
if((psSourceSurface->eSurfaceType == D3DMRTYPE_BACKBUFFER ||
psSourceSurface->eSurfaceType == D3DMRTYPE_FRONTBUFFER) &&
(psDestSurface->eSurfaceType == D3DMRTYPE_BACKBUFFER ||
psDestSurface->eSurfaceType == D3DMRTYPE_FRONTBUFFER))
{
/* Source and dest buffers are rotated so just rotated the rects and the blit will work */
RotateRects(psContext,
sNewRects,
(LPD3DMRECT)&pcrd->SourceRect,
1,
psSourceSurface->dwWidth,
psSourceSurface->dwHeight);
RotateRects(psContext,
&sNewRects[1],
(LPD3DMRECT)&sDest,
1,
psDestSurface->dwWidth,
psDestSurface->dwHeight);
psSourceRect = (RECT*)sNewRects;
psDestRect = (RECT*)&sNewRects[1];
}
else if(psSourceSurface->eSurfaceType == D3DMRTYPE_BACKBUFFER ||
psSourceSurface->eSurfaceType == D3DMRTYPE_FRONTBUFFER)
{
DWORD dwRotationAngle;
/* Source is rotated */
RotateRects(psContext,
sNewRects,
(LPD3DMRECT)&pcrd->SourceRect,
1,
psSourceSurface->dwWidth,
psSourceSurface->dwHeight);
switch(psContext->dwRotationAngle)
{
case 180:
{
dwRotationAngle = 180;
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -