/*
 * Swap handler.
 * Called from the swap chain work queue handler.
 * There is no need to take the swap chain creation lock in here, or use
 * some other method of stopping the swap chain from being destroyed.
 * This is because the swap chain creation lock is taken when queueing work,
 * and the work queue is flushed before the swap chain is destroyed.
 */
static void DC_SUNXISwapHandler(DC_SUNXI_BUFFER *psBuffer)
{
	DC_SUNXI_DEVINFO *psDevInfo = psBuffer->psDevInfo;
	DC_SUNXI_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
	bool bPreviouslyNotVSynced;

	DC_SUNXIFlip(psDevInfo, psBuffer);

	bPreviouslyNotVSynced = psSwapChain->bNotVSynced;
	psSwapChain->bNotVSynced = true;

	if (!DontWaitForVSync(psDevInfo))
	{
		psSwapChain->bNotVSynced = false;

		if (bPreviouslyNotVSynced)
		{
			psSwapChain->bNotVSynced = !WaitForVSyncSettle(psDevInfo);
		}
		else if (psBuffer->ulSwapInterval != 0)
		{
			psSwapChain->bNotVSynced = IMG_FALSE;
		}
	}
	
	psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psBuffer->hCmdComplete, IMG_TRUE);
}
static OMAPLFB_BOOL WaitForVSyncSettle(OMAPLFB_DEVINFO *psDevInfo)
{
		unsigned i;
		for(i = 0; i < OMAPLFB_VSYNC_SETTLE_COUNT; i++)
		{
			if (DontWaitForVSync(psDevInfo) || !OMAPLFBWaitForVSync(psDevInfo))
			{
				return OMAPLFB_FALSE;
			}
		}

		return OMAPLFB_TRUE;
}
/*
 * Called after the screen has unblanked, or after any other occasion
 * when we didn't wait for vsync, but now need to. Not doing this after
 * unblank leads to screen jitter on some screens.
 * Returns true if the screen has been deemed to have settled.
 */
static bool WaitForVSyncSettle(DC_SUNXI_DEVINFO *psDevInfo)
{
	unsigned int i;
	for(i = 0; i < DC_SUNXI_VSYNC_SETTLE_COUNT; i++)
	{
		if (DontWaitForVSync(psDevInfo))
		{
			return false;
		}
	}

	return true;
}
void OMAPLFBSwapHandler(OMAPLFB_BUFFER *psBuffer)
{
	OMAPLFB_DEVINFO *psDevInfo = psBuffer->psDevInfo;
	OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
	OMAPLFB_BOOL bPreviouslyNotVSynced;

#if defined(SUPPORT_DRI_DRM)
	if (!OMAPLFBAtomicBoolRead(&psDevInfo->sLeaveVT))
#endif
	{
		OMAPLFBFlip(psDevInfo, psBuffer);
	}

	bPreviouslyNotVSynced = psSwapChain->bNotVSynced;
	psSwapChain->bNotVSynced = OMAPLFB_TRUE;


	if (!DontWaitForVSync(psDevInfo))
	{
		OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
		int iBlankEvents = OMAPLFBAtomicIntRead(&psDevInfo->sBlankEvents);

		switch(eMode)
		{
			case OMAPLFB_UPDATE_MODE_AUTO:
				psSwapChain->bNotVSynced = OMAPLFB_FALSE;

				if (bPreviouslyNotVSynced || psSwapChain->iBlankEvents != iBlankEvents)
				{
					psSwapChain->iBlankEvents = iBlankEvents;
					psSwapChain->bNotVSynced = !WaitForVSyncSettle(psDevInfo);
				} else if (psBuffer->ulSwapInterval != 0)
				{
					psSwapChain->bNotVSynced = !OMAPLFBWaitForVSync(psDevInfo);
				}
				break;
#if defined(PVR_OMAPFB3_MANUAL_UPDATE_SYNC_IN_SWAP)
			case OMAPLFB_UPDATE_MODE_MANUAL:
				if (psBuffer->ulSwapInterval != 0)
				{
					(void) OMAPLFBManualSync(psDevInfo);
				}
				break;
#endif
			default:
				break;
		}
	}

	psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psBuffer->hCmdComplete, IMG_TRUE);
}