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

📄 blit.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    
 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 + -