Obviously we shouldn't be updating the front buffer offset in the rotation case, and I'm not sure how well resize (or other bits for that matter) will play with the fact that pI830->front_buffer changed out from under it. The flip should be queued from the kernel too...
diff --git a/src/i810_reg.h b/src/i810_reg.h index e2ffba1..4c8c023 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -2433,6 +2433,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. /* Wait for Events */ #define MI_WAIT_FOR_EVENT (0x03<<23) #define MI_WAIT_FOR_OVERLAY_FLIP (1<<16) +#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6) +#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2) /* Flush */ #define MI_FLUSH (0x04<<23) @@ -2464,6 +2466,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ENABLE_FOG_CONST (1<<24) #define ENABLE_FOG_DENSITY (1<<23) +#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2) +#define ASYNC_FLIP (1<<22) +#define DISPLAY_PLANE_A (0<<20) +#define DISPLAY_PLANE_B (1<<20) + /* * New regs for broadwater -- we need to split this file up sensibly somehow. */ diff --git a/src/i830_dri.c b/src/i830_dri.c index f03be43..76d7711 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -1634,6 +1634,7 @@ I830DRI2DestroyBuffers(DrawablePtr pDraw, DRI2BufferPtr buffers, int count) } } +/* Copy from the private back buffer to the real front buffer */ static void I830DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, DRI2BufferPtr pDestBuffer, DRI2BufferPtr pSrcBuffer) @@ -1672,6 +1673,166 @@ 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; + dri_bo *front_bo, *back_bo; + int plane = 1; + int pitch = pScrn->displayWidth * pI830->cpp; + + 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); + + /* Pin the new front & ref it so the set_pixmap_bo doesn't kill it */ + dri_bo_reference(back_bo); + dri_bo_pin(back_bo, 0); + dri_bo_unpin(front_bo); + + /* Now do the swap */ + + /* + * Update the DRI2 buffer with the new info: + * - pixmap private ptr (so we can get the buffer later) + * - name + */ + dri2_front->driverPrivate = back_priv; + dri_bo_flink(back_bo, &dri2_front->name); + + /* back -> front */ + dri2_back->driverPrivate = front_priv; + dri_bo_flink(front_bo, &dri2_back->name); + + pScrn->fbOffset = back_bo->offset; + + BEGIN_BATCH(4); + if (plane == 0) + OUT_BATCH(CMD_OP_DISPLAYBUFFER_INFO | DISPLAY_PLANE_A); + else + OUT_BATCH(CMD_OP_DISPLAYBUFFER_INFO | DISPLAY_PLANE_B); + OUT_BATCH((pitch / 8) << 3); /* flip queue and/or pitch */ + OUT_BATCH(back_bo->offset | 1); + OUT_BATCH(((pScrn->virtualX - 1) << 16) | (pScrn->virtualY - 1)); + ADVANCE_BATCH(); + + BEGIN_BATCH(2); + if (plane == 0) + OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); + else + OUT_BATCH(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_B_FLIP); + OUT_BATCH(0); + ADVANCE_BATCH(); + + 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); + + if (!i830_flip_ok(pDraw)) { + BoxRec box; + RegionRec region; + DRI2BufferPtr buffers, back, front; + + 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; + } + + /* Page flip the full screen buffer */ + I830Sync(pScrn); +#if 0 + if (pI830->use_drm_mode) + return drmmode_swapbuffers(pScrn); +#endif + return i830_do_pageflip(pDraw); +} + Bool I830DRI2ScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -1742,6 +1903,7 @@ Bool I830DRI2ScreenInit(ScreenPtr pScreen) info.CreateBuffers = I830DRI2CreateBuffers; info.DestroyBuffers = I830DRI2DestroyBuffers; info.CopyRegion = I830DRI2CopyRegion; + info.SwapBuffers = I830DRI2SwapBuffers; pI830->drmSubFD = info.fd; ------------------------------------------------------------------------------ Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM) software. With Adobe AIR, Ajax developers can use existing skills and code to build responsive, highly engaging applications that combine the power of local resources and data with the reach of the web. Download the Adobe AIR SDK and Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com -- _______________________________________________ Dri-devel mailing list Dri-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dri-devel