summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTapani Pälli <tapani.palli@intel.com>2023-05-07 21:28:54 +0300
committerMarge Bot <emma+marge@anholt.net>2023-05-11 10:51:11 +0000
commit5a7520d2529204c5b9eaeaf17675a7fe1d7c1852 (patch)
treeb1268a8e2947f7e181885c7518b7a06802f91ae7
parent2a1e6a140da135e428915245cb4bb010c702b6f5 (diff)
downloadmesa-5a7520d2529204c5b9eaeaf17675a7fe1d7c1852.tar.gz
egl/loader: move crtc resource infrastructure as common helper
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>
-rw-r--r--src/egl/drivers/dri2/egl_dri2.h3
-rw-r--r--src/egl/drivers/dri2/platform_x11.c10
-rw-r--r--src/loader/loader_dri3_helper.c176
-rw-r--r--src/loader/loader_dri3_helper.h35
-rw-r--r--src/loader/loader_dri_helper.c178
-rw-r--r--src/loader/loader_dri_helper.h48
-rw-r--r--src/loader/meson.build4
7 files changed, 235 insertions, 219 deletions
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index 0fab2aab157..7693fed3543 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -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
diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c
index 0a4889cb96c..917c82bdeb2 100644
--- a/src/egl/drivers/dri2/platform_x11.c
+++ b/src/egl/drivers/dri2/platform_x11.c
@@ -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);
diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index 63be04ed2a4..0d9f108a18d 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -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
diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h
index eb7f32513b3..1fd340bd145 100644
--- a/src/loader/loader_dri3_helper.h
+++ b/src/loader/loader_dri3_helper.h
@@ -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
diff --git a/src/loader/loader_dri_helper.c b/src/loader/loader_dri_helper.c
index 89d41bdcfb6..f1afce47b92 100644
--- a/src/loader/loader_dri_helper.c
+++ b/src/loader/loader_dri_helper.c
@@ -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
diff --git a/src/loader/loader_dri_helper.h b/src/loader/loader_dri_helper.h
index ba349802290..20ac24ea69d 100644
--- a/src/loader/loader_dri_helper.h
+++ b/src/loader/loader_dri_helper.h
@@ -18,11 +18,45 @@
* 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 */
diff --git a/src/loader/meson.build b/src/loader/meson.build
index b03b229cd85..81779a33a31 100644
--- a/src/loader/meson.build
+++ b/src/loader/meson.build
@@ -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,
)