[gnome-flashback] monitor-manager: add support for the "max bpc" connector property
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] monitor-manager: add support for the "max bpc" connector property
- Date: Sun, 4 Sep 2022 09:16:11 +0000 (UTC)
commit f8e94a9113d2c63ef8d8e90b6c9f4d9c8f53d82b
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Sun Aug 21 16:40:41 2022 +0300
monitor-manager: add support for the "max bpc" connector property
Based on mutter commits:
https://gitlab.gnome.org/GNOME/mutter/-/commit/e0e10c29d962ef902dba13b1115a1d2e4bf43f6e
https://gitlab.gnome.org/GNOME/mutter/-/commit/6ff0d600c3d0fcc945489428b5b1a2d1aca68bfe
https://gitlab.gnome.org/GNOME/mutter/-/commit/a907cef9050a4bc24dd8bf65f9a3121fa43f9a2d
https://gitlab.gnome.org/GNOME/mutter/-/commit/4eef54f80ad2daa4fc8758ed0821de02b07c573f
https://gitlab.gnome.org/GNOME/mutter/-/commit/99d84ae1cc8f027a35c32d266cef48758daaff6d
https://gitlab.gnome.org/GNOME/mutter/-/commit/d39137c63189775c23e962ef73a4bf41e7c29ca7
https://gitlab.gnome.org/GNOME/mutter/-/commit/03336788fb079cb8aa203e031f85d039a87832ce
https://gitlab.gnome.org/GNOME/mutter/-/commit/db0f12135ebc0d1ff11556140f36851228ce41bc
backends/gf-monitor-config-manager.c | 8 ++-
backends/gf-monitor-config-private.h | 2 +
backends/gf-monitor-config-store.c | 51 ++++++++++++++
backends/gf-monitor-config.c | 2 +
backends/gf-monitor-manager-xrandr.c | 12 ++++
backends/gf-monitor-private.h | 3 +
backends/gf-monitor.c | 11 +++
backends/gf-output-info-private.h | 3 +
backends/gf-output-private.h | 5 ++
backends/gf-output-xrandr.c | 125 ++++++++++++++++++++++++++++++++++-
backends/gf-output.c | 22 ++++++
11 files changed, 241 insertions(+), 3 deletions(-)
---
diff --git a/backends/gf-monitor-config-manager.c b/backends/gf-monitor-config-manager.c
index 706f241..07f8a4d 100644
--- a/backends/gf-monitor-config-manager.c
+++ b/backends/gf-monitor-config-manager.c
@@ -791,7 +791,9 @@ clone_monitor_config_list (GList *configs_in)
*config_out = (GfMonitorConfig) {
.monitor_spec = gf_monitor_spec_clone (config_in->monitor_spec),
.mode_spec = g_memdup2 (config_in->mode_spec, sizeof (GfMonitorModeSpec)),
- .enable_underscanning = config_in->enable_underscanning
+ .enable_underscanning = config_in->enable_underscanning,
+ .has_max_bpc = config_in->has_max_bpc,
+ .max_bpc = config_in->max_bpc
};
configs_out = g_list_append (configs_out, config_out);
@@ -1145,7 +1147,9 @@ assign_monitor_crtc (GfMonitor *monitor,
.output = output,
.is_primary = assign_output_as_primary,
.is_presentation = assign_output_as_presentation,
- .is_underscanning = data->monitor_config->enable_underscanning
+ .is_underscanning = data->monitor_config->enable_underscanning,
+ .has_max_bpc = data->monitor_config->has_max_bpc,
+ .max_bpc = data->monitor_config->max_bpc
};
g_ptr_array_add (data->crtc_assignments, crtc_assignment);
diff --git a/backends/gf-monitor-config-private.h b/backends/gf-monitor-config-private.h
index 44bd61e..0d8e0db 100644
--- a/backends/gf-monitor-config-private.h
+++ b/backends/gf-monitor-config-private.h
@@ -31,6 +31,8 @@ typedef struct
GfMonitorSpec *monitor_spec;
GfMonitorModeSpec *mode_spec;
gboolean enable_underscanning;
+ gboolean has_max_bpc;
+ unsigned int max_bpc;
} GfMonitorConfig;
GfMonitorConfig *gf_monitor_config_new (GfMonitor *monitor,
diff --git a/backends/gf-monitor-config-store.c b/backends/gf-monitor-config-store.c
index e377b67..2031f69 100644
--- a/backends/gf-monitor-config-store.c
+++ b/backends/gf-monitor-config-store.c
@@ -158,6 +158,7 @@ typedef enum
STATE_MONITOR_MODE_RATE,
STATE_MONITOR_MODE_FLAG,
STATE_MONITOR_UNDERSCANNING,
+ STATE_MONITOR_MAXBPC,
STATE_DISABLED,
STATE_POLICY,
STATE_STORES,
@@ -497,6 +498,10 @@ handle_start_element (GMarkupParseContext *context,
{
parser->state = STATE_MONITOR_UNDERSCANNING;
}
+ else if (g_str_equal (element_name, "maxbpc"))
+ {
+ parser->state = STATE_MONITOR_MAXBPC;
+ }
else
{
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
@@ -590,6 +595,13 @@ handle_start_element (GMarkupParseContext *context,
return;
}
+ case STATE_MONITOR_MAXBPC:
+ {
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
+ "Invalid element '%s' under maxbpc", element_name);
+ return;
+ }
+
case STATE_DISABLED:
{
if (!g_str_equal (element_name, "monitorspec"))
@@ -791,6 +803,7 @@ finish_monitor_spec (ConfigParser *parser)
case STATE_MONITOR_MODE_RATE:
case STATE_MONITOR_MODE_FLAG:
case STATE_MONITOR_UNDERSCANNING:
+ case STATE_MONITOR_MAXBPC:
case STATE_POLICY:
case STATE_STORES:
case STATE_STORE:
@@ -899,6 +912,14 @@ handle_end_element (GMarkupParseContext *context,
return;
}
+ case STATE_MONITOR_MAXBPC:
+ {
+ g_assert (g_str_equal (element_name, "maxbpc"));
+
+ parser->state = STATE_MONITOR;
+ return;
+ }
+
case STATE_MONITOR:
{
GfLogicalMonitorConfig *logical_monitor_config;
@@ -1378,6 +1399,29 @@ handle_text (GMarkupParseContext *context,
return;
}
+ case STATE_MONITOR_MAXBPC:
+ {
+ int signed_max_bpc;
+
+ if (read_int (text, text_len, &signed_max_bpc, error))
+ {
+ if (signed_max_bpc >= 0)
+ {
+ parser->current_monitor_config->has_max_bpc = TRUE;
+ parser->current_monitor_config->max_bpc = signed_max_bpc;
+ }
+ else
+ {
+ g_set_error (error, G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Invalid negative maxbpc value '%s'",
+ text);
+ }
+ }
+
+ return;
+ }
+
case STATE_STORE:
{
GfConfigStore store;
@@ -1623,6 +1667,13 @@ append_monitors (GString *buffer,
g_string_append (buffer, " </mode>\n");
if (monitor_config->enable_underscanning)
g_string_append (buffer, " <underscanning>yes</underscanning>\n");
+
+ if (monitor_config->has_max_bpc)
+ {
+ g_string_append_printf (buffer, " <maxbpc>%u</maxbpc>\n",
+ monitor_config->max_bpc);
+ }
+
g_string_append (buffer, " </monitor>\n");
}
}
diff --git a/backends/gf-monitor-config.c b/backends/gf-monitor-config.c
index 3bbe1d4..a4c1a67 100644
--- a/backends/gf-monitor-config.c
+++ b/backends/gf-monitor-config.c
@@ -42,6 +42,8 @@ gf_monitor_config_new (GfMonitor *monitor,
config->mode_spec = g_memdup2 (mode_spec, sizeof (GfMonitorModeSpec));
config->enable_underscanning = gf_monitor_is_underscanning (monitor);
+ config->has_max_bpc = gf_monitor_get_max_bpc (monitor, &config->max_bpc);
+
return config;
}
diff --git a/backends/gf-monitor-manager-xrandr.c b/backends/gf-monitor-manager-xrandr.c
index 9786852..cd9d3cb 100644
--- a/backends/gf-monitor-manager-xrandr.c
+++ b/backends/gf-monitor-manager-xrandr.c
@@ -141,6 +141,7 @@ is_output_assignment_changed (GfOutput *output,
for (i = 0; i < n_output_assignments; i++)
{
GfOutputAssignment *output_assignment;
+ unsigned int max_bpc;
output_assignment = output_assignments[i];
@@ -156,6 +157,17 @@ is_output_assignment_changed (GfOutput *output,
if (gf_output_is_underscanning (output) != output_assignment->is_underscanning)
return TRUE;
+ if (gf_output_get_max_bpc (output, &max_bpc))
+ {
+ if (!output_assignment->has_max_bpc ||
+ max_bpc != output_assignment->max_bpc)
+ return TRUE;
+ }
+ else if (output_assignment->has_max_bpc)
+ {
+ return TRUE;
+ }
+
output_is_found = TRUE;
}
diff --git a/backends/gf-monitor-private.h b/backends/gf-monitor-private.h
index ce6ea98..6c608dc 100644
--- a/backends/gf-monitor-private.h
+++ b/backends/gf-monitor-private.h
@@ -139,6 +139,9 @@ gboolean gf_monitor_supports_underscanning (GfMonitor
gboolean gf_monitor_is_underscanning (GfMonitor *monitor);
+gboolean gf_monitor_get_max_bpc (GfMonitor *self,
+ unsigned int *max_bpc);
+
gboolean gf_monitor_is_laptop_panel (GfMonitor *monitor);
gboolean gf_monitor_is_same_as (GfMonitor *monitor,
diff --git a/backends/gf-monitor.c b/backends/gf-monitor.c
index 7b1c374..e480467 100644
--- a/backends/gf-monitor.c
+++ b/backends/gf-monitor.c
@@ -781,6 +781,17 @@ gf_monitor_is_underscanning (GfMonitor *monitor)
return gf_output_is_underscanning (output);
}
+gboolean
+gf_monitor_get_max_bpc (GfMonitor *self,
+ unsigned int *max_bpc)
+{
+ GfOutput *output;
+
+ output = gf_monitor_get_main_output (self);
+
+ return gf_output_get_max_bpc (output, max_bpc);
+}
+
gboolean
gf_monitor_is_laptop_panel (GfMonitor *monitor)
{
diff --git a/backends/gf-output-info-private.h b/backends/gf-output-info-private.h
index d37b19e..5f3788e 100644
--- a/backends/gf-output-info-private.h
+++ b/backends/gf-output-info-private.h
@@ -74,6 +74,9 @@ typedef struct
gboolean supports_underscanning;
gboolean supports_color_transform;
+ unsigned int max_bpc_min;
+ unsigned int max_bpc_max;
+
/* Get a new preferred mode on hotplug events, to handle
* dynamic guest resizing
*/
diff --git a/backends/gf-output-private.h b/backends/gf-output-private.h
index e59cdd4..278644f 100644
--- a/backends/gf-output-private.h
+++ b/backends/gf-output-private.h
@@ -45,6 +45,8 @@ typedef struct
gboolean is_primary;
gboolean is_presentation;
gboolean is_underscanning;
+ gboolean has_max_bpc;
+ unsigned int max_bpc;
} GfOutputAssignment;
#define GF_TYPE_OUTPUT (gf_output_get_type ())
@@ -92,6 +94,9 @@ gboolean gf_output_is_presentation (GfOutput
gboolean gf_output_is_underscanning (GfOutput *self);
+gboolean gf_output_get_max_bpc (GfOutput *self,
+ unsigned int *max_bpc);
+
void gf_output_set_backlight (GfOutput *self,
int backlight);
diff --git a/backends/gf-output-xrandr.c b/backends/gf-output-xrandr.c
index c9ebda6..55d25fb 100644
--- a/backends/gf-output-xrandr.c
+++ b/backends/gf-output-xrandr.c
@@ -154,6 +154,25 @@ output_set_underscanning_xrandr (GfOutput *output,
}
}
+static void
+output_set_max_bpc_xrandr (GfOutput *output,
+ unsigned int max_bpc)
+{
+ Display *xdisplay;
+ Atom prop;
+ uint32_t value;
+
+ xdisplay = xdisplay_from_output (output);
+ prop = XInternAtom (xdisplay, "max bpc", False);
+ value = max_bpc;
+
+ xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
+ (XID) gf_output_get_id (output),
+ prop, XCB_ATOM_INTEGER, 32,
+ XCB_PROP_MODE_REPLACE,
+ 1, &value);
+}
+
static guint8 *
get_edid_property (Display *xdisplay,
RROutput output,
@@ -637,6 +656,52 @@ output_get_boolean_property (GfOutput *output,
return value;
}
+static gboolean
+output_get_max_bpc_xrandr (GfOutput *output,
+ unsigned int *max_bpc)
+{
+ Display *xdisplay;
+ Atom atom;
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems;
+ unsigned long bytes_after;
+ unsigned char *buffer;
+
+ xdisplay = xdisplay_from_output (output);
+ atom = XInternAtom (xdisplay, "max bpc", False);
+ buffer = NULL;
+
+ XRRGetOutputProperty (xdisplay,
+ (XID) gf_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)
+ {
+ if (buffer != NULL)
+ XFree (buffer);
+
+ return FALSE;
+ }
+
+ if (max_bpc)
+ *max_bpc = *((uint32_t*) buffer);
+
+ XFree (buffer);
+
+ return TRUE;
+}
+
static gboolean
output_get_presentation_xrandr (GfOutput *output)
{
@@ -724,6 +789,44 @@ 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;
+
+ if (!output_get_property_exists (xdisplay, output_id, "max bpc"))
+ return FALSE;
+
+ atom = XInternAtom (xdisplay, "max bpc", False);
+ property_info = XRRQueryOutputProperty (xdisplay, (XID) output_id, atom);
+
+ if (property_info == NULL)
+ return FALSE;
+
+ if (property_info->num_values != 2)
+ {
+ XFree (property_info);
+ return FALSE;
+ }
+
+ values = (long *) property_info->values;
+
+ if (min)
+ *min = values[0];
+
+ if (max)
+ *max = values[1];
+
+ XFree (property_info);
+
+ return TRUE;
+}
+
static gboolean
output_get_supports_color_transform_xrandr (Display *xdisplay,
RROutput output_id)
@@ -920,6 +1023,12 @@ gf_output_xrandr_new (GfGpuXrandr *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);
@@ -935,6 +1044,7 @@ gf_output_xrandr_new (GfGpuXrandr *gpu_xrandr,
if (assigned_crtc)
{
GfOutputAssignment output_assignment;
+ gboolean has_max_bpc;
output_assignment = (GfOutputAssignment) {
.is_primary = (XID) gf_output_get_id (output) == primary_output,
@@ -942,6 +1052,9 @@ gf_output_xrandr_new (GfGpuXrandr *gpu_xrandr,
.is_underscanning = output_get_underscanning_xrandr (output),
};
+ has_max_bpc = output_get_max_bpc_xrandr (output, &output_assignment.max_bpc);
+ output_assignment.has_max_bpc = has_max_bpc;
+
gf_output_assign_crtc (output, assigned_crtc, &output_assignment);
}
else
@@ -983,9 +1096,12 @@ gf_output_xrandr_apply_mode (GfOutputXrandr *self)
{
GfOutput *output;
Display *xdisplay;
+ const GfOutputInfo *output_info;
+ unsigned int max_bpc;
output = GF_OUTPUT (self);
xdisplay = xdisplay_from_output (output);
+ output_info = gf_output_get_info (output);
if (gf_output_is_primary (output))
{
@@ -995,11 +1111,18 @@ gf_output_xrandr_apply_mode (GfOutputXrandr *self)
output_set_presentation_xrandr (output, gf_output_is_presentation (output));
- if (gf_output_get_info (output)->supports_underscanning)
+ if (output_info->supports_underscanning)
{
output_set_underscanning_xrandr (output,
gf_output_is_underscanning (output));
}
+
+ if (gf_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);
+ }
}
void
diff --git a/backends/gf-output.c b/backends/gf-output.c
index ab7aed2..685ac0e 100644
--- a/backends/gf-output.c
+++ b/backends/gf-output.c
@@ -49,6 +49,9 @@ typedef struct
gboolean is_underscanning;
+ gboolean has_max_bpc;
+ unsigned int max_bpc;
+
int backlight;
} GfOutputPrivate;
@@ -311,6 +314,11 @@ gf_output_assign_crtc (GfOutput *self,
priv->is_primary = output_assignment->is_primary;
priv->is_presentation = output_assignment->is_presentation;
priv->is_underscanning = output_assignment->is_underscanning;
+
+ priv->has_max_bpc = output_assignment->has_max_bpc;
+
+ if (priv->has_max_bpc)
+ priv->max_bpc = output_assignment->max_bpc;
}
void
@@ -439,6 +447,20 @@ gf_output_is_underscanning (GfOutput *self)
return priv->is_underscanning;
}
+gboolean
+gf_output_get_max_bpc (GfOutput *self,
+ unsigned int *max_bpc)
+{
+ GfOutputPrivate *priv;
+
+ priv = gf_output_get_instance_private (self);
+
+ if (priv->has_max_bpc && max_bpc != NULL)
+ *max_bpc = priv->max_bpc;
+
+ return priv->has_max_bpc;
+}
+
void
gf_output_set_backlight (GfOutput *self,
int backlight)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]