static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice, IMG_HANDLE hSwapChain) { MTKLFB_DEVINFO *psDevInfo; MTKLFB_SWAPCHAIN *psSwapChain; MTKLFB_ERROR eError; if(!hDevice || !hSwapChain) { return PVRSRV_ERROR_INVALID_PARAMS; } psDevInfo = (MTKLFB_DEVINFO*)hDevice; psSwapChain = (MTKLFB_SWAPCHAIN*)hSwapChain; MTKLFBCreateSwapChainLock(psDevInfo); if (SwapChainHasChanged(psDevInfo, psSwapChain)) { printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Swap chain mismatch\n", __FUNCTION__, psDevInfo->uiFBDevID); eError = PVRSRV_ERROR_INVALID_PARAMS; goto ExitUnLock; } MTKLFBDestroySwapQueue(psSwapChain); eError = MTKLFBDisableLFBEventNotification(psDevInfo); if (eError != MTKLFB_OK) { printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't disable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID); } MTKLFBFreeKernelMem(psSwapChain->psBuffer); MTKLFBFreeKernelMem(psSwapChain); psDevInfo->psSwapChain = NULL; MTKLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer); (void) MTKLFBCheckModeAndSync(psDevInfo); eError = PVRSRV_OK; ExitUnLock: MTKLFBCreateSwapChainUnLock(psDevInfo); 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) { MTKLFB_DEVINFO *psDevInfo; MTKLFB_SWAPCHAIN *psSwapChain; MTKLFB_BUFFER *psBuffer; IMG_UINT32 i; PVRSRV_ERROR eError; IMG_UINT32 ui32BuffersToSkip; UNREFERENCED_PARAMETER(ui32OEMFlags); if(!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib || !ppsSyncData || !phSwapChain) { return PVRSRV_ERROR_INVALID_PARAMS; } psDevInfo = (MTKLFB_DEVINFO*)hDevice; if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0) { return PVRSRV_ERROR_NOT_SUPPORTED; } MTKLFBCreateSwapChainLock(psDevInfo); if(psDevInfo->psSwapChain != NULL) { eError = PVRSRV_ERROR_FLIP_CHAIN_EXISTS; goto ExitUnLock; } if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers) { eError = PVRSRV_ERROR_TOOMANYBUFFERS; goto ExitUnLock; } if ((psDevInfo->sFBInfo.ulRoundedBufferSize * (unsigned long)ui32BufferCount) > psDevInfo->sFBInfo.ulFBSize) { eError = PVRSRV_ERROR_TOOMANYBUFFERS; goto ExitUnLock; } 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) { eError = PVRSRV_ERROR_INVALID_PARAMS; goto ExitUnLock; } if(psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat || psDstSurfAttrib->sDims.ui32ByteStride != psSrcSurfAttrib->sDims.ui32ByteStride || psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width || psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height) { eError = PVRSRV_ERROR_INVALID_PARAMS; goto ExitUnLock; } UNREFERENCED_PARAMETER(ui32Flags); #if defined(PVR_MTKFB3_UPDATE_MODE) if (!MTKLFBSetUpdateMode(psDevInfo, PVR_MTKFB3_UPDATE_MODE)) { xlog_printk(ANDROID_LOG_WARN, DRIVER_PREFIX, DRIVER_PREFIX ": %s: Device %u: Couldn't set frame buffer update mode %d\n", __FUNCTION__, psDevInfo->uiFBDevID, PVR_MTKFB3_UPDATE_MODE); } #endif psSwapChain = (MTKLFB_SWAPCHAIN*)MTKLFBAllocKernelMem(sizeof(MTKLFB_SWAPCHAIN)); if(!psSwapChain) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ExitUnLock; } psBuffer = (MTKLFB_BUFFER*)MTKLFBAllocKernelMem(sizeof(MTKLFB_BUFFER) * ui32BufferCount); if(!psBuffer) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorFreeSwapChain; } psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount; psSwapChain->psBuffer = psBuffer; psSwapChain->bNotVSynced = MTKLFB_TRUE; psSwapChain->uiFBDevID = psDevInfo->uiFBDevID; 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; psBuffer[i].ulYOffset = ui32BufferOffset / psDevInfo->sFBInfo.ulByteStride; psBuffer[i].psDevInfo = psDevInfo; MTKLFBInitBufferForSwap(&psBuffer[i]); } if (MTKLFBCreateSwapQueue(psSwapChain) != MTKLFB_OK) { xlog_printk(ANDROID_LOG_WARN, DRIVER_PREFIX, DRIVER_PREFIX ": %s: Device %u: Failed to create workqueue\n", __FUNCTION__, psDevInfo->uiFBDevID); eError = PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR; goto ErrorFreeBuffers; } if (MTKLFBEnableLFBEventNotification(psDevInfo)!= MTKLFB_OK) { eError = PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT; xlog_printk(ANDROID_LOG_WARN, DRIVER_PREFIX, DRIVER_PREFIX ": %s: Device %u: Couldn't enable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID); goto ErrorDestroySwapQueue; } psDevInfo->uiSwapChainID++; if (psDevInfo->uiSwapChainID == 0) { psDevInfo->uiSwapChainID++; } psSwapChain->uiSwapChainID = psDevInfo->uiSwapChainID; psDevInfo->psSwapChain = psSwapChain; *pui32SwapChainID = psDevInfo->uiSwapChainID; *phSwapChain = (IMG_HANDLE)psSwapChain; eError = PVRSRV_OK; goto ExitUnLock; ErrorDestroySwapQueue: MTKLFBDestroySwapQueue(psSwapChain); ErrorFreeBuffers: MTKLFBFreeKernelMem(psBuffer); ErrorFreeSwapChain: MTKLFBFreeKernelMem(psSwapChain); ExitUnLock: MTKLFBCreateSwapChainUnLock(psDevInfo); return eError; }