/********************************************************************** * * Copyright (C) Imagination Technologies Ltd. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful but, except * as otherwise stated in writing, without any warranty; without even the * implied warranty of merchantability or fitness for a particular purpose. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * * The full GNU General Public License is included in this distribution in * the file called "COPYING". * * Contact Information: * Imagination Technologies Ltd. * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK * ******************************************************************************/ #include "services_headers.h" #include "buffer_manager.h" #include "kernelbuffer.h" #include "kerneldisplay.h" #include "pvr_bridge_km.h" #include "pdump_km.h" #include "deviceid.h" #include "lists.h" PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID); PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID); #if defined(SUPPORT_MISR_IN_THREAD) void OSVSyncMISR(IMG_HANDLE, IMG_BOOL); #endif #if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS) IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie, IMG_BOOL bScheduleMISR); #endif typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE; typedef struct PVRSRV_DC_BUFFER_TAG { PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer; struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo; struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain; } PVRSRV_DC_BUFFER; typedef struct PVRSRV_DC_SWAPCHAIN_TAG { IMG_HANDLE hExtSwapChain; IMG_UINT32 ui32SwapChainID; IMG_UINT32 ui32RefCount; IMG_UINT32 ui32Flags; PVRSRV_QUEUE_INFO *psQueue; PVRSRV_DC_BUFFER asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS]; IMG_UINT32 ui32BufferCount; PVRSRV_DC_BUFFER *psLastFlipBuffer; IMG_UINT32 ui32MinSwapInterval; IMG_UINT32 ui32MaxSwapInterval; #if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) PVRSRV_KERNEL_SYNC_INFO **ppsLastSyncInfos; IMG_UINT32 ui32LastNumSyncInfos; #endif struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo; struct PVRSRV_DC_SWAPCHAIN_TAG *psNext; } PVRSRV_DC_SWAPCHAIN; typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG { struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain; IMG_HANDLE hResItem; } PVRSRV_DC_SWAPCHAIN_REF; typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG { IMG_UINT32 ui32RefCount; IMG_UINT32 ui32DeviceID; IMG_HANDLE hExtDevice; PPVRSRV_DC_SRV2DISP_KMJTABLE psFuncTable; IMG_HANDLE hDevMemContext; PVRSRV_DC_BUFFER sSystemBuffer; struct PVRSRV_DC_SWAPCHAIN_TAG *psDCSwapChainShared; } PVRSRV_DISPLAYCLASS_INFO; typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PRESMAN_ITEM hResItem; } PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO; typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE; typedef struct PVRSRV_BC_BUFFER_TAG { PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer; struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo; } PVRSRV_BC_BUFFER; typedef struct PVRSRV_BUFFERCLASS_INFO_TAG { IMG_UINT32 ui32RefCount; IMG_UINT32 ui32DeviceID; IMG_HANDLE hExtDevice; PPVRSRV_BC_SRV2BUFFER_KMJTABLE psFuncTable; IMG_HANDLE hDevMemContext; IMG_UINT32 ui32BufferCount; PVRSRV_BC_BUFFER *psBuffer; } PVRSRV_BUFFERCLASS_INFO; typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG { PVRSRV_BUFFERCLASS_INFO *psBCInfo; IMG_HANDLE hResItem; } PVRSRV_BUFFERCLASS_PERCONTEXT_INFO; static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM) { PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM; return psDCPerContextInfo->psDCInfo; } static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM) { PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM; return psBCPerContextInfo->psBCInfo; } static IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) { IMG_UINT *pui32DevCount; IMG_UINT32 **ppui32DevID; PVRSRV_DEVICE_CLASS peDeviceClass; pui32DevCount = va_arg(va, IMG_UINT*); ppui32DevID = va_arg(va, IMG_UINT32**); peDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS); if ((psDeviceNode->sDevId.eDeviceClass == peDeviceClass) && (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_EXT)) { (*pui32DevCount)++; if(*ppui32DevID) { *(*ppui32DevID)++ = psDeviceNode->sDevId.ui32DeviceIndex; } } } IMG_EXPORT PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass, IMG_UINT32 *pui32DevCount, IMG_UINT32 *pui32DevID ) { IMG_UINT ui32DevCount = 0; SYS_DATA *psSysData; SysAcquireData(&psSysData); List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList, &PVRSRVEnumerateDCKM_ForEachVaCb, &ui32DevCount, &pui32DevID, DeviceClass); if(pui32DevCount) { *pui32DevCount = ui32DevCount; } else if(pui32DevID == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDCKM: Invalid parameters")); return (PVRSRV_ERROR_INVALID_PARAMS); } return PVRSRV_OK; } static PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable, IMG_UINT32 *pui32DeviceID) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL; PVRSRV_DEVICE_NODE *psDeviceNode; SYS_DATA *psSysData; SysAcquireData(&psSysData); if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psDCInfo), (IMG_VOID **)&psDCInfo, IMG_NULL, "Display Class Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet (psDCInfo, 0, sizeof(*psDCInfo)); if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), (IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL, "Function table for SRVKM->DISPLAY") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc")); goto ErrorExit; } OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE)); *psDCInfo->psFuncTable = *psFuncTable; if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), (IMG_VOID **)&psDeviceNode, IMG_NULL, "Device Node") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc")); goto ErrorExit; } OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE)); psDeviceNode->pvDevice = (IMG_VOID*)psDCInfo; psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo); psDeviceNode->ui32RefCount = 1; psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT; psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY; psDeviceNode->psSysData = psSysData; if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID")); goto ErrorExit; } psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex; if (pui32DeviceID) { *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex; } SysRegisterExternalDevice(psDeviceNode); List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode); return PVRSRV_OK; ErrorExit: if(psDCInfo->psFuncTable) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL); psDCInfo->psFuncTable = IMG_NULL; } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL); return PVRSRV_ERROR_OUT_OF_MEMORY; } static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex) { SYS_DATA *psSysData; PVRSRV_DEVICE_NODE *psDeviceNode; PVRSRV_DISPLAYCLASS_INFO *psDCInfo; SysAcquireData(&psSysData); psDeviceNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, &MatchDeviceKM_AnyVaCb, ui32DevIndex, IMG_FALSE, PVRSRV_DEVICE_CLASS_DISPLAY); if (!psDeviceNode) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex)); return PVRSRV_ERROR_NO_DEVICENODE_FOUND; } psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice; if(psDCInfo->ui32RefCount == 0) { List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode); SysRemoveExternalDevice(psDeviceNode); PVR_ASSERT(psDCInfo->ui32RefCount == 0); (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex); (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL); psDCInfo->psFuncTable = IMG_NULL; (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL); (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); } else { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: failed as %d Services DC API connections are still open", psDCInfo->ui32RefCount)); return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE; } return PVRSRV_OK; } static PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable, IMG_UINT32 *pui32DeviceID) { PVRSRV_BUFFERCLASS_INFO *psBCInfo = IMG_NULL; PVRSRV_DEVICE_NODE *psDeviceNode; SYS_DATA *psSysData; SysAcquireData(&psSysData); if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psBCInfo), (IMG_VOID **)&psBCInfo, IMG_NULL, "Buffer Class Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet (psBCInfo, 0, sizeof(*psBCInfo)); if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), (IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL, "Function table for SRVKM->BUFFER") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc")); goto ErrorExit; } OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE)); *psBCInfo->psFuncTable = *psFuncTable; if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), (IMG_VOID **)&psDeviceNode, IMG_NULL, "Device Node") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc")); goto ErrorExit; } OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE)); psDeviceNode->pvDevice = (IMG_VOID*)psBCInfo; psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo); psDeviceNode->ui32RefCount = 1; psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT; psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER; psDeviceNode->psSysData = psSysData; if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID")); goto ErrorExit; } psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex; if (pui32DeviceID) { *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex; } List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode); return PVRSRV_OK; ErrorExit: if(psBCInfo->psFuncTable) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PPVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL); psBCInfo->psFuncTable = IMG_NULL; } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL); return PVRSRV_ERROR_OUT_OF_MEMORY; } static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex) { SYS_DATA *psSysData; PVRSRV_DEVICE_NODE *psDevNode; PVRSRV_BUFFERCLASS_INFO *psBCInfo; SysAcquireData(&psSysData); psDevNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, &MatchDeviceKM_AnyVaCb, ui32DevIndex, IMG_FALSE, PVRSRV_DEVICE_CLASS_BUFFER); if (!psDevNode) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: requested device %d not present", ui32DevIndex)); return PVRSRV_ERROR_NO_DEVICENODE_FOUND; } psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice; if(psBCInfo->ui32RefCount == 0) { List_PVRSRV_DEVICE_NODE_Remove(psDevNode); (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex); (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL); psBCInfo->psFuncTable = IMG_NULL; (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL); (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL); } else { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: failed as %d Services BC API connections are still open", psBCInfo->ui32RefCount)); return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE; } return PVRSRV_OK; } IMG_EXPORT PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback) { PVRSRV_ERROR eError; PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; PVR_UNREFERENCED_PARAMETER(bResManCallback); psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM; eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem, CLEANUP_WITH_POLL); return eError; } static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy) { PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVR_UNREFERENCED_PARAMETER(ui32Param); PVR_UNREFERENCED_PARAMETER(bDummy); psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)pvParam; psDCInfo = psDCPerContextInfo->psDCInfo; if(psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount != 0) { PVR_DPF((PVR_DBG_MESSAGE,"CloseDCDeviceCallBack: system buffer (0x%p) still mapped (refcount = %d)", &psDCInfo->sSystemBuffer.sDeviceClassBuffer, psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount)); #if 0 return PVRSRV_ERROR_STILL_MAPPED; #endif } psDCInfo->ui32RefCount--; if(psDCInfo->ui32RefCount == 0) { psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice); PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); if (psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) { PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); } psDCInfo->hDevMemContext = IMG_NULL; psDCInfo->hExtDevice = IMG_NULL; } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL); return PVRSRV_OK; } IMG_EXPORT PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_UINT32 ui32DeviceID, IMG_HANDLE hDevCookie, IMG_HANDLE *phDeviceKM) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; PVRSRV_DEVICE_NODE *psDeviceNode; SYS_DATA *psSysData; PVRSRV_ERROR eError; if(!phDeviceKM || !hDevCookie) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params")); return PVRSRV_ERROR_INVALID_PARAMS; } SysAcquireData(&psSysData); psDeviceNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, &MatchDeviceKM_AnyVaCb, ui32DeviceID, IMG_FALSE, PVRSRV_DEVICE_CLASS_DISPLAY); if (!psDeviceNode) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID)); return PVRSRV_ERROR_NO_DEVICENODE_FOUND; } psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psDCPerContextInfo), (IMG_VOID **)&psDCPerContextInfo, IMG_NULL, "Display Class per Context Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo)); if(psDCInfo->ui32RefCount++ == 0) { psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie; psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext; eError = PVRSRVAllocSyncInfoKM(IMG_NULL, (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext, &psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc")); psDCInfo->ui32RefCount--; return eError; } eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID, &psDCInfo->hExtDevice, (PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device")); psDCInfo->ui32RefCount--; PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); return eError; } psDCPerContextInfo->psDCInfo = psDCInfo; eError = PVRSRVGetDCSystemBufferKM(psDCPerContextInfo, IMG_NULL); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to get system buffer")); psDCInfo->ui32RefCount--; PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); return eError; } PVRSRVKernelSyncInfoIncRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount = 0; } else { psDCPerContextInfo->psDCInfo = psDCInfo; } psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DISPLAYCLASS_DEVICE, psDCPerContextInfo, 0, &CloseDCDeviceCallBack); *phDeviceKM = (IMG_HANDLE)psDCPerContextInfo; return PVRSRV_OK; } IMG_EXPORT PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM, IMG_UINT32 *pui32Count, DISPLAY_FORMAT *psFormat) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; if(!hDeviceKM || !pui32Count || !psFormat) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCFormatsKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat); } IMG_EXPORT PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM, DISPLAY_FORMAT *psFormat, IMG_UINT32 *pui32Count, DISPLAY_DIMS *psDim) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; if(!hDeviceKM || !pui32Count || !psFormat) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim); } IMG_EXPORT PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM, IMG_HANDLE *phBuffer) { PVRSRV_ERROR eError; PVRSRV_DISPLAYCLASS_INFO *psDCInfo; IMG_HANDLE hExtBuffer; if(!hDeviceKM) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Failed to get valid buffer handle from external driver")); return eError; } psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr; psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext; psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice; psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer; psDCInfo->sSystemBuffer.psDCInfo = psDCInfo; if (phBuffer) { *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer); } return PVRSRV_OK; } IMG_EXPORT PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM, DISPLAY_INFO *psDisplayInfo) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_ERROR eError; if(!hDeviceKM || !psDisplayInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCInfoKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo); if (eError != PVRSRV_OK) { return eError; } if (psDisplayInfo->ui32MaxSwapChainBuffers > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS) { psDisplayInfo->ui32MaxSwapChainBuffers = PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS; } return PVRSRV_OK; } IMG_EXPORT PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChainRef) { PVRSRV_ERROR eError; PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef; if(!hSwapChainRef) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyDCSwapChainKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psSwapChainRef = hSwapChainRef; eError = ResManFreeResByPtr(psSwapChainRef->hResItem, CLEANUP_WITH_POLL); return eError; } static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain) { PVRSRV_ERROR eError; PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo; IMG_UINT32 i; if( psDCInfo->psDCSwapChainShared ) { if( psDCInfo->psDCSwapChainShared == psSwapChain ) { psDCInfo->psDCSwapChainShared = psSwapChain->psNext; } else { PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain; psCurrentSwapChain = psDCInfo->psDCSwapChainShared; while( psCurrentSwapChain->psNext ) { if( psCurrentSwapChain->psNext != psSwapChain ) { psCurrentSwapChain = psCurrentSwapChain->psNext; continue; } psCurrentSwapChain->psNext = psSwapChain->psNext; break; } } } PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue); eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice, psSwapChain->hExtSwapChain); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy DC swap chain")); return eError; } for(i=0; iui32BufferCount; i++) { if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); if (psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) { PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); } } } #if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) if (psSwapChain->ppsLastSyncInfos) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos, psSwapChain->ppsLastSyncInfos, IMG_NULL); } #endif OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL); return eError; } static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy) { PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF *) pvParam; PVRSRV_ERROR eError = PVRSRV_OK; IMG_UINT32 i; PVR_UNREFERENCED_PARAMETER(ui32Param); PVR_UNREFERENCED_PARAMETER(bDummy); for (i = 0; i < psSwapChainRef->psSwapChain->ui32BufferCount; i++) { if (psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0) { PVR_DPF((PVR_DBG_ERROR, "DestroyDCSwapChainRefCallBack: swapchain (0x%p) still mapped (ui32MemMapRefCount = %d)", &psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer, psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount)); #if 0 return PVRSRV_ERROR_STILL_MAPPED; #endif } } if(--psSwapChainRef->psSwapChain->ui32RefCount == 0) { eError = DestroyDCSwapChain(psSwapChainRef->psSwapChain); } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), psSwapChainRef, IMG_NULL); return eError; } static PVRSRV_DC_SWAPCHAIN* PVRSRVFindSharedDCSwapChainKM(PVRSRV_DISPLAYCLASS_INFO *psDCInfo, IMG_UINT32 ui32SwapChainID) { PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain; for(psCurrentSwapChain = psDCInfo->psDCSwapChainShared; psCurrentSwapChain; psCurrentSwapChain = psCurrentSwapChain->psNext) { if(psCurrentSwapChain->ui32SwapChainID == ui32SwapChainID) return psCurrentSwapChain; } return IMG_NULL; } static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA *psPerProc, PVRSRV_DC_SWAPCHAIN *psSwapChain, PVRSRV_DC_SWAPCHAIN_REF **ppsSwapChainRef) { PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL; if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), (IMG_VOID **)&psSwapChainRef, IMG_NULL, "Display Class Swapchain Reference") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainRefKM: Failed psSwapChainRef alloc")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF)); psSwapChain->ui32RefCount++; psSwapChainRef->psSwapChain = psSwapChain; psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, psSwapChainRef, 0, &DestroyDCSwapChainRefCallBack); *ppsSwapChainRef = psSwapChainRef; return PVRSRV_OK; } IMG_EXPORT PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDeviceKM, IMG_UINT32 ui32Flags, DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib, DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib, IMG_UINT32 ui32BufferCount, IMG_UINT32 ui32OEMFlags, IMG_HANDLE *phSwapChainRef, IMG_UINT32 *pui32SwapChainID) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_SWAPCHAIN *psSwapChain = IMG_NULL; PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL; PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS]; PVRSRV_QUEUE_INFO *psQueue = IMG_NULL; PVRSRV_ERROR eError; IMG_UINT32 i; DISPLAY_INFO sDisplayInfo; if(!hDeviceKM || !psDstSurfAttrib || !psSrcSurfAttrib || !phSwapChainRef || !pui32SwapChainID) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too many buffers")); return PVRSRV_ERROR_TOOMANYBUFFERS; } if (ui32BufferCount < 2) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too few buffers")); return PVRSRV_ERROR_TOO_FEW_BUFFERS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY ) { psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID ); if( psSwapChain ) { eError = PVRSRVCreateDCSwapChainRefKM(psPerProc, psSwapChain, &psSwapChainRef); if( eError != PVRSRV_OK ) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference")); return eError; } *phSwapChainRef = (IMG_HANDLE)psSwapChainRef; return PVRSRV_OK; } PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: No shared SwapChain found for query")); return PVRSRV_ERROR_FLIP_CHAIN_EXISTS; } if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), (IMG_VOID **)&psSwapChain, IMG_NULL, "Display Class Swapchain") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExit; } OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN)); eError = PVRSRVCreateCommandQueueKM(1024, &psQueue); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue")); goto ErrorExit; } psSwapChain->psQueue = psQueue; for(i=0; ihDevMemContext, &psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to alloc syninfo for psSwapChain")); goto ErrorExit; } PVRSRVKernelSyncInfoIncRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr; psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext; psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice; psSwapChain->asBuffer[i].psDCInfo = psDCInfo; psSwapChain->asBuffer[i].psSwapChain = psSwapChain; apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM; } psSwapChain->ui32BufferCount = ui32BufferCount; psSwapChain->psDCInfo = psDCInfo; #if defined(PDUMP) PDUMPCOMMENT("Allocate DC swap chain (SwapChainID == %u, BufferCount == %u)", *pui32SwapChainID, ui32BufferCount); PDUMPCOMMENT(" Src surface dimensions == %u x %u", psSrcSurfAttrib->sDims.ui32Width, psSrcSurfAttrib->sDims.ui32Height); PDUMPCOMMENT(" Dst surface dimensions == %u x %u", psDstSurfAttrib->sDims.ui32Width, psDstSurfAttrib->sDims.ui32Height); #endif eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, &sDisplayInfo); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to get DC info")); return eError; } psSwapChain->ui32MinSwapInterval = sDisplayInfo.ui32MinSwapInterval; psSwapChain->ui32MaxSwapInterval = sDisplayInfo.ui32MaxSwapInterval; eError = psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice, ui32Flags, psDstSurfAttrib, psSrcSurfAttrib, ui32BufferCount, apsSyncData, ui32OEMFlags, &psSwapChain->hExtSwapChain, &psSwapChain->ui32SwapChainID); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain")); PDUMPCOMMENT("Swapchain allocation failed."); goto ErrorExit; } eError = PVRSRVCreateDCSwapChainRefKM(psPerProc, psSwapChain, &psSwapChainRef); if( eError != PVRSRV_OK ) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference")); PDUMPCOMMENT("Swapchain allocation failed."); goto ErrorExit; } psSwapChain->ui32RefCount = 1; psSwapChain->ui32Flags = ui32Flags; if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED ) { if(! psDCInfo->psDCSwapChainShared ) { psDCInfo->psDCSwapChainShared = psSwapChain; } else { PVRSRV_DC_SWAPCHAIN *psOldHead = psDCInfo->psDCSwapChainShared; psDCInfo->psDCSwapChainShared = psSwapChain; psSwapChain->psNext = psOldHead; } } *pui32SwapChainID = psSwapChain->ui32SwapChainID; *phSwapChainRef= (IMG_HANDLE)psSwapChainRef; return eError; ErrorExit: for(i=0; iasBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); if (psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) { PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); } } } if(psQueue) { PVRSRVDestroyCommandQueueKM(psQueue); } if(psSwapChain) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL); } return eError; } IMG_EXPORT PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE hDeviceKM, IMG_HANDLE hSwapChainRef, IMG_RECT *psRect) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_SWAPCHAIN *psSwapChain; if(!hDeviceKM || !hSwapChainRef) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstRectKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain; return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice, psSwapChain->hExtSwapChain, psRect); } IMG_EXPORT PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE hDeviceKM, IMG_HANDLE hSwapChainRef, IMG_RECT *psRect) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_SWAPCHAIN *psSwapChain; if(!hDeviceKM || !hSwapChainRef) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcRectKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain; return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice, psSwapChain->hExtSwapChain, psRect); } IMG_EXPORT PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE hDeviceKM, IMG_HANDLE hSwapChainRef, IMG_UINT32 ui32CKColour) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_SWAPCHAIN *psSwapChain; if(!hDeviceKM || !hSwapChainRef) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstColourKeyKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain; return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice, psSwapChain->hExtSwapChain, ui32CKColour); } IMG_EXPORT PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE hDeviceKM, IMG_HANDLE hSwapChainRef, IMG_UINT32 ui32CKColour) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_SWAPCHAIN *psSwapChain; if(!hDeviceKM || !hSwapChainRef) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcColourKeyKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain; return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice, psSwapChain->hExtSwapChain, ui32CKColour); } IMG_EXPORT PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM, IMG_HANDLE hSwapChainRef, IMG_UINT32 *pui32BufferCount, IMG_HANDLE *phBuffer, IMG_SYS_PHYADDR *psPhyAddr) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_SWAPCHAIN *psSwapChain; IMG_HANDLE ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS]; PVRSRV_ERROR eError; IMG_UINT32 i; if(!hDeviceKM || !hSwapChainRef || !phBuffer || !psPhyAddr) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain; eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice, psSwapChain->hExtSwapChain, pui32BufferCount, ahExtBuffer); PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS); for(i=0; i<*pui32BufferCount; i++) { psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i]; phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i]; } #if defined(SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS) for(i = 0; i < *pui32BufferCount; i++) { IMG_UINT32 ui32ByteSize, ui32TilingStride; IMG_SYS_PHYADDR *pPhyAddr; IMG_BOOL bIsContiguous; IMG_HANDLE hOSMapInfo; IMG_VOID *pvVAddr; eError = psDCInfo->psFuncTable->pfnGetBufferAddr(psDCInfo->hExtDevice, ahExtBuffer[i], &pPhyAddr, &ui32ByteSize, &pvVAddr, &hOSMapInfo, &bIsContiguous, &ui32TilingStride); if(eError != PVRSRV_OK) { break; } psPhyAddr[i] = *pPhyAddr; } #endif return eError; } IMG_EXPORT PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM, IMG_HANDLE hBuffer, IMG_UINT32 ui32SwapInterval, IMG_HANDLE hPrivateTag, IMG_UINT32 ui32ClipRectCount, IMG_RECT *psClipRect) { PVRSRV_ERROR eError; PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_BUFFER *psBuffer; PVRSRV_QUEUE_INFO *psQueue; DISPLAYCLASS_FLIP_COMMAND *psFlipCmd; IMG_UINT32 i; IMG_BOOL bAddReferenceToLast = IMG_TRUE; IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND; IMG_UINT32 ui32NumSrcSyncs = 1; PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2]; PVRSRV_COMMAND *psCommand; SYS_DATA *psSysData; if(!hDeviceKM || !hBuffer || !psClipRect) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psBuffer = (PVRSRV_DC_BUFFER*)hBuffer; psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); if(ui32SwapInterval < psBuffer->psSwapChain->ui32MinSwapInterval || ui32SwapInterval > psBuffer->psSwapChain->ui32MaxSwapInterval) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid swap interval. Requested %u, Allowed range %u-%u", ui32SwapInterval, psBuffer->psSwapChain->ui32MinSwapInterval, psBuffer->psSwapChain->ui32MaxSwapInterval)); return PVRSRV_ERROR_INVALID_SWAPINTERVAL; } #if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS) if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL) { psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice, psBuffer->psSwapChain->hExtSwapChain, psBuffer->sDeviceClassBuffer.hExtBuffer, hPrivateTag, &ui16SwapCommandID, &bAddReferenceToLast); } #endif psQueue = psBuffer->psSwapChain->psQueue; apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo; if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer && psBuffer != psBuffer->psSwapChain->psLastFlipBuffer) { apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo; ui32NumSrcSyncs++; } eError = PVRSRVInsertCommandKM (psQueue, &psCommand, psDCInfo->ui32DeviceID, ui16SwapCommandID, 0, IMG_NULL, ui32NumSrcSyncs, apsSrcSync, sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount), IMG_NULL, IMG_NULL); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue")); goto Exit; } psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData; psFlipCmd->hExtDevice = psDCInfo->hExtDevice; psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain; psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer; psFlipCmd->hPrivateTag = hPrivateTag; psFlipCmd->ui32ClipRectCount = ui32ClipRectCount; psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND)); for(i=0; ipsClipRect[i] = psClipRect[i]; } psFlipCmd->ui32SwapInterval = ui32SwapInterval; SysAcquireData(&psSysData); { if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) { OSFlushCPUCacheKM(); } else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) { OSCleanCPUCacheKM(); } psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE; } eError = PVRSRVSubmitCommandKM (psQueue, psCommand); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command")); goto Exit; } eError = OSScheduleMISR(psSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to schedule MISR")); goto Exit; } psBuffer->psSwapChain->psLastFlipBuffer = psBuffer; Exit: if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE) { eError = PVRSRV_ERROR_RETRY; } return eError; } typedef struct _CALLBACK_DATA_ { IMG_PVOID pvPrivData; IMG_UINT32 ui32PrivDataLength; IMG_PVOID ppvMemInfos; IMG_UINT32 ui32NumMemInfos; } CALLBACK_DATA; static IMG_VOID FreePrivateData(IMG_HANDLE hCallbackData) { CALLBACK_DATA *psCallbackData = hCallbackData; OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psCallbackData->ui32PrivDataLength, psCallbackData->pvPrivData, IMG_NULL); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos, psCallbackData->ppvMemInfos, IMG_NULL); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), hCallbackData, IMG_NULL); } IMG_EXPORT PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE hDeviceKM, IMG_HANDLE hSwapChain, IMG_UINT32 ui32SwapInterval, PVRSRV_KERNEL_MEM_INFO **ppsMemInfos, PVRSRV_KERNEL_SYNC_INFO **ppsSyncInfos, IMG_UINT32 ui32NumMemSyncInfos, IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength) { PVRSRV_KERNEL_SYNC_INFO **ppsCompiledSyncInfos; IMG_UINT32 i, ui32NumCompiledSyncInfos; DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd; PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_SWAPCHAIN *psSwapChain; PVRSRV_ERROR eError = PVRSRV_OK; CALLBACK_DATA *psCallbackData; PVRSRV_QUEUE_INFO *psQueue; PVRSRV_COMMAND *psCommand; IMG_PVOID *ppvMemInfos; SYS_DATA *psSysData; if(!hDeviceKM || !hSwapChain || !ppsMemInfos || !ppsSyncInfos || ui32NumMemSyncInfos < 1) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChain)->psSwapChain; psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); if(ui32SwapInterval < psSwapChain->ui32MinSwapInterval || ui32SwapInterval > psSwapChain->ui32MaxSwapInterval) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid swap interval. Requested %u, Allowed range %u-%u", ui32SwapInterval, psSwapChain->ui32MinSwapInterval, psSwapChain->ui32MaxSwapInterval)); return PVRSRV_ERROR_INVALID_SWAPINTERVAL; } eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), (IMG_VOID **)&psCallbackData, IMG_NULL, "PVRSRVSwapToDCBuffer2KM callback data"); if (eError != PVRSRV_OK) { return eError; } psCallbackData->pvPrivData = pvPrivData; psCallbackData->ui32PrivDataLength = ui32PrivDataLength; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_VOID *) * ui32NumMemSyncInfos, (IMG_VOID **)&ppvMemInfos, IMG_NULL, "Swap Command Meminfos") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list")); psCallbackData->ppvMemInfos = IMG_NULL; goto Exit; } for(i = 0; i < ui32NumMemSyncInfos; i++) { ppvMemInfos[i] = ppsMemInfos[i]; } psCallbackData->ppvMemInfos = ppvMemInfos; psCallbackData->ui32NumMemInfos = ui32NumMemSyncInfos; psQueue = psSwapChain->psQueue; #if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) if(psSwapChain->ppsLastSyncInfos) { IMG_UINT32 ui32NumUniqueSyncInfos = psSwapChain->ui32LastNumSyncInfos; IMG_UINT32 j; for(j = 0; j < psSwapChain->ui32LastNumSyncInfos; j++) { for(i = 0; i < ui32NumMemSyncInfos; i++) { if(psSwapChain->ppsLastSyncInfos[j] == ppsSyncInfos[i]) { psSwapChain->ppsLastSyncInfos[j] = IMG_NULL; ui32NumUniqueSyncInfos--; } } } ui32NumCompiledSyncInfos = ui32NumMemSyncInfos + ui32NumUniqueSyncInfos; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos, (IMG_VOID **)&ppsCompiledSyncInfos, IMG_NULL, "Compiled syncinfos") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list")); goto Exit; } OSMemCopy(ppsCompiledSyncInfos, ppsSyncInfos, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos); for(j = 0, i = ui32NumMemSyncInfos; j < psSwapChain->ui32LastNumSyncInfos; j++) { if(psSwapChain->ppsLastSyncInfos[j]) { ppsCompiledSyncInfos[i] = psSwapChain->ppsLastSyncInfos[j]; i++; } } } else #endif { ppsCompiledSyncInfos = ppsSyncInfos; ui32NumCompiledSyncInfos = ui32NumMemSyncInfos; } eError = PVRSRVInsertCommandKM (psQueue, &psCommand, psDCInfo->ui32DeviceID, DC_FLIP_COMMAND, 0, IMG_NULL, ui32NumCompiledSyncInfos, ppsCompiledSyncInfos, sizeof(DISPLAYCLASS_FLIP_COMMAND2), FreePrivateData, psCallbackData); if (ppsCompiledSyncInfos != ppsSyncInfos) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos, (IMG_VOID *)ppsCompiledSyncInfos, IMG_NULL); } if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to get space in queue")); goto Exit; } psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND2*)psCommand->pvData; psFlipCmd->hUnused = IMG_NULL; psFlipCmd->hExtDevice = psDCInfo->hExtDevice; psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain; psFlipCmd->ui32SwapInterval = ui32SwapInterval; psFlipCmd->pvPrivData = pvPrivData; psFlipCmd->ui32PrivDataLength = ui32PrivDataLength; psFlipCmd->ppsMemInfos = (PDC_MEM_INFO *)ppvMemInfos; psFlipCmd->ui32NumMemInfos = ui32NumMemSyncInfos; SysAcquireData(&psSysData); { if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) { OSFlushCPUCacheKM(); } else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) { OSCleanCPUCacheKM(); } psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE; } eError = PVRSRVSubmitCommandKM (psQueue, psCommand); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to submit command")); goto Exit; } psCallbackData = IMG_NULL; eError = OSScheduleMISR(psSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to schedule MISR")); goto Exit; } #if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) if (psSwapChain->ui32LastNumSyncInfos < ui32NumMemSyncInfos) { if (psSwapChain->ppsLastSyncInfos) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos, psSwapChain->ppsLastSyncInfos, IMG_NULL); } if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos, (IMG_VOID **)&psSwapChain->ppsLastSyncInfos, IMG_NULL, "Last syncinfos") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list")); goto Exit; } } psSwapChain->ui32LastNumSyncInfos = ui32NumMemSyncInfos; for(i = 0; i < ui32NumMemSyncInfos; i++) { psSwapChain->ppsLastSyncInfos[i] = ppsSyncInfos[i]; } #endif Exit: if (psCallbackData) { if(psCallbackData->ppvMemInfos) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos, psCallbackData->ppvMemInfos, IMG_NULL); } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), psCallbackData, IMG_NULL); } if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE) { eError = PVRSRV_ERROR_RETRY; } return eError; } IMG_EXPORT PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM, IMG_HANDLE hSwapChainRef) { PVRSRV_ERROR eError; PVRSRV_QUEUE_INFO *psQueue; PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DC_SWAPCHAIN *psSwapChain; PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef; DISPLAYCLASS_FLIP_COMMAND *psFlipCmd; IMG_UINT32 ui32NumSrcSyncs = 1; PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2]; PVRSRV_COMMAND *psCommand; IMG_BOOL bAddReferenceToLast = IMG_TRUE; IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND; SYS_DATA *psSysData; if(!hDeviceKM || !hSwapChainRef) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef; psSwapChain = psSwapChainRef->psSwapChain; psQueue = psSwapChain->psQueue; #if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS) if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL) { psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice, psSwapChain->hExtSwapChain, psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer, 0, &ui16SwapCommandID, &bAddReferenceToLast); } #endif apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo; if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer) { if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo) { apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo; ui32NumSrcSyncs++; } } eError = PVRSRVInsertCommandKM (psQueue, &psCommand, psDCInfo->ui32DeviceID, ui16SwapCommandID, 0, IMG_NULL, ui32NumSrcSyncs, apsSrcSync, sizeof(DISPLAYCLASS_FLIP_COMMAND), IMG_NULL, IMG_NULL); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue")); goto Exit; } psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData; psFlipCmd->hExtDevice = psDCInfo->hExtDevice; psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain; psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer; psFlipCmd->hPrivateTag = IMG_NULL; psFlipCmd->ui32ClipRectCount = 0; psFlipCmd->ui32SwapInterval = 1; eError = PVRSRVSubmitCommandKM (psQueue, psCommand); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command")); goto Exit; } SysAcquireData(&psSysData); eError = OSScheduleMISR(psSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to schedule MISR")); goto Exit; } psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer; eError = PVRSRV_OK; Exit: if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE) { eError = PVRSRV_ERROR_RETRY; } return eError; } static PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER pfnISRHandler, IMG_VOID *pvISRHandlerData, IMG_UINT32 ui32ISRSourceMask, IMG_UINT32 ui32DeviceID) { SYS_DATA *psSysData; PVRSRV_DEVICE_NODE *psDevNode; PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask); SysAcquireData(&psSysData); psDevNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, &MatchDeviceKM_AnyVaCb, ui32DeviceID, IMG_TRUE); if (psDevNode == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterSystemISRHandler: Failed to get psDevNode")); PVR_DBG_BREAK; return PVRSRV_ERROR_NO_DEVICENODE_FOUND; } psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData; psDevNode->pfnDeviceISR = pfnISRHandler; return PVRSRV_OK; } static IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; IMG_UINT32 ui32State; ui32State = va_arg(va, IMG_UINT32); if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY) { psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice; if (psDCInfo->psFuncTable->pfnSetDCState && psDCInfo->hExtDevice) { psDCInfo->psFuncTable->pfnSetDCState(psDCInfo->hExtDevice, ui32State); } } } IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State) { SYS_DATA *psSysData; SysAcquireData(&psSysData); List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList, &PVRSRVSetDCState_ForEachVaCb, ui32State); } static PVRSRV_ERROR PVRSRVDCMemInfoGetCpuVAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, IMG_CPU_VIRTADDR *pVAddr) { *pVAddr = psKernelMemInfo->pvLinAddrKM; return PVRSRV_OK; } static PVRSRV_ERROR PVRSRVDCMemInfoGetCpuPAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr) { *pPAddr = OSMemHandleToCpuPAddr(psKernelMemInfo->sMemBlk.hOSMemHandle, uByteOffset); return PVRSRV_OK; } static PVRSRV_ERROR PVRSRVDCMemInfoGetByteSize(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, IMG_SIZE_T *uByteSize) { *uByteSize = psKernelMemInfo->uAllocSize; return PVRSRV_OK; } static IMG_BOOL PVRSRVDCMemInfoIsPhysContig(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) { return OSMemHandleIsPhysContig(psKernelMemInfo->sMemBlk.hOSMemHandle); } IMG_EXPORT IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable) { psJTable->ui32TableSize = sizeof(PVRSRV_DC_DISP2SRV_KMJTABLE); psJTable->pfnPVRSRVRegisterDCDevice = &PVRSRVRegisterDCDeviceKM; psJTable->pfnPVRSRVRemoveDCDevice = &PVRSRVRemoveDCDeviceKM; psJTable->pfnPVRSRVOEMFunction = &SysOEMFunction; psJTable->pfnPVRSRVRegisterCmdProcList = &PVRSRVRegisterCmdProcListKM; psJTable->pfnPVRSRVRemoveCmdProcList = &PVRSRVRemoveCmdProcListKM; #if defined(SUPPORT_MISR_IN_THREAD) psJTable->pfnPVRSRVCmdComplete = &OSVSyncMISR; #else psJTable->pfnPVRSRVCmdComplete = &PVRSRVCommandCompleteKM; #endif psJTable->pfnPVRSRVRegisterSystemISRHandler = &PVRSRVRegisterSystemISRHandler; psJTable->pfnPVRSRVRegisterPowerDevice = &PVRSRVRegisterPowerDevice; #if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS) psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM; #endif psJTable->pfnPVRSRVDCMemInfoGetCpuVAddr = &PVRSRVDCMemInfoGetCpuVAddr; psJTable->pfnPVRSRVDCMemInfoGetCpuPAddr = &PVRSRVDCMemInfoGetCpuPAddr; psJTable->pfnPVRSRVDCMemInfoGetByteSize = &PVRSRVDCMemInfoGetByteSize; psJTable->pfnPVRSRVDCMemInfoIsPhysContig = &PVRSRVDCMemInfoIsPhysContig; return IMG_TRUE; } IMG_EXPORT PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM, IMG_BOOL bResManCallback) { PVRSRV_ERROR eError; PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; PVR_UNREFERENCED_PARAMETER(bResManCallback); psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM; eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem, CLEANUP_WITH_POLL); return eError; } static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy) { PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; PVRSRV_BUFFERCLASS_INFO *psBCInfo; IMG_UINT32 i; PVR_UNREFERENCED_PARAMETER(ui32Param); PVR_UNREFERENCED_PARAMETER(bDummy); psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)pvParam; psBCInfo = psBCPerContextInfo->psBCInfo; for (i = 0; i < psBCInfo->ui32BufferCount; i++) { if (psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0) { PVR_DPF((PVR_DBG_ERROR, "CloseBCDeviceCallBack: buffer %d (0x%p) still mapped (ui32MemMapRefCount = %d)", i, &psBCInfo->psBuffer[i].sDeviceClassBuffer, psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount)); return PVRSRV_ERROR_STILL_MAPPED; } } psBCInfo->ui32RefCount--; if(psBCInfo->ui32RefCount == 0) { psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice); for(i=0; iui32BufferCount; i++) { if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); if (psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) { PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); } } } if(psBCInfo->psBuffer) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * psBCInfo->ui32BufferCount, psBCInfo->psBuffer, IMG_NULL); psBCInfo->psBuffer = IMG_NULL; } } OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL); return PVRSRV_OK; } IMG_EXPORT PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_UINT32 ui32DeviceID, IMG_HANDLE hDevCookie, IMG_HANDLE *phDeviceKM) { PVRSRV_BUFFERCLASS_INFO *psBCInfo; PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; PVRSRV_DEVICE_NODE *psDeviceNode; SYS_DATA *psSysData; IMG_UINT32 i; PVRSRV_ERROR eError; if(!phDeviceKM || !hDevCookie) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params")); return PVRSRV_ERROR_INVALID_PARAMS; } SysAcquireData(&psSysData); psDeviceNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, &MatchDeviceKM_AnyVaCb, ui32DeviceID, IMG_FALSE, PVRSRV_DEVICE_CLASS_BUFFER); if (!psDeviceNode) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID)); return PVRSRV_ERROR_NO_DEVICENODE_FOUND; } psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psBCPerContextInfo), (IMG_VOID **)&psBCPerContextInfo, IMG_NULL, "Buffer Class per Context Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo)); if(psBCInfo->ui32RefCount++ == 0) { BUFFER_INFO sBufferInfo; psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie; psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext; eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device")); return eError; } eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info")); return eError; } psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount; eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount, (IMG_VOID **)&psBCInfo->psBuffer, IMG_NULL, "Array of Buffer Class Buffer"); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers")); return eError; } OSMemSet (psBCInfo->psBuffer, 0, sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount); for(i=0; iui32BufferCount; i++) { eError = PVRSRVAllocSyncInfoKM(IMG_NULL, psBCInfo->hDevMemContext, &psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc")); goto ErrorExit; } PVRSRVKernelSyncInfoIncRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice, i, psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData, &psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers")); goto ErrorExit; } psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr; psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext; psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice; psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount = 0; } } psBCPerContextInfo->psBCInfo = psBCInfo; psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_BUFFERCLASS_DEVICE, psBCPerContextInfo, 0, &CloseBCDeviceCallBack); *phDeviceKM = (IMG_HANDLE)psBCPerContextInfo; return PVRSRV_OK; ErrorExit: for(i=0; iui32BufferCount; i++) { if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); if (psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0) { PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); } } } if(psBCInfo->psBuffer) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL); psBCInfo->psBuffer = IMG_NULL; } return eError; } IMG_EXPORT PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM, BUFFER_INFO *psBufferInfo) { PVRSRV_BUFFERCLASS_INFO *psBCInfo; PVRSRV_ERROR eError; if(!hDeviceKM || !psBufferInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM); eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, psBufferInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM : Failed to get BC Info")); return eError; } return PVRSRV_OK; } IMG_EXPORT PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM, IMG_UINT32 ui32BufferIndex, IMG_HANDLE *phBuffer) { PVRSRV_BUFFERCLASS_INFO *psBCInfo; if(!hDeviceKM || !phBuffer) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM); if(ui32BufferIndex < psBCInfo->ui32BufferCount) { *phBuffer = (IMG_HANDLE)&psBCInfo->psBuffer[ui32BufferIndex]; } else { PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Buffer index %d out of range (%d)", ui32BufferIndex,psBCInfo->ui32BufferCount)); return PVRSRV_ERROR_INVALID_PARAMS; } return PVRSRV_OK; } IMG_EXPORT IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable) { psJTable->ui32TableSize = sizeof(PVRSRV_BC_BUFFER2SRV_KMJTABLE); psJTable->pfnPVRSRVRegisterBCDevice = &PVRSRVRegisterBCDeviceKM; psJTable->pfnPVRSRVScheduleDevices = &PVRSRVScheduleDevicesKM; psJTable->pfnPVRSRVRemoveBCDevice = &PVRSRVRemoveBCDeviceKM; return IMG_TRUE; }