[Mesa-dev] [PATCH 11/11] loader_dri3: Make sure we have an updated back

Thomas Hellstrom thellstrom at vmware.com
Fri Aug 11 14:14:20 UTC 2017


With GLX_SWAP_COPY_OML and GLX_SWAP_EXCHANGE_OML it may happen in situations
when glXSwapBuffers() is immediately followed by for example another
glXSwapBuffers() or glXCopyBuffers() or back buffer age querying, that we
haven't yet allocated and initialized a new back buffer because there was
no GL rendering in between.

Make sure that we have a back buffer in those situations.

Signed-off-by: Thomas Hellstrom <thellstrom at vmware.com>
---
 src/loader/loader_dri3_helper.c | 64 ++++++++++++++++++++++++++++++++++-------
 src/loader/loader_dri3_helper.h |  3 ++
 2 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index dee0df8..0440633 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -35,6 +35,7 @@
 #include <c11/threads.h>
 #include "loader_dri3_helper.h"
 
+
 /* From xmlpool/options.h, user exposed so should be stable */
 #define DRI_CONF_VBLANK_NEVER 0
 #define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
@@ -59,6 +60,9 @@ static struct loader_dri3_blit_context blit_context = {
 static void
 dri3_flush_present_events(struct loader_dri3_drawable *draw);
 
+static struct loader_dri3_buffer *
+dri3_find_back_alloc(struct loader_dri3_drawable *draw);
+
 /**
  * Get and lock (for use with the current thread) a dri context associated
  * with the drawable's dri screen. The context is intended to be used with
@@ -259,6 +263,7 @@ loader_dri3_drawable_init(xcb_connection_t *conn,
    draw->have_image_blit = draw->ext->image->base.version >= 9 &&
       draw->ext->image->blitImage != NULL;
    draw->cur_blit_source = -1;
+   draw->have_back_format = false;
 
    if (draw->ext->config)
       draw->ext->config->configQueryi(draw->dri_screen,
@@ -606,7 +611,10 @@ loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw,
       flags |= __DRI2_FLUSH_CONTEXT;
    loader_dri3_flush(draw, flags, __DRI2_THROTTLE_SWAPBUFFER);
 
-   back = dri3_back_buffer(draw);
+   back = dri3_find_back_alloc(draw);
+   if (!back)
+      return;
+
    y = draw->height - y - height;
 
    if (draw->is_different_gpu) {
@@ -631,7 +639,7 @@ loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw,
    loader_dri3_swapbuffer_barrier(draw);
    dri3_fence_reset(draw->conn, back);
    dri3_copy_area(draw->conn,
-                  dri3_back_buffer(draw)->pixmap,
+                  back->pixmap,
                   draw->drawable,
                   dri3_drawable_gc(draw),
                   x, y, x, y, width, height);
@@ -642,7 +650,7 @@ loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw,
    if (draw->have_fake_front && !draw->is_different_gpu) {
       dri3_fence_reset(draw->conn, dri3_fake_front_buffer(draw));
       dri3_copy_area(draw->conn,
-                     dri3_back_buffer(draw)->pixmap,
+                     back->pixmap,
                      dri3_fake_front_buffer(draw)->pixmap,
                      dri3_drawable_gc(draw),
                      x, y, x, y, width, height);
@@ -753,7 +761,8 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
 
    draw->vtable->flush_drawable(draw, flush_flags);
 
-   back = draw->buffers[dri3_find_back(draw)];
+   back = dri3_find_back_alloc(draw);
+
    if (draw->is_different_gpu && back) {
       /* Update the linear buffer before presenting the pixmap */
       (void) loader_dri3_blit_image(draw,
@@ -882,15 +891,12 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
 int
 loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw)
 {
-   int back_id = LOADER_DRI3_BACK_ID(dri3_find_back(draw));
+   struct loader_dri3_buffer *back = dri3_find_back_alloc(draw);
 
-   if (back_id < 0 || !draw->buffers[back_id])
+   if (!back || back->last_swap == 0)
       return 0;
 
-   if (draw->buffers[back_id]->last_swap != 0)
-      return draw->send_sbc - draw->buffers[back_id]->last_swap + 1;
-   else
-      return 0;
+   return draw->send_sbc - back->last_swap + 1;
 }
 
 /** loader_dri3_open
@@ -1324,6 +1330,9 @@ dri3_get_buffer(__DRIdrawable *driDrawable,
    int buf_id;
 
    if (buffer_type == loader_dri3_buffer_back) {
+      draw->have_back_format = true;
+      draw->back_format = format;
+
       buf_id = dri3_find_back(draw);
 
       if (buf_id < 0)
@@ -1610,3 +1619,38 @@ loader_dri3_close_screen(__DRIscreen *dri_screen)
    }
    mtx_unlock(&blit_context.mtx);
 }
+
+/**
+ * Find a backbuffer slot - potentially allocating a back buffer
+ *
+ * \param draw[in,out]  Pointer to the drawable for which to find back.
+ * \return Pointer to a new back buffer or NULL if allocation failed or was
+ * not mandated.
+ *
+ * Find a potentially new back buffer, and if it's not been allocated yet and
+ * in addition needs initializing, then try to allocate and initialize it.
+ */
+static struct loader_dri3_buffer *
+dri3_find_back_alloc(struct loader_dri3_drawable *draw)
+{
+   struct loader_dri3_buffer *back;
+   int id;
+
+   id = dri3_find_back(draw);
+   back = (id >= 0) ? draw->buffers[id] : NULL;
+
+   if (!back && draw->have_back_format) {
+      (void) dri3_get_buffer(draw->dri_drawable,
+                             draw->back_format,
+                             loader_dri3_buffer_back,
+                             draw);
+   } else if (back) {
+      /* Make sure any server side operations are flushed.
+       * For example glXSwapBuffers server side fake-front-to-back copy
+       * followed by glXCopyBuffers
+       */
+      dri3_fence_await(draw->conn, back);
+   }
+
+   return back;
+}
diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h
index c8f63fd..b06a9ad 100644
--- a/src/loader/loader_dri3_helper.h
+++ b/src/loader/loader_dri3_helper.h
@@ -159,6 +159,9 @@ struct loader_dri3_drawable {
 
    bool have_image_blit;
    unsigned int swap_method;
+
+   bool have_back_format;
+   unsigned int back_format;
 };
 
 void
-- 
2.7.4



More information about the mesa-dev mailing list