Introduce new monitor configuration system

The new monitor configuration system (MetaMonitorConfigManager) aims to
replace the current MetaMonitorConfig. The main difference between the
two is that MetaMonitorConfigManager works with higher level input
(MetaMonitor, MetaMonitorMode) instead of directly looking at the CRTC
and connector state. It still produces CRTC and connector configuration
later applied by the respective backends.

Other difference the new system aims to introduce is that the
configuration system doesn't manipulate the monitor manager state; that
responsibility is left for the monitor manager to handle (it only
manages configuration and creates CRTC/connector assignments, it
doesn't apply anything).

The new configuration system allows backends to not rely on deriving the
current configuration from the CRTC/connector state, as this may no longer be
possible (i.e. when using KMS and multiple framebuffers).

The MetaMonitorConfigManager system is so far disabled by default, as
it does not yet have all the features of the old system, but eventually
it will replace MetaMonitorConfig which will at that point be removed.
This will make it possible to remove old hacks introduced due to
limitations in the old system.

https://bugzilla.gnome.org/show_bug.cgi?id=777732
This commit is contained in:
Jonas Ådahl 2017-01-09 14:31:18 +08:00
parent ee0677a021
commit 644ee666f6
11 changed files with 1166 additions and 64 deletions

View File

@ -105,6 +105,8 @@ libmutter_la_SOURCES = \
backends/meta-logical-monitor.h \
backends/meta-monitor-config.c \
backends/meta-monitor-config.h \
backends/meta-monitor-config-manager.c \
backends/meta-monitor-config-manager.h \
backends/meta-monitor.c \
backends/meta-monitor.h \
backends/meta-monitor-private.h \

View File

@ -0,0 +1,525 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2016 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
#include "backends/meta-monitor-config-manager.h"
#include "backends/meta-monitor-manager-private.h"
struct _MetaMonitorConfigManager
{
GObject parent;
MetaMonitorManager *monitor_manager;
MetaMonitorsConfig *current_config;
};
G_DEFINE_TYPE (MetaMonitorConfigManager, meta_monitor_config_manager,
G_TYPE_OBJECT)
G_DEFINE_TYPE (MetaMonitorsConfig, meta_monitors_config,
G_TYPE_OBJECT)
MetaMonitorConfigManager *
meta_monitor_config_manager_new (MetaMonitorManager *monitor_manager)
{
MetaMonitorConfigManager *config_manager;
config_manager = g_object_new (META_TYPE_MONITOR_CONFIG_MANAGER, NULL);
config_manager->monitor_manager = monitor_manager;
return config_manager;
}
static gboolean
is_crtc_assigned (MetaCrtc *crtc,
GPtrArray *crtc_infos)
{
unsigned int i;
for (i = 0; i < crtc_infos->len; i++)
{
MetaCrtcInfo *assigned_crtc_info = g_ptr_array_index (crtc_infos, i);
if (assigned_crtc_info->crtc == crtc)
return TRUE;
}
return FALSE;
}
static MetaCrtc *
find_unassigned_crtc (MetaOutput *output,
GPtrArray *crtc_infos)
{
unsigned int i;
for (i = 0; i < output->n_possible_crtcs; i++)
{
MetaCrtc *crtc = output->possible_crtcs[i];
if (is_crtc_assigned (crtc, crtc_infos))
continue;
return crtc;
}
return NULL;
}
typedef struct
{
MetaLogicalMonitorConfig *logical_monitor_config;
MetaMonitorConfig *monitor_config;
GPtrArray *crtc_infos;
GPtrArray *output_infos;
} MonitorAssignmentData;
static gboolean
assign_monitor_crtc (MetaMonitor *monitor,
MetaMonitorMode *mode,
MetaMonitorCrtcMode *monitor_crtc_mode,
gpointer user_data,
GError **error)
{
MonitorAssignmentData *data = user_data;
MetaOutput *output;
MetaCrtc *crtc;
MetaCrtcInfo *crtc_info;
MetaOutputInfo *output_info;
MetaMonitorConfig *first_monitor_config;
gboolean assign_output_as_primary;
gboolean assign_output_as_presentation;
output = monitor_crtc_mode->output;
crtc = find_unassigned_crtc (output, data->crtc_infos);
if (!crtc)
{
MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"No available CRTC for monitor '%s %s' not found",
monitor_spec->vendor, monitor_spec->product);
return FALSE;
}
crtc_info = g_slice_new0 (MetaCrtcInfo);
*crtc_info = (MetaCrtcInfo) {
.crtc = crtc,
.mode = monitor_crtc_mode->crtc_mode,
.x = monitor_crtc_mode->x,
.y = monitor_crtc_mode->y,
.transform = META_MONITOR_TRANSFORM_NORMAL,
.outputs = g_ptr_array_new ()
};
g_ptr_array_add (crtc_info->outputs, output);
/*
* Currently, MetaCrtcInfo are deliberately offset incorrectly to carry over
* logical monitor location inside the MetaCrtc struct, when in fact this
* depends on the framebuffer configuration. This will eventually be negated
* when setting the actual KMS mode.
*
* TODO: Remove this hack when we don't need to rely on MetaCrtc to pass
* logical monitor state.
*/
crtc_info->x += data->logical_monitor_config->layout.x;
crtc_info->y += data->logical_monitor_config->layout.y;
/*
* Only one output can be marked as primary (due to Xrandr limitation),
* so only mark the main output of the first monitor in the logical monitor
* as such.
*/
first_monitor_config = data->logical_monitor_config->monitor_configs->data;
if (data->monitor_config == first_monitor_config &&
meta_monitor_get_main_output (monitor) == output)
assign_output_as_primary = TRUE;
else
assign_output_as_primary = FALSE;
if (data->logical_monitor_config->is_presentation)
assign_output_as_presentation = TRUE;
else
assign_output_as_presentation = FALSE;
output_info = g_slice_new0 (MetaOutputInfo);
*output_info = (MetaOutputInfo) {
.output = output,
.is_primary = assign_output_as_primary,
.is_presentation = assign_output_as_presentation,
.is_underscanning = output->is_underscanning
};
g_ptr_array_add (data->crtc_infos, crtc_info);
g_ptr_array_add (data->output_infos, output_info);
return TRUE;
}
static gboolean
assign_monitor_crtcs (MetaMonitorManager *manager,
MetaLogicalMonitorConfig *logical_monitor_config,
MetaMonitorConfig *monitor_config,
GPtrArray *crtc_infos,
GPtrArray *output_infos,
GError **error)
{
MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec;
MetaMonitorModeSpec *monitor_mode_spec = monitor_config->mode_spec;
MetaMonitor *monitor;
MetaMonitorMode *monitor_mode;
MonitorAssignmentData data;
monitor = meta_monitor_manager_get_monitor_from_spec (manager, monitor_spec);
if (!monitor)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Configured monitor '%s %s' not found",
monitor_spec->vendor, monitor_spec->product);
return FALSE;
}
monitor_mode = meta_monitor_get_mode_from_spec (monitor, monitor_mode_spec);
if (!monitor_mode)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid mode %dx%d (%f) for monitor '%s %s'",
monitor_mode_spec->width, monitor_mode_spec->height,
monitor_mode_spec->refresh_rate,
monitor_spec->vendor, monitor_spec->product);
return FALSE;
}
data = (MonitorAssignmentData) {
.logical_monitor_config = logical_monitor_config,
.monitor_config = monitor_config,
.crtc_infos = crtc_infos,
.output_infos = output_infos
};
if (!meta_monitor_mode_foreach_crtc (monitor, monitor_mode,
assign_monitor_crtc,
&data,
error))
return FALSE;
return TRUE;
}
static gboolean
assign_logical_monitor_crtcs (MetaMonitorManager *manager,
MetaLogicalMonitorConfig *logical_monitor_config,
GPtrArray *crtc_infos,
GPtrArray *output_infos,
GError **error)
{
GList *l;
for (l = logical_monitor_config->monitor_configs; l; l = l->next)
{
MetaMonitorConfig *monitor_config = l->data;
if (!assign_monitor_crtcs (manager,
logical_monitor_config,
monitor_config,
crtc_infos, output_infos,
error))
return FALSE;
}
return TRUE;
}
gboolean
meta_monitor_config_manager_assign (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
GPtrArray **out_crtc_infos,
GPtrArray **out_output_infos,
GError **error)
{
GPtrArray *crtc_infos;
GPtrArray *output_infos;
GList *l;
crtc_infos =
g_ptr_array_new_with_free_func ((GDestroyNotify) meta_crtc_info_free);
output_infos =
g_ptr_array_new_with_free_func ((GDestroyNotify) meta_output_info_free);
for (l = config->logical_monitor_configs; l; l = l->next)
{
MetaLogicalMonitorConfig *logical_monitor_config = l->data;
if (!assign_logical_monitor_crtcs (manager, logical_monitor_config,
crtc_infos, output_infos,
error))
{
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
return FALSE;
}
}
*out_crtc_infos = crtc_infos;
*out_output_infos = output_infos;
return TRUE;
}
static MetaMonitor *
find_monitor_with_highest_preferred_resolution (MetaMonitorManager *monitor_manager)
{
GList *monitors;
GList *l;
int largest_area = 0;
MetaMonitor *largest_monitor = NULL;
monitors = meta_monitor_manager_get_monitors (monitor_manager);
for (l = monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
MetaMonitorMode *mode;
int width, height;
int area;
mode = meta_monitor_get_preferred_mode (monitor);
meta_monitor_mode_get_resolution (mode, &width, &height);
area = width * height;
if (area > largest_area)
{
largest_area = area;
largest_monitor = monitor;
}
}
return largest_monitor;
}
/*
* Tries to find the primary monitor as reported by the underlying system;
* or failing that, a monitor looks to be the laptop panel; or failing that, the
* monitor with the highest preferred resolution.
*/
static MetaMonitor *
find_primary_monitor (MetaMonitorManager *monitor_manager)
{
MetaMonitor *monitor;
monitor = meta_monitor_manager_get_primary_monitor (monitor_manager);
if (monitor)
return monitor;
monitor = meta_monitor_manager_get_laptop_panel (monitor_manager);
if (monitor)
return monitor;
return find_monitor_with_highest_preferred_resolution (monitor_manager);
}
static MetaMonitorConfig *
create_monitor_config (MetaMonitor *monitor,
MetaMonitorMode *mode)
{
MetaMonitorSpec *monitor_spec;
MetaMonitorModeSpec *mode_spec;
MetaMonitorConfig *monitor_config;
monitor_spec = meta_monitor_get_spec (monitor);
mode_spec = meta_monitor_mode_get_spec (mode);
monitor_config = g_new0 (MetaMonitorConfig, 1);
*monitor_config = (MetaMonitorConfig) {
.monitor_spec = meta_monitor_spec_clone (monitor_spec),
.mode_spec = g_memdup (mode_spec, sizeof (MetaMonitorModeSpec))
};
return monitor_config;
}
static MetaLogicalMonitorConfig *
create_preferred_logical_monitor_config (MetaMonitor *monitor,
int x,
int y)
{
MetaMonitorMode *mode;
int width, height;
MetaMonitorConfig *monitor_config;
MetaLogicalMonitorConfig *logical_monitor_config;
mode = meta_monitor_get_preferred_mode (monitor);
meta_monitor_mode_get_resolution (mode, &width, &height);
monitor_config = create_monitor_config (monitor, mode);
logical_monitor_config = g_new0 (MetaLogicalMonitorConfig, 1);
*logical_monitor_config = (MetaLogicalMonitorConfig) {
.layout = (MetaRectangle) {
.x = x,
.y = y,
.width = width,
.height = height
},
.monitor_configs = g_list_append (NULL, monitor_config)
};
return logical_monitor_config;
}
MetaMonitorsConfig *
meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager)
{
MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
MetaMonitor *primary_monitor;
MetaMonitorsConfig *config;
MetaLogicalMonitorConfig *primary_logical_monitor_config;
int x;
GList *monitors;
GList *l;
primary_monitor = find_primary_monitor (monitor_manager);
config = g_object_new (META_TYPE_MONITORS_CONFIG, NULL);
primary_logical_monitor_config =
create_preferred_logical_monitor_config (primary_monitor, 0, 0);
primary_logical_monitor_config->is_primary = TRUE;
config->logical_monitor_configs =
g_list_append (NULL, primary_logical_monitor_config);
x = primary_logical_monitor_config->layout.width;
monitors = meta_monitor_manager_get_monitors (monitor_manager);
for (l = monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
MetaLogicalMonitorConfig *logical_monitor_config;
if (monitor == primary_monitor)
continue;
logical_monitor_config =
create_preferred_logical_monitor_config (monitor, x, 0);
config->logical_monitor_configs =
g_list_append (config->logical_monitor_configs, logical_monitor_config);
x += logical_monitor_config->layout.width;
}
return config;
}
MetaMonitorsConfig *
meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_manager)
{
MetaMonitorManager *monitor_manager = config_manager->monitor_manager;
MetaMonitor *primary_monitor;
MetaMonitorsConfig *config;
MetaLogicalMonitorConfig *primary_logical_monitor_config;
primary_monitor = find_primary_monitor (monitor_manager);
config = g_object_new (META_TYPE_MONITORS_CONFIG, NULL);
primary_logical_monitor_config =
create_preferred_logical_monitor_config (primary_monitor, 0, 0);
primary_logical_monitor_config->is_primary = TRUE;
config->logical_monitor_configs =
g_list_append (NULL, primary_logical_monitor_config);
return config;
}
void
meta_monitor_config_manager_set_current (MetaMonitorConfigManager *config_manager,
MetaMonitorsConfig *config)
{
g_set_object (&config_manager->current_config, config);
}
MetaMonitorsConfig *
meta_monitor_config_manager_get_current (MetaMonitorConfigManager *config_manager)
{
return config_manager->current_config;
}
static void
meta_monitor_config_manager_dispose (GObject *object)
{
MetaMonitorConfigManager *config_manager =
META_MONITOR_CONFIG_MANAGER (object);
g_clear_object (&config_manager->current_config);
G_OBJECT_CLASS (meta_monitor_config_manager_parent_class)->dispose (object);
}
static void
meta_monitor_config_manager_init (MetaMonitorConfigManager *config_manager)
{
}
static void
meta_monitor_config_manager_class_init (MetaMonitorConfigManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_monitor_config_manager_dispose;
}
static void
meta_monitor_config_free (MetaMonitorConfig *monitor_config)
{
meta_monitor_spec_free (monitor_config->monitor_spec);
g_free (monitor_config->mode_spec);
g_free (monitor_config);
}
static void
meta_logical_monitor_config_free (MetaLogicalMonitorConfig *logical_monitor_config)
{
g_list_free_full (logical_monitor_config->monitor_configs,
(GDestroyNotify) meta_monitor_config_free);
g_free (logical_monitor_config);
}
static void
meta_monitors_config_finalize (GObject *object)
{
MetaMonitorsConfig *config = META_MONITORS_CONFIG (object);
g_list_free_full (config->logical_monitor_configs,
(GDestroyNotify) meta_logical_monitor_config_free);
}
static void
meta_monitors_config_init (MetaMonitorsConfig *config)
{
}
static void
meta_monitors_config_class_init (MetaMonitorsConfigClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_monitors_config_finalize;
}

