From d7b2ea37b15639c7c71b8c7f70f8647530264a71 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Thu, 8 Aug 2013 13:32:05 +0200 Subject: [PATCH] MonitorManager: add EDID properties to the output DBus description Add "edid-file", if we have one (in the KMS case, where we can point people to the right sysfs file), or "edid" with inline data. These are needed by colord to build the default ICC profile for uncalibrated displays. https://bugzilla.gnome.org/show_bug.cgi?id=705670 --- src/core/monitor-private.h | 6 ++++ src/core/monitor-xrandr.c | 70 ++++++++++++++++++++++++++++++++++++++ src/core/monitor.c | 38 +++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h index c3ac0eb0a..970bd3290 100644 --- a/src/core/monitor-private.h +++ b/src/core/monitor-private.h @@ -257,6 +257,12 @@ struct _MetaMonitorManagerClass MetaDBusDisplayConfigSkeletonClass parent_class; void (*read_current) (MetaMonitorManager *); + + char* (*get_edid_file) (MetaMonitorManager *, + MetaOutput *); + GBytes* (*read_edid) (MetaMonitorManager *, + MetaOutput *); + void (*apply_configuration) (MetaMonitorManager *, MetaCRTCInfo **, unsigned int , diff --git a/src/core/monitor-xrandr.c b/src/core/monitor-xrandr.c index 0f251ff1d..3e245c9ce 100644 --- a/src/core/monitor-xrandr.c +++ b/src/core/monitor-xrandr.c @@ -467,6 +467,75 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) } } +static guint8 * +get_edid_property (Display *dpy, + RROutput output, + Atom atom, + gsize *len) +{ + unsigned char *prop; + int actual_format; + unsigned long nitems, bytes_after; + Atom actual_type; + guint8 *result; + + XRRGetOutputProperty (dpy, output, atom, + 0, 100, False, False, + AnyPropertyType, + &actual_type, &actual_format, + &nitems, &bytes_after, &prop); + + if (actual_type == XA_INTEGER && actual_format == 8) + { + result = g_memdup (prop, nitems); + if (len) + *len = nitems; + } + else + { + result = NULL; + } + + XFree (prop); + + return result; +} + +static GBytes * +meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager, + MetaOutput *output) +{ + MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); + Atom edid_atom; + guint8 *result; + gsize len; + + edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE); + result = get_edid_property (manager_xrandr->xdisplay, output->output_id, edid_atom, &len); + + if (!result) + { + edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE); + result = get_edid_property (manager_xrandr->xdisplay, output->output_id, edid_atom, &len); + } + + if (!result) + { + edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE); + result = get_edid_property (manager_xrandr->xdisplay, output->output_id, edid_atom, &len); + } + + if (result) + { + if (len > 0 && len % 128 == 0) + return g_bytes_new_take (result, len); + else + g_free (result); + } + + return NULL; +} + static void meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager, MetaPowerSave mode) @@ -767,6 +836,7 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) object_class->finalize = meta_monitor_manager_xrandr_finalize; manager_class->read_current = meta_monitor_manager_xrandr_read_current; + manager_class->read_edid = meta_monitor_manager_xrandr_read_edid; manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration; manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode; manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight; diff --git a/src/core/monitor.c b/src/core/monitor.c index eee0360be..1fbcd9c79 100644 --- a/src/core/monitor.c +++ b/src/core/monitor.c @@ -353,6 +353,20 @@ apply_config_dummy (MetaMonitorManager *manager, invalidate_logical_config (manager); } +static GBytes * +read_edid_dummy (MetaMonitorManager *manager, + MetaOutput *output) +{ + return NULL; +} + +static char * +get_edid_file_dummy (MetaMonitorManager *manager, + MetaOutput *output) +{ + return NULL; +} + static void meta_monitor_manager_init (MetaMonitorManager *manager) { @@ -643,6 +657,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass) klass->read_current = read_current_dummy; klass->apply_configuration = apply_config_dummy; + klass->get_edid_file = get_edid_file_dummy; + klass->read_edid = read_edid_dummy; signals[MONITORS_CHANGED] = g_signal_new ("monitors-changed", @@ -712,6 +728,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, GDBusMethodInvocation *invocation) { MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton); + MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (skeleton); GVariantBuilder crtc_builder, output_builder, mode_builder; unsigned int i, j; @@ -746,6 +763,8 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, { MetaOutput *output = &manager->outputs[i]; GVariantBuilder crtcs, modes, clones, properties; + GBytes *edid; + char *edid_file; g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au")); for (j = 0; j < output->n_possible_crtcs; j++) @@ -778,6 +797,25 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, g_variant_builder_add (&properties, "{sv}", "presentation", g_variant_new_boolean (output->is_presentation)); + edid_file = manager_class->get_edid_file (manager, output); + if (edid_file) + { + g_variant_builder_add (&properties, "{sv}", "edid-file", + g_variant_new_take_string (edid_file)); + } + else + { + edid = manager_class->read_edid (manager, output); + + if (edid) + { + g_variant_builder_add (&properties, "{sv}", "edid", + g_variant_new_from_bytes (G_VARIANT_TYPE ("ay"), + edid, TRUE)); + g_bytes_unref (edid); + } + } + g_variant_builder_add (&output_builder, "(uxiausauaua{sv})", i, /* ID */ output->output_id,