From 27b5c190dcc7c5dd196dafaaa08c9a9e5d6a8ec8 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 | 12 +----------- 3 files changed, 34 insertions(+), 43 deletions(-) diff --git a/src/i830.h b/src/i830.h index aa7fedc..89101aa 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_uxa_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..3f9f9a8 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_uxa_set_pixmap_intel(front_priv->pixmap, back_intel); + i830_uxa_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_uxa_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..f202111 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; -- 1.7.1