From 99d84ae1cc8f027a35c32d266cef48758daaff6d Mon Sep 17 00:00:00 2001 From: Daniel van Vugt Date: Fri, 10 Jun 2022 16:34:40 +0800 Subject: [PATCH] output-xrandr: Add support for the "max bpc" KMS connector property Part-of: --- src/backends/x11/meta-output-xrandr.c | 88 +++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/backends/x11/meta-output-xrandr.c b/src/backends/x11/meta-output-xrandr.c index 6fde5667e..37a377e48 100644 --- a/src/backends/x11/meta-output-xrandr.c +++ b/src/backends/x11/meta-output-xrandr.c @@ -145,11 +145,28 @@ output_set_underscanning_xrandr (MetaOutput *output, } } +static void +output_set_max_bpc_xrandr (MetaOutput *output, + unsigned int max_bpc) +{ + Display *xdisplay = xdisplay_from_output (output); + Atom prop = XInternAtom (xdisplay, "max bpc", False); + uint32_t value = max_bpc; + + xcb_randr_change_output_property (XGetXCBConnection (xdisplay), + (XID) meta_output_get_id (output), + prop, XCB_ATOM_INTEGER, 32, + XCB_PROP_MODE_REPLACE, + 1, &value); +} + void meta_output_xrandr_apply_mode (MetaOutputXrandr *output_xrandr) { MetaOutput *output = META_OUTPUT (output_xrandr); Display *xdisplay = xdisplay_from_output (output); + const MetaOutputInfo *output_info = meta_output_get_info (output); + unsigned int max_bpc; if (meta_output_is_primary (output)) { @@ -164,6 +181,13 @@ meta_output_xrandr_apply_mode (MetaOutputXrandr *output_xrandr) output_set_underscanning_xrandr (output, meta_output_is_underscanning (output)); } + + if (meta_output_get_max_bpc (output, &max_bpc) && + max_bpc >= output_info->max_bpc_min && + max_bpc <= output_info->max_bpc_max) + { + output_set_max_bpc_xrandr (output, max_bpc); + } } static int @@ -347,6 +371,33 @@ output_get_underscanning_xrandr (MetaOutput *output) return (strcmp (str, "on") == 0); } +static gboolean +output_get_max_bpc_xrandr (MetaOutput *output, + unsigned int *max_bpc) +{ + Display *xdisplay = xdisplay_from_output (output); + Atom atom, actual_type; + int actual_format; + unsigned long nitems, bytes_after; + g_autofree unsigned char *buffer = NULL; + + atom = XInternAtom (xdisplay, "max bpc", False); + XRRGetOutputProperty (xdisplay, + (XID) meta_output_get_id (output), + atom, + 0, G_MAXLONG, False, False, XCB_ATOM_INTEGER, + &actual_type, &actual_format, + &nitems, &bytes_after, &buffer); + + if (actual_type != XCB_ATOM_INTEGER || actual_format != 32 || nitems < 1) + return FALSE; + + if (max_bpc) + *max_bpc = *((uint32_t*) buffer); + + return TRUE; +} + static gboolean output_get_supports_underscanning_xrandr (Display *xdisplay, RROutput output_id) @@ -392,6 +443,36 @@ output_get_supports_underscanning_xrandr (Display *xdisplay, return supports_underscanning; } +static gboolean +output_get_max_bpc_range_xrandr (Display *xdisplay, + RROutput output_id, + unsigned int *min, + unsigned int *max) +{ + Atom atom; + XRRPropertyInfo *property_info; + long *values; + + atom = XInternAtom (xdisplay, "max bpc", False); + + meta_clutter_x11_trap_x_errors (); + property_info = XRRQueryOutputProperty (xdisplay, + (XID) output_id, + atom); + meta_clutter_x11_untrap_x_errors (); + + if (!property_info || property_info->num_values != 2) + return FALSE; + + values = (long *) property_info->values; + if (min) + *min = values[0]; + if (max) + *max = values[1]; + + return TRUE; +} + static gboolean output_get_supports_color_transform_xrandr (Display *xdisplay, RROutput output_id) @@ -934,6 +1015,10 @@ meta_output_xrandr_new (MetaGpuXrandr *gpu_xrandr, output_info->supports_underscanning = output_get_supports_underscanning_xrandr (xdisplay, output_id); + output_get_max_bpc_range_xrandr (xdisplay, + output_id, + &output_info->max_bpc_min, + &output_info->max_bpc_max); output_info->supports_color_transform = output_get_supports_color_transform_xrandr (xdisplay, output_id); output_info_init_backlight_limits_xrandr (output_info, xdisplay, output_id); @@ -954,6 +1039,9 @@ meta_output_xrandr_new (MetaGpuXrandr *gpu_xrandr, .is_presentation = output_get_presentation_xrandr (output), .is_underscanning = output_get_underscanning_xrandr (output), }; + output_assignment.has_max_bpc = + output_get_max_bpc_xrandr (output, &output_assignment.max_bpc); + meta_output_assign_crtc (output, assigned_crtc, &output_assignment); } else