intel: Implement the DRI2 invalidate function properly
authorKristian Høgsberg <krh@bitplanet.net>
Thu, 18 Feb 2010 02:17:55 +0000 (21:17 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 18 Feb 2010 02:53:16 +0000 (21:53 -0500)
This uses a stamp mechanisms to mark the DRI drawable as invalid.
Instead of immediately updating the buffers we just bump the drawable
stamp and call out to DRI2GetBuffers "later".

"Later" used to be at LOCK_HARDWARE time, and this patch brings back
callouts at the points where we used to call LOCK_HARDWARE.  A new function,
intel_prepare_render(), is called where we used to call LOCK_HARDWARE,
and if the buffers are invalid, we call out to DRI2GetBuffers there.

This lets us invalidate buffers only when notified instead of on
every glViewport() call.  If the loader calls the DRI invalidate
entrypoint, we disable viewport triggered buffer invalidation.

Additionally, we can clean up the old viewport mechanism a bit,
since we can just invalidate the buffers and not worry about
reentrancy and whatnot.

16 files changed:
src/mesa/drivers/dri/common/dri_util.c
src/mesa/drivers/dri/common/dri_util.h
src/mesa/drivers/dri/i965/brw_draw.c
src/mesa/drivers/dri/intel/intel_blit.c
src/mesa/drivers/dri/intel/intel_buffers.c
src/mesa/drivers/dri/intel/intel_context.c
src/mesa/drivers/dri/intel/intel_context.h
src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
src/mesa/drivers/dri/intel/intel_pixel_copy.c
src/mesa/drivers/dri/intel/intel_pixel_read.c
src/mesa/drivers/dri/intel/intel_regions.c
src/mesa/drivers/dri/intel/intel_screen.c
src/mesa/drivers/dri/intel/intel_span.c
src/mesa/drivers/dri/intel/intel_tex_copy.c
src/mesa/drivers/dri/intel/intel_tex_image.c
src/mesa/drivers/dri/intel/intel_tex_subimage.c

index b891fca2b1cb4e64d9920fe07825c0f4b7b75db8..58a94b5868216188bceb73c16d04bf1258d27e4b 100644 (file)
@@ -585,6 +585,8 @@ driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
     pcp->driDrawablePriv = NULL;
     pcp->loaderPrivate = data;
     
+    pcp->dri2.draw_stamp = 0;
+    pcp->dri2.read_stamp = 0;
     /* When the first context is created for a screen, initialize a "dummy"
      * context.
      */
index 8f0cd4cf9d8d196cf0d74c0961ee923953c2797b..2eadb9ac8c52296d64b803179e9087f5938f99d0 100644 (file)
@@ -422,6 +422,11 @@ struct __DRIcontextRec {
      * The loaders's private context data.  This structure is opaque.
      */
     void *loaderPrivate;
+
+    struct {
+       int draw_stamp;
+       int read_stamp;
+    } dri2;
 };
 
 /**
index d510d767f97fd3774c66208c1313ede665919a7c..976249091e93caeaccaba30b7a0140a874c5286f 100644 (file)
@@ -337,6 +337,8 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
     * so can't access it earlier.
     */
 
+   intel_prepare_render(intel);
+
    for (i = 0; i < nr_prims; i++) {
       uint32_t hw_prim;
 
index 1fd07e8b82ea61292c70aafa11f7f10c1318b398..5a60a17500e8c4f8b6ed0f89a3a754bfa4c90553 100644 (file)
@@ -115,6 +115,8 @@ intelEmitCopyBlit(struct intel_context *intel,
            break;
    } while (pass < 2);
 
+   intel_prepare_render(intel);
+
    if (pass >= 2) {
        dri_bo_map(dst_buffer, GL_TRUE);
        dri_bo_map(src_buffer, GL_FALSE);
@@ -241,6 +243,8 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
    GLuint buf;
    all = (cw == fb->Width && ch == fb->Height);
 
+   intel_prepare_render(intel);
+
    /* Loop over all renderbuffers */
    for (buf = 0; buf < BUFFER_COUNT && mask; buf++) {
       const GLbitfield bufBit = 1 << buf;
index 2f03e450051badf44140687ca9b4fc8b1213f62c..b10693050a9485c314af6e86195a17bb66db4911 100644 (file)
@@ -271,13 +271,12 @@ intelDrawBuffer(GLcontext * ctx, GLenum mode)
       intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT)
        || (mode == GL_FRONT);
 
-      /* If we weren't front-buffer rendering before but we are now, make sure
-       * that the front-buffer has actually been allocated.
+      /* If we weren't front-buffer rendering before but we are now,
+       * invalidate our DRI drawable so we'll ask for new buffers
+       * (including the fake front) before we start rendering again.
        */
-      if (!was_front_buffer_rendering && intel->is_front_buffer_rendering) {
-        intel_update_renderbuffers(intel->driContext,
-                                   intel->driContext->driDrawablePriv);
-      }
+      if (!was_front_buffer_rendering && intel->is_front_buffer_rendering)
+        dri2InvalidateDrawable(intel->driContext->driDrawablePriv);
    }
 
    intel_draw_buffer(ctx, ctx->DrawBuffer);
@@ -295,13 +294,12 @@ intelReadBuffer(GLcontext * ctx, GLenum mode)
       intel->is_front_buffer_reading = (mode == GL_FRONT_LEFT)
        || (mode == GL_FRONT);
 
-      /* If we weren't front-buffer reading before but we are now, make sure
-       * that the front-buffer has actually been allocated.
+      /* If we weren't front-buffer reading before but we are now,
+       * invalidate our DRI drawable so we'll ask for new buffers
+       * (including the fake front) before we start reading again.
        */
-      if (!was_front_buffer_reading && intel->is_front_buffer_reading) {
-        intel_update_renderbuffers(intel->driContext,
-                                   intel->driContext->driDrawablePriv);
-      }
+      if (!was_front_buffer_reading && intel->is_front_buffer_reading)
+        dri2InvalidateDrawable(intel->driContext->driReadablePriv);
    }
 
    if (ctx->ReadBuffer == ctx->DrawBuffer) {
index 81d5a32476c435a288a1e1c75ec046d7f331eeac..8f37fb82c1a62090794b2d651eadd24b512330c2 100644 (file)
@@ -197,6 +197,15 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
    unsigned int attachments[10];
    const char *region_name;
 
+   /* If we're rendering to the fake front buffer, make sure all the
+    * pending drawing has landed on the real front buffer.  Otherwise
+    * when we eventually get to DRI2GetBuffersWithFormat the stale
+    * real front buffer contents will get copied to the new fake front
+    * buffer.
+    */
+   if (intel->is_front_buffer_rendering)
+      intel_flush(&intel->ctx, GL_FALSE);
+
    if (INTEL_DEBUG & DEBUG_DRI)
       fprintf(stderr, "enter %s, drawable %p\n", __func__, drawable);
 
@@ -370,37 +379,41 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
    drawable->lastStamp = drawable->dri2.stamp;
 }
 
+void
+intel_prepare_render(struct intel_context *intel)
+{
+   __DRIcontext *driContext = intel->driContext;
+   __DRIdrawable *drawable;
+
+   drawable = intel->driDrawable;
+   if (drawable->dri2.stamp != driContext->dri2.draw_stamp) {
+      if (drawable->lastStamp != drawable->dri2.stamp)
+        intel_update_renderbuffers(driContext, drawable);
+      intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
+      driContext->dri2.draw_stamp = drawable->dri2.stamp;
+   }
+
+   drawable = intel->driReadDrawable;
+   if (drawable->dri2.stamp != driContext->dri2.read_stamp) {
+      if (drawable->lastStamp != drawable->dri2.stamp)
+        intel_update_renderbuffers(driContext, drawable);
+      driContext->dri2.read_stamp = drawable->dri2.stamp;
+   }
+}
+
 void
 intel_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
 {
     struct intel_context *intel = intel_context(ctx);
     __DRIcontext *driContext = intel->driContext;
-    void (*old_viewport)(GLcontext *ctx, GLint x, GLint y,
-                        GLsizei w, GLsizei h);
-
-    if (!intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
-       /* If we're rendering to the fake front buffer, make sure all the pending
-       * drawing has landed on the real front buffer.  Otherwise when we
-       * eventually get to DRI2GetBuffersWithFormat the stale real front
-       * buffer contents will get copied to the new fake front buffer.
-       */
-       if (intel->is_front_buffer_rendering) {
-         intel_flush(ctx, GL_FALSE);
-       }
 
-       intel_update_renderbuffers(driContext, driContext->driDrawablePriv);
-       if (driContext->driDrawablePriv != driContext->driReadablePriv)
-         intel_update_renderbuffers(driContext, driContext->driReadablePriv);
+    if (!intel->using_dri2_swapbuffers &&
+       !intel->meta.internal_viewport_call && ctx->DrawBuffer->Name == 0) {
+       dri2InvalidateDrawable(driContext->driDrawablePriv);
+       dri2InvalidateDrawable(driContext->driReadablePriv);
     }
-
-    old_viewport = ctx->Driver.Viewport;
-    ctx->Driver.Viewport = NULL;
-    intel->driDrawable = driContext->driDrawablePriv;
-    intel_draw_buffer(ctx, intel->ctx.DrawBuffer);
-    ctx->Driver.Viewport = old_viewport;
 }
 
-
 static const struct dri_debug_control debug_control[] = {
    { "tex",   DEBUG_TEXTURE},
    { "state", DEBUG_STATE},
@@ -860,22 +873,12 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
    if (driContextPriv) {
       struct gl_framebuffer *fb = driDrawPriv->driverPrivate;
       struct gl_framebuffer *readFb = driReadPriv->driverPrivate;
-      intel_update_renderbuffers(driContextPriv, driDrawPriv);
-      if (driDrawPriv != driReadPriv)
-        intel_update_renderbuffers(driContextPriv, driReadPriv);
-
-      /* set GLframebuffer size to match window, if needed */
-      driUpdateFramebufferSize(&intel->ctx, driDrawPriv);
-
-      if (driReadPriv != driDrawPriv) {
-        driUpdateFramebufferSize(&intel->ctx, driReadPriv);
-      }
 
       _mesa_make_current(&intel->ctx, fb, readFb);
       intel->driReadDrawable = driReadPriv;
       intel->driDrawable = driDrawPriv;
-      intel_draw_buffer(&intel->ctx, fb);
+      driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1;
+      driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1;
    }
    else {
       _mesa_make_current(NULL, NULL, NULL);
index 0f0a194b3f5481270fb1f76b338badc11d90a57f..da5d901abf9c196c87e4096e710c4f329dfd42e6 100644 (file)
@@ -454,6 +454,7 @@ void intel_viewport(GLcontext * ctx, GLint x, GLint y,
 
 void intel_update_renderbuffers(__DRIcontext *context,
                                __DRIdrawable *drawable);
+void intel_prepare_render(struct intel_context *intel);
 
 void i915_set_buf_info_for_region(uint32_t *state, struct intel_region *region,
                                  uint32_t buffer_id);
index 1e517650b7a9aeb80ed53747e03114d0af84ee8b..eabfbf4af9494d1431d421680bcab4cc2c0e7458 100644 (file)
@@ -234,6 +234,8 @@ do_blit_bitmap( GLcontext *ctx,
    if (!intel_check_blit_fragment_ops(ctx, tmpColor[3] == 1.0F))
       return GL_FALSE;
 
+   intel_prepare_render(intel);
+
    /* Clip to buffer bounds and scissor. */
    if (!_mesa_clip_to_region(fb->_Xmin, fb->_Ymin,
                             fb->_Xmax, fb->_Ymax,
index 87c293d8b07f47107b170ae729f4800ec5aeb32f..f4f3fd6d889e9008dc0ede03f8d57c3342246c4b 100644 (file)
@@ -138,6 +138,8 @@ do_blit_copypixels(GLcontext * ctx,
 
    intelFlush(&intel->ctx);
 
+   intel_prepare_render(intel);
+
    /* XXX: We fail to handle different inversion between read and draw framebuffer. */
 
    /* Clip to destination buffer. */
index a98e8e16c240cbc9a83c418064f8230624c7783e..514a17e2aa30156b2438bcbc627d6ff26bf6225d 100644 (file)
@@ -132,6 +132,8 @@ do_blit_readpixels(GLcontext * ctx,
       return GL_TRUE;
    }
 
+   intel_prepare_render(intel);
+
    all = (width * height * src->cpp == dst->Base.Size &&
          x == 0 && dst_offset == 0);
 
@@ -172,6 +174,7 @@ intelReadPixels(GLcontext * ctx,
       fprintf(stderr, "%s\n", __FUNCTION__);
 
    intelFlush(ctx);
+   intel_prepare_render(intel_context(ctx));
 
    if (do_blit_readpixels
        (ctx, x, y, width, height, format, type, pack, pixels))
index 881653ff01f835dc4578da76f3e0c35c58fe801d..62b4ce61e44b4b2595deb7e1cce823367103178a 100644 (file)
@@ -378,6 +378,8 @@ intel_region_data(struct intel_context *intel,
          intel_region_cow(intel, dst);
    }
 
+   intel_prepare_render(intel);
+
    _mesa_copy_rect(intel_region_map(intel, dst) + dst_offset,
                    dst->cpp,
                    dst->pitch,
@@ -500,6 +502,7 @@ intel_region_cow(struct intel_context *intel, struct intel_region *region)
    /* Now blit from the texture buffer to the new buffer: 
     */
 
+   intel_prepare_render(intel);
    ok = intelEmitCopyBlit(intel,
                           region->cpp,
                           region->pitch, pbo->buffer, 0, region->tiling,
index 8eed8ee73753482f2f6f50e97db72dc88673d4e7..5e23aa8a1d6138c48da1a593caee7c0d71fe4419 100644 (file)
@@ -129,7 +129,6 @@ intelDRI2Invalidate(__DRIdrawable *drawable)
 
    intel->using_dri2_swapbuffers = GL_TRUE;
    dri2InvalidateDrawable(drawable);
-   intel_update_renderbuffers(intel->driContext, drawable);
 }
 
 static const struct __DRI2flushExtensionRec intelFlushExtension = {
index d925cb9997fedf88600f3a528ec6b38805eded26..97bb97265fb79a5c344e9357e9eb2e482b3f9055 100644 (file)
@@ -498,6 +498,7 @@ intelSpanRenderStart(GLcontext * ctx)
    GLuint i;
 
    intelFlush(&intel->ctx);
+   intel_prepare_render(intel);
 
    for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
       if (ctx->Texture.Unit[i]._ReallyEnabled) {
index d67451cf8ecab03143b876492a8c55764df7ba93..13b8bcfa86c31b9b1edfb6d5097b0e11d4970baa 100644 (file)
@@ -109,6 +109,7 @@ do_copy_texsubimage(struct intel_context *intel,
    }
 
    /* intelFlush(ctx); */
+   intel_prepare_render(intel);
    {
       drm_intel_bo *dst_bo = intel_region_buffer(intel,
                                                 intelImage->mt->region,
index bc4e5c6136738ae344cb30f5e1a4df4a9d39d3cb..aefd0b97d0c2758b336e9294001008bbb5aa66d1 100644 (file)
@@ -240,6 +240,7 @@ try_pbo_upload(struct intel_context *intel,
 
    if (drm_intel_bo_references(intel->batch->buf, dst_buffer))
       intelFlush(&intel->ctx);
+   intel_prepare_render(intel);
    {
       dri_bo *src_buffer = intel_bufferobj_buffer(intel, pbo, INTEL_READ);
 
@@ -472,6 +473,8 @@ intelTexImage(GLcontext * ctx,
                                           pixels, unpack, "glTexImage");
    }
 
+   intel_prepare_render(intel);
+
    if (intelImage->mt) {
       if (pixels != NULL) {
         /* Flush any queued rendering with the texture before mapping. */
@@ -748,7 +751,7 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
    if (!intelObj)
       return;
 
-   if (dPriv->lastStamp != *dPriv->pStamp)
+   if (dPriv->lastStamp != dPriv->dri2.stamp)
       intel_update_renderbuffers(pDRICtx, dPriv);
 
    rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
index 7f1dc8902208b55db79e5c37111eb6e5e8735c92..c35d2e875731ed130d9c96ca32aa3d3cee6016cd 100644 (file)
@@ -72,6 +72,8 @@ intelTexSubimage(GLcontext * ctx,
    if (!pixels)
       return;
 
+   intel_prepare_render(intel);
+
    /* Map buffer if necessary.  Need to lock to prevent other contexts
     * from uploading the buffer under us.
     */