View File

@ -0,0 +1,74 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2016 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_MONITOR_CONFIG_MANAGER_H
#define META_MONITOR_CONFIG_MANAGER_H
#include "backends/meta-monitor.h"
#include "backends/meta-monitor-manager-private.h"
#define META_TYPE_MONITOR_CONFIG_MANAGER (meta_monitor_config_manager_get_type ())
G_DECLARE_FINAL_TYPE (MetaMonitorConfigManager, meta_monitor_config_manager,
META, MONITOR_CONFIG_MANAGER, GObject)
typedef struct _MetaMonitorConfig
{
MetaMonitorSpec *monitor_spec;
MetaMonitorModeSpec *mode_spec;
} MetaMonitorConfig;
typedef struct _MetaLogicalMonitorConfig
{
MetaRectangle layout;
GList *monitor_configs;
gboolean is_primary;
gboolean is_presentation;
} MetaLogicalMonitorConfig;
struct _MetaMonitorsConfig
{
GObject parent;
GList *logical_monitor_configs;
};
#define META_TYPE_MONITORS_CONFIG (meta_monitors_config_get_type ())
G_DECLARE_FINAL_TYPE (MetaMonitorsConfig, meta_monitors_config,
META, MONITORS_CONFIG, GObject)
MetaMonitorConfigManager * meta_monitor_config_manager_new (MetaMonitorManager *monitor_manager);
gboolean meta_monitor_config_manager_assign (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
GPtrArray **crtc_infos,
GPtrArray **output_infos,
GError **error);
MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager);
MetaMonitorsConfig * meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_manager);
void meta_monitor_config_manager_set_current (MetaMonitorConfigManager *config_manager,
MetaMonitorsConfig *config);
MetaMonitorsConfig * meta_monitor_config_manager_get_current (MetaMonitorConfigManager *config_manager);
#endif /* META_MONITOR_CONFIG_MANAGER_H */

