st/dri: Track drawable context bindings
authorJakob Bornecrantz <wallbraker@gmail.com>
Wed, 1 Dec 2010 04:04:25 +0000 (05:04 +0100)
committerMarek Olšák <maraeo@gmail.com>
Sun, 20 Feb 2011 15:31:48 +0000 (16:31 +0100)
Needs to track this ourself since because we get into a race condition with
the dri_util.c code on make current when rendering to the front buffer.

This is what happens:
Old context is rendering to the front buffer.

App calls MakeCurrent with a new context. dri_util.c sets
drawable->driContextPriv to the new context and then calls the driver make
current. st/dri make current flushes the old context, which calls back into
st/dri via the flush frontbuffer hook. st/dri calls dri loader flush
frontbuffer, which calls invalidate buffer on the drawable into st/dri.

This is where things gets wrong. st/dri grabs the context from the dri
drawable (which now points to the new context) and calls invalidate
framebuffer to the new context which has not yet set the new drawable as its
framebuffers since we have not called make current yet, it asserts.

src/gallium/state_trackers/dri/common/dri_context.c
src/gallium/state_trackers/dri/common/dri_drawable.c
src/gallium/state_trackers/dri/common/dri_drawable.h
src/gallium/state_trackers/dri/drm/dri2.c

index 999b41152e1de241a56286be60c7ced54217434c..fc68ee13eaa3e20586b1f7ff1a0147f9fe9fa945 100644 (file)
@@ -141,12 +141,18 @@ GLboolean
 dri_unbind_context(__DRIcontext * cPriv)
 {
    /* dri_util.c ensures cPriv is not null */
+   struct dri_screen *screen = dri_screen(cPriv->driScreenPriv);
    struct dri_context *ctx = dri_context(cPriv);
+   struct dri_drawable *draw = dri_drawable(ctx->dPriv);
+   struct dri_drawable *read = dri_drawable(ctx->rPriv);
+   struct st_api *stapi = screen->st_api;
 
    if (--ctx->bind_count == 0) {
       if (ctx->st == ctx->stapi->get_current(ctx->stapi)) {
          ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
-         ctx->stapi->make_current(ctx->stapi, NULL, NULL, NULL);
+         stapi->make_current(stapi, NULL, NULL, NULL);
+         draw->context = NULL;
+         read->context = NULL;
       }
    }
 
@@ -174,10 +180,12 @@ dri_make_current(__DRIcontext * cPriv,
    else if (!driDrawPriv || !driReadPriv)
       return GL_FALSE;
 
+   draw->context = ctx;
    if (ctx->dPriv != driDrawPriv) {
       ctx->dPriv = driDrawPriv;
       draw->texture_stamp = driDrawPriv->lastStamp - 1;
    }
+   read->context = ctx;
    if (ctx->rPriv != driReadPriv) {
       ctx->rPriv = driReadPriv;
       read->texture_stamp = driReadPriv->lastStamp - 1;
index 060748622c9dfbc82857fd7382f955d5e96b89b5..28a33ac7d07c0077bc4f87880177a226996b80fc 100644 (file)
@@ -132,6 +132,7 @@ dri_create_buffer(__DRIscreen * sPriv,
    drawable->base.validate = dri_st_framebuffer_validate;
    drawable->base.st_manager_private = (void *) drawable;
 
+   drawable->screen = screen;
    drawable->sPriv = sPriv;
    drawable->dPriv = dPriv;
    dPriv->driverPrivate = (void *)drawable;
index 2ff6b7132935cd5892db62cd36019ee5137521fa..7f1aa512ca1bd4decd510c30e37c37b9398d0580 100644 (file)
@@ -41,6 +41,9 @@ struct dri_drawable
    struct st_framebuffer_iface base;
    struct st_visual stvis;
 
+   struct dri_screen *screen;
+   struct dri_context *context;
+
    /* dri */
    __DRIdrawable *dPriv;
    __DRIscreen *sPriv;
index a69f20e608586969393d5b75fb94e43f66322ab4..0181588096defeff826bdddcd2f8107096d3702b 100644 (file)
@@ -52,7 +52,7 @@ static void
 dri2_invalidate_drawable(__DRIdrawable *dPriv)
 {
    struct dri_drawable *drawable = dri_drawable(dPriv);
-   struct dri_context *ctx = dri_context(dPriv->driContextPriv);
+   struct dri_context *ctx = drawable->context;
 
    dri2InvalidateDrawable(dPriv);
    drawable->dPriv->lastStamp = *drawable->dPriv->pStamp;