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.
This commit is contained in:
Brian Paul 2008-04-09 18:39:51 -06:00
parent 54d7c399a8
commit 311e402684
7 changed files with 54 additions and 29 deletions

View 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;
}
}

View 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);

View file

@ -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;
}

View 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,

View 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,

View 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];

View 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;
}
}