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

📄 surface.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 4 页
字号:

    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 + -