summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-05-14 10:32:12 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-05-14 10:32:12 +0100
commit0d2392d44aae95d6b571d98f7ec323cf672a687f (patch)
tree543b835bd3a8d5bfe2a7178a04baae446e473f53 /src
parent8de09a0707ee1be1b919b979843711728618ef27 (diff)
dri: Hold reference to buffers across swap
As we schedule swaps for some time in the future and may process a detachment prior to receiving the vblank notification from the kernel, we need to hold a reference to the buffers for our swap event handler. Fixes: Bug 28080 - "glresize" causes X server segfault with indirect rendering. https://bugs.freedesktop.org/show_bug.cgi?id=28080 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r--src/i830_dri.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 9500dad8..21871c59 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -75,6 +75,7 @@ extern XF86ModuleData dri2ModuleData;
#endif
typedef struct {
+ int refcnt;
PixmapPtr pixmap;
unsigned int attachment;
} I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr;
@@ -147,6 +148,7 @@ I830DRI2CreateBuffers(DrawablePtr drawable, unsigned int *attachments,
buffers[i].cpp = pixmap->drawable.bitsPerPixel / 8;
buffers[i].driverPrivate = &privates[i];
buffers[i].flags = 0; /* not tiled */
+ privates[i].refcnt = 1;
privates[i].pixmap = pixmap;
privates[i].attachment = attachments[i];
@@ -223,6 +225,7 @@ I830DRI2CreateBuffer(DrawablePtr drawable, unsigned int attachment,
buffer->driverPrivate = privates;
buffer->format = format;
buffer->flags = 0; /* not tiled */
+ privates->refcnt = 1;
privates->pixmap = pixmap;
privates->attachment = attachment;
@@ -262,17 +265,27 @@ static void I830DRI2DestroyBuffer(DrawablePtr drawable, DRI2Buffer2Ptr buffer)
{
if (buffer) {
I830DRI2BufferPrivatePtr private = buffer->driverPrivate;
- ScreenPtr screen = drawable->pScreen;
+ if (--private->refcnt == 0) {
+ ScreenPtr screen = private->pixmap->drawable.pScreen;
- screen->DestroyPixmap(private->pixmap);
+ screen->DestroyPixmap(private->pixmap);
- xfree(private);
- xfree(buffer);
+ xfree(private);
+ xfree(buffer);
+ }
}
}
#endif
+static void I830DRI2ReferenceBuffer(DRI2Buffer2Ptr buffer)
+{
+ if (buffer) {
+ I830DRI2BufferPrivatePtr private = buffer->driverPrivate;
+ private->refcnt++;
+ }
+}
+
static void
I830DRI2CopyRegion(DrawablePtr drawable, RegionPtr pRegion,
DRI2BufferPtr destBuffer, DRI2BufferPtr sourceBuffer)
@@ -510,6 +523,8 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
M_ANY, DixWriteAccess);
if (status != Success) {
+ I830DRI2DestroyBuffer(NULL, event->front);
+ I830DRI2DestroyBuffer(NULL, event->back);
xfree(event);
return;
}
@@ -568,6 +583,8 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
break;
}
+ I830DRI2DestroyBuffer(drawable, event->front);
+ I830DRI2DestroyBuffer(drawable, event->back);
xfree(event);
}
@@ -661,6 +678,8 @@ I830DRI2ScheduleSwap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
swap_info->event_data = data;
swap_info->front = front;
swap_info->back = back;
+ I830DRI2ReferenceBuffer(front);
+ I830DRI2ReferenceBuffer(back);
/* Get current count */
vbl.request.type = DRM_VBLANK_RELATIVE;
@@ -791,8 +810,11 @@ blit_fallback:
I830DRI2CopyRegion(draw, &region, front, back);
DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
- if (swap_info)
+ if (swap_info) {
+ I830DRI2DestroyBuffer(draw, swap_info->front);
+ I830DRI2DestroyBuffer(draw, swap_info->back);
xfree(swap_info);
+ }
*target_msc = 0; /* offscreen, so zero out target vblank count */
return TRUE;
}