gallium: more elaborate tracking of front color buffer state
authorBrian Paul <brian.paul@tungstengraphics.com>
Thu, 10 Apr 2008 00:39:51 +0000 (18:39 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Thu, 10 Apr 2008 00:39:51 +0000 (18:39 -0600)
This fixes the case where the app calls SwapBuffers then calls glReadPixels
to read the front color buffer.  We now keep track of when the front buffer
is a _logically_ copy of the back buffer (after SwapBuffers) and read from
the back color buffer instead of the front.

src/mesa/state_tracker/st_atom_framebuffer.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_cb_flush.c
src/mesa/state_tracker/st_cb_readpixels.c
src/mesa/state_tracker/st_cb_readpixels.h
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_framebuffer.c

index 02573af8f0a7fff1ecbc1aa8ba05c23f3b549289..8a95096ec9af78ffbf0c52e9ef9b009038793732 100644 (file)
@@ -81,6 +81,14 @@ update_framebuffer_state( struct st_context *st )
    }
 
    cso_set_framebuffer(st->cso_context, framebuffer);
+
+   if (fb->_ColorDrawBufferMask[0] & BUFFER_BIT_FRONT_LEFT) {
+      if (st->frontbuffer_status == FRONT_STATUS_COPY_OF_BACK) {
+         /* XXX copy back buf to front? */
+      }
+      /* we're assuming we'll really draw to the front buffer */
+      st->frontbuffer_status = FRONT_STATUS_DIRTY;
+   }
 }
 
 
index b1affc4a91563b3dfdd85c48b4cc46f4835abf40..5f8c90cbba43f6b844267379de3ab696d7a16aaa 100644 (file)
@@ -961,7 +961,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
    }
 
    if (type == GL_COLOR) {
-      rbRead = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
+      rbRead = st_get_color_read_renderbuffer(ctx);
       color = NULL;
       stfp = combined_drawpix_fragment_program(ctx);
       stvp = st_make_passthrough_vertex_shader(ctx->st, GL_FALSE);
index 1bcd1b4cd98e7840e54cfa70135445e88eb74a96..1b3402cee245413d9b2e36a70adc664ccfed6c3b 100644 (file)
 #include "pipe/p_winsys.h"
 
 
-static GLboolean
+static INLINE GLboolean
 is_front_buffer_dirty(struct st_context *st)
 {
-   GLframebuffer *fb = st->ctx->DrawBuffer;
-
-   if (!fb)
-      return GL_FALSE;
-
-   /* XXX: temporary hack.  This flag should only be set if we do any
-    * rendering to the front buffer.
-    *
-    * Further more, the scissor rectangle could be tracked to
-    * construct a dirty region of the front buffer, to avoid
-    * situations where it must be copied repeatedly.
-    *
-    * In the extreme case, some kind of timer could be set up to allow
-    * coalescing of multiple flushes to the frontbuffer, which can be
-    * quite a performance drain if there are a sufficient number of
-    * them.
-    */
-   st->flags.frontbuffer_dirty
-      = (fb->_ColorDrawBufferMask[0] & BUFFER_BIT_FRONT_LEFT);
-
-   return st->flags.frontbuffer_dirty;
+   return st->frontbuffer_status == FRONT_STATUS_DIRTY;
 }
 
 
@@ -86,7 +66,8 @@ display_front_buffer(struct st_context *st)
     */
    st->pipe->winsys->flush_frontbuffer( st->pipe->winsys, front_surf,
                                         st->pipe->priv );
-   st->flags.frontbuffer_dirty = 0;
+
+   st->frontbuffer_status = FRONT_STATUS_UNDEFINED;
 }
 
 
index 2bcc8c99fb70105d8fa498a94cc42ecc0630aaaf..29a06ffaa90160cc838e680ffbe15a25ac0f3128 100644 (file)
@@ -128,6 +128,34 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
 }
 
 
+/**
+ * Return renderbuffer to use for reading color pixels for glRead/CopyPixel
+ * commands.
+ * Special care is needed for the front buffer.
+ */
+struct st_renderbuffer *
+st_get_color_read_renderbuffer(GLcontext *ctx)
+{
+   struct gl_framebuffer *fb = ctx->ReadBuffer;
+   struct st_renderbuffer *strb =
+      st_renderbuffer(fb->_ColorReadBuffer);
+   struct st_renderbuffer *front = 
+      st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+
+   if (strb == front
+       && ctx->st->frontbuffer_status == FRONT_STATUS_COPY_OF_BACK) {
+      /* reading from front color buffer, which is a logical copy of the
+       * back color buffer.
+       */
+      struct st_renderbuffer *back = 
+         st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+      strb = back;
+   }
+
+   return strb;
+}
+
+
 /**
  * Do glReadPixels by getting rows from the framebuffer surface with
  * get_tile().  Convert to requested format/type with Mesa image routines.
@@ -173,12 +201,13 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
       strb = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
    }
    else {
-      strb = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
+      /* Read color buffer */
+      strb = st_get_color_read_renderbuffer(ctx);
    }
+
    if (!strb)
       return;
 
-
    if (format == GL_RGBA && type == GL_FLOAT) {
       /* write tile(row) directly into user's buffer */
       df = (GLfloat *) _mesa_image_address2d(&clippedPacking, dest, width,
index 79acdad88e1ce5746ce28ce2c47cb4cf98b97719..9e151be51fb6857e963542e3c43f8550faf60051 100644 (file)
@@ -29,6 +29,9 @@
 #ifndef ST_CB_READPIXELS_H
 #define ST_CB_READPIXELS_H
 
+extern struct st_renderbuffer *
+st_get_color_read_renderbuffer(GLcontext *ctx);
+
 extern void
 st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y,
                        GLsizei width, GLsizei height, GLenum type,
index 212687cf4ab56f7825062049bcad1a11ca39f9f7..d89e54c43c14e599862be6f1270a64c980d827db 100644 (file)
@@ -45,6 +45,11 @@ struct blit_state;
 struct bitmap_cache;
 
 
+#define FRONT_STATUS_UNDEFINED    0
+#define FRONT_STATUS_DIRTY        1
+#define FRONT_STATUS_COPY_OF_BACK 2
+
+
 #define ST_NEW_MESA                    0x1 /* Mesa state has changed */
 #define ST_NEW_FRAGMENT_PROGRAM        0x2
 #define ST_NEW_VERTEX_PROGRAM          0x4
@@ -104,9 +109,7 @@ struct st_context
       struct gl_fragment_program *fragment_program;
    } cb;
 
-   struct {
-      GLuint frontbuffer_dirty:1;
-   } flags;
+   GLuint frontbuffer_status;  /**< one of FRONT_STATUS_ */
 
    char vendor[100];
    char renderer[100];
index ea09d9234cdf1a8b00b74484d85b0e424e8a51bb..47466c97d81ce4a3e0ffa345cc6f5efcb23fec3b 100644 (file)
@@ -188,6 +188,7 @@ st_notify_swapbuffers(struct st_framebuffer *stfb)
       st_flush( ctx->st, 
                PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_SWAPBUFFERS,
                 NULL );
+      ctx->st->frontbuffer_status = FRONT_STATUS_COPY_OF_BACK;
    }
 }