DC_ERROR Init(void) { DC_NOHW_DEVINFO *psDevInfo; DC_ERROR eError; unsigned long ulBBuf; unsigned long ulNBBuf; psDevInfo = GetAnchorPtr(); if (psDevInfo == 0) { PFN_CMD_PROC pfnCmdProcList[DC_NOHW_COMMAND_COUNT]; IMG_UINT32 aui32SyncCountList[DC_NOHW_COMMAND_COUNT][2]; psDevInfo = (DC_NOHW_DEVINFO *)AllocKernelMem(sizeof(*psDevInfo)); if(!psDevInfo) { eError = DC_ERROR_OUT_OF_MEMORY; goto ExitError; } memset(psDevInfo, 0, sizeof(*psDevInfo)); SetAnchorPtr((void*)psDevInfo); psDevInfo->ulRefCount = 0UL; if(OpenPVRServices(&psDevInfo->hPVRServices) != DC_OK) { eError = DC_ERROR_INIT_FAILURE; goto ExitFreeDevInfo; } if(GetLibFuncAddr (psDevInfo->hPVRServices, "PVRGetDisplayClassJTable", &pfnGetPVRJTable) != DC_OK) { eError = DC_ERROR_INIT_FAILURE; goto ExitCloseServices; } if((*pfnGetPVRJTable)(&psDevInfo->sPVRJTable) == IMG_FALSE) { eError = DC_ERROR_INIT_FAILURE; goto ExitCloseServices; } psDevInfo->psSwapChain = 0; psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0UL; psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 1UL; psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1UL; psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = DC_NOHW_MAX_BACKBUFFERS; strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE); psDevInfo->ulNumFormats = 1UL; psDevInfo->ulNumDims = 1UL; #if defined(DC_NOHW_GET_BUFFER_DIMENSIONS) if (!GetBufferDimensions(&psDevInfo->asDisplayDimList[0].ui32Width, &psDevInfo->asDisplayDimList[0].ui32Height, &psDevInfo->asDisplayFormatList[0].pixelformat, &psDevInfo->asDisplayDimList[0].ui32ByteStride)) { eError = DC_ERROR_INIT_FAILURE; goto ExitCloseServices; } #else #if defined (ENABLE_DISPLAY_MODE_TRACKING) psDevInfo->asDisplayFormatList[0].pixelformat = DC_NOHW_BUFFER_PIXEL_FORMAT; psDevInfo->asDisplayDimList[0].ui32Width = 0; psDevInfo->asDisplayDimList[0].ui32Height = 0; psDevInfo->asDisplayDimList[0].ui32ByteStride = 0; #else psDevInfo->asDisplayFormatList[0].pixelformat = DC_NOHW_BUFFER_PIXEL_FORMAT; psDevInfo->asDisplayDimList[0].ui32Width = DC_NOHW_BUFFER_WIDTH; psDevInfo->asDisplayDimList[0].ui32Height = DC_NOHW_BUFFER_HEIGHT; psDevInfo->asDisplayDimList[0].ui32ByteStride = DC_NOHW_BUFFER_BYTE_STRIDE; #endif #endif psDevInfo->sSysFormat = psDevInfo->asDisplayFormatList[0]; psDevInfo->sSysDims.ui32Width = psDevInfo->asDisplayDimList[0].ui32Width; psDevInfo->sSysDims.ui32Height = psDevInfo->asDisplayDimList[0].ui32Height; psDevInfo->sSysDims.ui32ByteStride = psDevInfo->asDisplayDimList[0].ui32ByteStride; psDevInfo->ui32BufferSize = psDevInfo->sSysDims.ui32Height * psDevInfo->sSysDims.ui32ByteStride; for(ulBBuf=0; ulBBuf<DC_NOHW_MAX_BACKBUFFERS; ulBBuf++) { #if defined(USE_BASE_VIDEO_FRAMEBUFFER) || defined (ENABLE_DISPLAY_MODE_TRACKING) psDevInfo->asBackBuffers[ulBBuf].sSysAddr.uiAddr = IMG_NULL; psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr = IMG_NULL; #else #if defined(DC_NOHW_DISCONTIG_BUFFERS) if (AllocDiscontigMemory(psDevInfo->ui32BufferSize, &psDevInfo->asBackBuffers[ulBBuf].hMemChunk, &psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr, &psDevInfo->asBackBuffers[ulBBuf].psSysAddr) != DC_OK) { eError = DC_ERROR_INIT_FAILURE; goto ExitFreeMem; } #else IMG_CPU_PHYADDR sBufferCPUPAddr; if (AllocContigMemory(psDevInfo->ui32BufferSize, &psDevInfo->asBackBuffers[ulBBuf].hMemChunk, &psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr, &sBufferCPUPAddr) != DC_OK) { eError = DC_ERROR_INIT_FAILURE; goto ExitFreeMem; } psDevInfo->asBackBuffers[ulBBuf].sSysAddr = CpuPAddrToSysPAddr(sBufferCPUPAddr); #endif #endif psDevInfo->asBackBuffers[ulBBuf].sDevVAddr.uiAddr = 0UL; psDevInfo->asBackBuffers[ulBBuf].hSwapChain = 0; psDevInfo->asBackBuffers[ulBBuf].psSyncData = 0; psDevInfo->asBackBuffers[ulBBuf].psNext = 0; } psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE); psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice; psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice; psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats; psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims; psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer; psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo; psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr; psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain; psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain; psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect; psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect; psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey; psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey; psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers; psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer; psDevInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem; psDevInfo->sDCJTable.pfnSetDCState = IMG_NULL; if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice (&psDevInfo->sDCJTable, &psDevInfo->uiDeviceID ) != PVRSRV_OK) { eError = DC_ERROR_DEVICE_REGISTER_FAILED; goto ExitFreeMem; } pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip; aui32SyncCountList[DC_FLIP_COMMAND][0] = 0UL; aui32SyncCountList[DC_FLIP_COMMAND][1] = 2UL; if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList(psDevInfo->uiDeviceID, &pfnCmdProcList[0], aui32SyncCountList, DC_NOHW_COMMAND_COUNT) != PVRSRV_OK) { eError = DC_ERROR_CANT_REGISTER_CALLBACK; goto ExitRemoveDevice; } } psDevInfo->ulRefCount++; return (DC_OK); ExitRemoveDevice: (IMG_VOID) psDevInfo->sPVRJTable.pfnPVRSRVRemoveDCDevice(psDevInfo->uiDeviceID); ExitFreeMem: ulNBBuf = ulBBuf; for(ulBBuf=0; ulBBuf<ulNBBuf; ulBBuf++) { #if defined(DC_NOHW_DISCONTIG_BUFFERS) FreeDiscontigMemory(psDevInfo->ui32BufferSize, psDevInfo->asBackBuffers[ulBBuf].hMemChunk, psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr, psDevInfo->asBackBuffers[ulBBuf].psSysAddr); #else #if !defined(USE_BASE_VIDEO_FRAMEBUFFER) FreeContigMemory(psDevInfo->ui32BufferSize, psDevInfo->asBackBuffers[ulBBuf].hMemChunk, psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr, SysPAddrToCpuPAddr(psDevInfo->asBackBuffers[ulBBuf].sSysAddr)); #endif #endif } ExitCloseServices: (void)ClosePVRServices(psDevInfo->hPVRServices); ExitFreeDevInfo: FreeKernelMem(psDevInfo); SetAnchorPtr(0); ExitError: return eError; }
DC_ERROR Init(void) { DC_NOHW_DEVINFO *psDevInfo; DC_ERROR eError; unsigned long ulBBuf; unsigned long ulNBBuf; /* - connect to services - register with services - allocate and setup private data structure */ /* in kernel driver, data structures must be anchored to something for subsequent retrieval this may be a single global pointer or TLS or something else - up to you call API to retrieve this ptr */ /* get the anchor pointer */ psDevInfo = GetAnchorPtr(); if (psDevInfo == 0) { PFN_CMD_PROC pfnCmdProcList[DC_NOHW_COMMAND_COUNT]; IMG_UINT32 aui32SyncCountList[DC_NOHW_COMMAND_COUNT][2]; /* allocate device info. structure */ psDevInfo = (DC_NOHW_DEVINFO *)AllocKernelMem(sizeof(*psDevInfo)); if(!psDevInfo) { eError = DC_ERROR_OUT_OF_MEMORY;/* failure */ goto ExitError; } /* initialise allocation */ memset(psDevInfo, 0, sizeof(*psDevInfo)); /* set the top-level anchor */ SetAnchorPtr((void*)psDevInfo); /* set ref count */ psDevInfo->ulRefCount = 0UL; if(OpenPVRServices(&psDevInfo->hPVRServices) != DC_OK) { eError = DC_ERROR_INIT_FAILURE; goto ExitFreeDevInfo; } if(GetLibFuncAddr (psDevInfo->hPVRServices, "PVRGetDisplayClassJTable", &pfnGetPVRJTable) != DC_OK) { eError = DC_ERROR_INIT_FAILURE; goto ExitCloseServices; } /* got the kernel services function table */ if((*pfnGetPVRJTable)(&psDevInfo->sPVRJTable) == IMG_FALSE) { eError = DC_ERROR_INIT_FAILURE; goto ExitCloseServices; } /* Setup the devinfo */ psDevInfo->psSwapChain = 0; psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0UL; psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 1UL; psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1UL; psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = DC_NOHW_MAX_BACKBUFFERS; strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE); psDevInfo->ulNumFormats = 1UL; psDevInfo->ulNumDims = 1UL; #if defined(DC_NOHW_GET_BUFFER_DIMENSIONS) if (!GetBufferDimensions(&psDevInfo->asDisplayDimList[0].ui32Width, &psDevInfo->asDisplayDimList[0].ui32Height, &psDevInfo->asDisplayFormatList[0].pixelformat, &psDevInfo->asDisplayDimList[0].ui32ByteStride)) { eError = DC_ERROR_INIT_FAILURE; goto ExitCloseServices; } #else /* defined(DC_NOHW_GET_BUFFER_DIMENSIONS) */ #if defined (ENABLE_DISPLAY_MODE_TRACKING) // Set sizes to zero to force re-alloc on display mode change. psDevInfo->asDisplayFormatList[0].pixelformat = DC_NOHW_BUFFER_PIXEL_FORMAT; psDevInfo->asDisplayDimList[0].ui32Width = 0; psDevInfo->asDisplayDimList[0].ui32Height = 0; psDevInfo->asDisplayDimList[0].ui32ByteStride = 0; #else psDevInfo->asDisplayFormatList[0].pixelformat = DC_NOHW_BUFFER_PIXEL_FORMAT; psDevInfo->asDisplayDimList[0].ui32Width = DC_NOHW_BUFFER_WIDTH; psDevInfo->asDisplayDimList[0].ui32Height = DC_NOHW_BUFFER_HEIGHT; psDevInfo->asDisplayDimList[0].ui32ByteStride = DC_NOHW_BUFFER_BYTE_STRIDE; #endif #endif /* defined(DC_NOHW_GET_BUFFER_DIMENSIONS) */ psDevInfo->sSysFormat = psDevInfo->asDisplayFormatList[0]; psDevInfo->sSysDims.ui32Width = psDevInfo->asDisplayDimList[0].ui32Width; psDevInfo->sSysDims.ui32Height = psDevInfo->asDisplayDimList[0].ui32Height; psDevInfo->sSysDims.ui32ByteStride = psDevInfo->asDisplayDimList[0].ui32ByteStride; psDevInfo->ui32BufferSize = psDevInfo->sSysDims.ui32Height * psDevInfo->sSysDims.ui32ByteStride; /* setup swapchain details */ for(ulBBuf=0; ulBBuf<DC_NOHW_MAX_BACKBUFFERS; ulBBuf++) { #if defined(USE_BASE_VIDEO_FRAMEBUFFER) || defined (ENABLE_DISPLAY_MODE_TRACKING) psDevInfo->asBackBuffers[ulBBuf].sSysAddr.uiAddr = IMG_NULL; psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr = IMG_NULL; #else #if defined(DC_NOHW_DISCONTIG_BUFFERS) if (AllocDiscontigMemory(psDevInfo->ui32BufferSize, &psDevInfo->asBackBuffers[ulBBuf].hMemChunk, &psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr, &psDevInfo->asBackBuffers[ulBBuf].psSysAddr) != DC_OK) { eError = DC_ERROR_INIT_FAILURE; goto ExitFreeMem; } #else IMG_CPU_PHYADDR sBufferCPUPAddr; if (AllocContigMemory(psDevInfo->ui32BufferSize, &psDevInfo->asBackBuffers[ulBBuf].hMemChunk, &psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr, &sBufferCPUPAddr) != DC_OK) { eError = DC_ERROR_INIT_FAILURE; goto ExitFreeMem; } psDevInfo->asBackBuffers[ulBBuf].sSysAddr = CpuPAddrToSysPAddr(sBufferCPUPAddr); #endif #endif /* #if defined(USE_BASE_VIDEO_FRAMEBUFFER) */ /* sDevVAddr not meaningful for nohw */ psDevInfo->asBackBuffers[ulBBuf].sDevVAddr.uiAddr = 0UL; psDevInfo->asBackBuffers[ulBBuf].hSwapChain = 0; psDevInfo->asBackBuffers[ulBBuf].psSyncData = 0; psDevInfo->asBackBuffers[ulBBuf].psNext = 0; } /* setup the DC Jtable so SRVKM can call into this driver */ psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE); psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice; psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice; psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats; psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims; psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer; psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo; psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr; psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain; psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain; psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect; psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect; psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey; psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey; psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers; psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer; psDevInfo->sDCJTable.pfnSetDCState = IMG_NULL; /* register device with services and retrieve device index */ if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice (&psDevInfo->sDCJTable, &psDevInfo->uiDeviceID ) != PVRSRV_OK) { eError = DC_ERROR_DEVICE_REGISTER_FAILED; goto ExitFreeMem; } /* setup private command processing function table */ pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip; /* and associated sync count(s) */ aui32SyncCountList[DC_FLIP_COMMAND][0] = 0UL;/* no writes */ aui32SyncCountList[DC_FLIP_COMMAND][1] = 2UL;/* 2 reads: To / From */ /* register private command processing functions with the Command Queue Manager and setup the general command complete function in the devinfo */ if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList(psDevInfo->uiDeviceID, &pfnCmdProcList[0], aui32SyncCountList, DC_NOHW_COMMAND_COUNT) != PVRSRV_OK) { eError = DC_ERROR_CANT_REGISTER_CALLBACK; goto ExitRemoveDevice; } } /* increment the ref count */ psDevInfo->ulRefCount++; /* return success */ return (DC_OK); ExitRemoveDevice: (IMG_VOID) psDevInfo->sPVRJTable.pfnPVRSRVRemoveDCDevice(psDevInfo->uiDeviceID); ExitFreeMem: ulNBBuf = ulBBuf; for(ulBBuf=0; ulBBuf<ulNBBuf; ulBBuf++) { #if defined(DC_NOHW_DISCONTIG_BUFFERS) FreeDiscontigMemory(psDevInfo->ui32BufferSize, psDevInfo->asBackBuffers[ulBBuf].hMemChunk, psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr, psDevInfo->asBackBuffers[ulBBuf].psSysAddr); #else #if !defined(USE_BASE_VIDEO_FRAMEBUFFER) FreeContigMemory(psDevInfo->ui32BufferSize, psDevInfo->asBackBuffers[ulBBuf].hMemChunk, psDevInfo->asBackBuffers[ulBBuf].sCPUVAddr, SysPAddrToCpuPAddr(psDevInfo->asBackBuffers[ulBBuf].sSysAddr)); #endif /* #if defined(USE_BASE_VIDEO_FRAMEBUFFER) */ #endif /* #if defined(DC_NOHW_DISCONTIG_BUFFERS) */ } ExitCloseServices: (void)ClosePVRServices(psDevInfo->hPVRServices); ExitFreeDevInfo: FreeKernelMem(psDevInfo); SetAnchorPtr(0); ExitError: 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) { DC_NOHW_DEVINFO *psDevInfo; DC_NOHW_SWAPCHAIN *psSwapChain; DC_NOHW_BUFFER *psBuffer; IMG_UINT32 i; UNREFERENCED_PARAMETER(ui32OEMFlags); UNREFERENCED_PARAMETER(pui32SwapChainID); if(!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib || !ppsSyncData || !phSwapChain) { return (PVRSRV_ERROR_INVALID_PARAMS); } psDevInfo = (DC_NOHW_DEVINFO*)hDevice; if(psDevInfo->psSwapChain) { return (PVRSRV_ERROR_FLIP_CHAIN_EXISTS); } if(ui32BufferCount > DC_NOHW_MAX_BACKBUFFERS) { return (PVRSRV_ERROR_TOOMANYBUFFERS); } if(psDstSurfAttrib->pixelformat != psDevInfo->sSysFormat.pixelformat || psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sSysDims.ui32ByteStride || psDstSurfAttrib->sDims.ui32Width != psDevInfo->sSysDims.ui32Width || psDstSurfAttrib->sDims.ui32Height != psDevInfo->sSysDims.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 = (DC_NOHW_SWAPCHAIN*)AllocKernelMem(sizeof(DC_NOHW_SWAPCHAIN)); if(!psSwapChain) { return (PVRSRV_ERROR_OUT_OF_MEMORY); } psBuffer = (DC_NOHW_BUFFER*)AllocKernelMem(sizeof(DC_NOHW_BUFFER) * ui32BufferCount); if(!psBuffer) { FreeKernelMem(psSwapChain); return (PVRSRV_ERROR_OUT_OF_MEMORY); } memset(psSwapChain, 0, sizeof(DC_NOHW_SWAPCHAIN)); memset(psBuffer, 0, sizeof(DC_NOHW_BUFFER) * ui32BufferCount); psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount; psSwapChain->psBuffer = psBuffer; for(i=0; i<ui32BufferCount-1; i++) { psBuffer[i].psNext = &psBuffer[i+1]; } psBuffer[i].psNext = &psBuffer[0]; for(i=0; i<ui32BufferCount; i++) { psBuffer[i].psSyncData = ppsSyncData[i]; #if defined(DC_NOHW_DISCONTIG_BUFFERS) psBuffer[i].psSysAddr = psDevInfo->asBackBuffers[i].psSysAddr; #else psBuffer[i].sSysAddr = psDevInfo->asBackBuffers[i].sSysAddr; #endif psBuffer[i].sDevVAddr = psDevInfo->asBackBuffers[i].sDevVAddr; psBuffer[i].sCPUVAddr = psDevInfo->asBackBuffers[i].sCPUVAddr; psBuffer[i].hSwapChain = (DC_HANDLE)psSwapChain; } psDevInfo->psSwapChain = psSwapChain; *phSwapChain = (IMG_HANDLE)psSwapChain; return (PVRSRV_OK); }
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) { DC_NOHW_DEVINFO *psDevInfo; DC_NOHW_SWAPCHAIN *psSwapChain; DC_NOHW_BUFFER *psBuffer; IMG_UINT32 i; UNREFERENCED_PARAMETER(ui32OEMFlags); UNREFERENCED_PARAMETER(pui32SwapChainID); /* check parameters */ if(!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib || !ppsSyncData || !phSwapChain) { return (PVRSRV_ERROR_INVALID_PARAMS); } psDevInfo = (DC_NOHW_DEVINFO*)hDevice; /* the dc_nohw only supports a single swapchain */ if(psDevInfo->psSwapChain) { return (PVRSRV_ERROR_FLIP_CHAIN_EXISTS); } /* check the buffer count */ if(ui32BufferCount > DC_NOHW_MAX_BACKBUFFERS) { return (PVRSRV_ERROR_TOOMANYBUFFERS); } /* verify the DST/SRC attributes - SRC/DST must match the current display mode config */ if(psDstSurfAttrib->pixelformat != psDevInfo->sSysFormat.pixelformat || psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sSysDims.ui32ByteStride || psDstSurfAttrib->sDims.ui32Width != psDevInfo->sSysDims.ui32Width || psDstSurfAttrib->sDims.ui32Height != psDevInfo->sSysDims.ui32Height) { /* DST doesn't match the current mode */ 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) { /* DST doesn't match the SRC */ return (PVRSRV_ERROR_INVALID_PARAMS); } /* INTEGRATION_POINT: check the flags */ UNREFERENCED_PARAMETER(ui32Flags); /* create a swapchain structure */ psSwapChain = (DC_NOHW_SWAPCHAIN*)AllocKernelMem(sizeof(DC_NOHW_SWAPCHAIN)); if(!psSwapChain) { return (PVRSRV_ERROR_OUT_OF_MEMORY); } psBuffer = (DC_NOHW_BUFFER*)AllocKernelMem(sizeof(DC_NOHW_BUFFER) * ui32BufferCount); if(!psBuffer) { FreeKernelMem(psSwapChain); return (PVRSRV_ERROR_OUT_OF_MEMORY); } /* initialise allocations */ memset(psSwapChain, 0, sizeof(DC_NOHW_SWAPCHAIN)); memset(psBuffer, 0, sizeof(DC_NOHW_BUFFER) * ui32BufferCount); psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount; psSwapChain->psBuffer = psBuffer; /* link the buffers */ for(i=0; i<ui32BufferCount-1; i++) { psBuffer[i].psNext = &psBuffer[i+1]; } /* and link last to first */ psBuffer[i].psNext = &psBuffer[0]; /* populate the buffers */ for(i=0; i<ui32BufferCount; i++) { psBuffer[i].psSyncData = ppsSyncData[i]; #if defined(DC_NOHW_DISCONTIG_BUFFERS) psBuffer[i].psSysAddr = psDevInfo->asBackBuffers[i].psSysAddr; #else psBuffer[i].sSysAddr = psDevInfo->asBackBuffers[i].sSysAddr; #endif psBuffer[i].sDevVAddr = psDevInfo->asBackBuffers[i].sDevVAddr; psBuffer[i].sCPUVAddr = psDevInfo->asBackBuffers[i].sCPUVAddr; psBuffer[i].hSwapChain = (DC_HANDLE)psSwapChain; } /* mark swapchain's existence */ psDevInfo->psSwapChain = psSwapChain; /* return swapchain handle */ *phSwapChain = (IMG_HANDLE)psSwapChain; /* INTEGRATION_POINT: enable Vsync ISR */ return (PVRSRV_OK); }