View File

@ -30,6 +30,7 @@
#include <stdlib.h>
#include <meta/util.h>
#include "backends/meta-monitor-config-manager.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
@ -172,13 +173,18 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
static void
meta_monitor_manager_dummy_ensure_initial_config (MetaMonitorManager *manager)
{
meta_monitor_manager_ensure_configured (manager);
MetaMonitorsConfig *config;
config = meta_monitor_manager_ensure_configured (manager);
if (manager->config_manager)
meta_monitor_manager_update_logical_state (manager, config);
else
meta_monitor_manager_update_logical_state_derived (manager);
}
static void
meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
apply_crtc_assignments (MetaMonitorManager *manager,
MetaCrtcInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
@ -287,6 +293,43 @@ meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
manager->screen_width = screen_width;
manager->screen_height = screen_height;
}
static gboolean
meta_monitor_manager_dummy_apply_monitors_config (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
GError **error)
{
GPtrArray *crtc_infos;
GPtrArray *output_infos;
if (!meta_monitor_config_manager_assign (manager, config,
&crtc_infos, &output_infos,
error))
return FALSE;
apply_crtc_assignments (manager,
(MetaCrtcInfo **) crtc_infos->pdata,
crtc_infos->len,
(MetaOutputInfo **) output_infos->pdata,
output_infos->len);
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
meta_monitor_manager_rebuild (manager, config);
return TRUE;
}
static void
meta_monitor_manager_dummy_apply_config (MetaMonitorManager *manager,
MetaCrtcInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
meta_monitor_manager_rebuild_derived (manager);
}
@ -298,6 +341,7 @@ meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass)
manager_class->read_current = meta_monitor_manager_dummy_read_current;
manager_class->ensure_initial_config = meta_monitor_manager_dummy_ensure_initial_config;
manager_class->apply_monitors_config = meta_monitor_manager_dummy_apply_monitors_config;
manager_class->apply_configuration = meta_monitor_manager_dummy_apply_config;
}

