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

📄 queue.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*!****************************************************************************
@File			services_um/common/queue.c

@Title			user side command queue functions

@Author			Imagination Technologies

@date   		08/09/2003
 
@Copyright     	Copyright 2003-2004 by Imagination 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.

@Platform		generic

@Description	user side command queue functions

@DoxygenVer		

******************************************************************************/

/******************************************************************************
Modifications :-

$Log: queue.c $
*****************************************************************************/

#ifndef QUEUE_C
#define QUEUE_C

#include "img_defs.h"
#include "services.h"
#include "pvr3dif.h"
#if defined(PVR_KERNEL)
#include "hostfunc.h"
#else
#include "hostfunc_um.h"
#endif
#include "syscommon.h"
#include "sharedutils.h"
#include "mbx1defs.h"
#include "mbx13ddef.h"
#include "pvr_debug.h"

#include <stdlib.h>


/*!
@page SyncOverview Synchronisation overview

  Services provide a synchronisation interface that allows drivers to issue 
  asynchronous commands to drive hardware that is shared between multiple 
  processes, using multiple hardware components, with a minimal processing overhead.

  In systems with user/kernel divides, commands are typically submitted by
  user space driver code, and executed as soon as possible (within interupt service routines typically)
  without requiring expensive mode transitions.
  
  Since the commands are executed asynchronously, and yet are only executed when
  all previous commands that might conflict in their use of buffers have completed, 
  there is no need to poll for completion of commands etc.

*/


PVRSRV_ERROR GetFreeHWContextID (PVRSRV_DEV_INFO *psDevInfo, 
								   PVRSRV_HW_INFO *psHWInfo, 
								   IMG_UINT32 *puiRetID);

/*!
 * Macro to return space in given command queue
 */
#define GET_SPACE_IN_HWQ(psQueue)										\
	(((psQueue->ui32ReadOffset - psQueue->ui32WriteOffset)				\
	+ (psQueue->ui32QueueSize - 1)) & (psQueue->ui32QueueSize - 1))

/*!
 * Macro to Write Offset in given command queue
 */
#define UPDATE_QUEUE_WOFF(psQueue, ui32Size)							\
	psQueue->ui32WriteOffset = (psQueue->ui32WriteOffset + ui32Size)	\
	& (psQueue->ui32QueueSize - 1);


/***************************************************************************** 
	User-only functions
*****************************************************************************/


