From 8c6d2072b97646bc8990c93e8eb5b6e501d6d653 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 11 May 2010 14:55:16 +0100 Subject: [PATCH] dri2: Handle reference counting across page flipping 1. Instead of swapping bos, swap the entire private structure. 2. If we update the pixmap bo for the Screen, make sure we update the reference inside intel->front_buffer so that xrandr still functions. 3. Don't double Exchange on page flipping -- only exchange the bos upon successful notification of the flip. Fixes: Bug 27922 - i965: Rapidly resizing OpenGL window causes GPU to hang. https://bugs.freedesktop.org/show_bug.cgi?id=27922 Signed-off-by: Chris Wilson --- src/i830.h | 12 +++++++++++- src/i830_dri.c | 53 ++++++++++++++++++++++------------------------------- src/i830_uxa.c | 18 ++++-------------- 3 files changed, 37 insertions(+), 46 deletions(-) diff --git a/src/i830.h b/src/i830.h index aa7fedc..61a656c 100644 --- a/src/i830.h +++ b/src/i830.h @@ -154,7 +154,17 @@ struct intel_pixmap { struct list flush, batch, in_flight; }; -struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap); +extern int uxa_pixmap_index; + +static inline struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap) +{ + return dixLookupPrivate(&pixmap->devPrivates, &uxa_pixmap_index); +} + +static inline void i830_set_pixmap_intel(PixmapPtr pixmap, struct intel_pixmap *intel) +{ + dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, intel); +} static inline Bool i830_uxa_pixmap_is_dirty(PixmapPtr pixmap) { diff --git a/src/i830_dri.c b/src/i830_dri.c index 321faf6..6d23842 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -434,7 +434,9 @@ I830DRI2ExchangeBuffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back) { I830DRI2BufferPrivatePtr front_priv, back_priv; - dri_bo *tmp_bo; + struct intel_pixmap *front_intel, *back_intel; + ScreenPtr screen; + intel_screen_private *intel; int tmp; front_priv = front->driverPrivate; @@ -446,17 +448,21 @@ I830DRI2ExchangeBuffers(DrawablePtr draw, DRI2BufferPtr front, back->name = tmp; /* Swap pixmap bos */ - - /* Hold a ref on the front so the set calls below don't destroy it */ - dri_bo_reference(i830_get_pixmap_bo(front_priv->pixmap)); - - tmp_bo = i830_get_pixmap_bo(front_priv->pixmap); - i830_set_pixmap_bo(front_priv->pixmap, - i830_get_pixmap_bo(back_priv->pixmap)); - i830_set_pixmap_bo(back_priv->pixmap, tmp_bo); /* should be screen */ - - /* Release our ref, the last set should have bumped it */ - dri_bo_unreference(tmp_bo); + front_intel = i830_get_pixmap_intel(front_priv->pixmap); + back_intel = i830_get_pixmap_intel(back_priv->pixmap); + i830_set_pixmap_intel(front_priv->pixmap, back_intel); + i830_set_pixmap_intel(back_priv->pixmap, front_intel); /* should be screen */ + + /* Do we need to update the Screen? */ + screen = draw->pScreen; + intel = intel_get_screen_private(xf86Screens[screen->myNum]); + if (front_intel->bo == intel->front_buffer) { + dri_bo_unreference (intel->front_buffer); + intel->front_buffer = back_intel->bo; + dri_bo_reference (intel->front_buffer); + i830_set_pixmap_intel(screen->GetScreenPixmap(screen), + back_intel); + } } /* @@ -469,9 +475,7 @@ I830DRI2ScheduleFlip(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, { ScreenPtr screen = draw->pScreen; I830DRI2BufferPrivatePtr front_priv, back_priv; - dri_bo *tmp_bo; DRI2FrameEventPtr flip_info; - Bool ret; flip_info = xcalloc(1, sizeof(DRI2FrameEventRec)); if (!flip_info) @@ -485,25 +489,12 @@ I830DRI2ScheduleFlip(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, front_priv = front->driverPrivate; back_priv = back->driverPrivate; - tmp_bo = i830_get_pixmap_bo(front_priv->pixmap); - - I830DRI2ExchangeBuffers(draw, front, back); /* Page flip the full screen buffer */ - ret = drmmode_do_pageflip(screen, - i830_get_pixmap_bo(front_priv->pixmap), - i830_get_pixmap_bo(back_priv->pixmap), - flip_info); - - /* Unwind in case of failure */ - if (!ret) { - i830_set_pixmap_bo(back_priv->pixmap, - i830_get_pixmap_bo(front_priv->pixmap)); - i830_set_pixmap_bo(front_priv->pixmap, tmp_bo); - return FALSE; - } - - return ret; + return drmmode_do_pageflip(screen, + i830_get_pixmap_bo(front_priv->pixmap), + i830_get_pixmap_bo(back_priv->pixmap), + flip_info); } void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec, diff --git a/src/i830_uxa.c b/src/i830_uxa.c index b5fc6b8..16d38bb 100644 --- a/src/i830_uxa.c +++ b/src/i830_uxa.c @@ -78,7 +78,7 @@ const int I830PatternROP[16] = { ROP_1 }; -static int uxa_pixmap_index; +int uxa_pixmap_index; Bool i830_get_aperture_space(ScrnInfoPtr scrn, drm_intel_bo ** bo_table, @@ -527,16 +527,6 @@ Bool i830_transform_is_affine(PictTransformPtr t) return t->matrix[2][0] == 0 && t->matrix[2][1] == 0; } -struct intel_pixmap *i830_get_pixmap_intel(PixmapPtr pixmap) -{ - return dixLookupPrivate(&pixmap->devPrivates, &uxa_pixmap_index); -} - -static void i830_uxa_set_pixmap_intel(PixmapPtr pixmap, struct intel_pixmap *intel) -{ - dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, intel); -} - dri_bo *i830_get_pixmap_bo(PixmapPtr pixmap) { struct intel_pixmap *intel; @@ -604,7 +594,7 @@ void i830_set_pixmap_bo(PixmapPtr pixmap, dri_bo * bo) } BAIL: - i830_uxa_set_pixmap_intel(pixmap, priv); + i830_set_pixmap_intel(pixmap, priv); } static Bool i830_uxa_prepare_access(PixmapPtr pixmap, uxa_access_t access) @@ -990,7 +980,7 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, list_del(&priv->in_flight); screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); - i830_uxa_set_pixmap_intel(pixmap, priv); + i830_set_pixmap_intel(pixmap, priv); return pixmap; } } @@ -1025,7 +1015,7 @@ i830_uxa_create_pixmap(ScreenPtr screen, int w, int h, int depth, list_init(&priv->batch); list_init(&priv->flush); - i830_uxa_set_pixmap_intel(pixmap, priv); + i830_set_pixmap_intel(pixmap, priv); } return pixmap; -- 1.7.1