View File

@ -48,6 +48,8 @@
#include "meta-cursor.h"
typedef struct _MetaMonitorConfig MetaMonitorConfig;
typedef struct _MetaMonitorConfigManager MetaMonitorConfigManager;
typedef struct _MetaMonitorsConfig MetaMonitorsConfig;
typedef struct _MetaMonitor MetaMonitor;
typedef struct _MetaMonitorNormal MetaMonitorNormal;
@ -284,6 +286,8 @@ struct _MetaMonitorManager
int persistent_timeout_id;
MetaMonitorConfig *legacy_config;
MetaMonitorConfigManager *config_manager;
GnomePnpIds *pnp_ids;
};
@ -300,6 +304,10 @@ struct _MetaMonitorManagerClass
void (*ensure_initial_config) (MetaMonitorManager *);
gboolean (*apply_monitors_config) (MetaMonitorManager *,
MetaMonitorsConfig *,
GError **);
void (*apply_configuration) (MetaMonitorManager *,
MetaCrtcInfo **,
unsigned int ,
@ -334,6 +342,8 @@ struct _MetaMonitorManagerClass
};
void meta_monitor_manager_rebuild (MetaMonitorManager *manager,
MetaMonitorsConfig *config);
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
int meta_monitor_manager_get_num_logical_monitors (MetaMonitorManager *manager);
@ -413,8 +423,10 @@ void meta_monitor_manager_tiled_monitor_added (MetaMonitorManager
void meta_monitor_manager_tiled_monitor_removed (MetaMonitorManager *manager,
MetaMonitor *monitor);
void meta_monitor_manager_ensure_configured (MetaMonitorManager *manager);
MetaMonitorsConfig * meta_monitor_manager_ensure_configured (MetaMonitorManager *manager);
void meta_monitor_manager_update_logical_state (MetaMonitorManager *manager,
MetaMonitorsConfig *config);
void meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager);
void meta_monitor_manager_clear_output (MetaOutput *output);

