mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 18:18:06 +02:00
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:
parent
54d7c399a8
commit
311e402684
7 changed files with 54 additions and 29 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue