}
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;
+ }
}
}
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);
#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;
}
*/
st->pipe->winsys->flush_frontbuffer( st->pipe->winsys, front_surf,
st->pipe->priv );
- st->flags.frontbuffer_dirty = 0;
+
+ st->frontbuffer_status = FRONT_STATUS_UNDEFINED;
}
}
+/**
+ * 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.
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,
#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,
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
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];
st_flush( ctx->st,
PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_SWAPBUFFERS,
NULL );
+ ctx->st->frontbuffer_status = FRONT_STATUS_COPY_OF_BACK;
}
}