View File

@ -39,6 +39,7 @@
#include "meta-monitor-config.h"
#include "backends/meta-logical-monitor.h"
#include "backends/meta-monitor.h"
#include "backends/meta-monitor-config-manager.h"
#include "backends/x11/meta-monitor-manager-xrandr.h"
#include "meta-backend-private.h"
@ -106,6 +107,85 @@ logical_monitor_from_layout (MetaMonitorManager *manager,
return NULL;
}
static MetaLogicalMonitor *
create_logical_monitor_from_config (MetaMonitorManager *manager,
MetaLogicalMonitorConfig *logical_monitor_config,
int monitor_number)
{
MetaLogicalMonitor *logical_monitor;
GList *monitor_configs;
MetaMonitorConfig *first_monitor_config;
MetaMonitorSpec *first_monitor_spec;
MetaMonitor *first_monitor;
GList *l;
monitor_configs = logical_monitor_config->monitor_configs;
first_monitor_config = g_list_first (monitor_configs)->data;
first_monitor_spec = first_monitor_config->monitor_spec;
first_monitor =
meta_monitor_manager_get_monitor_from_spec (manager, first_monitor_spec);
/* Create logical monitor from the first monitor. */
logical_monitor = meta_logical_monitor_new (first_monitor,
logical_monitor_config->layout.x,
logical_monitor_config->layout.y,
monitor_number);
/* Add the other monitors. */
for (l = monitor_configs->next; l; l = l->next)
{
MetaMonitorConfig *monitor_config = l->data;
MetaMonitorSpec *monitor_spec;
MetaMonitor *monitor;
monitor_spec = monitor_config->monitor_spec;
monitor = meta_monitor_manager_get_monitor_from_spec (manager,
monitor_spec);
meta_logical_monitor_add_monitor (logical_monitor, monitor);
}
return logical_monitor;
}
static void
meta_monitor_manager_rebuild_logical_monitors (MetaMonitorManager *manager,
MetaMonitorsConfig *config)
{
GList *logical_monitors = NULL;
GList *l;
int monitor_number = 0;
MetaLogicalMonitor *primary_logical_monitor = NULL;
for (l = config->logical_monitor_configs; l; l = l->next)
{
MetaLogicalMonitorConfig *logical_monitor_config = l->data;
MetaLogicalMonitor *logical_monitor;
logical_monitor =
create_logical_monitor_from_config (manager,
logical_monitor_config,
monitor_number);
monitor_number++;
if (logical_monitor_config->is_primary)
primary_logical_monitor = logical_monitor;
logical_monitors = g_list_append (logical_monitors, logical_monitor);
}
/*
* If no monitor was marked as primary, fall back on marking the first
* logical monitor the primary one.
*/
if (!primary_logical_monitor && logical_monitors)
primary_logical_monitor = g_list_first (logical_monitors)->data;
manager->logical_monitors = logical_monitors;
meta_monitor_manager_set_primary_logical_monitor (manager,
primary_logical_monitor);
}
static void
derive_monitor_position (MetaMonitor *monitor,
int *x,
@ -206,6 +286,17 @@ meta_monitor_manager_ensure_initial_config (MetaMonitorManager *manager)
META_MONITOR_MANAGER_GET_CLASS (manager)->ensure_initial_config (manager);
}
static gboolean
meta_monitor_manager_apply_monitors_config (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
GError **error)
{
MetaMonitorManagerClass *manager_class =
META_MONITOR_MANAGER_GET_CLASS (manager);
return manager_class->apply_monitors_config (manager, config, error);
}
gboolean
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
{
@ -229,10 +320,52 @@ legacy_ensure_configured (MetaMonitorManager *manager)
meta_monitor_config_make_default (manager->legacy_config, manager);
}
void
MetaMonitorsConfig *
meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
{
MetaMonitorsConfig *config = NULL;
GError *error = NULL;
if (!manager->config_manager)
{
legacy_ensure_configured (manager);
return NULL;
}
config = meta_monitor_config_manager_create_linear (manager->config_manager);
if (!meta_monitor_manager_apply_monitors_config (manager, config, &error))
{
g_clear_object (&config);
g_warning ("Failed to use linear monitor configuration: %s",
error->message);
g_clear_error (&error);
}
else
{
goto done;
}
config = meta_monitor_config_manager_create_fallback (manager->config_manager);
if (!meta_monitor_manager_apply_monitors_config (manager, config, &error))
{
g_clear_object (&config);
g_warning ("Failed to use fallback monitor configuration: %s",
error->message);
g_clear_error (&error);
}
else
{
goto done;
}
done:
if (!config)
meta_fatal ("Failed to find any working monitor configuration, giving up");
meta_monitor_config_manager_set_current (manager->config_manager, config);
g_object_unref (config);
return config;
}
static void
@ -245,6 +378,9 @@ meta_monitor_manager_constructed (GObject *object)
manager->in_init = TRUE;
if (g_strcmp0 (g_getenv ("MUTTER_USE_CONFIG_MANAGER"), "1") == 0)
manager->config_manager = meta_monitor_config_manager_new (manager);
else
manager->legacy_config = meta_monitor_config_new ();
meta_monitor_manager_read_current_state (manager);
@ -353,6 +489,8 @@ meta_monitor_manager_dispose (GObject *object)
manager->dbus_name_id = 0;
}
g_clear_object (&manager->config_manager);
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object);
}
@ -704,6 +842,9 @@ save_config_timeout (gpointer user_data)
{
MetaMonitorManager *manager = user_data;
if (manager->config_manager)
g_assert (!"missing implementation");
else
legacy_restore_previous_config (manager);
manager->persistent_timeout_id = 0;
@ -728,6 +869,14 @@ meta_monitor_manager_legacy_handle_apply_configuration (MetaDBusDisplayConfig *
guint output_index;
GPtrArray *crtc_infos, *output_infos;
if (manager->config_manager)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Used old configuration API with new configuration system");
return TRUE;
}
if (serial != manager->serial)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@ -968,6 +1117,9 @@ meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
g_source_remove (manager->persistent_timeout_id);
manager->persistent_timeout_id = 0;
if (manager->config_manager)
g_assert (!"not implemented");
else
legacy_confirm_configuration (manager, ok);
}
@ -1543,6 +1695,79 @@ meta_monitor_manager_notify_monitors_changed (MetaMonitorManager *manager)
g_signal_emit_by_name (manager, "monitors-changed");
}
static void
set_logical_monitor_modes (MetaMonitorManager *manager,
MetaLogicalMonitorConfig *logical_monitor_config)
{
GList *l;
for (l = logical_monitor_config->monitor_configs; l; l = l->next)
{
MetaMonitorConfig *monitor_config = l->data;
MetaMonitorSpec *monitor_spec;
MetaMonitor *monitor;
MetaMonitorModeSpec *monitor_mode_spec;
MetaMonitorMode *monitor_mode;
monitor_spec = monitor_config->monitor_spec;
monitor = meta_monitor_manager_get_monitor_from_spec (manager,
monitor_spec);
monitor_mode_spec = monitor_config->mode_spec;
monitor_mode = meta_monitor_get_mode_from_spec (monitor,
monitor_mode_spec);
meta_monitor_set_current_mode (monitor, monitor_mode);
}
}
static void
meta_monitor_manager_update_monitor_modes (MetaMonitorManager *manager,
MetaMonitorsConfig *config)
{
GList *l;
for (l = config->logical_monitor_configs; l; l = l->next)
{
MetaLogicalMonitorConfig *logical_monitor_config = l->data;
set_logical_monitor_modes (manager, logical_monitor_config);
}
for (l = manager->monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
if (!meta_monitor_get_logical_monitor (monitor))
meta_monitor_set_current_mode (monitor, NULL);
}
}
void
meta_monitor_manager_update_logical_state (MetaMonitorManager *manager,
MetaMonitorsConfig *config)
{
meta_monitor_manager_rebuild_logical_monitors (manager, config);
meta_monitor_manager_update_monitor_modes (manager, config);
}
void
meta_monitor_manager_rebuild (MetaMonitorManager *manager,
MetaMonitorsConfig *config)
{
GList *old_logical_monitors;
if (manager->in_init)
return;
old_logical_monitors = manager->logical_monitors;
meta_monitor_manager_update_logical_state (manager, config);
meta_monitor_manager_notify_monitors_changed (manager);
g_list_free_full (old_logical_monitors, g_object_unref);
}
static void
meta_monitor_manager_update_monitor_modes_derived (MetaMonitorManager *manager)
{
@ -1663,8 +1888,14 @@ legacy_on_hotplug (MetaMonitorManager *manager)
void
meta_monitor_manager_on_hotplug (MetaMonitorManager *manager)
{
if (manager->legacy_config)
{
legacy_on_hotplug (manager);
return;
}
meta_monitor_manager_ensure_configured (manager);
}
static gboolean

View File

@ -581,6 +581,17 @@ meta_monitor_get_spec (MetaMonitor *monitor)
return priv->spec;
}
MetaLogicalMonitor *
meta_monitor_get_logical_monitor (MetaMonitor *monitor)
{
MetaOutput *output = meta_monitor_get_main_output (monitor);
if (output->crtc)
return output->crtc->logical_monitor;
else
return NULL;
}
static gboolean
meta_monitor_mode_spec_equals (MetaMonitorModeSpec *monitor_mode_spec,
MetaMonitorModeSpec *other_monitor_mode_spec)
@ -668,6 +679,15 @@ meta_monitor_derive_current_mode (MetaMonitor *monitor)
priv->current_mode = current_mode;
}
void
meta_monitor_set_current_mode (MetaMonitor *monitor,
MetaMonitorMode *mode)
{
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
priv->current_mode = mode;
}
GList *
meta_monitor_get_modes (MetaMonitor *monitor)
{

View File

@ -115,6 +115,8 @@ const char * meta_monitor_get_serial (MetaMonitor *monitor);
uint32_t meta_monitor_tiled_get_tile_group_id (MetaMonitorTiled *monitor_tiled);
MetaLogicalMonitor * meta_monitor_get_logical_monitor (MetaMonitor *monitor);
MetaMonitorMode * meta_monitor_get_mode_from_spec (MetaMonitor *monitor,
MetaMonitorModeSpec *monitor_mode_spec);
@ -124,6 +126,9 @@ MetaMonitorMode * meta_monitor_get_current_mode (MetaMonitor *monitor);
void meta_monitor_derive_current_mode (MetaMonitor *monitor);
void meta_monitor_set_current_mode (MetaMonitor *monitor,
MetaMonitorMode *mode);
GList * meta_monitor_get_modes (MetaMonitor *monitor);
MetaMonitorModeSpec * meta_monitor_mode_get_spec (MetaMonitorMode *monitor_mode);

View File

@ -25,6 +25,7 @@
#include "meta-monitor-manager-kms.h"
#include "meta-monitor-config.h"
#include "meta-monitor-config-manager.h"
#include "meta-backend-private.h"
#include "meta-renderer-native.h"
@ -1177,24 +1178,6 @@ init_outputs (MetaMonitorManager *manager,
detect_and_setup_output_clones (manager, resources);
}
static void
calculate_screen_size (MetaMonitorManager *manager)
{
unsigned int i;
int width = 0, height = 0;
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCrtc *crtc = &manager->crtcs[i];
width = MAX (width, crtc->rect.x + crtc->rect.width);
height = MAX (height, crtc->rect.y + crtc->rect.height);
}
manager->screen_width = width;
manager->screen_height = height;
}
static void
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
{
@ -1220,8 +1203,6 @@ meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
init_crtcs (manager, resources);
init_outputs (manager, resources);
calculate_screen_size (manager);
drmModeFreeResources (resources);
}
@ -1340,13 +1321,18 @@ set_underscan (MetaMonitorManagerKms *manager_kms,
static void
meta_monitor_manager_kms_ensure_initial_config (MetaMonitorManager *manager)
{
meta_monitor_manager_ensure_configured (manager);
MetaMonitorsConfig *config;
config = meta_monitor_manager_ensure_configured (manager);
if (manager->config_manager)
meta_monitor_manager_update_logical_state (manager, config);
else
meta_monitor_manager_update_logical_state_derived (manager);
}
static void
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
apply_crtc_assignments (MetaMonitorManager *manager,
MetaCrtcInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
@ -1354,9 +1340,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
unsigned i;
int screen_width, screen_height;
screen_width = 0; screen_height = 0;
for (i = 0; i < n_crtcs; i++)
{
MetaCrtcInfo *crtc_info = crtcs[i];
@ -1393,9 +1377,6 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
height = mode->height;
}
screen_width = MAX (screen_width, crtc_info->x + width);
screen_height = MAX (screen_height, crtc_info->y + height);
crtc->rect.x = crtc_info->x;
crtc->rect.y = crtc_info->y;
crtc->rect.width = width;
@ -1479,10 +1460,93 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
output->crtc = NULL;
output->is_primary = FALSE;
}
}
static void
update_screen_size (MetaMonitorManager *manager,
MetaMonitorsConfig *config)
{
GList *l;
int screen_width = 0;
int screen_height = 0;
for (l = config->logical_monitor_configs; l; l = l->next)
{
MetaLogicalMonitorConfig *logical_monitor_config = l->data;
int right_edge;
int bottom_edge;
right_edge = (logical_monitor_config->layout.width +
logical_monitor_config->layout.x);
if (right_edge > screen_width)
screen_width = right_edge;
bottom_edge = (logical_monitor_config->layout.height +
logical_monitor_config->layout.y);
if (bottom_edge > screen_height)
screen_height = bottom_edge;
}
manager->screen_width = screen_width;
manager->screen_height = screen_height;
}
static gboolean
meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
GError **error)
{
GPtrArray *crtc_infos;
GPtrArray *output_infos;
if (!meta_monitor_config_manager_assign (manager, config,
&crtc_infos, &output_infos,
error))
return FALSE;
apply_crtc_assignments (manager,
(MetaCrtcInfo **) crtc_infos->pdata,
crtc_infos->len,
(MetaOutputInfo **) output_infos->pdata,
output_infos->len);
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
update_screen_size (manager, config);
meta_monitor_manager_rebuild (manager, config);
return TRUE;
}
static void
legacy_calculate_screen_size (MetaMonitorManager *manager)
{
unsigned int i;
int width = 0, height = 0;
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCrtc *crtc = &manager->crtcs[i];
width = MAX (width, crtc->rect.x + crtc->rect.width);
height = MAX (height, crtc->rect.y + crtc->rect.height);
}
manager->screen_width = width;
manager->screen_height = height;
}
static void
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
MetaCrtcInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
legacy_calculate_screen_size (manager);
meta_monitor_manager_rebuild_derived (manager);
}
@ -1931,6 +1995,7 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
manager_class->read_current = meta_monitor_manager_kms_read_current;
manager_class->read_edid = meta_monitor_manager_kms_read_edid;
manager_class->ensure_initial_config = meta_monitor_manager_kms_ensure_initial_config;
manager_class->apply_monitors_config = meta_monitor_manager_kms_apply_monitors_config;
manager_class->apply_configuration = meta_monitor_manager_kms_apply_configuration;
manager_class->set_power_save_mode = meta_monitor_manager_kms_set_power_save_mode;
manager_class->get_crtc_gamma = meta_monitor_manager_kms_get_crtc_gamma;

