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.
This commit is contained in:
Giovanni Campagna 2013-08-08 13:32:05 +02:00
parent 804c2be976
commit bbf07c9b17
3 changed files with 114 additions and 0 deletions

View File

@ -258,6 +258,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 ,

View File

@ -466,6 +466,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)
@ -766,6 +835,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;

View File

@ -339,6 +339,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)
{
@ -633,6 +647,8 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
object_class->finalize = meta_monitor_manager_finalize;
klass->read_current = read_current_dummy;
klass->read_edid = read_edid_dummy;
klass->get_edid_file = get_edid_file_dummy;
klass->apply_configuration = apply_config_dummy;
signals[MONITORS_CHANGED] =
@ -703,6 +719,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;
@ -737,6 +754,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++)
@ -769,6 +788,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,