summaryrefslogtreecommitdiff
path: root/src/mesa/state_tracker/st_framebuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/state_tracker/st_framebuffer.c')
-rw-r--r--src/mesa/state_tracker/st_framebuffer.c125
1 files changed, 117 insertions, 8 deletions
diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c
index 33a90ea7db..13589151ba 100644
--- a/src/mesa/state_tracker/st_framebuffer.c
+++ b/src/mesa/state_tracker/st_framebuffer.c
@@ -58,19 +58,19 @@ st_create_framebuffer( const __GLcontextModes *visual,
_mesa_initialize_framebuffer(&stfb->Base, visual);
- {
- /* fake frontbuffer */
- /* XXX allocation should only happen in the unusual case
- it's actually needed */
+ if (visual->doubleBufferMode) {
struct gl_renderbuffer *rb
= st_new_renderbuffer_fb(colorFormat, samples, FALSE);
- _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_BACK_LEFT, rb);
}
-
- if (visual->doubleBufferMode) {
+ else {
+ /* Only allocate front buffer right now if we're single buffered.
+ * If double-buffered, allocate front buffer on demand later.
+ * See check_create_front_buffers().
+ */
struct gl_renderbuffer *rb
= st_new_renderbuffer_fb(colorFormat, samples, FALSE);
- _mesa_add_renderbuffer(&stfb->Base, BUFFER_BACK_LEFT, rb);
+ _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb);
}
if (depthFormat == stencilFormat && depthFormat != PIPE_FORMAT_NONE) {
@@ -285,6 +285,115 @@ st_notify_swapbuffers(struct st_framebuffer *stfb)
}
+/**
+ * Swap the front/back color buffers. Exchange the front/back pointers
+ * and update some derived state.
+ * No need to call st_notify_swapbuffers() first.
+ *
+ * For a single-buffered framebuffer, no swap occurs, but we still return
+ * the pointer(s) to the front color buffer(s).
+ *
+ * \param front_left returns pointer to front-left renderbuffer after swap
+ * \param front_right returns pointer to front-right renderbuffer after swap
+ */
+void
+st_swapbuffers(struct st_framebuffer *stfb,
+ struct pipe_surface **front_left,
+ struct pipe_surface **front_right)
+{
+ struct gl_framebuffer *fb = &stfb->Base;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (ctx && ctx->DrawBuffer == &stfb->Base) {
+ st_flush( ctx->st,
+ PIPE_FLUSH_RENDER_CACHE |
+ PIPE_FLUSH_SWAPBUFFERS |
+ PIPE_FLUSH_FRAME,
+ NULL );
+ }
+
+ if (!fb->Visual.doubleBufferMode) {
+ /* single buffer mode - return pointers to front surfaces */
+ if (front_left) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ *front_left = strb->surface;
+ }
+ if (front_right) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer);
+ *front_right = strb ? strb->surface : NULL;
+ }
+ return;
+ }
+
+ /* swap left buffers */
+ if (fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer &&
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer) {
+ struct gl_renderbuffer *rbTemp;
+ rbTemp = fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer =
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer = rbTemp;
+ if (front_left) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+ *front_left = strb->surface;
+ }
+ /* mark back buffer contents as undefined */
+ {
+ struct st_renderbuffer *back =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+ back->defined = GL_FALSE;
+ }
+ }
+ else {
+ /* no front buffer, display the back buffer */
+ if (front_left) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
+ *front_left = strb->surface;
+ }
+ }
+
+ /* swap right buffers (for stereo) */
+ if (fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer &&
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer) {
+ struct gl_renderbuffer *rbTemp;
+ rbTemp = fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer;
+ fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer =
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer;
+ fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer = rbTemp;
+ if (front_right) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_FRONT_RIGHT].Renderbuffer);
+ *front_right = strb->surface;
+ }
+ /* mark back buffer contents as undefined */
+ {
+ struct st_renderbuffer *back =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
+ back->defined = GL_FALSE;
+ }
+ }
+ else {
+ /* no front right buffer, display back right buffer (if exists) */
+ if (front_right) {
+ struct st_renderbuffer *strb =
+ st_renderbuffer(fb->Attachment[BUFFER_BACK_RIGHT].Renderbuffer);
+ *front_right = strb ? strb->surface : NULL;
+ }
+ }
+
+ /* Update the _ColorDrawBuffers[] array and _ColorReadBuffer pointer */
+ _mesa_update_framebuffer(ctx);
+
+ /* Make sure we draw into the new back surface */
+ st_invalidate_state(ctx, _NEW_BUFFERS);
+}
+
+
void *st_framebuffer_private( struct st_framebuffer *stfb )
{
return stfb->Private;