egl/loader: move crtc resource infrastructure as common helper
authorTapani Pälli <tapani.palli@intel.com>
Sun, 7 May 2023 18:28:54 +0000 (21:28 +0300)
committerMarge Bot <emma+marge@anholt.net>
Thu, 11 May 2023 10:51:11 +0000 (10:51 +0000)
Patch moves (and renames) the infrastructure to fix compilation
failures when dri3 is not enabled in the build.

Fixes: 3170b63314f ("loader: Add infrastructure for tracking active CRTC resources");
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/8476
Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22897>

src/egl/drivers/dri2/egl_dri2.h
src/egl/drivers/dri2/platform_x11.c
src/loader/loader_dri3_helper.c
src/loader/loader_dri3_helper.h
src/loader/loader_dri_helper.c
src/loader/loader_dri_helper.h
src/loader/meson.build

index 0fab2aa..7693fed 100644 (file)
@@ -38,6 +38,7 @@
 #include <xcb/xfixes.h>
 #include <X11/Xlib-xcb.h>
 
+#include "loader_dri_helper.h"
 #ifdef HAVE_DRI3
 #include "loader_dri3_helper.h"
 #endif
@@ -287,7 +288,7 @@ struct dri2_egl_display
    int present_major_version;
    int present_minor_version;
    struct loader_dri3_extensions loader_dri3_ext;
-   struct loader_dri3_screen_resources screen_resources;
+   struct loader_screen_resources screen_resources;
 #endif
 #endif
 
