summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGiovanni Campagna <gcampagn@redhat.com>2013-07-24 18:01:31 +0200
committerGiovanni Campagna <gcampagna@src.gnome.org>2013-08-18 00:34:15 +0200
commitd0529b7482770c7d9ae3dcd581be3a3e65ac9748 (patch)
tree6eae434b202f9ae606a28207904205d4c1c61c9b /src/core
parent8f4621240a417ad83e1e453a03e04538c0d4b848 (diff)
downloadmutter-d0529b7482770c7d9ae3dcd581be3a3e65ac9748.tar.gz
MonitorConfig: add CRTC assignment
Ripped off libgnome-desktop, trimming the parts that checked that the configuration was plausible, as that should be done in gnome-control-center before asking mutter for a change. https://bugzilla.gnome.org/show_bug.cgi?id=705670
Diffstat (limited to 'src/core')
-rw-r--r--src/core/monitor-config.c381
-rw-r--r--src/core/monitor-private.h48
-rw-r--r--src/core/monitor.c176
3 files changed, 510 insertions, 95 deletions
diff --git a/src/core/monitor-config.c b/src/core/monitor-config.c
index da4f8a080..d6ab967f0 100644
--- a/src/core/monitor-config.c
+++ b/src/core/monitor-config.c
@@ -25,6 +25,15 @@
* 02111-1307, USA.
*/
+/*
+ * Portions of this file are derived from gnome-desktop/libgnome-desktop/gnome-rr-config.c
+ *
+ * Copyright 2007, 2008, Red Hat, Inc.
+ * Copyright 2010 Giovanni Campagna
+ *
+ * Author: Soren Sandmann <sandmann@redhat.com>
+ */
+
#include "config.h"
#include <string.h>
@@ -90,6 +99,11 @@ struct _MetaMonitorConfigClass {
G_DEFINE_TYPE (MetaMonitorConfig, meta_monitor_config, G_TYPE_OBJECT);
+static gboolean meta_monitor_config_assign_crtcs (MetaConfiguration *config,
+ MetaMonitorManager *manager,
+ GPtrArray *crtcs,
+ GPtrArray *outputs);
+
static void
free_output_key (MetaOutputKey *key)
{
@@ -774,35 +788,37 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
return stored;
}
-static void
-make_crtcs (MetaConfiguration *config,
- MetaMonitorManager *manager,
- GVariant **crtcs,
- GVariant **outputs)
-{
- *crtcs = NULL;
- *outputs = NULL;
- /* FIXME */
-}
-
-static void
+static gboolean
apply_configuration (MetaMonitorConfig *self,
MetaConfiguration *config,
MetaMonitorManager *manager,
gboolean stored)
{
- GVariant *crtcs, *outputs;
-
- make_crtcs (config, manager, &crtcs, &outputs);
- meta_monitor_manager_apply_configuration (manager, crtcs, outputs);
+ GPtrArray *crtcs, *outputs;
+
+ crtcs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_crtc_info_free);
+ outputs = g_ptr_array_new_full (config->n_outputs, (GDestroyNotify)meta_output_info_free);
+
+ if (!meta_monitor_config_assign_crtcs (config, manager, crtcs, outputs))
+ {
+ g_ptr_array_unref (crtcs);
+ g_ptr_array_unref (outputs);
+
+ return FALSE;
+ }
+
+ meta_monitor_manager_apply_configuration (manager,
+ (MetaCRTCInfo**)crtcs->pdata, crtcs->len,
+ (MetaOutputInfo**)outputs->pdata, outputs->len);
if (self->current && !self->current_is_stored)
config_free (self->current);
self->current = config;
self->current_is_stored = stored;
- g_variant_unref (crtcs);
- g_variant_unref (outputs);
+ g_ptr_array_unref (crtcs);
+ g_ptr_array_unref (outputs);
+ return TRUE;
}
gboolean
@@ -818,8 +834,7 @@ meta_monitor_config_apply_stored (MetaMonitorConfig *self,
if (stored)
{
- apply_configuration (self, stored, manager, TRUE);
- return TRUE;
+ return apply_configuration (self, stored, manager, TRUE);
}
else
return FALSE;
@@ -1039,3 +1054,329 @@ meta_monitor_config_make_persistent (MetaMonitorConfig *self)
meta_monitor_config_save (self);
}
+
+/*
+ * CRTC assignment
+ */
+typedef struct
+{
+ MetaConfiguration *config;
+ MetaMonitorManager *manager;
+ GHashTable *info;
+} CrtcAssignment;
+
+static gboolean
+output_can_clone (MetaOutput *output,
+ MetaOutput *clone)
+{
+ unsigned int i;
+
+ for (i = 0; i < output->n_possible_clones; i++)
+ if (output->possible_clones[i] == clone)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+can_clone (MetaCRTCInfo *info,
+ MetaOutput *output)
+{
+ unsigned int i;
+
+ for (i = 0; i < info->outputs->len; ++i)
+ {
+ MetaOutput *clone = info->outputs->pdata[i];
+
+ if (!output_can_clone (clone, output))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+crtc_can_drive_output (MetaCRTC *crtc,
+ MetaOutput *output)
+{
+ unsigned int i;
+
+ for (i = 0; i < output->n_possible_crtcs; i++)
+ if (output->possible_crtcs[i] == crtc)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+output_supports_mode (MetaOutput *output,
+ MetaMonitorMode *mode)
+{
+ unsigned int i;
+
+ for (i = 0; i < output->n_modes; i++)
+ if (output->modes[i] == mode)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+crtc_assignment_assign (CrtcAssignment *assign,
+ MetaCRTC *crtc,
+ MetaMonitorMode *mode,
+ int x,
+ int y,
+ enum wl_output_transform transform,
+ MetaOutput *output)
+{
+ MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);
+
+ if (!crtc_can_drive_output (crtc, output))
+ return FALSE;
+
+ if (!output_supports_mode (output, mode))
+ return FALSE;
+
+ if ((crtc->all_transforms & (1 << transform)) == 0)
+ return FALSE;
+
+ if (info)
+ {
+ if (!(info->mode == mode &&
+ info->x == x &&
+ info->y == y &&
+ info->transform == transform))
+ return FALSE;
+
+ if (!can_clone (info, output))
+ return FALSE;
+
+ g_ptr_array_add (info->outputs, output);
+ return TRUE;
+ }
+ else
+ {
+ MetaCRTCInfo *info = g_slice_new0 (MetaCRTCInfo);
+
+ info->crtc = crtc;
+ info->mode = mode;
+ info->x = x;
+ info->y = y;
+ info->transform = transform;
+ info->outputs = g_ptr_array_new ();
+
+ g_ptr_array_add (info->outputs, output);
+ g_hash_table_insert (assign->info, crtc, info);
+
+ return TRUE;
+ }
+}
+
+static void
+crtc_assignment_unassign (CrtcAssignment *assign,
+ MetaCRTC *crtc,
+ MetaOutput *output)
+{
+ MetaCRTCInfo *info = g_hash_table_lookup (assign->info, crtc);
+
+ if (info)
+ {
+ g_ptr_array_remove (info->outputs, output);
+
+ if (info->outputs->len == 0)
+ g_hash_table_remove (assign->info, crtc);
+ }
+}
+
+static MetaOutput *
+find_output_by_key (MetaOutput *outputs,
+ unsigned int n_outputs,
+ MetaOutputKey *key)
+{
+ unsigned int i;
+
+ for (i = 0; i < n_outputs; i++)
+ {
+ if (strcmp (outputs[i].name, key->connector) == 0)
+ {
+ /* This should be checked a lot earlier! */
+
+ g_warn_if_fail (strcmp (outputs[i].vendor, key->vendor) == 0 &&
+ strcmp (outputs[i].product, key->product) == 0 &&
+ strcmp (outputs[i].serial, key->serial) == 0);
+ return &outputs[i];
+ }
+ }
+
+ /* Just to satisfy GCC - this is a fatal error if occurs */
+ return NULL;
+}
+
+/* Check whether the given set of settings can be used
+ * at the same time -- ie. whether there is an assignment
+ * of CRTC's to outputs.
+ *
+ * Brute force - the number of objects involved is small
+ * enough that it doesn't matter.
+ */
+static gboolean
+real_assign_crtcs (CrtcAssignment *assignment,
+ unsigned int output_num)
+{
+ MetaMonitorMode *modes;
+ MetaCRTC *crtcs;
+ MetaOutput *outputs;
+ unsigned int n_crtcs, n_modes, n_outputs;
+ MetaOutputKey *output_key;
+ MetaOutputConfig *output_config;
+ unsigned int i;
+ gboolean success;
+
+ if (output_num == assignment->config->n_outputs)
+ return TRUE;
+
+ output_key = &assignment->config->keys[output_num];
+ output_config = &assignment->config->outputs[output_num];
+
+ /* It is always allowed for an output to be turned off */
+ if (!output_config->enabled)
+ return real_assign_crtcs (assignment, output_num + 1);
+
+ meta_monitor_manager_get_resources (assignment->manager,
+ &modes, &n_modes,
+ &crtcs, &n_crtcs,
+ &outputs, &n_outputs);
+
+ success = FALSE;
+
+ for (i = 0; i < n_crtcs; i++)
+ {
+ MetaCRTC *crtc = &crtcs[i];
+ unsigned int pass;
+
+ /* Make two passes, one where frequencies must match, then
+ * one where they don't have to
+ */
+ for (pass = 0; pass < 2; pass++)
+ {
+ MetaOutput *output = find_output_by_key (outputs, n_outputs, output_key);
+ unsigned int j;
+
+ for (j = 0; j < n_modes; j++)
+ {
+ MetaMonitorMode *mode = &modes[j];
+ int width, height;
+
+ if (meta_monitor_transform_is_rotated (output_config->transform))
+ {
+ width = mode->height;
+ height = mode->width;
+ }
+ else
+ {
+ width = mode->width;
+ height = mode->height;
+ }
+
+ if (width == output_config->rect.width &&
+ height == output_config->rect.height &&
+ (pass == 1 || mode->refresh_rate == output_config->refresh_rate))
+ {
+ meta_verbose ("CRTC %ld: trying mode %dx%d@%fHz with output at %dx%d@%fHz (transform %d) (pass %d)\n",
+ crtc->crtc_id,
+ mode->width, mode->height, mode->refresh_rate,
+ output_config->rect.width, output_config->rect.height, output_config->refresh_rate,
+ output_config->transform,
+ pass);
+
+
+ if (crtc_assignment_assign (assignment, crtc, &modes[j],
+ output_config->rect.x, output_config->rect.y,
+ output_config->transform,
+ output))
+ {
+ if (real_assign_crtcs (assignment, output_num + 1))
+ {
+ success = TRUE;
+ goto out;
+ }
+
+ crtc_assignment_unassign (assignment, crtc, output);
+ }
+ }
+ }
+ }
+ }
+
+out:
+ if (!success)
+ meta_warning ("Could not assign CRTC to outputs, ignoring configuration\n");
+
+ return success;
+}
+
+static gboolean
+meta_monitor_config_assign_crtcs (MetaConfiguration *config,
+ MetaMonitorManager *manager,
+ GPtrArray *crtcs,
+ GPtrArray *outputs)
+{
+ CrtcAssignment assignment;
+ GHashTableIter iter;
+ MetaCRTC *crtc;
+ MetaCRTCInfo *info;
+ unsigned int i;
+ MetaOutput *all_outputs;
+ unsigned int n_outputs;
+
+ assignment.config = config;
+ assignment.manager = manager;
+ assignment.info = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)meta_crtc_info_free);
+
+ if (!real_assign_crtcs (&assignment, 0))
+ {
+ g_hash_table_destroy (assignment.info);
+ return FALSE;
+ }
+
+ g_hash_table_iter_init (&iter, assignment.info);
+ while (g_hash_table_iter_next (&iter, (void**)&crtc, (void**)&info))
+ {
+ g_hash_table_iter_steal (&iter);
+ g_ptr_array_add (crtcs, info);
+ }
+
+ all_outputs = meta_monitor_manager_get_outputs (manager,
+ &n_outputs);
+ g_assert (n_outputs == config->n_outputs);
+
+ for (i = 0; i < n_outputs; i++)
+ {
+ MetaOutputInfo *output_info = g_slice_new (MetaOutputInfo);
+ MetaOutputConfig *output_config = &config->outputs[0];
+
+ output_info->output = find_output_by_key (all_outputs, n_outputs,
+ &config->keys[0]);
+ output_info->is_primary = output_config->is_primary;
+ output_info->is_presentation = output_config->is_presentation;
+
+ g_ptr_array_add (outputs, output_info);
+ }
+
+ g_hash_table_destroy (assignment.info);
+ return TRUE;
+}
+
+void
+meta_crtc_info_free (MetaCRTCInfo *info)
+{
+ g_ptr_array_free (info->outputs, TRUE);
+ g_slice_free (MetaCRTCInfo, info);
+}
+
+void
+meta_output_info_free (MetaOutputInfo *info)
+{
+ g_slice_free (MetaOutputInfo, info);
+}
diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h
index 1576182f3..efbafd726 100644
--- a/src/core/monitor-private.h
+++ b/src/core/monitor-private.h
@@ -65,6 +65,8 @@ typedef struct _MetaOutput MetaOutput;
typedef struct _MetaCRTC MetaCRTC;
typedef struct _MetaMonitorMode MetaMonitorMode;
typedef struct _MetaMonitorInfo MetaMonitorInfo;
+typedef struct _MetaCRTCInfo MetaCRTCInfo;
+typedef struct _MetaOutputInfo MetaOutputInfo;
struct _MetaOutput
{
@@ -161,6 +163,33 @@ struct _MetaMonitorInfo
glong output_id;
};
+/*
+ * MetaCRTCInfo:
+ * This represents the writable part of a CRTC, as deserialized from DBus
+ * or built by MetaMonitorConfig
+ *
+ * Note: differently from the other structures in this file, MetaCRTCInfo
+ * is handled by pointer. This is to accomodate the usage in MetaMonitorConfig
+ */
+struct _MetaCRTCInfo {
+ MetaCRTC *crtc;
+ MetaMonitorMode *mode;
+ int x;
+ int y;
+ enum wl_output_transform transform;
+ GPtrArray *outputs;
+};
+
+/*
+ * MetaOutputInfo:
+ * this is the same as MetaOutputInfo, but for CRTCs
+ */
+struct _MetaOutputInfo {
+ MetaOutput *output;
+ gboolean is_primary;
+ gboolean is_presentation;
+};
+
#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ())
#define META_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManager))
#define META_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
@@ -182,6 +211,14 @@ MetaMonitorInfo *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *
MetaOutput *meta_monitor_manager_get_outputs (MetaMonitorManager *manager,
unsigned int *n_outputs);
+void meta_monitor_manager_get_resources (MetaMonitorManager *manager,
+ MetaMonitorMode **modes,
+ unsigned int *n_modes,
+ MetaCRTC **crtcs,
+ unsigned int *n_crtcs,
+ MetaOutput **outputs,
+ unsigned int *n_outputs);
+
int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
gboolean meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
@@ -191,9 +228,11 @@ void meta_monitor_manager_get_screen_size (MetaMonitorManager *
int *width,
int *height);
-void meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
- GVariant *crtcs,
- GVariant *outputs);
+void meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
+ MetaCRTCInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs);
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
@@ -222,6 +261,9 @@ void meta_monitor_config_update_current (MetaMonitorConfig *confi
MetaMonitorManager *manager);
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
+void meta_crtc_info_free (MetaCRTCInfo *info);
+void meta_output_info_free (MetaOutputInfo *info);
+
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */
static inline gboolean
diff --git a/src/core/monitor.c b/src/core/monitor.c
index 867a1e81e..3c34b916a 100644
--- a/src/core/monitor.c
+++ b/src/core/monitor.c
@@ -1160,22 +1160,20 @@ wl_transform_to_xrandr (enum wl_output_transform transform)
static void
apply_config_xrandr (MetaMonitorManager *manager,
- GVariantIter *crtcs,
- GVariantIter *outputs)
+ MetaCRTCInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
{
- GVariant *nested_outputs, *properties;
- guint crtc_id, output_id, transform;
- int new_mode, x, y;
unsigned i;
- while (g_variant_iter_loop (crtcs, "(uiiiu@aua{sv})",
- &crtc_id, &new_mode, &x, &y,
- &transform, &nested_outputs, NULL))
+ for (i = 0; i < n_crtcs; i++)
{
- MetaCRTC *crtc = &manager->crtcs[crtc_id];
+ MetaCRTCInfo *crtc_info = crtcs[i];
+ MetaCRTC *crtc = crtc_info->crtc;
crtc->is_dirty = TRUE;
- if (new_mode == -1)
+ if (crtc_info->mode == NULL)
{
XRRSetCrtcConfig (manager->xdisplay,
manager->resources,
@@ -1190,54 +1188,47 @@ apply_config_xrandr (MetaMonitorManager *manager,
{
MetaMonitorMode *mode;
XID *outputs;
- int i, n_outputs;
- guint output_id;
+ int j, n_outputs;
Status ok;
- mode = &manager->modes[new_mode];
+ mode = crtc_info->mode;
- n_outputs = g_variant_n_children (nested_outputs);
+ n_outputs = crtc_info->outputs->len;
outputs = g_new (XID, n_outputs);
- for (i = 0; i < n_outputs; i++)
- {
- g_variant_get_child (nested_outputs, i, "u", &output_id);
-
- outputs[i] = manager->outputs[output_id].output_id;
- }
+ for (j = 0; j < n_outputs; j++)
+ outputs[i] = ((MetaOutput**)crtc_info->outputs->pdata)[i]->output_id;
meta_error_trap_push (meta_get_display ());
ok = XRRSetCrtcConfig (manager->xdisplay,
manager->resources,
(XID)crtc->crtc_id,
manager->time,
- x, y,
+ crtc_info->x, crtc_info->y,
(XID)mode->mode_id,
- wl_transform_to_xrandr (transform),
+ wl_transform_to_xrandr (crtc_info->transform),
outputs, n_outputs);
meta_error_trap_pop (meta_get_display ());
if (ok != Success)
meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom %u failed\n",
(unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id),
- mode->width, mode->height, (float)mode->refresh_rate, x, y, transform);
+ mode->width, mode->height, (float)mode->refresh_rate,
+ crtc_info->x, crtc_info->y, crtc_info->transform);
g_free (outputs);
}
}
- while (g_variant_iter_loop (outputs, "(u@a{sv})",
- &output_id, &properties))
+ for (i = 0; i < n_outputs; i++)
{
- gboolean primary;
+ MetaOutputInfo *output_info = outputs[i];
- if (g_variant_lookup (properties, "primary", "b", &primary) && primary)
+ if (output_info->is_primary)
{
- MetaOutput *output = &manager->outputs[output_id];
-
XRRSetOutputPrimary (manager->xdisplay,
DefaultRootWindow (manager->xdisplay),
- (XID)output->output_id);
+ (XID)output_info->output->output_id);
}
}
@@ -1268,23 +1259,21 @@ apply_config_xrandr (MetaMonitorManager *manager,
static void
apply_config_dummy (MetaMonitorManager *manager,
- GVariantIter *crtcs,
- GVariantIter *outputs)
+ MetaCRTCInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
{
- GVariant *nested_outputs, *properties;
- guint crtc_id, output_id, transform;
- int new_mode, x, y;
unsigned i;
int screen_width = 0, screen_height = 0;
- while (g_variant_iter_loop (crtcs, "(uiiiu@aua{sv})",
- &crtc_id, &new_mode, &x, &y,
- &transform, &nested_outputs, NULL))
+ for (i = 0; i < n_crtcs; i++)
{
- MetaCRTC *crtc = &manager->crtcs[crtc_id];
+ MetaCRTCInfo *crtc_info = crtcs[i];
+ MetaCRTC *crtc = crtc_info->crtc;
crtc->is_dirty = TRUE;
- if (new_mode == -1)
+ if (crtc_info->mode == NULL)
{
crtc->rect.x = 0;
crtc->rect.y = 0;
@@ -1297,12 +1286,11 @@ apply_config_dummy (MetaMonitorManager *manager,
MetaMonitorMode *mode;
MetaOutput *output;
int i, n_outputs;
- guint output_id;
int width, height;
- mode = &manager->modes[new_mode];
+ mode = crtc_info->mode;
- if (meta_monitor_transform_is_rotated (transform))
+ if (meta_monitor_transform_is_rotated (crtc_info->transform))
{
width = mode->height;
height = mode->width;
@@ -1313,22 +1301,20 @@ apply_config_dummy (MetaMonitorManager *manager,
height = mode->height;
}
- crtc->rect.x = x;
- crtc->rect.y = y;
+ crtc->rect.x = crtc_info->x;
+ crtc->rect.y = crtc_info->y;
crtc->rect.width = width;
crtc->rect.height = height;
crtc->current_mode = mode;
- crtc->transform = transform;
+ crtc->transform = crtc_info->transform;
- screen_width = MAX (screen_width, x + width);
- screen_height = MAX (screen_height, y + height);
+ screen_width = MAX (screen_width, crtc_info->x + width);
+ screen_height = MAX (screen_height, crtc_info->y + height);
- n_outputs = g_variant_n_children (nested_outputs);
+ n_outputs = crtc_info->outputs->len;
for (i = 0; i < n_outputs; i++)
{
- g_variant_get_child (nested_outputs, i, "u", &output_id);
-
- output = &manager->outputs[output_id];
+ output = ((MetaOutput**)crtc_info->outputs->pdata)[i];
output->is_dirty = TRUE;
output->crtc = crtc;
@@ -1336,17 +1322,13 @@ apply_config_dummy (MetaMonitorManager *manager,
}
}
- while (g_variant_iter_loop (outputs, "(u@a{sv})",
- &output_id, &properties))
+ for (i = 0; i < n_outputs; i++)
{
- MetaOutput *output = &manager->outputs[output_id];
- gboolean primary, presentation;
-
- if (g_variant_lookup (properties, "primary", "b", &primary))
- output->is_primary = primary;
+ MetaOutputInfo *output_info = outputs[i];
+ MetaOutput *output = output_info->output;
- if (g_variant_lookup (properties, "presentation", "b", &presentation))
- output->is_presentation = presentation;
+ output->is_primary = output_info->is_primary;
+ output->is_presentation = output_info->is_presentation;
}
/* Disable CRTCs not mentioned in the list */
@@ -1392,18 +1374,15 @@ apply_config_dummy (MetaMonitorManager *manager,
void
meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
- GVariant *crtcs,
- GVariant *outputs)
+ MetaCRTCInfo **crtcs,
+ unsigned int n_crtcs,
+ MetaOutputInfo **outputs,
+ unsigned int n_outputs)
{
- GVariantIter crtc_iter, output_iter;
-
- g_variant_iter_init (&crtc_iter, crtcs);
- g_variant_iter_init (&output_iter, outputs);
-
if (manager->backend == META_BACKEND_XRANDR)
- apply_config_xrandr (manager, &crtc_iter, &output_iter);
+ apply_config_xrandr (manager, crtcs, n_crtcs, outputs, n_outputs);
else
- apply_config_dummy (manager, &crtc_iter, &output_iter);
+ apply_config_dummy (manager, crtcs, n_crtcs, outputs, n_outputs);
}
static gboolean
@@ -1426,10 +1405,12 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
GVariantIter crtc_iter, output_iter, *nested_outputs;
+ GVariant *properties;
guint crtc_id;
int new_mode, x, y;
guint transform;
guint output_id;
+ GPtrArray *crtc_infos, *output_infos;
if (serial != manager->serial)
{
@@ -1439,17 +1420,26 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
return TRUE;
}
+ crtc_infos = g_ptr_array_new_full (g_variant_n_children (crtcs),
+ (GDestroyNotify) meta_crtc_info_free);
+ output_infos = g_ptr_array_new_full (g_variant_n_children (outputs),
+ (GDestroyNotify) meta_output_info_free);
+
/* Validate all arguments */
g_variant_iter_init (&crtc_iter, crtcs);
while (g_variant_iter_loop (&crtc_iter, "(uiiiuaua{sv})",
&crtc_id, &new_mode, &x, &y, &transform,
&nested_outputs, NULL))
{
+ MetaCRTCInfo *crtc_info;
MetaOutput *first_output;
MetaCRTC *crtc;
MetaMonitorMode *mode;
guint output_id;
+ crtc_info = g_slice_new (MetaCRTCInfo);
+ crtc_info->outputs = g_ptr_array_new ();
+
if (crtc_id >= manager->n_crtcs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@@ -1458,6 +1448,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
return TRUE;
}
crtc = &manager->crtcs[crtc_id];
+ crtc_info->crtc = crtc;
if (new_mode != -1 && (new_mode < 0 || (unsigned)new_mode >= manager->n_modes))
{
@@ -1467,6 +1458,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
return TRUE;
}
mode = new_mode != -1 ? &manager->modes[new_mode] : NULL;
+ crtc_info->mode = mode;
if (mode)
{
@@ -1494,6 +1486,8 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
return TRUE;
}
}
+ crtc_info->x = x;
+ crtc_info->y = y;
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270 ||
@@ -1504,6 +1498,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
"Invalid transform");
return TRUE;
}
+ crtc_info->transform = transform;
first_output = NULL;
while (g_variant_iter_loop (nested_outputs, "u", &output_id))
@@ -1526,6 +1521,7 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
"Output cannot be assigned to this CRTC or mode");
return TRUE;
}
+ g_ptr_array_add (crtc_info->outputs, output);
if (first_output)
{
@@ -1551,8 +1547,11 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
}
g_variant_iter_init (&output_iter, outputs);
- while (g_variant_iter_loop (&output_iter, "(ua{sv})", &output_id, NULL))
+ while (g_variant_iter_loop (&output_iter, "(u@a{sv})", &output_id, &properties))
{
+ MetaOutputInfo *output_info;
+ gboolean primary, presentation;
+
if (output_id >= manager->n_outputs)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@@ -1560,6 +1559,15 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
"Invalid output id");
return TRUE;
}
+
+ output_info = g_slice_new0 (MetaOutputInfo);
+ output_info->output = &manager->outputs[output_id];
+
+ if (g_variant_lookup (properties, "primary", "b", &primary))
+ output_info->is_primary = primary;
+
+ if (g_variant_lookup (properties, "presentation", "b", &presentation))
+ output_info->is_presentation = presentation;
}
/* If we were in progress of making a persistent change and we see a
@@ -1572,7 +1580,14 @@ meta_monitor_manager_handle_apply_configuration (MetaDBusDisplayConfig *skeleto
manager->persistent_timeout_id = 0;
}
- meta_monitor_manager_apply_configuration (manager, crtcs, outputs);
+ meta_monitor_manager_apply_configuration (manager,
+ (MetaCRTCInfo**)crtc_infos->pdata,
+ crtc_infos->len,
+ (MetaOutputInfo**)output_infos->pdata,
+ output_infos->len);
+
+ g_ptr_array_unref (crtc_infos);
+ g_ptr_array_unref (output_infos);
/* Update MetaMonitorConfig data structures immediately so that we
don't revert the change at the next XRandR event, then wait 20
@@ -1671,6 +1686,23 @@ meta_monitor_manager_get_outputs (MetaMonitorManager *manager,
return manager->outputs;
}
+void
+meta_monitor_manager_get_resources (MetaMonitorManager *manager,
+ MetaMonitorMode **modes,
+ unsigned int *n_modes,
+ MetaCRTC **crtcs,
+ unsigned int *n_crtcs,
+ MetaOutput **outputs,
+ unsigned int *n_outputs)
+{
+ *modes = manager->modes;
+ *n_modes = manager->n_modes;
+ *crtcs = manager->crtcs;
+ *n_crtcs = manager->n_crtcs;
+ *outputs = manager->outputs;
+ *n_outputs = manager->n_outputs;
+}
+
int
meta_monitor_manager_get_primary_index (MetaMonitorManager *manager)
{