📄 surface.c
字号:
return D3DM_DRIVER_HANDLED;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: PVRD3DM_LockSurface
PURPOSE:
PARAMETERS: In:
RETURNS: D3DM_DRIVER_HANDLED || D3DM_DRIVER_NOTHANDLED
</function>
------------------------------------------------------------------------------*/
DWORD PVRD3DM_LockSurface(D3DM_LOCKSURFACE_DATA *plsd)
{
LPD3DM_SURFACE psSurface = (LPD3DM_SURFACE) plsd->nSurfaceId;
D3DMLOCKED_RECT *pLockedRect = &plsd->LockedRect;
/* Check to see if we can lock surfaces of this type */
if(!ValidateLockTarget(psSurface->eSurfaceType, psSurface->dwUsage))
{
D3DM_DPF((DPF_ERROR, "PVRD3DM_LockSurface:Can't Lock surfaces of this type"));
plsd->rval = D3DMERR_DRIVERUNSUPPORTED;
return D3DM_DRIVER_HANDLED;
}
/* Determine the type of surface we want to lock */
switch(psSurface->eSurfaceType)
{
case D3DMRTYPE_BACKBUFFER:
case D3DMRTYPE_FRONTBUFFER:
case D3DMRTYPE_SURFACE:
{
LPD3DM_CONTEXT psContext = psSurface->psContext;
PVRSRV_DEV_INFO *psDevInfo = GetDevInfo(psContext);
/* Check if the surface is already Locked */
if(psSurface->hLockWait != NULL)
{
plsd->rval = D3DMERR_ALREADYLOCKED;
return D3DM_DRIVER_HANDLED;
}
if(!(psContext->sRegData.dwFlags & D3DMREG2_DISABLE_RENDER_ON_LOCK))
{
/* Flush and render render any outstanding geometry on RT's */
FlushGeometryOnSurface(psSurface);
}
/* Use services handle as unique ID for event name (required for interprocess sync) */
psSurface->hLockWait = psSurface->psContext->hServices;
/* Queue the lock */
if(PVRSRVQueueLock( psContext->psContextQueue,
psSurface->psMemInfo->psSyncInfo,
(PVRSRV_MUTEX_HANDLE *) &psSurface->hLockWait,
TRUE,
FALSE) != PVRSRV_OK)
{
plsd->rval = D3DM_GENERICFAILURE;
return D3DM_DRIVER_HANDLED;
}
/* Wait for lock wait handle to be signaled */
while(WaitForSingleObject(psSurface->hLockWait, 1) != WAIT_OBJECT_0)
{
/* Kick the command processor */
SysKickCmdProc(GetKickerAddress(psContext));
}
if(psContext->dwRotationAngle == 0 || psSurface->eSurfaceType == D3DMRTYPE_SURFACE)
{
/* Fill in locked rect struct */
pLockedRect->Pitch = psSurface->dwStrideByte;
/* Check if we're locking a specific rectangle */
if(plsd->Rect.left != 0 && plsd->Rect.right != 0)
{
pLockedRect->pBits = (VOID*)((DWORD) psSurface->psMemInfo->pvLinAddr +
(plsd->Rect.top * psSurface->dwStrideByte) +
((plsd->Rect.left * psSurface->dwBpp) >> 3));
}
else
{
pLockedRect->pBits = psSurface->psMemInfo->pvLinAddr;
}
break;
}
else
{
DWORD dwWidth = (plsd->Rect.right - plsd->Rect.left);
DWORD dwHeight = (plsd->Rect.bottom - plsd->Rect.top);
/* Surface is rotated so we need to un-rotate to a temporary */
psSurface->sDescription.sTexture.pvTempLockSurface = D3DMAllocate( dwWidth *
dwHeight *
(psSurface->dwBpp >> 3));
/* Do unrotate blit */
SoftwareRotateBlit(psContext,
psSurface,
&plsd->Rect,
(IMG_UINT8*) psSurface->sDescription.sTexture.pvTempLockSurface,
IMG_FALSE);
/* Store Rect */
psSurface->sDescription.sTexture.sTempLockSurfaceRect = plsd->Rect;
/* Fill in locked rect struct */
pLockedRect->Pitch = dwWidth * (psSurface->dwBpp >> 3);
pLockedRect->pBits = psSurface->sDescription.sTexture.pvTempLockSurface;
if(plsd->Flags & D3DMLOCK_READONLY)
{
psSurface->dwFlags &= D3DM_SURFACE_FLAGS_READ_ONLY_LOCK;
}
}
plsd->rval = D3DM_OK;
break;
}
case D3DMRTYPE_TEXTURE:
{
LPD3DM_CONTEXT psContext = psSurface->psContext;
PVRSRV_DEV_INFO *psDevInfo = GetDevInfo(psContext);
/* Check if the surface is already Locked */
if(psSurface->hLockWait != NULL)
{
plsd->rval = D3DMERR_ALREADYLOCKED;
return D3DM_DRIVER_HANDLED;
}
/* Use services handle as unique ID for event name (required for interprocess sync) */
psSurface->hLockWait = psSurface->psContext->hServices;
/* Queue the lock */
if(PVRSRVQueueLock( psContext->psContextQueue,
psSurface->psMemInfo->psSyncInfo,
(PVRSRV_MUTEX_HANDLE *) &psSurface->hLockWait,
TRUE,
FALSE) != PVRSRV_OK)
{
plsd->rval = D3DM_GENERICFAILURE;
return D3DM_DRIVER_HANDLED;
}
/* Wait for lock wait handle to be signaled */
while(WaitForSingleObject(psSurface->hLockWait, 1) != WAIT_OBJECT_0)
{
/* Kick the command processor */
SysKickCmdProc(GetKickerAddress(psContext));
}
/* Check twiddle status of Texture */
if(psSurface->dwFlags & D3DM_SURFACE_FLAGS_TWIDDLED)
{
DWORD dwWidth = (plsd->Rect.right - plsd->Rect.left);
DWORD dwHeight = (plsd->Rect.bottom - plsd->Rect.top);
/* Surface is twiddled so we need to un-twiddle to a temporary */
psSurface->sDescription.sTexture.pvTempLockSurface = D3DMAllocate( dwWidth *
dwHeight *
(psSurface->dwBpp >> 3));
/* Untwiddle data to temp surface */
UnTwiddleRegionToBuffer(psSurface,
psSurface->sDescription.sTexture.pvTempLockSurface,
dwWidth,
psSurface->dwBpp >> 3,
&plsd->Rect);
/* Store Rect */
psSurface->sDescription.sTexture.sTempLockSurfaceRect = plsd->Rect;
/* Fill in locked rect struct */
pLockedRect->Pitch = dwWidth * (psSurface->dwBpp >> 3);
pLockedRect->pBits = psSurface->sDescription.sTexture.pvTempLockSurface;
if(plsd->Flags & D3DMLOCK_READONLY)
{
psSurface->dwFlags &= D3DM_SURFACE_FLAGS_READ_ONLY_LOCK;
}
}
else
{
/* Set temp buffer pointer to null */
psSurface->sDescription.sTexture.pvTempLockSurface = NULL;
/* Fill in locked rect struct */
pLockedRect->Pitch = psSurface->dwStrideByte;
/* Check if we're locking a specific rectangle */
if(plsd->Rect.left != 0 && plsd->Rect.right != 0)
{
pLockedRect->pBits = (VOID*)((DWORD) psSurface->psMemInfo->pvLinAddr +
psSurface->sDescription.sTexture.dwLevelOffset +
(plsd->Rect.top * psSurface->dwStrideByte) +
((plsd->Rect.left * psSurface->dwBpp) >> 3));
}
else
{
pLockedRect->pBits = (VOID*)(((DWORD) psSurface->psMemInfo->pvLinAddr) +
psSurface->sDescription.sTexture.dwLevelOffset);
}
}
plsd->rval = D3DM_OK;
break;
}
case D3DMRTYPE_VERTEXBUFFER:
{
LPD3DM_VBUFFER psBuffer = (LPD3DM_VBUFFER) plsd->nSurfaceId;
pLockedRect->Pitch = psBuffer->dwStrideDW << 2;
pLockedRect->pBits = (VOID*)(((DWORD) psBuffer->pvVertexData) + plsd->Rect.left);
plsd->rval = D3DM_OK;
break;
}
case D3DMRTYPE_INDEXBUFFER:
{
LPD3DM_IBUFFER psBuffer = (LPD3DM_IBUFFER) plsd->nSurfaceId;
pLockedRect->Pitch = psBuffer->dwStrideByte;
pLockedRect->pBits = (VOID*)(((DWORD) psBuffer->pvIndexData) + plsd->Rect.left);
plsd->rval = D3DM_OK;
break;
}
default:
{
D3DM_DPF((DPF_ERROR, "PVRD3DM_LockSurface:Undefined surface type"));
plsd->rval = D3DMERR_DRIVERINVALIDCALL;
}
}
return D3DM_DRIVER_HANDLED;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: PVRD3DM_UnlockSurface
PURPOSE:
PARAMETERS: In:
RETURNS: D3DM_DRIVER_HANDLED || D3DM_DRIVER_NOTHANDLED
</function>
------------------------------------------------------------------------------*/
DWORD PVRD3DM_UnlockSurface(D3DM_UNLOCKSURFACE_DATA *pusd)
{
LPD3DM_SURFACE psSurface = (LPD3DM_SURFACE) pusd->nSurfaceId;
/* Determine the type of surface we want to lock */
switch(psSurface->eSurfaceType)
{
case D3DMRTYPE_BACKBUFFER:
case D3DMRTYPE_FRONTBUFFER:
case D3DMRTYPE_SURFACE:
{
LPD3DM_CONTEXT psContext = psSurface->psContext;
PVRSRV_DEV_INFO *psDevInfo = GetDevInfo(psContext);
/* Check if the surface is Locked */
if(psSurface->hLockWait == NULL)
{
/* Just return OK */
pusd->rval = D3DM_OK;
return D3DM_DRIVER_HANDLED;
}
/* Use services handle as unique ID for event name (required for interprocess sync) */
psSurface->hLockWait = psSurface->psContext->hServices;
/* Queue the unlock */
if(PVRSRVQueueLock( psContext->psContextQueue,
psSurface->psMemInfo->psSyncInfo,
(PVRSRV_MUTEX_HANDLE *) &psSurface->hLockWait,
FALSE,
FALSE) != PVRSRV_OK)
{
pusd->rval = D3DM_GENERICFAILURE;
return D3DM_DRIVER_HANDLED;
}
/* Wait for lock wait handle to be signaled */
while(WaitForSingleObject(psSurface->hLockWait, 1) != WAIT_OBJECT_0)
{
/* Kick the command processor */
SysKickCmdProc(GetKickerAddress(psContext));
}
/* Check the temp surface pointer */
if(psSurface->sDescription.sTexture.pvTempLockSurface != NULL)
{
/* There is a temporary surface to deal with */
if(!(psSurface->dwFlags & D3DM_SURFACE_FLAGS_READ_ONLY_LOCK))
{
/* Do rotate blit back to surface */
SoftwareRotateBlit(psContext,
psSurface,
&psSurface->sDescription.sTexture.sTempLockSurfaceRect,
(IMG_UINT8*) psSurface->sDescription.sTexture.pvTempLockSurface,
IMG_TRUE);
}
else
{
/* read only lock so no copy necessary */
psSurface->dwFlags &= ~D3DM_SURFACE_FLAGS_READ_ONLY_LOCK;
}
D3DMFree(psSurface->sDescription.sTexture.pvTempLockSurface);
psSurface->sDescription.sTexture.pvTempLockSurface = NULL;
}
/* Reset Lock variables */
psSurface->hLockWait = NULL;
pusd->rval = D3DM_OK;
break;
}
case D3DMRTYPE_TEXTURE:
{
LPD3DM_CONTEXT psContext = psSurface->psContext;
PVRSRV_DEV_INFO *psDevInfo = GetDevInfo(psContext);
/* Check if the surface is Locked */
if(psSurface->hLockWait == NULL)
{
/* Just return OK */
pusd->rval = D3DM_OK;
return D3DM_DRIVER_HANDLED;
}
/* Check the temp surface pointer */
if(psSurface->sDescription.sTexture.pvTempLockSurface != NULL)
{
/* There is a temporary surface to deal with */
if(!(psSurface->dwFlags & D3DM_SURFACE_FLAGS_READ_ONLY_LOCK))
{
/* We need to twiddle copy data back into the surface */
TwiddleRegionFromBuffer(psSurface->sDescription.sTexture.pvTempLockSurface,
psSurface,
&psSurface->sDescription.sTexture.sTempLockSurfaceRect);
}
else
{
/* read only lock so no copy necessary */
psSurface->dwFlags &= ~D3DM_SURFACE_FLAGS_READ_ONLY_LOCK;
}
D3DMFree(psSurface->sDescription.sTexture.pvTempLockSurface);
psSurface->sDescription.sTexture.pvTempLockSurface = NULL;
}
/* Use services handle as unique ID for event name (required for interprocess sync) */
psSurface->hLockWait = psSurface->psContext->hServices;
/* Queue the unlock */
if(PVRSRVQueueLock( psContext->psContextQueue,
psSurface->psMemInfo->psSyncInfo,
(PVRSRV_MUTEX_HANDLE *) &psSurface->hLockWait,
FALSE,
FALSE) != PVRSRV_OK)
{
pusd->rval = D3DM_GENERICFAILURE;
return D3DM_DRIVER_HANDLED;
}
/* Wait for lock wait handle to be signaled */
while(WaitForSingleObject(psSurface->hLockWait, 1) != WAIT_OBJECT_0)
{
/* Kick the command processor */
SysKickCmdProc(GetKickerAddress(psContext));
}
/* Reset Lock variables */
psSurface->hLockWait = NULL;
pusd->rval = D3DM_OK;
break;
}
case D3DMRTYPE_VERTEXBUFFER:
case D3DMRTYPE_INDEXBUFFER:
{
/* Nothing to do */
pusd->rval = D3DM_OK;
break;
}
default:
{
D3DM_DPF((DPF_ERROR, "PVRD3DM_UnlockSurface:Undefined surface type"));
pusd->rval = D3DMERR_DRIVERINVALIDCALL;
}
}
return D3DM_DRIVER_HANDLED;
}
/*****************************************************************************
End of file (Surface.c)
*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -