overlay.c

来自「Lido PXA270平台开发板的最新BSP,包括源代码」· C语言 代码 · 共 764 行 · 第 1/2 页

C
764
字号
/*****************************************************************************
 Name			: OVERLAY.C
 
 Title			: Direct Draw surface Overlay callbacks	
 
 C Author 		: Kevan Ahmadi
 
 Created  		: 13/01/03
 
 Copyright      : 2003 by Imaginationc 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 	: DDRAW Overlay callbacks
                  This source file is a modified version of overlay.c, originally located in:
                  embedded\wince\directx\dxcommon
   
 Program Type	: 32-bit DLL

 Version	 	: $Revision: 1.9.1.2 $

 Modifications	:

 $Log: overlay.c $
*****************************************************************************/
#include "ddraw_headers.h"
#include "vlddrawi.h"
#include "overlay.h"
#include "services.h"
#include "drvescape.h"

enum {eOVERLAY_SUCCESS = 0, eOVERLAY_ERROR = 1};

DISP_STATE		g_DISPState	= { FALSE, 0, NULL, 0, 0, 0, FALSE};

static IMG_INT32 DisplayStateInit();

/***********************************************************************************
 Function Name      : GetRotationAngle
 Inputs             : 
 Outputs            : 
 Returns            : ui32Angle
 Description        : Returns display rotation angle.
************************************************************************************/
static IMG_UINT32 GetRotationAngle()
{
	IMG_UINT32 ui32Angle=0;
	
	/* 
	 * This driver escape gives us a consistant interpretation of rotation angle
	 * Otherwise we get different angles for PocketPC and WinCE
	 */
	ExtEscape(g_DISPState.hdcDriver, DRVESC_GET_PHYS_ROTATION, 0,                      	
			  NULL, sizeof(PDWORD), (LPSTR)&ui32Angle);

	switch(ui32Angle)
	{
		case DMDO_0:
			/* do nothing */
		default:
			break;
		case DMDO_90:
			ui32Angle=90;
			break;
		case DMDO_180:
			ui32Angle=180;
			break;
		case DMDO_270:
			ui32Angle=270;
			break;
	}

	return(ui32Angle);
}

/***********************************************************************************
 Function Name      : DisplayStateInit
 Inputs             : 
 Outputs            : 
 Returns            : IMG_UINT32
 Description        : Initialize global DISP_STATE struct.
************************************************************************************/
static IMG_INT32 DisplayStateInit()
{
	if (g_DISPState.bHardwareInUse)
	{
		return eOVERLAY_SUCCESS;
	}

	g_DISPState.psLastSyncObject = NULL;
	g_DISPState.bFirstSyncIncremented = IMG_FALSE;

	memset(&g_DISPState, 0, sizeof(g_DISPState));

	g_DISPState.bHardwareInUse	= TRUE;

	g_DISPState.hdcDriver = GetWindowDC(NULL);

	if (PVRSRVAcquireDeviceData(NULL, 0, &g_DISPState.sDevData, PVRSRV_DEVICE_TYPE_MBX1_LITE) != PVRSRV_OK)
	{
		DPF("UpdateOverlay : failed call to PVRSRVAcquireDeviceData");
		g_DISPState.hServices = NULL;
		return eOVERLAY_ERROR;
	}
	return eOVERLAY_SUCCESS;
}

