summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brian.paul@tungstengraphics.com>2008-04-09 18:39:51 -0600
committerBrian Paul <brian.paul@tungstengraphics.com>2008-04-09 18:39:51 -0600
commit311e40268414649f047ee177ba22a17a2d437843 (patch)
tree41aa5d3e308e25c1753eb882eb25d1bc80918316
parent54d7c399a888283711bdc00f93cb54a3ce0b30eb (diff)
gallium: more elaborate tracking of front color buffer state
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.
-rw-r--r--src/mesa/state_tracker/st_atom_framebuffer.c8
-rw-r--r--src/mesa/state_tracker/st_cb_drawpixels.c2
-rw-r--r--src/mesa/state_tracker/st_cb_flush.c27
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.c33
-rw-r--r--src/mesa/state_tracker/st_cb_readpixels.h3
-rw-r--r--src/mesa/state_tracker/st_context.h9
-rw-r--r--src/mesa/state_tracker/st_framebuffer.c1
7 files changed, 54 insertions, 29 deletions
diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c
index 02573af8f0..8a95096ec9 100644
--- a/src/mesa/state_tracker/st_atom_framebuffer.c
+++ b/src/mesa/state_tracker/st_atom_framebuffer.c
@@ -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;
+ }
}
diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c
index b1affc4a91..5f8c90cbba 100644
--- a/src/mesa/state_tracker/st_cb_drawpixels.c
+++ b/src/mesa/state_tracker/st_cb_drawpixels.c
@@ -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);
diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c
index 1bcd1b4cd9..1b3402cee2 100644
--- a/src/mesa/state_tracker/st_cb_flush.c
+++ b/src/mesa/state_tracker/st_cb_flush.c
@@ -44,30 +44,10 @@
#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;
}
diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c
index 2bcc8c99fb..29a06ffaa9 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.c
+++ b/src/mesa/state_tracker/st_cb_readpixels.c
@@ -129,6 +129,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.
* Image transfer ops are done in software too.
@@ -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,
diff --git a/src/mesa/state_tracker/st_cb_readpixels.h b/src/mesa/state_tracker/st_cb_readpixels.h
index 79acdad88e..9e151be51f 100644
--- a/src/mesa/state_tracker/st_cb_readpixels.h
+++ b/src/mesa/state_tracker/st_cb_readpixels.h
@@ -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,
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 212687cf4a..d89e54c43c 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -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];
diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c
index ea09d9234c..47466c97d8 100644
--- a/src/mesa/state_tracker/st_framebuffer.c
+++ b/src/mesa/state_tracker/st_framebuffer.c
@@ -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;
}
}