/*!
****************************************************************************
 @Function	: PVRSRVGetNextWriteOp
    
 @Description	: Gets the next operation to wait for in a sync object

 @Input	: psSyncInfo	- pointer to sync information struct
 @Input	: bIsReadOp		- Is this a read or write op
		  
 @Return : Next op value
*****************************************************************************/
IMG_EXPORT
IMG_UINT32 PVRSRVGetNextWriteOp(PVRSRV_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
{
	IMG_UINT32 ui32NextOp;			

	if(bIsReadOp)
	{
		ui32NextOp = psSyncInfo->ui32NextWriteOp;
	}
	else
	{
		/* Doesnt this need to be atomic??? - yes*/
		ui32NextOp = psSyncInfo->ui32NextWriteOp++;
	}

	return ui32NextOp;
}



/*!
*****************************************************************************
 @Function	: PVRSRVGetReadOpsPending
    
 @Description	: Gets the number of pending read ops

 @Input	: psSyncInfo	- pointer to sync information struct
 @Input : bIsReadOp		- Is this a read or write op

 @Return : Next op value
*****************************************************************************/
IMG_EXPORT
IMG_UINT32 PVRSRVGetReadOpsPending(PVRSRV_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
{
	IMG_UINT32 ui32ReadOps;			

	if(bIsReadOp)
	{
		ui32ReadOps = psSyncInfo->ui32ReadOpsPending++;
	}
	else
	{
		ui32ReadOps = psSyncInfo->ui32ReadOpsPending;
		psSyncInfo->ui32ReadOpsPending = 0;
	}

	return ui32ReadOps;
}

/*!
*****************************************************************************
 @Function	: PVRSRVReleaseQueue
    
 @Description	: Free the queue access member

 @Input	: psQueue - pointer to queue information struct
		  
 @Return	: None
*****************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVReleaseQueue(PVRSRV_QUEUE_INFO *psQueue)
{
   	return HostUnlockResource(&psQueue->hAccess); 	
}
         
                  
/*!
*****************************************************************************

 @Function	: PVRSRVGetQueueSpace
    
 @Description	: Waits for queue access rights and checks for available space in
			  queue for task param structure

 @Input	: psQueue	   	- pointer to queue information struct
 @Input : ui32ParamSize - size of task data structure
		  
 @Return	: 0 if not enough space, else pointer to param start addr in queue on success
*****************************************************************************/
IMG_EXPORT
IMG_VOID * PVRSRVGetQueueSpace(PVRSRV_QUEUE_INFO *psQueue, IMG_UINT32 ui32ParamSize)
{	
	IMG_VOID *pvRetVal;
	IMG_BOOL bTimeout;
	IMG_BOOL bStart;
	IMG_UINT32 uiStart;

	if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE)
	{
		PVR_DPF((PVR_DBG_WARNING,"PVRSRVGetQueueSpace: max command size is %d bytes", PVRSRV_MAX_CMD_SIZE));
		return NULL;
	}

	bTimeout = IMG_TRUE;
	bStart = IMG_FALSE;
	uiStart = 0;
	do
	{
		if(HostLockResource (&psQueue->hAccess, IMG_FALSE)==PVRSRV_OK)
		{
			if (GET_SPACE_IN_HWQ(psQueue) > ui32ParamSize)
			{
				bTimeout = IMG_FALSE;
				break;	
			}
			/* Not enough space in the queue, so release the mutex for a bit and try again*/
			if(HostUnlockResource (&psQueue->hAccess) != PVRSRV_OK)
			{
				PVR_DPF((PVR_DBG_ERROR,"HostUnlockResource: failed to unlock resource"));
			}
		}

		if (bStart == IMG_FALSE)
		{
			bStart = IMG_TRUE;
			uiStart = HostClockus();
		}
		HostWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
	} while ((HostClockus() - uiStart) < MAX_HW_TIME_US);

	if (bTimeout == IMG_TRUE)
	{
		/* failure */
		if(HostUnlockResource (&psQueue->hAccess) != PVRSRV_OK)
		{
			PVR_DPF((PVR_DBG_ERROR,"HostUnlockResource: failed to unlock resource"));
		}
	    pvRetVal = IMG_NULL;
	}
	else
	{
		pvRetVal = (IMG_VOID *)(psQueue->ui32WriteOffset + (IMG_UINT32)psQueue->pvLinQueueUM);
	}

	return pvRetVal;
}


/*!
*****************************************************************************
 @Function	: PVRSRVUpdateQueue
 
 @Description	: Updates the Queue Write pointer to take into account the new
			  params added to the Queue			  

 @Input	: psQueue		- pointer to queue information struct
 @Input : ui32ParamSize	- size of task data structure
		  
 @Return : None
*****************************************************************************/
IMG_EXPORT
IMG_VOID PVRSRVUpdateQueue(	PVRSRV_QUEUE_INFO *psQueue, 
							IMG_UINT32 ui32ParamSize)
{
	UPDATE_QUEUE_WOFF(psQueue, ui32ParamSize)

	SysKickCmdProc (psQueue->pui32KickerAddr);
}

/*!
****************************************************************************
 @Function	: QueueRender
    
 @Description	: Inserts a render command into a Q

 @Input	psQueue		- pointer to queue information struct
 @Input	psTARenderInfo 	- pointer to the render info
 @Input	psBGObjInfo - pointer to the info needed to complete the background object
 @Input	bExternalDepthBuffer - has an external Z buffer been allocated
 @Input	psDstSync - Destination sync structure
 @Input	ui32NumSrcSyncs - How many sources are we synchronising with
 @Input	apsSrcSync[] - Pointers to the SyncInfos within the source MEM_INFOs
 @Input	ui32NumRegs	 - number of 3D registers
 @Input	psRegs		 - array of register (address:value) pairs
			  
 @Return : PVRSRV_ERROR_INVALID_PARAMS if too many SRCs
*****************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVQueueRender (PVRSRV_QUEUE_INFO *psQueue, 
								PVRSRV_TARENDERINFO *psTARenderInfo,
								PVRSRV_BGOBJ_INFO *psBGObjInfo,
								IMG_BOOL bExternalDepthBuffer,
								PVRSRV_SYNC_INFO *psDstSync,
					  			IMG_UINT32 ui32NumSrcSyncs, 
					  			PVRSRV_SYNC_INFO *apsSrcSync[], 
					  			IMG_UINT32 ui32NumRegs, 
					  			PVRSRV_HWREG *psRegs)
{
	PVRSRV_RENDER_CMD_INFO	*psRenderCmd;
	IMG_UINT32 ui32CommandSize;
	PVRSRV_SRCSYNC_INFO *psSrcSyncInfo;
	PVRSRV_HWREG *psRegData;
	IMG_UINT32 i;

	if (ui32NumSrcSyncs > PVRSRV_MAX_RENDER_SRC)
	{
		return PVRSRV_ERROR_INVALID_PARAMS;
	}
	
	ui32CommandSize = sizeof(PVRSRV_RENDER_CMD_INFO) + (ui32NumRegs * sizeof(PVRSRV_HWREG)) - sizeof(IMG_UINT32) + 
					(sizeof(PVRSRV_SRCSYNC_INFO) * ui32NumSrcSyncs);

	/*
		round to 4byte units
	*/
	ui32CommandSize =  (ui32CommandSize+3) & ~3L;

	psRenderCmd = (PVRSRV_RENDER_CMD_INFO *) PVRSRVGetQueueSpace(psQueue, ui32CommandSize);

	if(!psRenderCmd)
	{
		PVR_DPF((PVR_DBG_ERROR,"Couldn't get space in queue"));
		return PVRSRV_ERROR_TIMEOUT;
	}

	psRenderCmd->sCmdInfo.ui32CommandID = PVRSRV_CMD_ID_RENDER;
	psRenderCmd->sCmdInfo.ui32Size = ui32CommandSize;

	psRenderCmd->ui32TexFormatStride = psBGObjInfo->ui32TexFormatStride;
	psRenderCmd->ui32TexAddrStride = psBGObjInfo->ui32TexAddrStride;

	psRenderCmd->bExternalDepthBuffer = bExternalDepthBuffer;
	psRenderCmd->ui32CurrentRenderData = psTARenderInfo->psSharedData->ui32CurrentRenderData;
	psRenderCmd->psTARenderInfo = psTARenderInfo->psTARenderInfoKM;

	psRenderCmd->ui32DstNextWriteOpVal = PVRSRVGetNextWriteOp(psDstSync, IMG_FALSE);
	
	psRenderCmd->ui32DstReadOpsPending = PVRSRVGetReadOpsPending(psDstSync, IMG_FALSE);
	psRenderCmd->psDstSyncInfoKM = psDstSync->psKernSyncInfo;
	
	psSrcSyncInfo = (PVRSRV_SRCSYNC_INFO *)&psRenderCmd->aui32Data[0];

	for(i = 0; i < ui32NumSrcSyncs; i++)
	{
		psSrcSyncInfo[i].ui32NextWriteOpVal = PVRSRVGetNextWriteOp(apsSrcSync[i], IMG_TRUE);

		PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);

		psSrcSyncInfo[i].psSyncInfoKM = apsSrcSync[i]->psKernSyncInfo;
	}

	psRenderCmd->ui32NumSrcSyncInfos = ui32NumSrcSyncs;

	psRegData = (PVRSRV_HWREG *)&psSrcSyncInfo[i];

⌨️ 快捷键说明

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