Start re-working SwapBuffers.
authorBrian <brian.paul@tungstengraphics.com>
Fri, 2 Nov 2007 00:37:00 +0000 (18:37 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Fri, 2 Nov 2007 00:37:00 +0000 (18:37 -0600)
intelCopyBuffer() is now intelDisplayBuffer(): it displays the given surface
in the on-screen window.
Added a pipe_surface parameter to winsys->flush_frontbuffer().
Front buffer rendering/flushing actually works now.
But, we should only allocate the front surface on demand...

src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.c
src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.h
src/mesa/drivers/dri/intel_winsys/intel_winsys_pipe.c
src/mesa/pipe/p_winsys.h
src/mesa/pipe/xlib/xm_winsys.c
src/mesa/state_tracker/st_cb_flush.c

index 2ffc757469e673504e1987a82f32746988312044..350c3f38a229f40ae700c375c3704aedd01f2d32 100644 (file)
@@ -58,15 +58,33 @@ typedef struct drm_i915_flip {
 #endif
 
 
+/**
+ * Return the pipe_surface for the given renderbuffer.
+ */
+static struct pipe_surface *
+get_color_surface(struct intel_framebuffer *intel_fb,
+                  GLuint bufferIndex)
+{
+   struct st_renderbuffer *strb
+      = st_renderbuffer(intel_fb->Base.Attachment[bufferIndex].Renderbuffer);
+   if (strb)
+      return strb->surface;
+   return NULL;
+}
 
 
 /**
- * Copy the back color buffer to the front color buffer. 
- * Used for SwapBuffers().
+ * Display a colorbuffer surface in an X window.
+ * Used for SwapBuffers and flushing front buffer rendering.
+ *
+ * \param dPriv  the window/drawable to display into
+ * \param surf  the surface to display
+ * \param rect  optional subrect of surface to display (may be NULL).
  */
 void
-intelCopyBuffer(__DRIdrawablePrivate * dPriv,
-                const drm_clip_rect_t * rect)
+intelDisplayBuffer(__DRIdrawablePrivate * dPriv,
+                   struct pipe_surface *surf,
+                   const drm_clip_rect_t * rect)
 {
 
    struct intel_context *intel;
@@ -103,49 +121,24 @@ intelCopyBuffer(__DRIdrawablePrivate * dPriv,
 
    if (dPriv && dPriv->numClipRects) {
       struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
-#if 0
-      const struct pipe_region *backRegion
-        = intel_fb->Base._ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT ?
-          intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT) :
-          intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT);
-#endif
       const int backWidth = intel_fb->Base.Width;
       const int backHeight = intel_fb->Base.Height;
       const int nbox = dPriv->numClipRects;
       const drm_clip_rect_t *pbox = dPriv->pClipRects;
       const int pitch = intelScreen->front.pitch / intelScreen->front.cpp;
-#if 0
-      const int srcpitch = backRegion->pitch;
-#endif
       const int cpp = intelScreen->front.cpp;
       int BR13, CMD;
       int i;
-
-      const struct pipe_surface *backSurf;
-      const struct pipe_region *backRegion;
-      int srcpitch;
-      struct st_renderbuffer *strb;
-
-      /* blit from back color buffer if it exists, else front buffer */
-      strb = st_renderbuffer(intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer);
-      if (strb) {
-         backSurf = strb->surface;
-      }
-      else {
-         strb = st_renderbuffer(intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
-         backSurf = strb->surface;
-      }
-
-      backRegion = backSurf->region;
-      srcpitch = backRegion->pitch;
+      const struct pipe_region *srcRegion = surf->region;
+      const int srcpitch= srcRegion->pitch;
 
       ASSERT(intel_fb);
       ASSERT(intel_fb->Base.Name == 0);    /* Not a user-created FBO */
-      ASSERT(backRegion);
-      ASSERT(backRegion->cpp == cpp);
+      ASSERT(srcRegion);
+      ASSERT(srcRegion->cpp == cpp);
 
       DBG(SWAP, "front pitch %d back pitch %d\n",
-         pitch, backRegion->pitch);
+         pitch, srcRegion->pitch);
 
       if (cpp == 2) {
         BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
@@ -164,12 +157,15 @@ intelCopyBuffer(__DRIdrawablePrivate * dPriv,
         if (pbox->x1 > pbox->x2 ||
             pbox->y1 > pbox->y2 ||
             pbox->x2 > intelScreen->front.width || 
-            pbox->y2 > intelScreen->front.height)
+            pbox->y2 > intelScreen->front.height) {
+            /* invalid cliprect, skip it */
            continue;
+         }
 
         box = *pbox;
 
         if (rect) {
+            /* intersect cliprect with user-provided src rect */
            drm_clip_rect_t rrect;
 
            rrect.x1 = dPriv->x + rect->x1;
@@ -212,7 +208,7 @@ intelCopyBuffer(__DRIdrawablePrivate * dPriv,
                   DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
         OUT_BATCH((sbox.y1 << 16) | sbox.x1);
         OUT_BATCH((srcpitch * cpp) & 0xffff);
-        OUT_RELOC(dri_bo(backRegion->buffer),
+        OUT_RELOC(dri_bo(srcRegion->buffer),
                    DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
                   DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
 
@@ -590,10 +586,13 @@ intelSwapBuffers(__DRIdrawablePrivate * dPriv)
         _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */
 
          if (!intelScheduleSwap(dPriv, &missed_target)) {
+            struct pipe_surface *back_surf
+               = get_color_surface(intel_fb, BUFFER_BACK_LEFT);
+
            driWaitForVBlank(dPriv, &intel_fb->vbl_seq, intel_fb->vblank_flags,
                             &missed_target);
 
-            intelCopyBuffer(dPriv, NULL);
+            intelDisplayBuffer(dPriv, back_surf, NULL);
         }
 
         intel_fb->swap_count++;
@@ -621,6 +620,10 @@ intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
       GLcontext *ctx = intel->st->ctx;
 
       if (ctx->Visual.doubleBufferMode) {
+         struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
+         struct pipe_surface *back_surf
+            = get_color_surface(intel_fb, BUFFER_BACK_LEFT);
+
          drm_clip_rect_t rect;
         /* fixup cliprect (driDrawable may have changed?) later */
          rect.x1 = x;
@@ -628,7 +631,7 @@ intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
          rect.x2 = w;
          rect.y2 = h;
          _mesa_notifySwapBuffers(ctx);  /* flush pending rendering comands */
-         intelCopyBuffer(dPriv, &rect);
+         intelDisplayBuffer(dPriv, back_surf, &rect);
       }
    }
    else {
index 0065eac9b2b6ff3e014c11aa0a93c5bfbc3374fd..15ed6704d2319ac9b8957333d0710b3536df6adc 100644 (file)
@@ -62,8 +62,9 @@ struct intel_framebuffer
 };
 
 
-void intelCopyBuffer(__DRIdrawablePrivate * dPriv,
-                    const drm_clip_rect_t * rect);
+extern void intelDisplayBuffer(__DRIdrawablePrivate * dPriv,
+                               struct pipe_surface *surf,
+                               const drm_clip_rect_t * rect);
 
 extern void intel_wait_flips(struct intel_context *intel, GLuint batch_flags);
 
index 4569b1e3bf6b9e0b90322bfe537037b48eebb6f8..7f788b8537e11f0f55d3c3dc0cc5f995cbd635a8 100644 (file)
@@ -185,12 +185,13 @@ static void intel_wait_idle( struct pipe_winsys *sws )
  * we copied its contents to the real frontbuffer.  Our task is easy:
  */
 static void
-intel_flush_frontbuffer( struct pipe_winsys *sws )
+intel_flush_frontbuffer( struct pipe_winsys *sws,
+                         struct pipe_surface *surf )
 {
    struct intel_context *intel = intel_pipe_winsys(sws)->intel;
    __DRIdrawablePrivate *dPriv = intel->driDrawable;
-   
-   intelCopyBuffer(dPriv, NULL);
+
+   intelDisplayBuffer(dPriv, surf, NULL);
 }
 
 
index 10a2caf1a242c6de3c22707355fc61a2f1cb670e..2d4432dbca424af79d2e753b5008db10ffb7f8a3 100644 (file)
@@ -53,6 +53,7 @@ struct pipe_buffer_handle;
 
 
 struct pipe_region;
+struct pipe_surface;
 
 /** Opaque type */
 struct pipe_buffer_handle;
@@ -63,7 +64,8 @@ struct pipe_winsys
     * Do any special operations to ensure frontbuffer contents are
     * displayed, eg copy fake frontbuffer.
     */
-   void (*flush_frontbuffer)( struct pipe_winsys *sws );
+   void (*flush_frontbuffer)( struct pipe_winsys *sws,
+                              struct pipe_surface *surf );
 
    /** Debug output */
    void (*printf)( struct pipe_winsys *sws,
index e6e98ed39605957d2e534177563a4d97b06de4ff..5de811a66fa886595a19767354fc9e9c0bcec92f 100644 (file)
@@ -157,14 +157,14 @@ xm_buffer_get_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
 }
 
 static void
-xm_flush_frontbuffer(struct pipe_winsys *pws)
+xm_flush_frontbuffer(struct pipe_winsys *pws,
+                     struct pipe_surface *surf )
 {
-   /*
-   struct intel_context *intel = intel_pipe_winsys(sws)->intel;
-   __DRIdrawablePrivate *dPriv = intel->driDrawable;
-   
-   intelCopyBuffer(dPriv, NULL);
-   */
+   /* The Xlib driver's front color surfaces are actually X Windows so
+    * this flush is a no-op.
+    * If we instead did front buffer rendering to a temporary XImage,
+    * this would be the place to copy the Ximage to the on-screen Window.
+    */
 }
 
 static void
index 41f21c361cdd7080f486eb7fa3b49bd0e37d63c8..c2c3c80b875d4d846f1008798bc9858608e9b024 100644 (file)
@@ -35,6 +35,7 @@
 #include "main/macros.h"
 #include "st_context.h"
 #include "st_cb_flush.h"
+#include "st_cb_fbo.h"
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_winsys.h"
@@ -59,9 +60,13 @@ static void st_flush(GLcontext *ctx)
 
 
    if (st->flags.frontbuffer_dirty) {
+      struct st_renderbuffer *strb
+         = st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
+      struct pipe_surface *front_surf = strb->surface;
+
       /* Hook for copying "fake" frontbuffer if necessary:
        */
-      st->pipe->winsys->flush_frontbuffer( st->pipe->winsys );
+      st->pipe->winsys->flush_frontbuffer( st->pipe->winsys, front_surf );
       st->flags.frontbuffer_dirty = 0;
    }
 }