Mesa (master): dri3: Track current Present swap mode and adjust buffer counts

Eric Anholt anholt at kemper.freedesktop.org
Fri Jan 31 01:30:07 UTC 2014


Module: Mesa
Branch: master
Commit: 3fbd1b0cb576b46ac8df2697cb388db78f48012d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=3fbd1b0cb576b46ac8df2697cb388db78f48012d

Author: Keith Packard <keithp at keithp.com>
Date:   Sun Jan 26 16:14:29 2014 -0800

dri3: Track current Present swap mode and adjust buffer counts

This automatically adjusts the number of buffers that we want based on
what swapping mode the X server is using and the current swap interval:

        swap mode       interval        buffers
        copy            > 0             1
        copy            0               2
        flip            > 0             2
        flip            0               3

Note that flip with swap interval 0 is currently limited to twice the
underlying refresh rate because of how the kernel manages flipping. Moving
from 3 to 4 buffers would help, but that seems ridiculous.

v2: Just update num_back at the point that the values that change num_back
    change.  This means we'll have the updated value at the point that the
    freeing of old going-to-be-unused backbuffers happens, which might not
    have been the case before (change by anholt, acked by keithp).

Signed-off-by: Keith Packard <keithp at keithp.com>
Signed-off-by: Eric Anholt <eric at anholt.net>
Reviewed-by: Eric Anholt <eric at anholt.net>

---

 src/glx/dri3_glx.c  |   35 ++++++++++++++++++++++++++++++-----
 src/glx/dri3_priv.h |   24 +++++-------------------
 2 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
index 94f0eca..70ec057 100644
--- a/src/glx/dri3_glx.c
+++ b/src/glx/dri3_glx.c
@@ -270,6 +270,16 @@ static void
 dri3_free_render_buffer(struct dri3_drawable *pdraw, struct dri3_buffer *buffer);
 
 static void
+dri3_update_num_back(struct dri3_drawable *priv)
+{
+   priv->num_back = 1;
+   if (priv->flipping)
+      priv->num_back++;
+   if (priv->swap_interval == 0)
+      priv->num_back++;
+}
+
+static void
 dri3_destroy_drawable(__GLXDRIdrawable *base)
 {
    struct dri3_screen *psc = (struct dri3_screen *) base->psc;
@@ -326,6 +336,8 @@ dri3_create_drawable(struct glx_screen *base, XID xDrawable,
       break;
    }
 
+   dri3_update_num_back(pdraw);
+
    (void) __glXInitialize(psc->base.dpy);
 
    /* Create a new drawable */
@@ -373,6 +385,15 @@ dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_
          priv->recv_sbc = (priv->send_sbc & 0xffffffff00000000LL) | ce->serial;
          if (priv->recv_sbc > priv->send_sbc)
             priv->recv_sbc -= 0x100000000;
+         switch (ce->mode) {
+         case XCB_PRESENT_COMPLETE_MODE_FLIP:
+            priv->flipping = true;
+            break;
+         case XCB_PRESENT_COMPLETE_MODE_COPY:
+            priv->flipping = false;
+            break;
+         }
+         dri3_update_num_back(priv);
       } else {
          priv->recv_msc_serial = ce->serial;
       }
@@ -389,6 +410,10 @@ dri3_handle_present_event(struct dri3_drawable *priv, xcb_present_generic_event_
 
          if (buf && buf->pixmap == ie->pixmap) {
             buf->busy = 0;
+            if (priv->num_back <= b && b < DRI3_MAX_BACK) {
+               dri3_free_render_buffer(priv, buf);
+               priv->buffers[b] = NULL;
+            }
             break;
          }
       }
@@ -1067,10 +1092,9 @@ dri3_find_back(xcb_connection_t *c, struct dri3_drawable *priv)
    xcb_present_generic_event_t *ge;
 
    for (;;) {
-
-      for (b = 0; b < DRI3_NUM_BACK; b++) {
-         int                    id = DRI3_BACK_ID(b);
-         struct dri3_buffer        *buffer = priv->buffers[id];
+      for (b = 0; b < priv->num_back; b++) {
+         int id = DRI3_BACK_ID(b);
+         struct dri3_buffer *buffer = priv->buffers[id];
 
          if (!buffer)
             return b;
@@ -1185,7 +1209,7 @@ dri3_free_buffers(__DRIdrawable *driDrawable,
    switch (buffer_type) {
    case dri3_buffer_back:
       first_id = DRI3_BACK_ID(0);
-      n_id = DRI3_NUM_BACK;
+      n_id = DRI3_MAX_BACK;
       break;
    case dri3_buffer_front:
       first_id = DRI3_FRONT_ID;
@@ -1437,6 +1461,7 @@ dri3_set_swap_interval(__GLXDRIdrawable *pdraw, int interval)
    }
 
    priv->swap_interval = interval;
+   dri3_update_num_back(priv);
 
    return 0;
 }
diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h
index 9d142cf..1d124f8 100644
--- a/src/glx/dri3_priv.h
+++ b/src/glx/dri3_priv.h
@@ -143,25 +143,9 @@ struct dri3_context
    __DRIcontext *driContext;
 };
 
-#define DRI3_NUM_BACK   2
+#define DRI3_MAX_BACK   3
 #define DRI3_BACK_ID(i) (i)
-#define DRI3_FRONT_ID   (DRI3_NUM_BACK)
-
-static inline int
-dri3_buf_id_next(int buf_id)
-{
-   if (buf_id == DRI3_NUM_BACK - 1)
-      return 0;
-   return buf_id + 1;
-}
-
-static inline int
-dri3_buf_id_prev(int buf_id)
-{
-   if (buf_id == 0)
-      return DRI3_NUM_BACK - 1;
-   return buf_id - 1;
-}
+#define DRI3_FRONT_ID   (DRI3_MAX_BACK)
 
 static inline int
 dri3_pixmap_buf_id(enum dri3_buffer_type buffer_type)
@@ -172,7 +156,7 @@ dri3_pixmap_buf_id(enum dri3_buffer_type buffer_type)
       return DRI3_FRONT_ID;
 }
 
-#define DRI3_NUM_BUFFERS        (1 + DRI3_NUM_BACK)
+#define DRI3_NUM_BUFFERS        (1 + DRI3_MAX_BACK)
 
 struct dri3_drawable {
    __GLXDRIdrawable base;
@@ -182,6 +166,7 @@ struct dri3_drawable {
    uint8_t have_back;
    uint8_t have_fake_front;
    uint8_t is_pixmap;
+   uint8_t flipping;
 
    /* SBC numbers are tracked by using the serial numbers
     * in the present request and complete events
@@ -198,6 +183,7 @@ struct dri3_drawable {
 
    struct dri3_buffer *buffers[DRI3_NUM_BUFFERS];
    int cur_back;
+   int num_back;
 
    uint32_t *stamp;
 




More information about the mesa-commit mailing list