index 0a4889c..917c82b 100644 (file)
@@ -1226,7 +1226,7 @@ dri2_x11_get_msc_rate(_EGLDisplay *display, _EGLSurface *surface,
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(display);
 
-   loader_dri3_update_screen_resources(&dri2_dpy->screen_resources);
+   loader_update_screen_resources(&dri2_dpy->screen_resources);
 
    if (dri2_dpy->screen_resources.num_crtcs == 0) {
       /* If there's no CRTC active, use the present fake vblank of 1Hz */
@@ -1267,7 +1267,7 @@ dri2_x11_get_msc_rate(_EGLDisplay *display, _EGLSurface *surface,
    int area = 0;
 
    for (unsigned c = 0; c < dri2_dpy->screen_resources.num_crtcs; c++) {
-      struct loader_dri3_crtc_info *crtc =
+      struct loader_crtc_info *crtc =
          &dri2_dpy->screen_resources.crtcs[c];
 
       int c_area = box_intersection_area(reply->dst_x, reply->dst_y,
@@ -1663,8 +1663,8 @@ dri2_initialize_x11_dri3(_EGLDisplay *disp)
    if (!dri2_x11_add_configs_for_visuals(dri2_dpy, disp, false))
       goto cleanup;
 
-   loader_dri3_init_screen_resources(&dri2_dpy->screen_resources,
-                                     dri2_dpy->conn, dri2_dpy->screen);
+   loader_init_screen_resources(&dri2_dpy->screen_resources,
+                                dri2_dpy->conn, dri2_dpy->screen);
 
    dri2_dpy->loader_dri3_ext.core = dri2_dpy->core;
    dri2_dpy->loader_dri3_ext.image_driver = dri2_dpy->image_driver;
@@ -1815,7 +1815,7 @@ void
 dri2_teardown_x11(struct dri2_egl_display *dri2_dpy)
 {
    if (dri2_dpy->dri2_major >= 3)
-      loader_dri3_destroy_screen_resources(&dri2_dpy->screen_resources);
+      loader_destroy_screen_resources(&dri2_dpy->screen_resources);
 
    if (dri2_dpy->own_device)
       xcb_disconnect(dri2_dpy->conn);
index 63be04e..0d9f108 100644 (file)
@@ -2329,182 +2329,6 @@ loader_dri3_update_drawable_geometry(struct loader_dri3_drawable *draw)
    }
 }
 
-void
-loader_dri3_init_screen_resources(struct loader_dri3_screen_resources *res,
-                                  xcb_connection_t *conn,
-                                  xcb_screen_t *screen)
-{
-   res->conn = conn;
-   res->screen = screen;
-   res->crtcs = NULL;
-
-   mtx_init(&res->mtx, mtx_plain);
-}
-
-void
-loader_dri3_destroy_screen_resources(struct loader_dri3_screen_resources *res)
-{
-   mtx_destroy(&res->mtx);
-}
-
-static unsigned
-gcd_u32(unsigned a, unsigned b)
-{
-   assert(a > 0 || b > 0);
-
-   while (b != 0) {
-      unsigned remainder = a % b;
-      a = b;
-      b = remainder;
-   }
-
-   return a;
-}
-
-static void
-calculate_refresh_rate(const xcb_randr_mode_info_t *mode,
-                       unsigned *numerator, unsigned *denominator)
-{
-   unsigned vtotal = mode->vtotal;
-
-   /* Double-scan doubles the number of lines */
-   if (mode->mode_flags & XCB_RANDR_MODE_FLAG_DOUBLE_SCAN)
-      vtotal *= 2;
-
-   /* Interlace splits the frame into two fields; typically the monitor
-    * reports field rate.
-    */
-   if (mode->mode_flags & XCB_RANDR_MODE_FLAG_INTERLACE)
-      vtotal /= 2;
-
-   uint32_t dots = mode->htotal * vtotal;
-
-   if (dots == 0) {
-      *numerator = 0;
-      *denominator = 1;
-   } else {
-      uint32_t gcd = gcd_u32(mode->dot_clock, dots);
-
-      *numerator = mode->dot_clock / gcd;
-      *denominator = dots / gcd;
-   }
-}
-
-bool
-loader_dri3_update_screen_resources(struct loader_dri3_screen_resources *res)
-{
-   xcb_randr_get_crtc_info_cookie_t *crtc_cookies;
-
-   /* If we have cached screen resources information, check each CRTC to
-    * see if it's up to date.  Ideally, we'd watch PresentConfigureNotify
-    * events on the root window to see if something changed, but those only
-    * fire if the geometry changes.  It misses CRTC changes which only
-    * alter the refresh rate.  We also can't watch RandR events internally
-    * because they aren't XGE events.  So, we just check every CRTC for now.
-    */
-   bool config_unchanged = res->crtcs != NULL;
-
-   crtc_cookies = malloc(res->num_crtcs * sizeof(*crtc_cookies));
-
-   for (unsigned c = 0; c < res->num_crtcs; c++) {
-      crtc_cookies[c] =
-         xcb_randr_get_crtc_info_unchecked(res->conn, res->crtcs[c].id,
-                                           res->config_timestamp);
-   }
-
-   for (unsigned c = 0; c < res->num_crtcs; c++) {
-      xcb_randr_get_crtc_info_reply_t *reply =
-         xcb_randr_get_crtc_info_reply(res->conn, crtc_cookies[c], NULL);
-
-      /* Although randrproto 1.4.0 says that RRGetCrtcInfo is supposed to
-       * return InvalidConfigTime if config_timestamp is out of date, the
-       * implementation in xserver as of 21.x doesn't actually do so.  To
-       * detect changes in refresh rate, we check the returned timestamp
-       * on each tracked CRTC.
-       */
-      if (!reply ||
-          reply->status == XCB_RANDR_SET_CONFIG_INVALID_CONFIG_TIME ||
-          reply->timestamp != res->crtcs[c].timestamp) {
-         config_unchanged = false;
-         /* continue to consume all replies */
-      }
-
-      free(reply);
-   }
-
-   free(crtc_cookies);
-
-   if (config_unchanged)
-      return false;
-
-   /* Do RRGetScreenResourcesCurrent to query the list of CRTCs and modes,
-    * then RRGetCrtcInfo on each CRTC to determine what mode each uses, and
-    * use the mode to calculate the refresh rate.
-    */
-   mtx_lock(&res->mtx);
-
-   xcb_randr_get_screen_resources_current_cookie_t cookie =
-      xcb_randr_get_screen_resources_current_unchecked(res->conn,
-                                                       res->screen->root);
-   xcb_randr_get_screen_resources_current_reply_t *reply =
-      xcb_randr_get_screen_resources_current_reply(res->conn, cookie, NULL);
-
-   xcb_randr_crtc_t *new_crtcs =
-      xcb_randr_get_screen_resources_current_crtcs(reply);
-
-   xcb_randr_mode_info_t *new_modes =
-      xcb_randr_get_screen_resources_current_modes(reply);
-
-   res->config_timestamp = reply->config_timestamp;
-
-   free(res->crtcs);
-   res->crtcs = calloc(reply->num_crtcs, sizeof(*res->crtcs));
-
-   crtc_cookies = malloc(reply->num_crtcs * sizeof(*crtc_cookies));
-
-   for (unsigned c = 0; c < reply->num_crtcs; c++) {
-      crtc_cookies[c] =
-         xcb_randr_get_crtc_info_unchecked(res->conn, new_crtcs[c],
-                                           res->config_timestamp);
-   }
-
-   unsigned i = 0;
-   for (unsigned c = 0; c < reply->num_crtcs; c++) {
-      xcb_randr_get_crtc_info_reply_t *crtc_info =
-         xcb_randr_get_crtc_info_reply(res->conn, crtc_cookies[c], NULL);
-
-      if (!crtc_info || crtc_info->mode == XCB_NONE)
-         continue;
-
-      res->crtcs[i].id = new_crtcs[c];
-      res->crtcs[i].timestamp = crtc_info->timestamp;
-      res->crtcs[i].x = crtc_info->x;
-      res->crtcs[i].y = crtc_info->y;
-      res->crtcs[i].width = crtc_info->width;
-      res->crtcs[i].height = crtc_info->height;
-
-      for (int m = 0; m < reply->num_modes; m++) {
-         if (new_modes[m].id == crtc_info->mode) {
-            calculate_refresh_rate(&new_modes[m],
-                                   &res->crtcs[i].refresh_numerator,
-                                   &res->crtcs[i].refresh_denominator);
-            break;
-         }
-      }
-
-      i++;
-      free(crtc_info);
-   }
-
-   res->num_crtcs = i;
-
-   free(crtc_cookies);
-   free(reply);
-
-   mtx_unlock(&res->mtx);
-   return true;
-}
-
 /**
  * Make sure the server has flushed all pending swap buffers to hardware
  * for this drawable. Ideally we'd want to send an X protocol request to
index eb7f325..1fd340b 100644 (file)
@@ -298,39 +298,4 @@ loader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw);
 void
 loader_dri3_close_screen(__DRIscreen *dri_screen);
 
-struct loader_dri3_crtc_info {
-   xcb_randr_crtc_t id;
-   xcb_timestamp_t timestamp;
-
-   int16_t x, y;
-   uint16_t width, height;
-
-   unsigned refresh_numerator;
-   unsigned refresh_denominator;
-};
-
-struct loader_dri3_screen_resources {
-   mtx_t mtx;
-
-   xcb_connection_t *conn;
-   xcb_screen_t *screen;
-
-   xcb_timestamp_t config_timestamp;
-
-   /* Number of CRTCs with an active mode set */
-   unsigned num_crtcs;
-   struct loader_dri3_crtc_info *crtcs;
-};
-
-void
-loader_dri3_init_screen_resources(struct loader_dri3_screen_resources *res,
-                                  xcb_connection_t *conn,
-                                  xcb_screen_t *screen);
-bool
-loader_dri3_update_screen_resources(struct loader_dri3_screen_resources *res);
-
-void
-loader_dri3_destroy_screen_resources(struct loader_dri3_screen_resources *res);
-
-
 #endif
index 89d41bd..f1afce4 100644 (file)
@@ -151,3 +151,181 @@ loader_image_format_to_fourcc(int format)
    }
    return 0;
 }
+
+#ifdef HAVE_X11_PLATFORM
+void
+loader_init_screen_resources(struct loader_screen_resources *res,
+                             xcb_connection_t *conn,
+                             xcb_screen_t *screen)
+{
+   res->conn = conn;
+   res->screen = screen;
+   res->crtcs = NULL;
+
+   mtx_init(&res->mtx, mtx_plain);
+}
+
+void
+loader_destroy_screen_resources(struct loader_screen_resources *res)
+{
+   mtx_destroy(&res->mtx);
+}
+
+static unsigned
+gcd_u32(unsigned a, unsigned b)
+{
+   assert(a > 0 || b > 0);
+
+   while (b != 0) {
+      unsigned remainder = a % b;
+      a = b;
+      b = remainder;
+   }
+
+   return a;
+}
+
+static void
+calculate_refresh_rate(const xcb_randr_mode_info_t *mode,
+                       unsigned *numerator, unsigned *denominator)
+{
+   unsigned vtotal = mode->vtotal;
+
+   /* Double-scan doubles the number of lines */
+   if (mode->mode_flags & XCB_RANDR_MODE_FLAG_DOUBLE_SCAN)
+      vtotal *= 2;
+
+   /* Interlace splits the frame into two fields; typically the monitor
+    * reports field rate.
+    */
+   if (mode->mode_flags & XCB_RANDR_MODE_FLAG_INTERLACE)
+      vtotal /= 2;
+
+   uint32_t dots = mode->htotal * vtotal;
+
+   if (dots == 0) {
+      *numerator = 0;
+      *denominator = 1;
+   } else {
+      uint32_t gcd = gcd_u32(mode->dot_clock, dots);
+
+      *numerator = mode->dot_clock / gcd;
+      *denominator = dots / gcd;
+   }
+}
+
+bool
+loader_update_screen_resources(struct loader_screen_resources *res)
+{
+   xcb_randr_get_crtc_info_cookie_t *crtc_cookies;
+
+   /* If we have cached screen resources information, check each CRTC to
+    * see if it's up to date.  Ideally, we'd watch PresentConfigureNotify
+    * events on the root window to see if something changed, but those only
+    * fire if the geometry changes.  It misses CRTC changes which only
+    * alter the refresh rate.  We also can't watch RandR events internally
+    * because they aren't XGE events.  So, we just check every CRTC for now.
+    */
+   bool config_unchanged = res->crtcs != NULL;
+
+   crtc_cookies = malloc(res->num_crtcs * sizeof(*crtc_cookies));
+
+   for (unsigned c = 0; c < res->num_crtcs; c++) {
+      crtc_cookies[c] =
+         xcb_randr_get_crtc_info_unchecked(res->conn, res->crtcs[c].id,
+                                           res->config_timestamp);
+   }
+
+   for (unsigned c = 0; c < res->num_crtcs; c++) {
+      xcb_randr_get_crtc_info_reply_t *reply =
+         xcb_randr_get_crtc_info_reply(res->conn, crtc_cookies[c], NULL);
+
+      /* Although randrproto 1.4.0 says that RRGetCrtcInfo is supposed to
+       * return InvalidConfigTime if config_timestamp is out of date, the
+       * implementation in xserver as of 21.x doesn't actually do so.  To
+       * detect changes in refresh rate, we check the returned timestamp
+       * on each tracked CRTC.
+       */
+      if (!reply ||
+          reply->status == XCB_RANDR_SET_CONFIG_INVALID_CONFIG_TIME ||
+          reply->timestamp != res->crtcs[c].timestamp) {
+         config_unchanged = false;
+         /* continue to consume all replies */
+      }
+
+      free(reply);
+   }
+
+   free(crtc_cookies);
+
+   if (config_unchanged)
+      return false;
+
+   /* Do RRGetScreenResourcesCurrent to query the list of CRTCs and modes,
+    * then RRGetCrtcInfo on each CRTC to determine what mode each uses, and
+    * use the mode to calculate the refresh rate.
+    */
+   mtx_lock(&res->mtx);
+
+   xcb_randr_get_screen_resources_current_cookie_t cookie =
+      xcb_randr_get_screen_resources_current_unchecked(res->conn,
+                                                       res->screen->root);
+   xcb_randr_get_screen_resources_current_reply_t *reply =
+      xcb_randr_get_screen_resources_current_reply(res->conn, cookie, NULL);
+
+   xcb_randr_crtc_t *new_crtcs =
+      xcb_randr_get_screen_resources_current_crtcs(reply);
+
+   xcb_randr_mode_info_t *new_modes =
+      xcb_randr_get_screen_resources_current_modes(reply);
+
+   res->config_timestamp = reply->config_timestamp;
+
+   free(res->crtcs);
+   res->crtcs = calloc(reply->num_crtcs, sizeof(*res->crtcs));
+
+   crtc_cookies = malloc(reply->num_crtcs * sizeof(*crtc_cookies));
+
+   for (unsigned c = 0; c < reply->num_crtcs; c++) {
+      crtc_cookies[c] =
+         xcb_randr_get_crtc_info_unchecked(res->conn, new_crtcs[c],
+                                           res->config_timestamp);
+   }
+
+   unsigned i = 0;
+   for (unsigned c = 0; c < reply->num_crtcs; c++) {
+      xcb_randr_get_crtc_info_reply_t *crtc_info =
+         xcb_randr_get_crtc_info_reply(res->conn, crtc_cookies[c], NULL);
+
+      if (!crtc_info || crtc_info->mode == XCB_NONE)
+         continue;
+
+      res->crtcs[i].id = new_crtcs[c];
+      res->crtcs[i].timestamp = crtc_info->timestamp;
+      res->crtcs[i].x = crtc_info->x;
+      res->crtcs[i].y = crtc_info->y;
+      res->crtcs[i].width = crtc_info->width;
+      res->crtcs[i].height = crtc_info->height;
+
+      for (int m = 0; m < reply->num_modes; m++) {
+         if (new_modes[m].id == crtc_info->mode) {
+            calculate_refresh_rate(&new_modes[m],
+                                   &res->crtcs[i].refresh_numerator,
+                                   &res->crtcs[i].refresh_denominator);
+            break;
+         }
+      }
+
+      i++;
+      free(crtc_info);
+   }
+
+   res->num_crtcs = i;
+
+   free(crtc_cookies);
+   free(reply);
+
+   mtx_unlock(&res->mtx);
+   return true;
+}
+#endif
index ba34980..20ac24e 100644 (file)
  * OF THIS SOFTWARE.
  */
 
+#ifndef LOADER_DRI_HELPER_H
+#define LOADER_DRI_HELPER_H
+
 #include <stdbool.h>
 #include <sys/types.h>
 
 #include <GL/gl.h> /* dri_interface needs GL types */
 #include <GL/internal/dri_interface.h>
+#include <c11/threads.h>
+
+#ifdef HAVE_X11_PLATFORM
+#include <xcb/xcb.h>
+#include <xcb/dri3.h>
+#include <xcb/present.h>
+
+struct loader_crtc_info {
+   xcb_randr_crtc_t id;
+   xcb_timestamp_t timestamp;
+
+   int16_t x, y;
+   uint16_t width, height;
+
+   unsigned refresh_numerator;
+   unsigned refresh_denominator;
+};
+
+struct loader_screen_resources {
+   mtx_t mtx;
+
+   xcb_connection_t *conn;
+   xcb_screen_t *screen;
+
+   xcb_timestamp_t config_timestamp;
+
+   /* Number of CRTCs with an active mode set */
+   unsigned num_crtcs;
+   struct loader_crtc_info *crtcs;
+};
+#endif
 
 __DRIimage *loader_dri_create_image(__DRIscreen *screen,
                                     const __DRIimageExtension *image,
@@ -40,3 +74,17 @@ bool dri_valid_swap_interval(__DRIscreen *driScreen,
 
 int
 loader_image_format_to_fourcc(int format);
+
+#ifdef HAVE_X11_PLATFORM
+void
+loader_init_screen_resources(struct loader_screen_resources *res,
+                             xcb_connection_t *conn,
+                             xcb_screen_t *screen);
+bool
+loader_update_screen_resources(struct loader_screen_resources *res);
+
+void
+loader_destroy_screen_resources(struct loader_screen_resources *res);
+#endif
+
+#endif /* LOADER_DRI_HELPER_H */
index b03b229..81779a3 100644 (file)
@@ -28,7 +28,7 @@ if with_platform_x11 and with_dri3
     include_directories : [inc_include, inc_src],
     dependencies : [
       dep_libdrm, dep_xcb_dri3, dep_xcb_present, dep_xcb_sync, dep_xshmfence,
-      dep_xcb_xfixes, dep_xcb_xrandr,
+      dep_xcb_xfixes,
     ],
     build_by_default : false,
   )
@@ -46,6 +46,6 @@ libloader = static_library(
   c_args : loader_c_args,
   gnu_symbol_visibility : 'hidden',
   include_directories : [inc_include, inc_src, inc_util],
-  dependencies : [dep_libdrm, dep_thread],
+  dependencies : [dep_libdrm, dep_thread, dep_xcb_xrandr],
   build_by_default : false,
 )