View File

@ -42,6 +42,7 @@
#include <meta/main.h>
#include <meta/errors.h>
#include "meta-monitor-config.h"
#include "backends/meta-monitor-config-manager.h"
#include "backends/meta-logical-monitor.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
@ -1060,7 +1061,7 @@ output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
}
static void
meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
apply_crtc_assignments (MetaMonitorManager *manager,
MetaCrtcInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
@ -1294,6 +1295,41 @@ meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager)
meta_monitor_manager_update_logical_state_derived (manager);
}
static gboolean
meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
GError **error)
{
GPtrArray *crtc_infos;
GPtrArray *output_infos;
if (!meta_monitor_config_manager_assign (manager, config,
&crtc_infos, &output_infos,
error))
return FALSE;
apply_crtc_assignments (manager,
(MetaCrtcInfo **) crtc_infos->pdata,
crtc_infos->len,
(MetaOutputInfo **) output_infos->pdata,
output_infos->len);
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
return TRUE;
}
static void
meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
MetaCrtcInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
}
static void
meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
MetaOutput *output,
@ -1587,6 +1623,7 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
manager_class->read_current = meta_monitor_manager_xrandr_read_current;
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
manager_class->ensure_initial_config = meta_monitor_manager_xrandr_ensure_initial_config;
manager_class->apply_monitors_config = meta_monitor_manager_xrandr_apply_monitors_config;
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

