1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
4
* Copyright (C) 2001, 2002 Havoc Pennington
5
* Copyright (C) 2002, 2003 Red Hat Inc.
6
* Some ICCCM manager selection code derived from fvwm2,
7
* Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
8
* Copyright (C) 2003 Rob Adams
9
* Copyright (C) 2004-2006 Elijah Newren
10
* Copyright (C) 2013 Red Hat Inc.
12
* This program is free software; you can redistribute it and/or
13
* modify it under the terms of the GNU General Public License as
14
* published by the Free Software Foundation; either version 2 of the
15
* License, or (at your option) any later version.
17
* This program is distributed in the hope that it will be useful, but
18
* WITHOUT ANY WARRANTY; without even the implied warranty of
19
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
* General Public License for more details.
22
* You should have received a copy of the GNU General Public License
23
* along with this program; if not, see <http://www.gnu.org/licenses/>.
28
#include "meta-monitor-manager-dummy.h"
32
#include <meta/util.h>
33
#include "backends/meta-backend-private.h"
34
#include "backends/meta-crtc.h"
35
#include "backends/meta-monitor.h"
36
#include "backends/meta-monitor-config-manager.h"
37
#include "backends/meta-output.h"
39
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
41
#define MAX_MONITORS 5
42
#define MAX_OUTPUTS (MAX_MONITORS * 2)
43
#define MAX_CRTCS (MAX_MONITORS * 2)
44
#define MAX_MODES (MAX_MONITORS * 4)
46
struct _MetaMonitorManagerDummy
48
MetaMonitorManager parent_instance;
52
gboolean is_transform_handled;
55
struct _MetaMonitorManagerDummyClass
57
MetaMonitorManagerClass parent_class;
60
typedef struct _MetaOutputDummy
65
G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MONITOR_MANAGER);
72
G_DEFINE_TYPE (MetaGpuDummy, meta_gpu_dummy, META_TYPE_GPU)
75
meta_output_dummy_notify_destroy (MetaOutput *output);
77
typedef struct _CrtcModeSpec
85
create_mode (CrtcModeSpec *spec,
90
mode = g_object_new (META_TYPE_CRTC_MODE, NULL);
92
mode->mode_id = mode_id;
93
mode->width = spec->width;
94
mode->height = spec->height;
95
mode->refresh_rate = spec->refresh_rate;
101
append_monitor (MetaMonitorManager *manager,
107
MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager);
108
MetaGpu *gpu = manager_dummy->gpu;
109
CrtcModeSpec mode_specs[] = {
121
GList *new_modes = NULL;
123
MetaOutputDummy *output_dummy;
129
for (i = 0; i < G_N_ELEMENTS (mode_specs); i++)
134
mode_id = g_list_length (*modes) + i + 1;
135
mode = create_mode (&mode_specs[i], mode_id);
137
new_modes = g_list_append (new_modes, mode);
139
*modes = g_list_concat (*modes, new_modes);
141
crtc = g_object_new (META_TYPE_CRTC, NULL);
142
crtc->crtc_id = g_list_length (*crtcs) + 1;
143
crtc->all_transforms = ALL_TRANSFORMS;
144
*crtcs = g_list_append (*crtcs, crtc);
146
output = g_object_new (META_TYPE_OUTPUT, NULL);
148
output_dummy = g_new0 (MetaOutputDummy, 1);
149
*output_dummy = (MetaOutputDummy) {
153
number = g_list_length (*outputs) + 1;
156
output->winsys_id = number;
157
output->name = g_strdup_printf ("LVDS%d", number);
158
output->vendor = g_strdup ("MetaProducts Inc.");
159
output->product = g_strdup ("MetaMonitor");
160
output->serial = g_strdup_printf ("0xC0FFEE-%d", number);
161
output->suggested_x = -1;
162
output->suggested_y = -1;
163
output->width_mm = 222;
164
output->height_mm = 125;
165
output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
166
output->preferred_mode = g_list_last (*modes)->data;
167
output->n_possible_clones = 0;
168
output->backlight = -1;
169
output->connector_type = META_CONNECTOR_TYPE_LVDS;
170
output->driver_private = output_dummy;
171
output->driver_notify =
172
(GDestroyNotify) meta_output_dummy_notify_destroy;
174
output->modes = g_new0 (MetaCrtcMode *, G_N_ELEMENTS (mode_specs));
175
for (l = new_modes, i = 0; l; l = l->next, i++)
177
MetaCrtcMode *mode = l->data;
179
output->modes[i] = mode;
181
output->n_modes = G_N_ELEMENTS (mode_specs);
182
output->possible_crtcs = g_new0 (MetaCrtc *, 1);
183
output->possible_crtcs[0] = g_list_last (*crtcs)->data;
184
output->n_possible_crtcs = 1;
186
*outputs = g_list_append (*outputs, output);
190
append_tiled_monitor (MetaMonitorManager *manager,
196
MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager);
197
MetaGpu *gpu = manager_dummy->gpu;
198
CrtcModeSpec mode_specs[] = {
210
unsigned int n_tiles = 2;
211
GList *new_modes = NULL;
212
GList *new_crtcs = NULL;
215
uint32_t tile_group_id;
217
for (i = 0; i < G_N_ELEMENTS (mode_specs); i++)
222
mode_id = g_list_length (*modes) + i + 1;
223
mode = create_mode (&mode_specs[i], mode_id);
225
new_modes = g_list_append (new_modes, mode);
227
*modes = g_list_concat (*modes, new_modes);
229
for (i = 0; i < n_tiles; i++)
233
crtc = g_object_new (META_TYPE_CRTC, NULL);
235
crtc->crtc_id = g_list_length (*crtcs) + i + 1;
236
crtc->all_transforms = ALL_TRANSFORMS;
237
new_crtcs = g_list_append (new_crtcs, crtc);
239
*crtcs = g_list_concat (*crtcs, new_crtcs);
241
tile_group_id = g_list_length (*outputs) + 1;
242
for (i = 0; i < n_tiles; i++)
244
MetaOutputDummy *output_dummy;
245
MetaCrtcMode *preferred_mode;
250
output_dummy = g_new0 (MetaOutputDummy, 1);
251
*output_dummy = (MetaOutputDummy) {
255
/* Arbitrary ID unique for this output */
256
number = g_list_length (*outputs) + 1;
258
preferred_mode = g_list_last (*modes)->data;
260
output = g_object_new (META_TYPE_OUTPUT, NULL);
263
output->winsys_id = number;
264
output->name = g_strdup_printf ("LVDS%d", number);
265
output->vendor = g_strdup ("MetaProducts Inc.");
266
output->product = g_strdup ("MetaMonitor");
267
output->serial = g_strdup_printf ("0xC0FFEE-%d", number);
268
output->suggested_x = -1;
269
output->suggested_y = -1;
270
output->width_mm = 222;
271
output->height_mm = 125;
272
output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
273
output->preferred_mode = preferred_mode;
274
output->n_possible_clones = 0;
275
output->backlight = -1;
276
output->connector_type = META_CONNECTOR_TYPE_LVDS;
277
output->tile_info = (MetaTileInfo) {
278
.group_id = tile_group_id,
279
.max_h_tiles = n_tiles,
283
.tile_w = preferred_mode->width,
284
.tile_h = preferred_mode->height
286
output->driver_private = output_dummy;
287
output->driver_notify =
288
(GDestroyNotify) meta_output_dummy_notify_destroy;
290
output->modes = g_new0 (MetaCrtcMode *, G_N_ELEMENTS (mode_specs));
291
for (l = new_modes, j = 0; l; l = l->next, j++)
293
MetaCrtcMode *mode = l->data;
295
output->modes[j] = mode;
297
output->n_modes = G_N_ELEMENTS (mode_specs);
299
output->possible_crtcs = g_new0 (MetaCrtc *, n_tiles);
300
for (l = new_crtcs, j = 0; l; l = l->next, j++)
302
MetaCrtc *crtc = l->data;
304
output->possible_crtcs[j] = crtc;
306
output->n_possible_crtcs = n_tiles;
308
*outputs = g_list_append (*outputs, output);
313
meta_output_dummy_notify_destroy (MetaOutput *output)
315
g_clear_pointer (&output->driver_private, g_free);
319
meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
321
MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager);
322
MetaGpu *gpu = manager_dummy->gpu;
323
unsigned int num_monitors = 1;
324
float *monitor_scales = NULL;
325
const char *num_monitors_str;
326
const char *monitor_scales_str;
327
const char *tiled_monitors_str;
328
gboolean tiled_monitors;
334
/* To control what monitor configuration is generated, there are two available
335
* environmental variables that can be used:
337
* MUTTER_DEBUG_NUM_DUMMY_MONITORS
339
* Specifies the number of dummy monitors to include in the stage. Every
340
* monitor is 1024x786 pixels and they are placed on a horizontal row.
342
* MUTTER_DEBUG_DUMMY_MONITOR_SCALES
344
* A comma separated list that specifies the scales of the dummy monitors.
346
* MUTTER_DEBUG_TILED_DUMMY_MONITORS
348
* If set to "1" the dummy monitors will emulate being tiled, i.e. each have a
349
* unique tile group id, made up of multiple outputs and CRTCs.
351
* For example the following configuration results in two monitors, where the
352
* first one has the monitor scale 1, and the other the monitor scale 2.
354
* MUTTER_DEBUG_NUM_DUMMY_MONITORS=2
355
* MUTTER_DEBUG_DUMMY_MONITOR_SCALES=1,2
356
* MUTTER_DEBUG_TILED_DUMMY_MONITORS=1
358
num_monitors_str = getenv ("MUTTER_DEBUG_NUM_DUMMY_MONITORS");
359
if (num_monitors_str)
361
num_monitors = g_ascii_strtoll (num_monitors_str, NULL, 10);
362
if (num_monitors <= 0)
364
meta_warning ("Invalid number of dummy monitors");
368
if (num_monitors > MAX_MONITORS)
370
meta_warning ("Clamping monitor count to max (%d)",
372
num_monitors = MAX_MONITORS;
376
monitor_scales = g_newa (typeof (*monitor_scales), num_monitors);
377
for (i = 0; i < num_monitors; i++)
378
monitor_scales[i] = 1.0;
380
monitor_scales_str = getenv ("MUTTER_DEBUG_DUMMY_MONITOR_SCALES");
381
if (monitor_scales_str)
383
gchar **scales_str_list;
385
scales_str_list = g_strsplit (monitor_scales_str, ",", -1);
386
if (g_strv_length (scales_str_list) != num_monitors)
387
meta_warning ("Number of specified monitor scales differ from number "
388
"of monitors (defaults to 1).\n");
389
for (i = 0; i < num_monitors && scales_str_list[i]; i++)
391
float scale = g_ascii_strtod (scales_str_list[i], NULL);
393
monitor_scales[i] = scale;
395
g_strfreev (scales_str_list);
398
tiled_monitors_str = g_getenv ("MUTTER_DEBUG_TILED_DUMMY_MONITORS");
399
tiled_monitors = g_strcmp0 (tiled_monitors_str, "1") == 0;
405
for (i = 0; i < num_monitors; i++)
408
append_tiled_monitor (manager,
409
&modes, &crtcs, &outputs, monitor_scales[i]);
411
append_monitor (manager, &modes, &crtcs, &outputs, monitor_scales[i]);
414
meta_gpu_take_modes (gpu, modes);
415
meta_gpu_take_crtcs (gpu, crtcs);
416
meta_gpu_take_outputs (gpu, outputs);
420
meta_monitor_manager_dummy_ensure_initial_config (MetaMonitorManager *manager)
422
MetaMonitorsConfig *config;
424
config = meta_monitor_manager_ensure_configured (manager);
426
if (meta_is_stage_views_enabled ())
427
meta_monitor_manager_update_logical_state (manager, config);
429
meta_monitor_manager_update_logical_state_derived (manager, NULL);
433
apply_crtc_assignments (MetaMonitorManager *manager,
434
MetaCrtcInfo **crtcs,
435
unsigned int n_crtcs,
436
MetaOutputInfo **outputs,
437
unsigned int n_outputs)
439
MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager);
443
for (i = 0; i < n_crtcs; i++)
445
MetaCrtcInfo *crtc_info = crtcs[i];
446
MetaCrtc *crtc = crtc_info->crtc;
447
crtc->is_dirty = TRUE;
449
if (crtc_info->mode == NULL)
453
crtc->rect.width = 0;
454
crtc->rect.height = 0;
455
crtc->current_mode = NULL;
464
mode = crtc_info->mode;
466
if (meta_monitor_transform_is_rotated (crtc_info->transform))
468
width = mode->height;
469
height = mode->width;
474
height = mode->height;
477
crtc->rect.x = crtc_info->x;
478
crtc->rect.y = crtc_info->y;
479
crtc->rect.width = width;
480
crtc->rect.height = height;
481
crtc->current_mode = mode;
482
crtc->transform = crtc_info->transform;
484
for (j = 0; j < crtc_info->outputs->len; j++)
486
output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
488
output->is_dirty = TRUE;
494
for (i = 0; i < n_outputs; i++)
496
MetaOutputInfo *output_info = outputs[i];
497
MetaOutput *output = output_info->output;
499
output->is_primary = output_info->is_primary;
500
output->is_presentation = output_info->is_presentation;
503
/* Disable CRTCs not mentioned in the list */
504
for (l = meta_gpu_get_crtcs (manager_dummy->gpu); l; l = l->next)
506
MetaCrtc *crtc = l->data;
508
crtc->logical_monitor = NULL;
512
crtc->is_dirty = FALSE;
518
crtc->rect.width = 0;
519
crtc->rect.height = 0;
520
crtc->current_mode = NULL;
523
/* Disable outputs not mentioned in the list */
524
for (l = meta_gpu_get_outputs (manager_dummy->gpu); l; l = l->next)
526
MetaOutput *output = l->data;
528
if (output->is_dirty)
530
output->is_dirty = FALSE;
535
output->is_primary = FALSE;
540
update_screen_size (MetaMonitorManager *manager,
541
MetaMonitorsConfig *config)
544
int screen_width = 0;
545
int screen_height = 0;
547
for (l = config->logical_monitor_configs; l; l = l->next)
549
MetaLogicalMonitorConfig *logical_monitor_config = l->data;
553
right_edge = (logical_monitor_config->layout.width +
554
logical_monitor_config->layout.x);
555
if (right_edge > screen_width)
556
screen_width = right_edge;
558
bottom_edge = (logical_monitor_config->layout.height +
559
logical_monitor_config->layout.y);
560
if (bottom_edge > screen_height)
561
screen_height = bottom_edge;
564
manager->screen_width = screen_width;
565
manager->screen_height = screen_height;
569
meta_monitor_manager_dummy_apply_monitors_config (MetaMonitorManager *manager,
570
MetaMonitorsConfig *config,
571
MetaMonitorsConfigMethod method,
574
GPtrArray *crtc_infos;
575
GPtrArray *output_infos;
579
manager->screen_width = META_MONITOR_MANAGER_MIN_SCREEN_WIDTH;
580
manager->screen_height = META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT;
582
meta_monitor_manager_rebuild (manager, NULL);
586
if (!meta_monitor_config_manager_assign (manager, config,
587
&crtc_infos, &output_infos,
591
if (method == META_MONITORS_CONFIG_METHOD_VERIFY)
593
g_ptr_array_free (crtc_infos, TRUE);
594
g_ptr_array_free (output_infos, TRUE);
598
apply_crtc_assignments (manager,
599
(MetaCrtcInfo **) crtc_infos->pdata,
601
(MetaOutputInfo **) output_infos->pdata,
604
g_ptr_array_free (crtc_infos, TRUE);
605
g_ptr_array_free (output_infos, TRUE);
607
update_screen_size (manager, config);
608
meta_monitor_manager_rebuild (manager, config);
614
meta_monitor_manager_dummy_is_transform_handled (MetaMonitorManager *manager,
616
MetaMonitorTransform transform)
618
MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager);
620
return manager_dummy->is_transform_handled;
624
meta_monitor_manager_dummy_calculate_monitor_mode_scale (MetaMonitorManager *manager,
625
MetaMonitor *monitor,
626
MetaMonitorMode *monitor_mode)
629
MetaOutputDummy *output_dummy;
631
output = meta_monitor_get_main_output (monitor);
632
output_dummy = output->driver_private;
634
return output_dummy->scale;
638
meta_monitor_manager_dummy_calculate_supported_scales (MetaMonitorManager *manager,
639
MetaLogicalMonitorLayoutMode layout_mode,
640
MetaMonitor *monitor,
641
MetaMonitorMode *monitor_mode,
642
int *n_supported_scales)
644
MetaMonitorScalesConstraint constraints =
645
META_MONITOR_SCALES_CONSTRAINT_NONE;
649
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
651
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
652
constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
656
return meta_monitor_calculate_supported_scales (monitor, monitor_mode,
662
is_monitor_framebuffers_scaled (void)
664
MetaBackend *backend = meta_get_backend ();
665
MetaSettings *settings = meta_backend_get_settings (backend);
667
return meta_settings_is_experimental_feature_enabled (
669
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER);
672
static MetaMonitorManagerCapability
673
meta_monitor_manager_dummy_get_capabilities (MetaMonitorManager *manager)
675
MetaBackend *backend = meta_get_backend ();
676
MetaSettings *settings = meta_backend_get_settings (backend);
677
MetaMonitorManagerCapability capabilities =
678
META_MONITOR_MANAGER_CAPABILITY_NONE;
680
capabilities |= META_MONITOR_MANAGER_CAPABILITY_MIRRORING;
682
if (meta_settings_is_experimental_feature_enabled (
684
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER))
685
capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE;
691
meta_monitor_manager_dummy_get_max_screen_size (MetaMonitorManager *manager,
695
if (meta_is_stage_views_enabled ())
704
static MetaLogicalMonitorLayoutMode
705
meta_monitor_manager_dummy_get_default_layout_mode (MetaMonitorManager *manager)
707
if (!meta_is_stage_views_enabled ())
708
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
710
if (is_monitor_framebuffers_scaled ())
711
return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
713
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
717
meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass)
719
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
721
manager_class->ensure_initial_config = meta_monitor_manager_dummy_ensure_initial_config;
722
manager_class->apply_monitors_config = meta_monitor_manager_dummy_apply_monitors_config;
723
manager_class->is_transform_handled = meta_monitor_manager_dummy_is_transform_handled;
724
manager_class->calculate_monitor_mode_scale = meta_monitor_manager_dummy_calculate_monitor_mode_scale;
725
manager_class->calculate_supported_scales = meta_monitor_manager_dummy_calculate_supported_scales;
726
manager_class->get_capabilities = meta_monitor_manager_dummy_get_capabilities;
727
manager_class->get_max_screen_size = meta_monitor_manager_dummy_get_max_screen_size;
728
manager_class->get_default_layout_mode = meta_monitor_manager_dummy_get_default_layout_mode;
732
meta_monitor_manager_dummy_init (MetaMonitorManagerDummy *manager_dummy)
734
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_dummy);
735
const char *nested_offscreen_transform;
737
nested_offscreen_transform =
738
g_getenv ("MUTTER_DEBUG_NESTED_OFFSCREEN_TRANSFORM");
739
if (g_strcmp0 (nested_offscreen_transform, "1") == 0)
740
manager_dummy->is_transform_handled = FALSE;
742
manager_dummy->is_transform_handled = TRUE;
744
manager_dummy->gpu = g_object_new (META_TYPE_GPU_DUMMY,
745
"monitor-manager", manager,
747
meta_monitor_manager_add_gpu (manager, manager_dummy->gpu);
751
meta_gpu_dummy_read_current (MetaGpu *gpu,
754
MetaMonitorManager *manager = meta_gpu_get_monitor_manager (gpu);
756
meta_monitor_manager_dummy_read_current (manager);
762
meta_gpu_dummy_init (MetaGpuDummy *gpu_dummy)
767
meta_gpu_dummy_class_init (MetaGpuDummyClass *klass)
769
MetaGpuClass *gpu_class = META_GPU_CLASS (klass);
771
gpu_class->read_current = meta_gpu_dummy_read_current;