[Mesa-dev] [PATCH 11/11] egl/x11: Re-allocate buffers if format is suboptimal

Daniel Stone daniels at collabora.com
Thu Feb 15 15:57:41 UTC 2018


From: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>

If PresentCompleteNotify event says the pixmap was presented
with mode PresentCompleteModeSuboptimalCopy, it means the pixmap
could possibly have been flipped instead if allocated with a
different format/modifier.

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Reviewed-by: Daniel Stone <daniels at collabora.com>
Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 src/egl/drivers/dri2/egl_dri2.c          |  2 ++
 src/egl/drivers/dri2/egl_dri2.h          |  2 ++
 src/egl/drivers/dri2/platform_x11_dri3.c |  3 +++
 src/loader/loader_dri3_helper.c          | 37 ++++++++++++++++++++++++++++----
 src/loader/loader_dri3_helper.h          |  2 ++
 src/loader/meson.build                   |  2 +-
 6 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 9a7e43bafb6..921d1a52931 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -885,6 +885,8 @@ dri2_setup_extensions(_EGLDisplay *disp)
    dri2_dpy->multibuffers_available =
       (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version == 1 &&
                                             dri2_dpy->dri3_minor_version >= 1)) &&
+      (dri2_dpy->present_major_version > 1 || (dri2_dpy->present_major_version == 1 &&
+                                               dri2_dpy->present_minor_version >= 1)) &&
       (dri2_dpy->image && dri2_dpy->image->base.version >= 15);
 #endif
 
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 00c4768d421..bd637f73c9d 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -202,6 +202,8 @@ struct dri2_egl_display
    bool                     multibuffers_available;
    int                      dri3_major_version;
    int                      dri3_minor_version;
+   int                      present_major_version;
+   int                      present_minor_version;
    struct loader_dri3_extensions loader_dri3_ext;
 #endif
 #endif
diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c
index 15c349eb828..ae2588d04c4 100644
--- a/src/egl/drivers/dri2/platform_x11_dri3.c
+++ b/src/egl/drivers/dri2/platform_x11_dri3.c
@@ -557,6 +557,9 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
       free(error);
       return EGL_FALSE;
    }
+
+   dri2_dpy->present_major_version = present_query->major_version;
+   dri2_dpy->present_minor_version = present_query->minor_version;
    free(present_query);
 
    dri2_dpy->fd = loader_dri3_open(dri2_dpy->conn, dri2_dpy->screen->root, 0);
diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index 038216c2637..855ec5ce343 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -34,6 +34,8 @@
 #include <X11/Xlib-xcb.h>
 
 #include "loader_dri3_helper.h"
+#include "util/macros.h"
+#include "drm_fourcc.h"
 
 /* From xmlpool/options.h, user exposed so should be stable */
 #define DRI_CONF_VBLANK_NEVER 0
@@ -373,11 +375,25 @@ dri3_handle_present_event(struct loader_dri3_drawable *draw,
             draw->recv_sbc -= 0x100000000;
          switch (ce->mode) {
          case XCB_PRESENT_COMPLETE_MODE_FLIP:
-            draw->flipping = true;
+            if (!draw->flipping) {
+               draw->flipping = true;
+               for (int b = 0; b < ARRAY_SIZE(draw->buffers); b++) {
+                  if (draw->buffers[b])
+                     draw->buffers[b]->realloc_suboptimal = true;
+               }
+            }
             break;
          case XCB_PRESENT_COMPLETE_MODE_COPY:
             draw->flipping = false;
             break;
+#if XCB_PRESENT_MAJOR_VERSION > 1 || (XCB_PRESENT_MAJOR_VERSION == 1 && XCB_PRESENT_MINOR_VERSION >= 1)
+         case XCB_PRESENT_COMPLETE_MODE_SUBOPTIMAL_COPY:
+            draw->flipping = false;
+            for (int b = 0; b < ARRAY_SIZE(draw->buffers); b++) {
+               if (draw->buffers[b])
+                  draw->buffers[b]->suboptimal = true;
+            }
+#endif
          }
 
          if (draw->vtable->show_fps)
@@ -885,6 +901,11 @@ loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
       if (!loader_dri3_have_image_blit(draw) && draw->cur_blit_source != -1)
          options |= XCB_PRESENT_OPTION_COPY;
 
+#if XCB_PRESENT_MAJOR_VERSION > 1 || (XCB_PRESENT_MAJOR_VERSION == 1 && XCB_PRESENT_MINOR_VERSION >= 1)
+      if (draw->multiplanes_available)
+         options  |= XCB_PRESENT_OPTION_SUBOPTIMAL;
+#endif
+
       back->busy = 1;
       back->last_swap = draw->send_sbc;
       xcb_present_pixmap(draw->conn,
@@ -1287,6 +1308,8 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
    buffer->shm_fence = shm_fence;
    buffer->width = width;
    buffer->height = height;
+   buffer->suboptimal = false;
+   buffer->realloc_suboptimal = true;
 
    /* Mark the buffer as idle
     */
@@ -1629,11 +1652,12 @@ dri3_get_buffer(__DRIdrawable *driDrawable,
 
    buffer = draw->buffers[buf_id];
 
-   /* Allocate a new buffer if there isn't an old one, or if that
-    * old one is the wrong size
+   /* Allocate a new buffer if there isn't an old one, if that
+    * old one is the wrong size, or if it's suboptimal
     */
    if (!buffer || buffer->width != draw->width ||
-       buffer->height != draw->height) {
+       buffer->height != draw->height ||
+       (buffer->suboptimal && buffer->realloc_suboptimal)) {
       struct loader_dri3_buffer *new_buffer;
 
       /* Allocate the new buffers
@@ -1692,6 +1716,11 @@ dri3_get_buffer(__DRIdrawable *driDrawable,
                                           0, 0, 0);
          }
       }
+
+      /* Avoid multiple reallocations when the best we can use is a suboptimal
+       * format/modifier. */
+      new_buffer->realloc_suboptimal = buffer ? !buffer->suboptimal : true;
+
       buffer = new_buffer;
       draw->buffers[buf_id] = buffer;
    }
diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h
index 5689e2707c5..2668a05b758 100644
--- a/src/loader/loader_dri3_helper.h
+++ b/src/loader/loader_dri3_helper.h
@@ -61,6 +61,8 @@ struct loader_dri3_buffer {
    struct xshmfence *shm_fence; /* pointer to xshmfence object */
    bool         busy;           /* Set on swap, cleared on IdleNotify */
    bool         own_pixmap;     /* We allocated the pixmap ID, free on destroy */
+   bool         suboptimal;     /* Set when CompleteNotify has ModeSuboptimalCopy */
+   bool         realloc_suboptimal; /* Avoid constant reallocation on worst cases */
 
    uint32_t     num_planes;
    uint32_t     size;
diff --git a/src/loader/meson.build b/src/loader/meson.build
index e4455e9a72b..76fcae2cb44 100644
--- a/src/loader/meson.build
+++ b/src/loader/meson.build
@@ -25,7 +25,7 @@ if with_platform_x11 and with_dri3
     'loader_dri3_helper',
     ['loader_dri3_helper.c', 'loader_dri3_helper.h'],
     c_args : c_vis_args,
-    include_directories : inc_include,
+    include_directories : [inc_include, inc_src, inc_drm_uapi],
     dependencies : [
       dep_libdrm, dep_xcb_dri3, dep_xcb_present, dep_xcb_sync, dep_xshmfence,
     ],
-- 
2.14.3



More information about the mesa-dev mailing list