示例#1
0
/**
 * Get current frame count and frame count timestamp, based on drawable's
 * crtc.
 */
static int
MSMDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
{
	ScreenPtr pScreen = pDraw->pScreen;
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	MSMPtr pMsm = MSMPTR(pScrn);
	drmVBlank vbl = { .request = {
		.type = DRM_VBLANK_RELATIVE,
		.sequence = 0,
	} };
	int ret;

	ret = drmWaitVBlank(pMsm->drmFD, &vbl);
	if (ret) {
		static int limit = 5;
		if (limit) {
			WARNING_MSG("get vblank counter failed: %s", strerror(errno));
			limit--;
		}
		return FALSE;
	}

	if (ust) {
		*ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
	}
	if (msc) {
		*msc = vbl.reply.sequence;
	}

	return TRUE;
}
void
MSMAccelFini(ScreenPtr pScreen)
{
	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
	MSMPtr pMsm = MSMPTR(pScrn);

	/* Close DRI2 */
	if (pMsm->dri) {
		MSMDRI2CloseScreen(pScreen);
	}

	/* Close EXA */
	if (pMsm->pExa) {
		exaDriverFini(pScreen);
		free(pMsm->pExa);
		pMsm->pExa = NULL;
	}

#ifdef HAVE_XA
	if (pMsm->xa) {
		xa_tracker_destroy(pMsm->xa);
		pMsm->xa = NULL;
	}
#endif
}
void
MSMFlushAccel(ScreenPtr pScreen)
{
	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
	MSMPtr pMsm = MSMPTR(pScrn);
	if (pMsm->xa) {
#ifdef HAVE_XA
		MSMFlushXA(pMsm);
#endif
	} else {
		FIRE_RING(pMsm);
	}
}
示例#4
0
static void
MSMDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
		DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
{
	ScreenPtr pScreen = pDraw->pScreen;
	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
	DrawablePtr pSrcDraw = dri2draw(pDraw, pSrcBuffer);
	DrawablePtr pDstDraw = dri2draw(pDraw, pDstBuffer);
	RegionPtr pCopyClip;
	GCPtr pGC;

	DEBUG_MSG("pDraw=%p, pDstBuffer=%p (%p), pSrcBuffer=%p (%p)",
			pDraw, pDstBuffer, pSrcDraw, pSrcBuffer, pDstDraw);

	/* hack.. since we don't have proper fencing / kernel synchronization
	 * we can get in a scenario where we get many frames ahead of the gpu,
	 * with queued up cmd sequence like: render -> blit -> render -> blit ..
	 * This hack makes sure the previous blit has completed.
	 */
	{
	MSMPtr pMsm = MSMPTR(pScrn);
	MSMDRI2BufferPtr buf = MSMBUF(pDstBuffer);
	pMsm->pExa->PrepareAccess(buf->pPixmap, 0);
	pMsm->pExa->FinishAccess(buf->pPixmap, 0);
	}

	pGC = GetScratchGC(pDstDraw->depth, pScreen);
	if (!pGC) {
		return;
	}

	pCopyClip = REGION_CREATE(pScreen, NULL, 0);
	RegionCopy(pCopyClip, pRegion);
	(*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
	ValidateGC(pDstDraw, pGC);

	/* If the dst is the framebuffer, and we had a way to
	 * schedule a deferred blit synchronized w/ vsync, that
	 * would be a nice thing to do utilize here to avoid
	 * tearing..  when we have sync object support for GEM
	 * buffers, I think we could do something more clever
	 * here.
	 */

	pGC->ops->CopyArea(pSrcDraw, pDstDraw, pGC,
			0, 0, pDraw->width, pDraw->height, 0, 0);

	FreeScratchGC(pGC);

	MSMFlushAccel(pScreen);
}
Bool
MSMAccelInit(ScreenPtr pScreen)
{
	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
	MSMPtr pMsm = MSMPTR(pScrn);
	Bool ret, softexa = FALSE;

	pMsm->pipe = fd_pipe_new(pMsm->dev, FD_PIPE_2D);
#ifdef HAVE_XA
	if (!pMsm->pipe && !pMsm->NoAccel) {
		struct fd_pipe *p;

		INFO_MSG("no 2D, trying 3D/XA");

		p = fd_pipe_new(pMsm->dev, FD_PIPE_3D);
		if (!p) {
			ERROR_MSG("no 3D pipe");
			goto no_xa;
		}

		pMsm->xa = xa_tracker_create(pMsm->drmFD);
		if (!pMsm->xa) {
			ERROR_MSG("could not setup XA");
			goto no_xa;
		}

		pMsm->pipe = p;

		INFO_MSG("using 3D/XA");

		goto out;
	}
no_xa:
#endif
	if (!pMsm->pipe) {
		INFO_MSG("no 2D pipe, falling back to software!");
		if (pMsm->NoKMS) {
			/* fbdev mode is lame.. we need a pipe, any pipe, to get a
			 * bo for the scanout/fbdev buffer.  So just do this instead
			 * of special casing the PrepareAccess stuff for scanout bo:
			 */
			pMsm->pipe = fd_pipe_new(pMsm->dev, FD_PIPE_3D);
		}
		softexa = TRUE;
		goto out;
	}

	if (pMsm->NoAccel) {
		INFO_MSG("Acceleration disabled in config file");
		softexa = TRUE;
	}

out:
#ifdef HAVE_XA
	if (pMsm->xa)
		ret = MSMSetupExaXA(pScreen);
	else
#endif
	ret = MSMSetupExa(pScreen, softexa);
	if (ret) {
		pMsm->dri = MSMDRI2ScreenInit(pScreen);
	}
	return ret;
}