mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
30e1c51b33
Using g_memdup() is dangerous due to the type of the size argument. See https://gitlab.gnome.org/GNOME/glib/-/issues/2319 and https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1926 for details. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1708>
817 lines
24 KiB
C
817 lines
24 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/*
|
|
* Copyright (C) 2001, 2002 Havoc Pennington
|
|
* Copyright (C) 2002, 2003 Red Hat Inc.
|
|
* Some ICCCM manager selection code derived from fvwm2,
|
|
* Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
|
|
* Copyright (C) 2003 Rob Adams
|
|
* Copyright (C) 2004-2006 Elijah Newren
|
|
* Copyright (C) 2013 Red Hat Inc.
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "backends/meta-monitor-manager-dummy.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "backends/meta-backend-private.h"
|
|
#include "backends/meta-crtc.h"
|
|
#include "backends/meta-monitor.h"
|
|
#include "backends/meta-monitor-config-manager.h"
|
|
#include "backends/meta-output.h"
|
|
#include "meta/main.h"
|
|
#include "meta/util.h"
|
|
|
|
#define MAX_MONITORS 5
|
|
#define MAX_OUTPUTS (MAX_MONITORS * 2)
|
|
#define MAX_CRTCS (MAX_MONITORS * 2)
|
|
#define MAX_MODES (MAX_MONITORS * 4)
|
|
|
|
struct _MetaMonitorManagerDummy
|
|
{
|
|
MetaMonitorManager parent_instance;
|
|
|
|
gboolean is_transform_handled;
|
|
};
|
|
|
|
struct _MetaMonitorManagerDummyClass
|
|
{
|
|
MetaMonitorManagerClass parent_class;
|
|
};
|
|
|
|
struct _MetaOutputDummy
|
|
{
|
|
MetaOutput parent;
|
|
|
|
float scale;
|
|
};
|
|
|
|
struct _MetaCrtcDummy
|
|
{
|
|
MetaCrtc parent;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaOutputDummy, meta_output_dummy, META_TYPE_OUTPUT)
|
|
G_DEFINE_TYPE (MetaCrtcDummy, meta_crtc_dummy, META_TYPE_CRTC)
|
|
G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MONITOR_MANAGER);
|
|
|
|
struct _MetaGpuDummy
|
|
{
|
|
MetaGpu parent;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaGpuDummy, meta_gpu_dummy, META_TYPE_GPU)
|
|
|
|
typedef struct _CrtcModeSpec
|
|
{
|
|
int width;
|
|
int height;
|
|
float refresh_rate;
|
|
} CrtcModeSpec;
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(CrtcModeSpec, g_free);
|
|
|
|
static MetaCrtcMode *
|
|
create_mode (CrtcModeSpec *spec,
|
|
long mode_id)
|
|
{
|
|
g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL;
|
|
|
|
crtc_mode_info = meta_crtc_mode_info_new ();
|
|
crtc_mode_info->width = spec->width;
|
|
crtc_mode_info->height = spec->height;
|
|
crtc_mode_info->refresh_rate = spec->refresh_rate;
|
|
|
|
return g_object_new (META_TYPE_CRTC_MODE,
|
|
"id", (uint64_t) mode_id,
|
|
"info", crtc_mode_info,
|
|
NULL);
|
|
}
|
|
|
|
static MetaGpu *
|
|
get_gpu (MetaMonitorManager *manager)
|
|
{
|
|
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
|
|
|
|
return META_GPU (meta_backend_get_gpus (backend)->data);
|
|
}
|
|
|
|
static void
|
|
append_monitor (MetaMonitorManager *manager,
|
|
GList **modes,
|
|
GList **crtcs,
|
|
GList **outputs,
|
|
float scale)
|
|
{
|
|
MetaGpu *gpu = get_gpu (manager);
|
|
CrtcModeSpec default_specs[] = {
|
|
{
|
|
.width = 800,
|
|
.height = 600,
|
|
.refresh_rate = 60.0
|
|
},
|
|
{
|
|
.width = 1024,
|
|
.height = 768,
|
|
.refresh_rate = 60.0
|
|
},
|
|
{
|
|
.width = 1440,
|
|
.height = 900,
|
|
.refresh_rate = 60.0
|
|
},
|
|
{
|
|
.width = 1600,
|
|
.height = 920,
|
|
.refresh_rate = 60.0
|
|
},
|
|
};
|
|
g_autolist (CrtcModeSpec) mode_specs = NULL;
|
|
unsigned int n_mode_specs = 0;
|
|
GList *new_modes = NULL;
|
|
MetaCrtc *crtc;
|
|
MetaOutputDummy *output_dummy;
|
|
MetaOutput *output;
|
|
unsigned int i;
|
|
unsigned int number;
|
|
g_autoptr (MetaOutputInfo) output_info = NULL;
|
|
const char *mode_specs_str;
|
|
GList *l;
|
|
|
|
mode_specs_str = getenv ("MUTTER_DEBUG_DUMMY_MODE_SPECS");
|
|
if (mode_specs_str && *mode_specs_str != '\0')
|
|
{
|
|
g_auto (GStrv) specs = g_strsplit (mode_specs_str, ":", -1);
|
|
for (i = 0; specs[i]; ++i)
|
|
{
|
|
int width, height;
|
|
float refresh_rate = 60.0;
|
|
|
|
if (sscanf (specs[i], "%dx%d@%f",
|
|
&width, &height, &refresh_rate) == 3 ||
|
|
sscanf (specs[i], "%dx%d",
|
|
&width, &height) == 2)
|
|
{
|
|
CrtcModeSpec *spec;
|
|
|
|
spec = g_new0 (CrtcModeSpec, 1);
|
|
spec->width = width;
|
|
spec->height = height;
|
|
spec->refresh_rate = refresh_rate;
|
|
mode_specs = g_list_prepend (mode_specs, spec);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < G_N_ELEMENTS (default_specs); i++)
|
|
{
|
|
CrtcModeSpec *spec;
|
|
|
|
spec = g_memdup2 (&default_specs[i], sizeof (CrtcModeSpec));
|
|
mode_specs = g_list_prepend (mode_specs, spec);
|
|
}
|
|
}
|
|
|
|
if (!mode_specs)
|
|
{
|
|
g_warning ("Cannot create dummy output: No valid mode specs.");
|
|
meta_exit (META_EXIT_ERROR);
|
|
}
|
|
|
|
for (l = mode_specs; l; l = l->next)
|
|
{
|
|
CrtcModeSpec *spec = l->data;
|
|
long mode_id;
|
|
MetaCrtcMode *mode;
|
|
|
|
mode_id = g_list_length (*modes) + n_mode_specs + 1;
|
|
mode = create_mode (spec, mode_id);
|
|
|
|
new_modes = g_list_append (new_modes, mode);
|
|
n_mode_specs++;
|
|
}
|
|
*modes = g_list_concat (*modes, new_modes);
|
|
|
|
crtc = g_object_new (META_TYPE_CRTC_DUMMY,
|
|
"id", (uint64_t) g_list_length (*crtcs) + 1,
|
|
"gpu", gpu,
|
|
NULL);
|
|
*crtcs = g_list_append (*crtcs, crtc);
|
|
|
|
number = g_list_length (*outputs) + 1;
|
|
|
|
output_info = meta_output_info_new ();
|
|
output_info->name = g_strdup_printf ("LVDS%d", number);
|
|
output_info->vendor = g_strdup ("MetaProducts Inc.");
|
|
output_info->product = g_strdup ("MetaMonitor");
|
|
output_info->serial = g_strdup_printf ("0xC0FFEE-%d", number);
|
|
output_info->width_mm = 222;
|
|
output_info->height_mm = 125;
|
|
output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
|
output_info->preferred_mode = g_list_last (*modes)->data;
|
|
output_info->n_possible_clones = 0;
|
|
output_info->connector_type = META_CONNECTOR_TYPE_LVDS;
|
|
|
|
output_info->modes = g_new0 (MetaCrtcMode *, n_mode_specs);
|
|
for (l = new_modes, i = 0; l; l = l->next, i++)
|
|
{
|
|
MetaCrtcMode *mode = l->data;
|
|
|
|
output_info->modes[i] = mode;
|
|
}
|
|
output_info->n_modes = n_mode_specs;
|
|
output_info->possible_crtcs = g_new0 (MetaCrtc *, 1);
|
|
output_info->possible_crtcs[0] = g_list_last (*crtcs)->data;
|
|
output_info->n_possible_crtcs = 1;
|
|
|
|
output = g_object_new (META_TYPE_OUTPUT_DUMMY,
|
|
"id", (uint64_t) number,
|
|
"gpu", gpu,
|
|
"info", output_info,
|
|
NULL);
|
|
output_dummy = META_OUTPUT_DUMMY (output);
|
|
output_dummy->scale = scale;
|
|
|
|
*outputs = g_list_append (*outputs, output);
|
|
}
|
|
|
|
static void
|
|
append_tiled_monitor (MetaMonitorManager *manager,
|
|
GList **modes,
|
|
GList **crtcs,
|
|
GList **outputs,
|
|
int scale)
|
|
{
|
|
MetaGpu *gpu = get_gpu (manager);
|
|
CrtcModeSpec mode_specs[] = {
|
|
{
|
|
.width = 800,
|
|
.height = 600,
|
|
.refresh_rate = 60.0
|
|
},
|
|
{
|
|
.width = 512,
|
|
.height = 768,
|
|
.refresh_rate = 60.0
|
|
}
|
|
};
|
|
unsigned int n_tiles = 2;
|
|
GList *new_modes = NULL;
|
|
GList *new_crtcs = NULL;
|
|
MetaOutput *output;
|
|
unsigned int i;
|
|
uint32_t tile_group_id;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (mode_specs); i++)
|
|
{
|
|
long mode_id;
|
|
MetaCrtcMode *mode;
|
|
|
|
mode_id = g_list_length (*modes) + i + 1;
|
|
mode = create_mode (&mode_specs[i], mode_id);
|
|
|
|
new_modes = g_list_append (new_modes, mode);
|
|
}
|
|
*modes = g_list_concat (*modes, new_modes);
|
|
|
|
for (i = 0; i < n_tiles; i++)
|
|
{
|
|
MetaCrtc *crtc;
|
|
|
|
crtc = g_object_new (META_TYPE_CRTC_DUMMY,
|
|
"id", (uint64_t) g_list_length (*crtcs) + i + 1,
|
|
"gpu", gpu,
|
|
NULL);
|
|
new_crtcs = g_list_append (new_crtcs, crtc);
|
|
}
|
|
*crtcs = g_list_concat (*crtcs, new_crtcs);
|
|
|
|
tile_group_id = g_list_length (*outputs) + 1;
|
|
for (i = 0; i < n_tiles; i++)
|
|
{
|
|
MetaOutputDummy *output_dummy;
|
|
MetaCrtcMode *preferred_mode;
|
|
const MetaCrtcModeInfo *preferred_mode_info;
|
|
unsigned int j;
|
|
unsigned int number;
|
|
g_autoptr (MetaOutputInfo) output_info = NULL;
|
|
GList *l;
|
|
|
|
/* Arbitrary ID unique for this output */
|
|
number = g_list_length (*outputs) + 1;
|
|
|
|
preferred_mode = g_list_last (*modes)->data;
|
|
preferred_mode_info = meta_crtc_mode_get_info (preferred_mode);
|
|
|
|
output_info = meta_output_info_new ();
|
|
|
|
output_info->name = g_strdup_printf ("LVDS%d", number);
|
|
output_info->vendor = g_strdup ("MetaProducts Inc.");
|
|
output_info->product = g_strdup ("MetaMonitor");
|
|
output_info->serial = g_strdup_printf ("0xC0FFEE-%d", number);
|
|
output_info->suggested_x = -1;
|
|
output_info->suggested_y = -1;
|
|
output_info->width_mm = 222;
|
|
output_info->height_mm = 125;
|
|
output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
|
output_info->preferred_mode = preferred_mode;
|
|
output_info->n_possible_clones = 0;
|
|
output_info->connector_type = META_CONNECTOR_TYPE_LVDS;
|
|
output_info->tile_info = (MetaTileInfo) {
|
|
.group_id = tile_group_id,
|
|
.max_h_tiles = n_tiles,
|
|
.max_v_tiles = 1,
|
|
.loc_h_tile = i,
|
|
.loc_v_tile = 0,
|
|
.tile_w = preferred_mode_info->width,
|
|
.tile_h = preferred_mode_info->height
|
|
},
|
|
|
|
output_info->modes = g_new0 (MetaCrtcMode *, G_N_ELEMENTS (mode_specs));
|
|
for (l = new_modes, j = 0; l; l = l->next, j++)
|
|
{
|
|
MetaCrtcMode *mode = l->data;
|
|
|
|
output_info->modes[j] = mode;
|
|
}
|
|
output_info->n_modes = G_N_ELEMENTS (mode_specs);
|
|
|
|
output_info->possible_crtcs = g_new0 (MetaCrtc *, n_tiles);
|
|
for (l = new_crtcs, j = 0; l; l = l->next, j++)
|
|
{
|
|
MetaCrtc *crtc = l->data;
|
|
|
|
output_info->possible_crtcs[j] = crtc;
|
|
}
|
|
output_info->n_possible_crtcs = n_tiles;
|
|
|
|
output = g_object_new (META_TYPE_OUTPUT_DUMMY,
|
|
"id", (uint64_t) number,
|
|
"gpu", gpu,
|
|
"info", output_info,
|
|
NULL);
|
|
output_dummy = META_OUTPUT_DUMMY (output);
|
|
output_dummy->scale = scale;
|
|
|
|
*outputs = g_list_append (*outputs, output);
|
|
}
|
|
}
|
|
|
|
static void
|
|
meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
|
|
{
|
|
MetaGpu *gpu = get_gpu (manager);
|
|
unsigned int num_monitors = 1;
|
|
float *monitor_scales = NULL;
|
|
const char *num_monitors_str;
|
|
const char *monitor_scales_str;
|
|
const char *tiled_monitors_str;
|
|
gboolean tiled_monitors;
|
|
unsigned int i;
|
|
GList *outputs;
|
|
GList *crtcs;
|
|
GList *modes;
|
|
|
|
/* To control what monitor configuration is generated, there are two available
|
|
* environmental variables that can be used:
|
|
*
|
|
* MUTTER_DEBUG_NUM_DUMMY_MONITORS
|
|
*
|
|
* Specifies the number of dummy monitors to include in the stage. Every
|
|
* monitor is 1024x786 pixels and they are placed on a horizontal row.
|
|
*
|
|
* MUTTER_DEBUG_DUMMY_MODE_SPECS
|
|
*
|
|
* A colon separated list of mode specifications that can be used to
|
|
* configure the monitor via dbus API. Setting this environment variable
|
|
* overrides the default set of modes available.
|
|
* Format should be WWxHH:WWxHH@RR
|
|
*
|
|
* MUTTER_DEBUG_DUMMY_MONITOR_SCALES
|
|
*
|
|
* A comma separated list that specifies the scales of the dummy monitors.
|
|
*
|
|
* MUTTER_DEBUG_TILED_DUMMY_MONITORS
|
|
*
|
|
* If set to "1" the dummy monitors will emulate being tiled, i.e. each have a
|
|
* unique tile group id, made up of multiple outputs and CRTCs.
|
|
*
|
|
* For example the following configuration results in two monitors, where the
|
|
* first one has the monitor scale 1, and the other the monitor scale 2.
|
|
*
|
|
* MUTTER_DEBUG_NUM_DUMMY_MONITORS=2
|
|
* MUTTER_DEBUG_DUMMY_MONITOR_SCALES=1,2
|
|
* MUTTER_DEBUG_TILED_DUMMY_MONITORS=1
|
|
*/
|
|
num_monitors_str = getenv ("MUTTER_DEBUG_NUM_DUMMY_MONITORS");
|
|
if (num_monitors_str)
|
|
{
|
|
num_monitors = g_ascii_strtoll (num_monitors_str, NULL, 10);
|
|
if (num_monitors <= 0)
|
|
{
|
|
meta_warning ("Invalid number of dummy monitors");
|
|
num_monitors = 1;
|
|
}
|
|
|
|
if (num_monitors > MAX_MONITORS)
|
|
{
|
|
meta_warning ("Clamping monitor count to max (%d)",
|
|
MAX_MONITORS);
|
|
num_monitors = MAX_MONITORS;
|
|
}
|
|
}
|
|
|
|
monitor_scales = g_newa (typeof (*monitor_scales), num_monitors);
|
|
for (i = 0; i < num_monitors; i++)
|
|
monitor_scales[i] = 1.0;
|
|
|
|
monitor_scales_str = getenv ("MUTTER_DEBUG_DUMMY_MONITOR_SCALES");
|
|
if (monitor_scales_str)
|
|
{
|
|
gchar **scales_str_list;
|
|
|
|
scales_str_list = g_strsplit (monitor_scales_str, ",", -1);
|
|
if (g_strv_length (scales_str_list) != num_monitors)
|
|
meta_warning ("Number of specified monitor scales differ from number "
|
|
"of monitors (defaults to 1).");
|
|
for (i = 0; i < num_monitors && scales_str_list[i]; i++)
|
|
{
|
|
float scale = g_ascii_strtod (scales_str_list[i], NULL);
|
|
|
|
monitor_scales[i] = scale;
|
|
}
|
|
g_strfreev (scales_str_list);
|
|
}
|
|
|
|
tiled_monitors_str = g_getenv ("MUTTER_DEBUG_TILED_DUMMY_MONITORS");
|
|
tiled_monitors = g_strcmp0 (tiled_monitors_str, "1") == 0;
|
|
|
|
modes = NULL;
|
|
crtcs = NULL;
|
|
outputs = NULL;
|
|
|
|
for (i = 0; i < num_monitors; i++)
|
|
{
|
|
if (tiled_monitors)
|
|
append_tiled_monitor (manager,
|
|
&modes, &crtcs, &outputs, monitor_scales[i]);
|
|
else
|
|
append_monitor (manager, &modes, &crtcs, &outputs, monitor_scales[i]);
|
|
}
|
|
|
|
meta_gpu_take_modes (gpu, modes);
|
|
meta_gpu_take_crtcs (gpu, crtcs);
|
|
meta_gpu_take_outputs (gpu, outputs);
|
|
}
|
|
|
|
static void
|
|
meta_monitor_manager_dummy_ensure_initial_config (MetaMonitorManager *manager)
|
|
{
|
|
MetaMonitorsConfig *config;
|
|
|
|
config = meta_monitor_manager_ensure_configured (manager);
|
|
|
|
if (meta_is_stage_views_enabled ())
|
|
meta_monitor_manager_update_logical_state (manager, config);
|
|
else
|
|
meta_monitor_manager_update_logical_state_derived (manager, NULL);
|
|
}
|
|
|
|
static void
|
|
apply_crtc_assignments (MetaMonitorManager *manager,
|
|
MetaCrtcAssignment **crtcs,
|
|
unsigned int n_crtcs,
|
|
MetaOutputAssignment **outputs,
|
|
unsigned int n_outputs)
|
|
{
|
|
g_autoptr (GList) to_configure_outputs = NULL;
|
|
g_autoptr (GList) to_configure_crtcs = NULL;
|
|
unsigned i;
|
|
|
|
to_configure_outputs = g_list_copy (meta_gpu_get_outputs (get_gpu (manager)));
|
|
to_configure_crtcs = g_list_copy (meta_gpu_get_crtcs (get_gpu (manager)));
|
|
|
|
for (i = 0; i < n_crtcs; i++)
|
|
{
|
|
MetaCrtcAssignment *crtc_assignment = crtcs[i];
|
|
MetaCrtc *crtc = crtc_assignment->crtc;
|
|
|
|
to_configure_crtcs = g_list_remove (to_configure_crtcs, crtc);
|
|
|
|
if (crtc_assignment->mode == NULL)
|
|
{
|
|
meta_crtc_unset_config (crtc);
|
|
}
|
|
else
|
|
{
|
|
unsigned int j;
|
|
|
|
meta_crtc_set_config (crtc,
|
|
&crtc_assignment->layout,
|
|
crtc_assignment->mode,
|
|
crtc_assignment->transform);
|
|
|
|
for (j = 0; j < crtc_assignment->outputs->len; j++)
|
|
{
|
|
MetaOutput *output;
|
|
MetaOutputAssignment *output_assignment;
|
|
|
|
output = ((MetaOutput**) crtc_assignment->outputs->pdata)[j];
|
|
|
|
to_configure_outputs = g_list_remove (to_configure_outputs,
|
|
output);
|
|
|
|
output_assignment = meta_find_output_assignment (outputs,
|
|
n_outputs,
|
|
output);
|
|
meta_output_assign_crtc (output, crtc, output_assignment);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_list_foreach (to_configure_crtcs,
|
|
(GFunc) meta_crtc_unset_config,
|
|
NULL);
|
|
g_list_foreach (to_configure_outputs,
|
|
(GFunc) meta_output_unassign_crtc,
|
|
NULL);
|
|
}
|
|
|
|
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_dummy_apply_monitors_config (MetaMonitorManager *manager,
|
|
MetaMonitorsConfig *config,
|
|
MetaMonitorsConfigMethod method,
|
|
GError **error)
|
|
{
|
|
GPtrArray *crtc_assignments;
|
|
GPtrArray *output_assignments;
|
|
|
|
if (!config)
|
|
{
|
|
manager->screen_width = META_MONITOR_MANAGER_MIN_SCREEN_WIDTH;
|
|
manager->screen_height = META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT;
|
|
|
|
meta_monitor_manager_rebuild (manager, NULL);
|
|
return TRUE;
|
|
}
|
|
|
|
if (!meta_monitor_config_manager_assign (manager, config,
|
|
&crtc_assignments,
|
|
&output_assignments,
|
|
error))
|
|
return FALSE;
|
|
|
|
if (method == META_MONITORS_CONFIG_METHOD_VERIFY)
|
|
{
|
|
g_ptr_array_free (crtc_assignments, TRUE);
|
|
g_ptr_array_free (output_assignments, TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
apply_crtc_assignments (manager,
|
|
(MetaCrtcAssignment **) crtc_assignments->pdata,
|
|
crtc_assignments->len,
|
|
(MetaOutputAssignment **) output_assignments->pdata,
|
|
output_assignments->len);
|
|
|
|
g_ptr_array_free (crtc_assignments, TRUE);
|
|
g_ptr_array_free (output_assignments, TRUE);
|
|
|
|
update_screen_size (manager, config);
|
|
meta_monitor_manager_rebuild (manager, config);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
meta_monitor_manager_dummy_is_transform_handled (MetaMonitorManager *manager,
|
|
MetaCrtc *crtc,
|
|
MetaMonitorTransform transform)
|
|
{
|
|
MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager);
|
|
|
|
return manager_dummy->is_transform_handled;
|
|
}
|
|
|
|
static float
|
|
meta_monitor_manager_dummy_calculate_monitor_mode_scale (MetaMonitorManager *manager,
|
|
MetaMonitor *monitor,
|
|
MetaMonitorMode *monitor_mode)
|
|
{
|
|
MetaOutput *output;
|
|
MetaOutputDummy *output_dummy;
|
|
|
|
output = meta_monitor_get_main_output (monitor);
|
|
output_dummy = META_OUTPUT_DUMMY (output);
|
|
|
|
return output_dummy->scale;
|
|
}
|
|
|
|
static float *
|
|
meta_monitor_manager_dummy_calculate_supported_scales (MetaMonitorManager *manager,
|
|
MetaLogicalMonitorLayoutMode layout_mode,
|
|
MetaMonitor *monitor,
|
|
MetaMonitorMode *monitor_mode,
|
|
int *n_supported_scales)
|
|
{
|
|
MetaMonitorScalesConstraint constraints =
|
|
META_MONITOR_SCALES_CONSTRAINT_NONE;
|
|
|
|
switch (layout_mode)
|
|
{
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
|
|
break;
|
|
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
|
|
constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
|
|
break;
|
|
}
|
|
|
|
return meta_monitor_calculate_supported_scales (monitor, monitor_mode,
|
|
constraints,
|
|
n_supported_scales);
|
|
}
|
|
|
|
static gboolean
|
|
is_monitor_framebuffers_scaled (void)
|
|
{
|
|
MetaBackend *backend = meta_get_backend ();
|
|
MetaSettings *settings = meta_backend_get_settings (backend);
|
|
|
|
return meta_settings_is_experimental_feature_enabled (
|
|
settings,
|
|
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER);
|
|
}
|
|
|
|
static MetaMonitorManagerCapability
|
|
meta_monitor_manager_dummy_get_capabilities (MetaMonitorManager *manager)
|
|
{
|
|
MetaBackend *backend = meta_get_backend ();
|
|
MetaSettings *settings = meta_backend_get_settings (backend);
|
|
MetaMonitorManagerCapability capabilities =
|
|
META_MONITOR_MANAGER_CAPABILITY_NONE;
|
|
|
|
if (meta_settings_is_experimental_feature_enabled (
|
|
settings,
|
|
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER))
|
|
capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE;
|
|
|
|
return capabilities;
|
|
}
|
|
|
|
static gboolean
|
|
meta_monitor_manager_dummy_get_max_screen_size (MetaMonitorManager *manager,
|
|
int *max_width,
|
|
int *max_height)
|
|
{
|
|
if (meta_is_stage_views_enabled ())
|
|
return FALSE;
|
|
|
|
*max_width = 65535;
|
|
*max_height = 65535;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static MetaLogicalMonitorLayoutMode
|
|
meta_monitor_manager_dummy_get_default_layout_mode (MetaMonitorManager *manager)
|
|
{
|
|
if (!meta_is_stage_views_enabled ())
|
|
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
|
|
|
|
if (is_monitor_framebuffers_scaled ())
|
|
return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
|
|
else
|
|
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
|
|
}
|
|
|
|
static void
|
|
meta_monitor_manager_dummy_constructed (GObject *object)
|
|
{
|
|
MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (object);
|
|
const char *nested_offscreen_transform;
|
|
GObjectClass *parent_object_class =
|
|
G_OBJECT_CLASS (meta_monitor_manager_dummy_parent_class);
|
|
|
|
parent_object_class->constructed (object);
|
|
|
|
nested_offscreen_transform =
|
|
g_getenv ("MUTTER_DEBUG_NESTED_OFFSCREEN_TRANSFORM");
|
|
if (g_strcmp0 (nested_offscreen_transform, "1") == 0)
|
|
manager_dummy->is_transform_handled = FALSE;
|
|
else
|
|
manager_dummy->is_transform_handled = TRUE;
|
|
}
|
|
|
|
static void
|
|
meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
|
|
|
|
object_class->constructed = meta_monitor_manager_dummy_constructed;
|
|
|
|
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->is_transform_handled = meta_monitor_manager_dummy_is_transform_handled;
|
|
manager_class->calculate_monitor_mode_scale = meta_monitor_manager_dummy_calculate_monitor_mode_scale;
|
|
manager_class->calculate_supported_scales = meta_monitor_manager_dummy_calculate_supported_scales;
|
|
manager_class->get_capabilities = meta_monitor_manager_dummy_get_capabilities;
|
|
manager_class->get_max_screen_size = meta_monitor_manager_dummy_get_max_screen_size;
|
|
manager_class->get_default_layout_mode = meta_monitor_manager_dummy_get_default_layout_mode;
|
|
}
|
|
|
|
static void
|
|
meta_monitor_manager_dummy_init (MetaMonitorManagerDummy *manager_dummy)
|
|
{
|
|
}
|
|
|
|
static gboolean
|
|
meta_gpu_dummy_read_current (MetaGpu *gpu,
|
|
GError **error)
|
|
{
|
|
MetaBackend *backend = meta_gpu_get_backend (gpu);
|
|
MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend);
|
|
|
|
meta_monitor_manager_dummy_read_current (manager);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
meta_gpu_dummy_init (MetaGpuDummy *gpu_dummy)
|
|
{
|
|
}
|
|
|
|
static void
|
|
meta_gpu_dummy_class_init (MetaGpuDummyClass *klass)
|
|
{
|
|
MetaGpuClass *gpu_class = META_GPU_CLASS (klass);
|
|
|
|
gpu_class->read_current = meta_gpu_dummy_read_current;
|
|
}
|
|
|
|
static void
|
|
meta_output_dummy_init (MetaOutputDummy *output_dummy)
|
|
{
|
|
output_dummy->scale = 1;
|
|
}
|
|
|
|
static void
|
|
meta_output_dummy_class_init (MetaOutputDummyClass *klass)
|
|
{
|
|
}
|
|
|
|
static void
|
|
meta_crtc_dummy_init (MetaCrtcDummy *crtc_dummy)
|
|
{
|
|
}
|
|
|
|
static void
|
|
meta_crtc_dummy_class_init (MetaCrtcDummyClass *klass)
|
|
{
|
|
}
|