r600: fix warning
[mesa.git] / src / mesa / state_tracker / st_framebuffer.c
index fe99fc08926c9e2f7df5fd6d2953cee957528513..ca32b2e573c98cbd3c7e7906b9eaf3ce4e384c41 100644 (file)
@@ -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) {
@@ -286,6 +286,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;