summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-05-11 14:55:16 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-05-12 21:37:49 +0100
commit9f54107f866a25cf670f81f7c52b8c108728c6a5 (patch)
tree2a47cfa1e4e01980b0f91f8863637e6943c7269a
parent6c27f6e4f76b97df71094acf25083b2922966b42 (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.h12
-rw-r--r--src/i830_dri.c55
-rw-r--r--src/i830_uxa.c18
3 files changed, 39 insertions, 46 deletions
diff --git a/src/i830.h b/src/i830.h
index fdaa47ee..9e1b4ca2 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 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;