Exemplo n.º 1
0
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;
}