diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-14 10:32:12 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-05-14 10:32:12 +0100 |
commit | 0d2392d44aae95d6b571d98f7ec323cf672a687f (patch) | |
tree | 543b835bd3a8d5bfe2a7178a04baae446e473f53 /src | |
parent | 8de09a0707ee1be1b919b979843711728618ef27 (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.c | 32 |
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, ®ion, 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; } |