/** * 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); } }
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; }