/***********************************************************************************
 Function Name      : DisplayStateDeinit
 Inputs             : 
 Outputs            : 
 Returns            : IMG_UINT32
 Description        : Deinitialize global DISP_STATE struct - free resources.
************************************************************************************/
IMG_UINT32 DisplayStateDeinit()
{
	IMG_UINT32 ui32i;

	if (!g_DISPState.bHardwareInUse)
	{
		return eOVERLAY_SUCCESS;
	}

	if (g_DISPState.psLastSyncObject != NULL)
	{
		/* The method by which ui32ReadOpsComplete is incremented does not handle 
		the last surface to be flipped to. Hence this must be corrected during
		deinitialization. */
		g_DISPState.psLastSyncObject->ui32ReadOpsComplete = g_DISPState.psLastSyncObject->ui32ReadOpsPending;
	}

	g_DISPState.psLastSyncObject = NULL;
	g_DISPState.bFirstSyncIncremented = IMG_FALSE;

	if (g_DISPState.bRotatedBuffersAllocated == TRUE)
	{
		/* free the device memory we allocated for rotation */	
		for (ui32i=0; ui32i < DISP_NUM_ROT_SURFACES; ui32i++)
		{
			if (PVRSRVFreeDeviceMem(&g_DISPState.sDevData, g_DISPState.apsDisplaySurfaces[ui32i]) != PVRSRV_OK)
			{
				DPF("UpdateOverlay : failed call to PVRSRVFreeDeviceMem");
				return eOVERLAY_ERROR;
			}
			g_DISPState.apsDisplaySurfaces[ui32i] = NULL;
		}

		/* Destroy the command queue */
		PVRSRVDestroyCommandQueue(&g_DISPState.sDevData,g_DISPState.psBlitQueueInfo); 
		g_DISPState.bRotatedBuffersAllocated = FALSE;
	}

	ReleaseDC(NULL, g_DISPState.hdcDriver);

	PVRSRVReleaseDeviceData(&g_DISPState.sDevData);
	g_DISPState.hServices = NULL;
	g_DISPState.hdcDriver = NULL;
	g_DISPState.bHardwareInUse = FALSE;

	return eOVERLAY_SUCCESS;
}


