Fixed it up a bit: we now fall back correctly if pageflipping fails or can't be done. Also use the new ioctl in the do_pageflip code and check for shadow framebuffers.
diff --git a/src/i830.h b/src/i830.h index bfd78dc..607037f 100644 --- a/src/i830.h +++ b/src/i830.h @@ -452,6 +452,7 @@ typedef struct _I830Rec { #endif XF86ModReqInfo shadowReq; /* to test for later libshadow */ + Bool shadow_present; Rotation rotation; void (*PointerMoved)(int, int, int); CreateScreenResourcesProcPtr CreateScreenResources; diff --git a/src/i830_display.c b/src/i830_display.c index 8ecb5e5..ca43537 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -1650,6 +1650,9 @@ i830_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) } if (intel_crtc->rotate_mem && intel_crtc->rotate_mem->bo) i830_set_pixmap_bo(rotate_pixmap, intel_crtc->rotate_mem->bo); + + pI830->shadow_present = TRUE; + return rotate_pixmap; } @@ -1658,6 +1661,7 @@ i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) { ScrnInfoPtr pScrn = crtc->scrn; I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + I830Ptr pI830 = I830PTR(pScrn); if (rotate_pixmap) FreeScratchPixmapHeader(rotate_pixmap); @@ -1668,6 +1672,7 @@ i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) i830_free_memory(pScrn, intel_crtc->rotate_mem); intel_crtc->rotate_mem = NULL; } + pI830->shadow_present = FALSE; } #if RANDR_13_INTERFACE diff --git a/src/i830_dri.c b/src/i830_dri.c index f03be43..6c44777 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -1672,6 +1672,161 @@ I830DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, } +static DRI2BufferPtr +i830_get_buffer(DrawablePtr pDraw, int attachment) +{ + DRI2DrawablePtr pPriv; + int i; + + pPriv = DRI2GetDrawable(pDraw); + if (!pPriv) + return NULL; + + for (i = 0; i < pPriv->bufferCount; i++) + if (pPriv->buffers[i].attachment == attachment) + return &pPriv->buffers[i]; + + return NULL; +} + +/* + * At flip time we need to: + * - pin the new front buffer + * - update X screen pixmap with the new front buffer info + * - update new back buffer info with old front buffer info + * - queue the flip + * - queue a wait so we don't clobber rendering + * - return the new front & back buffer info + */ +static DRI2BufferPtr +i830_do_pageflip(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + DRI2BufferPtr buffers, dri2_front, dri2_back; + I830DRI2BufferPrivatePtr back_priv, front_priv; + PixmapPtr tmp; + dri_bo *front_bo, *back_bo; + struct drm_i915_gem_page_flip flip; + int ret; + + dri2_back = i830_get_buffer(pDraw, DRI2BufferBackLeft); + dri2_front = i830_get_buffer(pDraw, DRI2BufferFrontLeft); + if (!dri2_back || !dri2_front) + return NULL; + + back_priv = dri2_back->driverPrivate; + back_bo = i830_get_pixmap_bo(back_priv->pPixmap); + + /* This should actually be the screen pixmap */ + front_priv = dri2_front->driverPrivate; + front_bo = i830_get_pixmap_bo(front_priv->pPixmap); + + /* Now do the swap */ + + /* + * Update the DRI2 buffer with the new info: + * - pixmap private ptr (so we can get the buffer later) + * - name + */ + tmp = front_priv->pPixmap; + front_priv->pPixmap = back_priv->pPixmap; + dri_bo_flink(back_bo, &dri2_front->name); + + /* back -> front */ + back_priv->pPixmap = tmp; + dri_bo_flink(front_bo, &dri2_back->name); + + pScrn->fbOffset = back_bo->offset; + + /* If we're in charge of the front buffer, we can flip */ + if (!pI830->shadow_present) { + flip.handle = back_bo->handle; + flip.pipe = 1; + flip.x = pScrn->virtualX; + flip.y = pScrn->virtualY; + flip.flags = 0; + + ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_GEM_PAGE_FLIP, &flip, + sizeof(flip)); + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", + strerror(errno)); + return NULL; + } + } + + /* Return the new front & back buffers */ + buffers = xnfcalloc(sizeof(DRI2BufferRec), 2); + buffers[0] = *dri2_front; + buffers[1] = *dri2_back; + + return buffers; +} + +/* Check various flip constraints (drawable parameters vs screen params) */ +static Bool +i830_flip_ok(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + if (pDraw->width != pScrn->virtualX) + return FALSE; + if (pDraw->height != pScrn->virtualY) + return FALSE; + if (pDraw->depth != pScrn->depth) + return FALSE; + + return TRUE; +} + +/* + * DRI2SwapBuffers should try to do a buffer swap if possible, however: + * - if we're swapping buffers smaller than the screen, we have to blit + * - if the back buffer doesn't match the screen depth, we have to blit + * - otherwise we try to swap, and return to the caller the new front + * and back buffers + */ +static DRI2BufferPtr +I830DRI2SwapBuffers(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + BoxRec box; + RegionRec region; + DRI2BufferPtr buffers = NULL, back, front; + + if (i830_flip_ok(pDraw)) { + /* Page flip the full screen buffer */ + I830Sync(pScrn); + buffers = i830_do_pageflip(pDraw); + } + + /* If the flip failed or we couldn't do it, we need to blit */ + if (!buffers) { + box.x1 = 0; + box.y1 = 0; + box.x2 = pDraw->width; + box.y2 = pDraw->height; + REGION_INIT(pScreen, ®ion, &box, 0); + + DRI2CopyRegion(pDraw, ®ion, DRI2BufferFrontLeft, + DRI2BufferBackLeft); + REGION_UNINIT(pScreen, ®ion); + + buffers = xnfcalloc(sizeof(DRI2BufferRec), 2); + front = i830_get_buffer(pDraw, DRI2BufferFrontLeft); + back = i830_get_buffer(pDraw, DRI2BufferBackLeft); + buffers[0] = *front; + buffers[1] = *back; + } + + return buffers; +} + Bool I830DRI2ScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -1742,6 +1897,7 @@ Bool I830DRI2ScreenInit(ScreenPtr pScreen) info.CreateBuffers = I830DRI2CreateBuffers; info.DestroyBuffers = I830DRI2DestroyBuffers; info.CopyRegion = I830DRI2CopyRegion; + info.SwapBuffers = I830DRI2SwapBuffers; pI830->drmSubFD = info.fd; ------------------------------------------------------------------------------ Open Source Business Conference (OSBC), March 24-25, 2009, San Francisco, CA -OSBC tackles the biggest issue in open source: Open Sourcing the Enterprise -Strategies to boost innovation and cut costs with open source participation -Receive a $600 discount off the registration fee with the source code: SFAD http://p.sf.net/sfu/XcvMzF8H -- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel