diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-11 14:55:16 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-12 21:37:49 +0100 |
commit | 9f54107f866a25cf670f81f7c52b8c108728c6a5 (patch) | |
tree | 2a47cfa1e4e01980b0f91f8863637e6943c7269a | |
parent | 6c27f6e4f76b97df71094acf25083b2922966b42 (diff) |
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.
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 <chris@chris-wilson.co.uk>
-rw-r--r-- | src/i830.h | 12 | ||||
-rw-r--r-- | src/i830_dri.c | 55 | ||||
-rw-r--r-- | src/i830_uxa.c | 18 |
3 files changed, 39 insertions, 46 deletions
@@ -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 321faf60..9500dad8 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, @@ -535,6 +526,8 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec, I830DRI2ScheduleFlip(event->client, drawable, event->front, event->back, event->event_complete, event->event_data)) { + I830DRI2ExchangeBuffers(drawable, + event->front, event->back); break; } /* else fall through to exchange/blit */ diff --git a/src/i830_uxa.c b/src/i830_uxa.c index 3f9610e4..6a454ac0 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) @@ -985,7 +975,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; } } @@ -1020,7 +1010,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; |