/*****************************************************************************
 FUNCTION	: UpdateOverlay
    
 PURPOSE	: Updates overlay properties

 PARAMETERS	: psData from DirectX
 			  
 RETURNS	: DDHAL return code.
*****************************************************************************/
DWORD __stdcall HALUpdateOverlay(LPDDHAL_UPDATEOVERLAYDATA psData)
{

	PSURFDATA			psSurfData;
	PDXHALDATA			psDriverData;
	PVRSRV_DEV_INFO		*psDevInfo;
	PPDP_OVERLAYATTRIBS	psOverlayAttribs;
	DDCOLORKEY			*psColourKey;
	WORD				wFlags =0;
	IMG_UINT32			ui32Size;
	IMG_UINT32			ui32ScreenWidth, ui32ScreenHeight;
	PDP_OVERLAY*		psFlipToOverlay;
	IMG_UINT32			ui32i;
	IMG_BOOL			bTimeout = IMG_TRUE;
	IMG_BOOL			bStart	= IMG_FALSE;
	IMG_UINT32			uiStart = 0;

	// FIXME - Part of temp flush fix below
	PVRSRV_SYNC_INFO	*psSyncInfo;

	/*Extract our driver data from global object*/
	psDriverData = GetDriverData(psData->lpDD);
	psDevInfo = psDriverData->sDisplayDevData.psDevInfoKM;
	psSurfData = (PSURFDATA) psData->lpDDSrcSurface->lpGbl->dwReserved1;

	psOverlayAttribs = &psDriverData->sOverlayAttributes;

	/* 
	 * source and dest rectangles are always updated.  
	 * The Pixel format is always valid 
	 * Colour key is always either enabled or disabled 
	 */

	/* If we need to hide the overlay, assume all other overlay attributes
	in psData are invalid. */

	if (psData->dwFlags & DDOVER_HIDE)
	{
		psOverlayAttribs->wValidFlags = PDP_OVERLAYATTRIB_VALID_VISIBILITY;
		psOverlayAttribs->bOverlayOn = FALSE;
	}
	else
	{
		psOverlayAttribs->wValidFlags = PDP_OVERLAYATTRIB_VALID_DSTPOSITION | 
									PDP_OVERLAYATTRIB_VALID_SRCPOSITION |
									PDP_OVERLAYATTRIB_VALID_PIXFMT |
									PDP_OVERLAYATTRIB_VALID_CKEY;
	}

	/************************************ Rotation ********************************/

	/* Note: the code below (handling rotation) was adapted from VDISP_SetOverlayAttributes. */

	if (DisplayStateInit() != 0)
	{
		/* Failed to initialize DISP_STATE struct */
		DPF("HALUpdateOverlay: ERROR: Call to DisplayStateInit failed");
		psData->ddRVal = DDERR_GENERIC;
		return DDHAL_DRIVER_NOTHANDLED;
	}

	g_DISPState.ui32DisplayRotation = GetRotationAngle();

	if (g_DISPState.ui32DisplayRotation)
	{
		/* If rotation is performed pixel format must be IMC2 */
		if (psOverlayAttribs->PixFormat != PDP_OVL_IMC2)
		{
			/* If pixel format is not IMC2, then disable rotation. */
			g_DISPState.ui32DisplayRotation = 0;
			g_DISPState.ui32SourceRotation = 0;
		}
	}

	ui32ScreenWidth  	= GetDeviceCaps(g_DISPState.hdcDriver, HORZRES);
	ui32ScreenHeight	= GetDeviceCaps(g_DISPState.hdcDriver, VERTRES);

	/* If the screen is rotated (and assuming a Disable Rotation flag is not set) then we need to 
	make sure we have rotated display surfaces allocated and that we tell PDPAPI the 
	rotated coordinates. */

	if (g_DISPState.ui32DisplayRotation)
    {
    	/* we need to rotate the video */
		g_DISPState.ui32SourceRotation = g_DISPState.ui32DisplayRotation;

		/* Create command queue and allocate buffers if not already done. */
		if (!g_DISPState.bRotatedBuffersAllocated)
		{
			IMG_UINT32 ui32RotatedDisplaySurfStride;

			/* Create the blit queue that we need */
			if (PVRSRVCreateCommandQueue(&g_DISPState.sDevData, DISP_QUEUE_SIZE, &g_DISPState.psBlitQueueInfo) != PVRSRV_OK)
			{
				/* Failed to get the blit queue so we can't rotate the video. */
				DPF("HALUpdateOverlay: ERROR: Call to PVRSRVCreateCommandQueue failed - cannot perform rotation-blit");
				psData->ddRVal = DDERR_GENERIC;
				return DDHAL_DRIVER_NOTHANDLED;
			}

			/* allocate the buffers */

			/* assume that the width and height will have suitable alignments */

			ui32RotatedDisplaySurfStride = (g_DISPState.ui32DisplayRotation == 180) ? 
												      ((psData->rSrc.right  + (4 - 1)) & ~(4 - 1)):
												      ((psData->rSrc.bottom + (4 - 1)) & ~(4 - 1));

			ui32Size = (g_DISPState.ui32DisplayRotation == 180) ?
							psData->rSrc.bottom * ((ui32RotatedDisplaySurfStride * 3) / 2):
							psData->rSrc.right  * ((ui32RotatedDisplaySurfStride * 3) / 2);

			for (ui32i=0; ui32i < DISP_NUM_ROT_SURFACES; ui32i++)
			{
				if (PVRSRVAllocDeviceMem(&g_DISPState.sDevData, 0, ui32Size, ALLOCATION_ALIGNMENT, &g_DISPState.apsDisplaySurfaces[ui32i]) != PVRSRV_OK)
				{
					/* Allocation failed so clean up any we successfully allocated then exit */
					DPF("HALUpdateOverlay: ERROR: Call to PVRSRVAllocDeviceMem failed - cannot perform rotation-blit");
					psData->ddRVal = DDERR_GENERIC;
					return DDHAL_DRIVER_NOTHANDLED;
				}
			}
			g_DISPState.bRotatedBuffersAllocated = TRUE;
		}
    }
	else
	{
		g_DISPState.ui32SourceRotation = 0;
	}

	switch (g_DISPState.ui32DisplayRotation)
	{
		case 0:
			psOverlayAttribs->nTop    = psData->rDest.top;
			psOverlayAttribs->nBottom = psData->rDest.bottom;
			psOverlayAttribs->nLeft   = psData->rDest.left;
			psOverlayAttribs->nRight  = psData->rDest.right;
			break;

		case 90:
			psOverlayAttribs->nTop    = ui32ScreenWidth - psData->rDest.right;
			psOverlayAttribs->nBottom = ui32ScreenWidth - psData->rDest.left;
			psOverlayAttribs->nLeft   = psData->rDest.top;
			psOverlayAttribs->nRight  = psData->rDest.bottom;
			break;

		case 180:
			psOverlayAttribs->nTop    = ui32ScreenHeight - psData->rDest.bottom;
			psOverlayAttribs->nBottom = ui32ScreenHeight - psData->rDest.top;
			psOverlayAttribs->nLeft   = ui32ScreenWidth - psData->rDest.right;
			psOverlayAttribs->nRight  = ui32ScreenWidth - psData->rDest.left;
			break;

		case 270:
			psOverlayAttribs->nTop    = psData->rDest.left;
			psOverlayAttribs->nBottom = psData->rDest.right;
			psOverlayAttribs->nLeft   = ui32ScreenHeight - psData->rDest.bottom;
			psOverlayAttribs->nRight  = ui32ScreenHeight - psData->rDest.top;
			break;
	}

	switch (g_DISPState.ui32SourceRotation)
	{
		case 0:
			psOverlayAttribs->wSrcX1 = (WORD)psData->rSrc.left;
			psOverlayAttribs->wSrcY1 = (WORD)psData->rSrc.top;
			psOverlayAttribs->wSrcX2 = (WORD)psData->rSrc.right;
			psOverlayAttribs->wSrcY2 = (WORD)psData->rSrc.bottom;
			break;

		case 90:
			psOverlayAttribs->wSrcX1 = (WORD) psData->rSrc.top;
			psOverlayAttribs->wSrcY1 = (WORD) (psSurfData->dwWidth - psData->rSrc.right);
			psOverlayAttribs->wSrcX2 = (WORD) psData->rSrc.bottom;
			psOverlayAttribs->wSrcY2 = (WORD) (psSurfData->dwWidth - psData->rSrc.left);
			break;

		case 180:
			psOverlayAttribs->wSrcX1 = (WORD) (psSurfData->dwWidth - psData->rSrc.right);
			psOverlayAttribs->wSrcY1 = (WORD) (psSurfData->dwHeight - psData->rSrc.bottom);
			psOverlayAttribs->wSrcX2 = (WORD) (psSurfData->dwWidth - psData->rSrc.left);
			psOverlayAttribs->wSrcY2 = (WORD) (psSurfData->dwHeight - psData->rSrc.top);
			break;

		case 270:
			psOverlayAttribs->wSrcX1 = (WORD) (psSurfData->dwHeight - psData->rSrc.bottom);
			psOverlayAttribs->wSrcY1 = (WORD) psData->rSrc.left;
			psOverlayAttribs->wSrcX2 = (WORD) (psSurfData->dwHeight - psData->rSrc.top);
			psOverlayAttribs->wSrcY2 = (WORD) psData->rSrc.right;
			break;
	}

	/*Check if we need to show the overlay*/
	if (psData->dwFlags & DDOVER_SHOW)
	{
		psOverlayAttribs->wValidFlags |= PDP_OVERLAYATTRIB_VALID_VISIBILITY;
		psOverlayAttribs->bOverlayOn = TRUE;
	}

	if (psData->dwFlags & (DDOVER_KEYDEST | DDOVER_KEYDESTOVERRIDE))
	{
		/*Find colour key structure to use*/
		if (psData->dwFlags & DDOVER_KEYDESTOVERRIDE)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?