static enum PVRSRV_ERROR CreateDCSwapChain(void *hDevice, u32 ui32Flags, struct DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib, struct DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib, u32 ui32BufferCount, struct PVRSRV_SYNC_DATA **ppsSyncData, u32 ui32OEMFlags, void **phSwapChain, u32 *pui32SwapChainID) { struct OMAPLFB_DEVINFO *psDevInfo; struct OMAPLFB_SWAPCHAIN *psSwapChain; struct OMAPLFB_BUFFER *psBuffer; u32 i; enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC; PVR_UNREFERENCED_PARAMETER(ui32OEMFlags); PVR_UNREFERENCED_PARAMETER(pui32SwapChainID); if (!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib || !ppsSyncData || !phSwapChain) return PVRSRV_ERROR_INVALID_PARAMS; psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice; if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0) return PVRSRV_ERROR_NOT_SUPPORTED; if (psDevInfo->psSwapChain != NULL) return PVRSRV_ERROR_FLIP_CHAIN_EXISTS; if (ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers) return PVRSRV_ERROR_TOOMANYBUFFERS; if ((psDevInfo->sFBInfo.ui32RoundedBufferSize * ui32BufferCount) > psDevInfo->sFBInfo.ui32FBSize) return PVRSRV_ERROR_TOOMANYBUFFERS; if (psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat || psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride || psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width || psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height) return PVRSRV_ERROR_INVALID_PARAMS; if (psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat || psDstSurfAttrib->sDims.ui32ByteStride != psSrcSurfAttrib->sDims.ui32ByteStride || psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width || psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height) return PVRSRV_ERROR_INVALID_PARAMS; PVR_UNREFERENCED_PARAMETER(ui32Flags); psSwapChain = (struct OMAPLFB_SWAPCHAIN *) OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_SWAPCHAIN)); if (!psSwapChain) return PVRSRV_ERROR_OUT_OF_MEMORY; psBuffer = (struct OMAPLFB_BUFFER *) OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_BUFFER) * ui32BufferCount); if (!psBuffer) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorFreeSwapChain; } psSwapChain->ui32BufferCount = ui32BufferCount; psSwapChain->psBuffer = psBuffer; psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable; for (i = 0; i < ui32BufferCount - 1; i++) psBuffer[i].psNext = &psBuffer[i + 1]; psBuffer[i].psNext = &psBuffer[0]; for (i = 0; i < ui32BufferCount; i++) { u32 ui32BufferOffset = i * psDevInfo->sFBInfo.ui32RoundedBufferSize; psBuffer[i].psSyncData = ppsSyncData[i]; psBuffer[i].sSysAddr.uiAddr = psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset; psBuffer[i].sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset; } psDevInfo->psSwapChain = psSwapChain; eError = EnableLFBEventNotification(psDevInfo); if (eError != PVRSRV_OK) { printk(DRIVER_PREFIX ": Couldn't enable framebuffer event notification\n"); goto ErrorFreeBuffer; } *phSwapChain = (void *) psSwapChain; return PVRSRV_OK; ErrorFreeBuffer: OMAPLFBFreeKernelMem(psBuffer); ErrorFreeSwapChain: OMAPLFBFreeKernelMem(psSwapChain); return eError; }
static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice, IMG_UINT32 ui32Flags, DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib, DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib, IMG_UINT32 ui32BufferCount, PVRSRV_SYNC_DATA **ppsSyncData, IMG_UINT32 ui32OEMFlags, IMG_HANDLE *phSwapChain, IMG_UINT32 *pui32SwapChainID) { OMAPLFB_DEVINFO *psDevInfo; OMAPLFB_SWAPCHAIN *psSwapChain; OMAPLFB_BUFFER *psBuffer; OMAPLFB_VSYNC_FLIP_ITEM *psVSyncFlips; IMG_UINT32 i; PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC; unsigned long ulLockFlags; IMG_UINT32 ui32BuffersToSkip; UNREFERENCED_PARAMETER(ui32OEMFlags); UNREFERENCED_PARAMETER(pui32SwapChainID); if(!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib || !ppsSyncData || !phSwapChain) { return (PVRSRV_ERROR_INVALID_PARAMS); } psDevInfo = (OMAPLFB_DEVINFO*)hDevice; if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0) { return (PVRSRV_ERROR_NOT_SUPPORTED); } if(psDevInfo->psSwapChain != NULL) { return (PVRSRV_ERROR_FLIP_CHAIN_EXISTS); } if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers) { return (PVRSRV_ERROR_TOOMANYBUFFERS); } if ((psDevInfo->sFBInfo.ulRoundedBufferSize * (unsigned long)ui32BufferCount) > psDevInfo->sFBInfo.ulFBSize) { return (PVRSRV_ERROR_TOOMANYBUFFERS); } ui32BuffersToSkip = psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers - ui32BufferCount; if(psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat || psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride || psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width || psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height) { return (PVRSRV_ERROR_INVALID_PARAMS); } if(psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat || psDstSurfAttrib->sDims.ui32ByteStride != psSrcSurfAttrib->sDims.ui32ByteStride || psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width || psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height) { return (PVRSRV_ERROR_INVALID_PARAMS); } UNREFERENCED_PARAMETER(ui32Flags); psSwapChain = (OMAPLFB_SWAPCHAIN*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_SWAPCHAIN)); if(!psSwapChain) { return (PVRSRV_ERROR_OUT_OF_MEMORY); } psBuffer = (OMAPLFB_BUFFER*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_BUFFER) * ui32BufferCount); if(!psBuffer) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorFreeSwapChain; } psVSyncFlips = (OMAPLFB_VSYNC_FLIP_ITEM *)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_VSYNC_FLIP_ITEM) * ui32BufferCount); if (!psVSyncFlips) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorFreeBuffers; } psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount; psSwapChain->psBuffer = psBuffer; psSwapChain->psVSyncFlips = psVSyncFlips; psSwapChain->ulInsertIndex = 0; psSwapChain->ulRemoveIndex = 0; psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable; psSwapChain->psSwapChainLock = &psDevInfo->sSwapChainLock; for(i=0; i<ui32BufferCount-1; i++) { psBuffer[i].psNext = &psBuffer[i+1]; } psBuffer[i].psNext = &psBuffer[0]; for(i=0; i<ui32BufferCount; i++) { IMG_UINT32 ui32SwapBuffer = i + ui32BuffersToSkip; IMG_UINT32 ui32BufferOffset = ui32SwapBuffer * (IMG_UINT32)psDevInfo->sFBInfo.ulRoundedBufferSize; psBuffer[i].psSyncData = ppsSyncData[i]; psBuffer[i].sSysAddr.uiAddr = psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset; psBuffer[i].sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset; } for(i=0; i<ui32BufferCount; i++) { INIT_LIST_HEAD(&psBuffer[i].list); psVSyncFlips[i].bValid = OMAP_FALSE; psVSyncFlips[i].bFlipped = OMAP_FALSE; psVSyncFlips[i].bCmdCompleted = OMAP_FALSE; } spin_lock_irqsave(&psDevInfo->sSwapChainLock, ulLockFlags); psDevInfo->psSwapChain = psSwapChain; psSwapChain->bFlushCommands = psDevInfo->bFlushCommands; if (psSwapChain->bFlushCommands) { psSwapChain->ulSetFlushStateRefCount = 1; } else { psSwapChain->ulSetFlushStateRefCount = 0; } spin_unlock_irqrestore(&psDevInfo->sSwapChainLock, ulLockFlags); if (EnableLFBEventNotification(psDevInfo)!= OMAP_OK) { printk(KERN_WARNING DRIVER_PREFIX ": Couldn't enable framebuffer event notification\n"); goto ErrorFreeVsyncFlips; } *phSwapChain = (IMG_HANDLE)psSwapChain; return (PVRSRV_OK); ErrorFreeVsyncFlips: OMAPLFBFreeKernelMem(psVSyncFlips); ErrorFreeBuffers: OMAPLFBFreeKernelMem(psBuffer); ErrorFreeSwapChain: OMAPLFBFreeKernelMem(psSwapChain); return eError; }