@ -21,6 +21,8 @@
#include "tests/meta-monitor-manager-test.h"
#include "backends/meta-monitor-config-manager.h"
struct _MetaMonitorManagerTest
{
MetaMonitorManager parent;
@ -86,20 +88,24 @@ meta_monitor_manager_test_read_current (MetaMonitorManager *manager)
static void
meta_monitor_manager_test_ensure_initial_config (MetaMonitorManager *manager)
{
meta_monitor_manager_ensure_configured (manager);
MetaMonitorsConfig *config;
config = meta_monitor_manager_ensure_configured (manager);
if (manager->config_manager)
meta_monitor_manager_update_logical_state (manager, config);
else
meta_monitor_manager_update_logical_state_derived (manager);
}
static void
meta_monitor_manager_test_apply_configuration (MetaMonitorManager *manager,
apply_crtc_assignments (MetaMonitorManager *manager,
MetaCrtcInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
unsigned int i;
int screen_width = 0, screen_height = 0;
for (i = 0; i < n_crtcs; i++)
{
@ -142,9 +148,6 @@ meta_monitor_manager_test_apply_configuration (MetaMonitorManager *manager,
crtc->current_mode = mode;
crtc->transform = crtc_info->transform;
screen_width = MAX (screen_width, crtc_info->x + width);
screen_height = MAX (screen_height, crtc_info->y + height);
for (j = 0; j < crtc_info->outputs->len; j++)
{
output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
@ -198,10 +201,93 @@ meta_monitor_manager_test_apply_configuration (MetaMonitorManager *manager,
output->crtc = NULL;
output->is_primary = FALSE;
}
}
static void
update_screen_size (MetaMonitorManager *manager,
MetaMonitorsConfig *config)
{
GList *l;
int screen_width = 0;
int screen_height = 0;
for (l = config->logical_monitor_configs; l; l = l->next)
{
MetaLogicalMonitorConfig *logical_monitor_config = l->data;
int right_edge;
int bottom_edge;
right_edge = (logical_monitor_config->layout.width +
logical_monitor_config->layout.x);
if (right_edge > screen_width)
screen_width = right_edge;
bottom_edge = (logical_monitor_config->layout.height +
logical_monitor_config->layout.y);
if (bottom_edge > screen_height)
screen_height = bottom_edge;
}
manager->screen_width = screen_width;
manager->screen_height = screen_height;
}
static gboolean
meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager *manager,
MetaMonitorsConfig *config,
GError **error)
{
GPtrArray *crtc_infos;
GPtrArray *output_infos;
if (!meta_monitor_config_manager_assign (manager, config,
&crtc_infos,
&output_infos,
error))
return FALSE;
apply_crtc_assignments (manager,
(MetaCrtcInfo **) crtc_infos->pdata,
crtc_infos->len,
(MetaOutputInfo **) output_infos->pdata,
output_infos->len);
g_ptr_array_free (crtc_infos, TRUE);
g_ptr_array_free (output_infos, TRUE);
update_screen_size (manager, config);
meta_monitor_manager_rebuild (manager, config);
return TRUE;
}
static void
legacy_calculate_screen_size (MetaMonitorManager *manager)
{
unsigned int i;
int width = 0, height = 0;
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCrtc *crtc = &manager->crtcs[i];
width = MAX (width, crtc->rect.x + crtc->rect.width);
height = MAX (height, crtc->rect.y + crtc->rect.height);
}
manager->screen_width = width;
manager->screen_height = height;
}
static void
meta_monitor_manager_test_apply_configuration (MetaMonitorManager *manager,
MetaCrtcInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
apply_crtc_assignments (manager, crtcs, n_crtcs, outputs, n_outputs);
legacy_calculate_screen_size (manager);
meta_monitor_manager_rebuild_derived (manager);
}
@ -249,6 +335,7 @@ meta_monitor_manager_test_class_init (MetaMonitorManagerTestClass *klass)
manager_class->read_current = meta_monitor_manager_test_read_current;
manager_class->ensure_initial_config = meta_monitor_manager_test_ensure_initial_config;
manager_class->apply_monitors_config = meta_monitor_manager_test_apply_monitors_config;
manager_class->apply_configuration = meta_monitor_manager_test_apply_configuration;
manager_class->tiled_monitor_added = meta_monitor_manager_test_tiled_monitor_added;
manager_class->tiled_monitor_removed = meta_monitor_manager_test_tiled_monitor_removed;