Extend the DBus XRandR protocol to expose cloning restriction

Turns out that even if two outputs say that they can be controlled
by a given CRTC, you can't configure them in the same CRTC unless
they are marked as "possible clones" one of the other.
This can further restrict the configuration options, so we need
to expose this limitation in the DBus API.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
This commit is contained in:
Giovanni Campagna 2013-07-19 18:47:01 +02:00 committed by Giovanni Campagna
parent 7e1d1003c9
commit dc242e46c2
3 changed files with 54 additions and 4 deletions

View File

@ -70,6 +70,9 @@ struct _MetaOutput
MetaCRTC **possible_crtcs; MetaCRTC **possible_crtcs;
unsigned int n_possible_crtcs; unsigned int n_possible_crtcs;
MetaOutput **possible_clones;
unsigned int n_possible_clones;
/* The low-level bits used to build the high-level info /* The low-level bits used to build the high-level info
in MetaMonitorInfo in MetaMonitorInfo

View File

@ -144,6 +144,8 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
manager->outputs[0].n_possible_crtcs = 1; manager->outputs[0].n_possible_crtcs = 1;
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1); manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1);
manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0]; manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[0].n_possible_clones = 0;
manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
} }
#ifdef HAVE_RANDR #ifdef HAVE_RANDR
@ -273,6 +275,17 @@ read_monitor_infos_from_xrandr (MetaMonitorManager *manager)
} }
} }
meta_output->n_possible_clones = output->nclone;
meta_output->possible_clones = g_new0 (MetaOutput *, meta_output->n_possible_clones);
/* We can build the list of clones now, because we don't have the list of outputs
yet, so temporarily set the pointers to the bare XIDs, and then we'll fix them
in a second pass
*/
for (j = 0; j < (unsigned)output->nclone; j++)
{
meta_output->possible_clones = GINT_TO_POINTER (output->clones[j]);
}
meta_output->is_primary = ((XID)meta_output->output_id == primary_output); meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
meta_output->is_presentation = FALSE; meta_output->is_presentation = FALSE;
@ -284,6 +297,28 @@ read_monitor_infos_from_xrandr (MetaMonitorManager *manager)
manager->n_outputs = n_actual_outputs; manager->n_outputs = n_actual_outputs;
/* Now fix the clones */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *meta_output;
meta_output = &manager->outputs[i];
for (j = 0; j < meta_output->n_possible_clones; j++)
{
RROutput clone = GPOINTER_TO_INT (meta_output->possible_clones[j]);
for (k = 0; k < manager->n_outputs; k++)
{
if (clone == (XID)manager->outputs[k].output_id)
{
meta_output->possible_clones[j] = &manager->outputs[k];
break;
}
}
}
}
XRRFreeScreenResources (resources); XRRFreeScreenResources (resources);
} }
@ -463,6 +498,7 @@ free_output_array (MetaOutput *old_outputs,
g_free (old_outputs[i].serial); g_free (old_outputs[i].serial);
g_free (old_outputs[i].modes); g_free (old_outputs[i].modes);
g_free (old_outputs[i].possible_crtcs); g_free (old_outputs[i].possible_crtcs);
g_free (old_outputs[i].possible_clones);
} }
g_free (old_outputs); g_free (old_outputs);
@ -567,7 +603,7 @@ handle_get_resources (MetaDBusDisplayConfig *skeleton,
unsigned int i, j; unsigned int i, j;
g_variant_builder_init (&crtc_builder, G_VARIANT_TYPE ("a(uxiiiiiuaua{sv})")); g_variant_builder_init (&crtc_builder, G_VARIANT_TYPE ("a(uxiiiiiuaua{sv})"));
g_variant_builder_init (&output_builder, G_VARIANT_TYPE ("a(uxiausaua{sv})")); g_variant_builder_init (&output_builder, G_VARIANT_TYPE ("a(uxiausauaua{sv})"));
g_variant_builder_init (&mode_builder, G_VARIANT_TYPE ("a(uxuud)")); g_variant_builder_init (&mode_builder, G_VARIANT_TYPE ("a(uxuud)"));
for (i = 0; i < manager->n_crtcs; i++) for (i = 0; i < manager->n_crtcs; i++)
@ -594,7 +630,7 @@ handle_get_resources (MetaDBusDisplayConfig *skeleton,
for (i = 0; i < manager->n_outputs; i++) for (i = 0; i < manager->n_outputs; i++)
{ {
MetaOutput *output = &manager->outputs[i]; MetaOutput *output = &manager->outputs[i];
GVariantBuilder crtcs, modes, properties; GVariantBuilder crtcs, modes, clones, properties;
g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au")); g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au"));
for (j = 0; j < output->n_possible_crtcs; j++) for (j = 0; j < output->n_possible_crtcs; j++)
@ -606,6 +642,11 @@ handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&modes, "u", g_variant_builder_add (&modes, "u",
(unsigned)(output->modes[j] - manager->modes)); (unsigned)(output->modes[j] - manager->modes));
g_variant_builder_init (&clones, G_VARIANT_TYPE ("au"));
for (j = 0; j < output->n_possible_clones; j++)
g_variant_builder_add (&clones, "u",
(unsigned)(output->possible_clones[j] - manager->outputs));
g_variant_builder_init (&properties, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_init (&properties, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&properties, "{sv}", "vendor", g_variant_builder_add (&properties, "{sv}", "vendor",
g_variant_new_string (output->vendor)); g_variant_new_string (output->vendor));
@ -620,13 +661,14 @@ handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&properties, "{sv}", "presentation", g_variant_builder_add (&properties, "{sv}", "presentation",
g_variant_new_boolean (output->is_presentation)); g_variant_new_boolean (output->is_presentation));
g_variant_builder_add (&output_builder, "(uxiausaua{sv})", g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */ i, /* ID */
output->output_id, output->output_id,
(int)(output->crtc ? output->crtc - manager->crtcs : -1), (int)(output->crtc ? output->crtc - manager->crtcs : -1),
&crtcs, &crtcs,
output->name, output->name,
&modes, &modes,
&clones,
&properties); &properties);
} }

View File

@ -76,6 +76,11 @@
* s name: the name of the connector to which the output is attached * s name: the name of the connector to which the output is attached
(like VGA1 or HDMI) (like VGA1 or HDMI)
* au modes: valid modes for this output * au modes: valid modes for this output
* au clones: valid clones for this output, ie other outputs that
can be assigned the same CRTC as this one; if you
want to mirror two outputs that don't have each other
in the clone list, you must configure two different
CRTCs for the same geometry
* a{sv} properties: other high-level properties that affect this * a{sv} properties: other high-level properties that affect this
output; they are not necessarily reflected in output; they are not necessarily reflected in
the hardware. the hardware.
@ -123,7 +128,7 @@
<method name="GetResources"> <method name="GetResources">
<arg name="serial" direction="out" type="u" /> <arg name="serial" direction="out" type="u" />
<arg name="crtcs" direction="out" type="a(uxiiiiiuaua{sv})" /> <arg name="crtcs" direction="out" type="a(uxiiiiiuaua{sv})" />
<arg name="outputs" direction="out" type="a(uxiausaua{sv})" /> <arg name="outputs" direction="out" type="a(uxiausauaua{sv})" />
<arg name="modes" direction="out" type="a(uxuud)" /> <arg name="modes" direction="out" type="a(uxuud)" />
</method> </method>