1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
3 /*
4 * Copyright (C) 2016 Red Hat, Inc.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "config.h"
21
22 #include "tests/meta-monitor-manager-test.h"
23
24 #include "backends/meta-backend-private.h"
25 #include "backends/meta-crtc.h"
26 #include "backends/meta-gpu.h"
27 #include "backends/meta-monitor-config-manager.h"
28 #include "backends/meta-output.h"
29 #include "tests/meta-backend-test.h"
30 #include "tests/monitor-test-utils.h"
31
32 G_DEFINE_TYPE (MetaCrtcTest, meta_crtc_test, META_TYPE_CRTC)
33 G_DEFINE_TYPE (MetaOutputTest, meta_output_test, META_TYPE_OUTPUT)
34
35 struct _MetaMonitorManagerTest
36 {
37 MetaMonitorManager parent;
38
39 gboolean handles_transforms;
40
41 int tiled_monitor_count;
42
43 MetaMonitorTestSetup *test_setup;
44 };
45
G_DEFINE_TYPE(MetaMonitorManagerTest,meta_monitor_manager_test,META_TYPE_MONITOR_MANAGER)46 G_DEFINE_TYPE (MetaMonitorManagerTest, meta_monitor_manager_test,
47 META_TYPE_MONITOR_MANAGER)
48
49 static CreateTestSetupFunc initial_setup_func;
50
51 void
52 meta_monitor_manager_test_init_test_setup (CreateTestSetupFunc func)
53 {
54 initial_setup_func = func;
55 }
56
57 void
meta_monitor_manager_test_emulate_hotplug(MetaMonitorManagerTest * manager_test,MetaMonitorTestSetup * test_setup)58 meta_monitor_manager_test_emulate_hotplug (MetaMonitorManagerTest *manager_test,
59 MetaMonitorTestSetup *test_setup)
60 {
61 MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_test);
62 MetaMonitorTestSetup *old_test_setup;
63
64 old_test_setup = manager_test->test_setup;
65 manager_test->test_setup = test_setup;
66
67 meta_monitor_manager_reload (manager);
68
69 g_free (old_test_setup);
70 }
71
72 void
meta_monitor_manager_test_set_handles_transforms(MetaMonitorManagerTest * manager_test,gboolean handles_transforms)73 meta_monitor_manager_test_set_handles_transforms (MetaMonitorManagerTest *manager_test,
74 gboolean handles_transforms)
75 {
76 g_assert (handles_transforms || meta_is_stage_views_enabled());
77
78 manager_test->handles_transforms = handles_transforms;
79 }
80
81 int
meta_monitor_manager_test_get_tiled_monitor_count(MetaMonitorManagerTest * manager_test)82 meta_monitor_manager_test_get_tiled_monitor_count (MetaMonitorManagerTest *manager_test)
83 {
84 return manager_test->tiled_monitor_count;
85 }
86
87 void
meta_monitor_manager_test_read_current(MetaMonitorManager * manager)88 meta_monitor_manager_test_read_current (MetaMonitorManager *manager)
89 {
90 MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (manager);
91 MetaBackend *backend = meta_monitor_manager_get_backend (manager);
92 MetaBackendTest *backend_test = META_BACKEND_TEST (backend);
93 MetaGpu *gpu = meta_backend_test_get_gpu (backend_test);
94
95 g_assert (manager_test->test_setup);
96
97 meta_gpu_take_modes (gpu, manager_test->test_setup->modes);
98 meta_gpu_take_crtcs (gpu, manager_test->test_setup->crtcs);
99 meta_gpu_take_outputs (gpu, manager_test->test_setup->outputs);
100 }
101
102 static void
meta_monitor_manager_test_ensure_initial_config(MetaMonitorManager * manager)103 meta_monitor_manager_test_ensure_initial_config (MetaMonitorManager *manager)
104 {
105 MetaMonitorsConfig *config;
106
107 config = meta_monitor_manager_ensure_configured (manager);
108
109 if (meta_is_stage_views_enabled ())
110 {
111 meta_monitor_manager_update_logical_state (manager, config);
112 }
113 else
114 {
115 meta_monitor_manager_update_logical_state_derived (manager, NULL);
116 }
117 }
118
119 static void
apply_crtc_assignments(MetaMonitorManager * manager,MetaCrtcAssignment ** crtcs,unsigned int n_crtcs,MetaOutputAssignment ** outputs,unsigned int n_outputs)120 apply_crtc_assignments (MetaMonitorManager *manager,
121 MetaCrtcAssignment **crtcs,
122 unsigned int n_crtcs,
123 MetaOutputAssignment **outputs,
124 unsigned int n_outputs)
125 {
126 MetaBackend *backend = meta_monitor_manager_get_backend (manager);
127 MetaBackendTest *backend_test = META_BACKEND_TEST (backend);
128 MetaGpu *gpu = meta_backend_test_get_gpu (backend_test);
129 g_autoptr (GList) to_configure_outputs = NULL;
130 g_autoptr (GList) to_configure_crtcs = NULL;
131 unsigned int i;
132
133 to_configure_outputs = g_list_copy (meta_gpu_get_outputs (gpu));
134 to_configure_crtcs = g_list_copy (meta_gpu_get_crtcs (gpu));
135
136 for (i = 0; i < n_crtcs; i++)
137 {
138 MetaCrtcAssignment *crtc_assignment = crtcs[i];
139 MetaCrtc *crtc = crtc_assignment->crtc;
140
141 to_configure_crtcs = g_list_remove (to_configure_crtcs, crtc);
142
143 if (crtc_assignment->mode == NULL)
144 {
145 meta_crtc_unset_config (crtc);
146 }
147 else
148 {
149 unsigned int j;
150
151 meta_crtc_set_config (crtc,
152 &crtc_assignment->layout,
153 crtc_assignment->mode,
154 crtc_assignment->transform);
155
156 for (j = 0; j < crtc_assignment->outputs->len; j++)
157 {
158 MetaOutput *output;
159 MetaOutputAssignment *output_assignment;
160
161 output = ((MetaOutput**) crtc_assignment->outputs->pdata)[j];
162
163 to_configure_outputs = g_list_remove (to_configure_outputs,
164 output);
165
166 output_assignment = meta_find_output_assignment (outputs,
167 n_outputs,
168 output);
169 meta_output_assign_crtc (output, crtc, output_assignment);
170 }
171 }
172 }
173
174 g_list_foreach (to_configure_crtcs,
175 (GFunc) meta_crtc_unset_config,
176 NULL);
177 g_list_foreach (to_configure_outputs,
178 (GFunc) meta_output_unassign_crtc,
179 NULL);
180 }
181
182 static void
update_screen_size(MetaMonitorManager * manager,MetaMonitorsConfig * config)183 update_screen_size (MetaMonitorManager *manager,
184 MetaMonitorsConfig *config)
185 {
186 GList *l;
187 int screen_width = 0;
188 int screen_height = 0;
189
190 for (l = config->logical_monitor_configs; l; l = l->next)
191 {
192 MetaLogicalMonitorConfig *logical_monitor_config = l->data;
193 int right_edge;
194 int bottom_edge;
195
196 right_edge = (logical_monitor_config->layout.width +
197 logical_monitor_config->layout.x);
198 if (right_edge > screen_width)
199 screen_width = right_edge;
200
201 bottom_edge = (logical_monitor_config->layout.height +
202 logical_monitor_config->layout.y);
203 if (bottom_edge > screen_height)
204 screen_height = bottom_edge;
205 }
206
207 manager->screen_width = screen_width;
208 manager->screen_height = screen_height;
209 }
210
211 static gboolean
meta_monitor_manager_test_apply_monitors_config(MetaMonitorManager * manager,MetaMonitorsConfig * config,MetaMonitorsConfigMethod method,GError ** error)212 meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager *manager,
213 MetaMonitorsConfig *config,
214 MetaMonitorsConfigMethod method,
215 GError **error)
216 {
217 GPtrArray *crtc_assignments;
218 GPtrArray *output_assignments;
219
220 if (!config)
221 {
222 manager->screen_width = META_MONITOR_MANAGER_MIN_SCREEN_WIDTH;
223 manager->screen_height = META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT;
224
225 if (meta_is_stage_views_enabled ())
226 meta_monitor_manager_rebuild (manager, NULL);
227 else
228 meta_monitor_manager_rebuild_derived (manager, config);
229
230 return TRUE;
231 }
232
233 if (!meta_monitor_config_manager_assign (manager, config,
234 &crtc_assignments,
235 &output_assignments,
236 error))
237 return FALSE;
238
239 if (method == META_MONITORS_CONFIG_METHOD_VERIFY)
240 {
241 g_ptr_array_free (crtc_assignments, TRUE);
242 g_ptr_array_free (output_assignments, TRUE);
243 return TRUE;
244 }
245
246 apply_crtc_assignments (manager,
247 (MetaCrtcAssignment **) crtc_assignments->pdata,
248 crtc_assignments->len,
249 (MetaOutputAssignment **) output_assignments->pdata,
250 output_assignments->len);
251
252 g_ptr_array_free (crtc_assignments, TRUE);
253 g_ptr_array_free (output_assignments, TRUE);
254
255 update_screen_size (manager, config);
256
257 if (meta_is_stage_views_enabled ())
258 meta_monitor_manager_rebuild (manager, config);
259 else
260 meta_monitor_manager_rebuild_derived (manager, config);
261
262 return TRUE;
263 }
264
265 static void
meta_monitor_manager_test_tiled_monitor_added(MetaMonitorManager * manager,MetaMonitor * monitor)266 meta_monitor_manager_test_tiled_monitor_added (MetaMonitorManager *manager,
267 MetaMonitor *monitor)
268 {
269 MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (manager);
270
271 manager_test->tiled_monitor_count++;
272 }
273
274 static void
meta_monitor_manager_test_tiled_monitor_removed(MetaMonitorManager * manager,MetaMonitor * monitor)275 meta_monitor_manager_test_tiled_monitor_removed (MetaMonitorManager *manager,
276 MetaMonitor *monitor)
277 {
278 MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (manager);
279
280 manager_test->tiled_monitor_count--;
281 }
282
283 static gboolean
meta_monitor_manager_test_is_transform_handled(MetaMonitorManager * manager,MetaCrtc * crtc,MetaMonitorTransform transform)284 meta_monitor_manager_test_is_transform_handled (MetaMonitorManager *manager,
285 MetaCrtc *crtc,
286 MetaMonitorTransform transform)
287 {
288 MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (manager);
289
290 return manager_test->handles_transforms;
291 }
292
293 static float
meta_monitor_manager_test_calculate_monitor_mode_scale(MetaMonitorManager * manager,MetaLogicalMonitorLayoutMode layout_mode,MetaMonitor * monitor,MetaMonitorMode * monitor_mode)294 meta_monitor_manager_test_calculate_monitor_mode_scale (MetaMonitorManager *manager,
295 MetaLogicalMonitorLayoutMode layout_mode,
296 MetaMonitor *monitor,
297 MetaMonitorMode *monitor_mode)
298 {
299 MetaOutput *output;
300 MetaOutputTest *output_test;
301
302 output = meta_monitor_get_main_output (monitor);
303 output_test = META_OUTPUT_TEST (output);
304
305 if (output_test)
306 return output_test->scale;
307 else
308 return 1;
309 }
310
311 static float *
meta_monitor_manager_test_calculate_supported_scales(MetaMonitorManager * manager,MetaLogicalMonitorLayoutMode layout_mode,MetaMonitor * monitor,MetaMonitorMode * monitor_mode,int * n_supported_scales)312 meta_monitor_manager_test_calculate_supported_scales (MetaMonitorManager *manager,
313 MetaLogicalMonitorLayoutMode layout_mode,
314 MetaMonitor *monitor,
315 MetaMonitorMode *monitor_mode,
316 int *n_supported_scales)
317 {
318 MetaMonitorScalesConstraint constraints =
319 META_MONITOR_SCALES_CONSTRAINT_NONE;
320
321 switch (layout_mode)
322 {
323 case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
324 break;
325 case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
326 constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
327 break;
328 }
329
330 return meta_monitor_calculate_supported_scales (monitor, monitor_mode,
331 constraints,
332 n_supported_scales);
333 }
334
335 static gboolean
is_monitor_framebuffer_scaled(void)336 is_monitor_framebuffer_scaled (void)
337 {
338 MetaBackend *backend = meta_get_backend ();
339 MetaSettings *settings = meta_backend_get_settings (backend);
340
341 return meta_settings_is_experimental_feature_enabled (
342 settings,
343 META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER);
344 }
345
346 static MetaMonitorManagerCapability
meta_monitor_manager_test_get_capabilities(MetaMonitorManager * manager)347 meta_monitor_manager_test_get_capabilities (MetaMonitorManager *manager)
348 {
349 MetaMonitorManagerCapability capabilities =
350 META_MONITOR_MANAGER_CAPABILITY_NONE;
351
352 if (is_monitor_framebuffer_scaled ())
353 capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE;
354
355 return capabilities;
356 }
357
358 static gboolean
meta_monitor_manager_test_get_max_screen_size(MetaMonitorManager * manager,int * max_width,int * max_height)359 meta_monitor_manager_test_get_max_screen_size (MetaMonitorManager *manager,
360 int *max_width,
361 int *max_height)
362 {
363 if (meta_is_stage_views_enabled ())
364 return FALSE;
365
366 *max_width = 65535;
367 *max_height = 65535;
368
369 return TRUE;
370 }
371
372 static MetaLogicalMonitorLayoutMode
meta_monitor_manager_test_get_default_layout_mode(MetaMonitorManager * manager)373 meta_monitor_manager_test_get_default_layout_mode (MetaMonitorManager *manager)
374 {
375 if (!meta_is_stage_views_enabled ())
376 return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
377
378 if (is_monitor_framebuffer_scaled ())
379 return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
380 else
381 return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
382 }
383
384 static void
meta_monitor_manager_test_dispose(GObject * object)385 meta_monitor_manager_test_dispose (GObject *object)
386 {
387 MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (object);
388
389 g_clear_pointer (&manager_test->test_setup, g_free);
390
391 G_OBJECT_CLASS (meta_monitor_manager_test_parent_class)->dispose (object);
392 }
393
394 static MonitorTestCaseSetup default_test_case_setup = {
395 .modes = {
396 {
397 .width = 800,
398 .height = 600,
399 .refresh_rate = 60.0
400 }
401 },
402 .n_modes = 1,
403 .outputs = {
404 {
405 .crtc = 0,
406 .modes = { 0 },
407 .n_modes = 1,
408 .preferred_mode = 0,
409 .possible_crtcs = { 0 },
410 .n_possible_crtcs = 1,
411 .width_mm = 222,
412 .height_mm = 125
413 },
414
415 },
416 .n_outputs = 1,
417 .crtcs = {
418 {
419 .current_mode = 0
420 },
421 },
422 .n_crtcs = 1,
423 };
424
425 static MetaMonitorTestSetup *
create_default_test_setup(void)426 create_default_test_setup (void)
427 {
428 return create_monitor_test_setup (&default_test_case_setup,
429 MONITOR_TEST_FLAG_NO_STORED);
430 }
431
432 static void
meta_monitor_manager_test_constructed(GObject * object)433 meta_monitor_manager_test_constructed (GObject *object)
434 {
435 MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (object);
436
437 if (initial_setup_func)
438 manager_test->test_setup = initial_setup_func ();
439 else
440 manager_test->test_setup = create_default_test_setup ();
441
442 G_OBJECT_CLASS (meta_monitor_manager_test_parent_class)->constructed (object);
443 }
444
445 static void
meta_monitor_manager_test_init(MetaMonitorManagerTest * manager_test)446 meta_monitor_manager_test_init (MetaMonitorManagerTest *manager_test)
447 {
448 manager_test->handles_transforms = TRUE;
449 }
450
451 static void
meta_monitor_manager_test_class_init(MetaMonitorManagerTestClass * klass)452 meta_monitor_manager_test_class_init (MetaMonitorManagerTestClass *klass)
453 {
454 GObjectClass *object_class = G_OBJECT_CLASS (klass);
455 MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
456
457 object_class->dispose = meta_monitor_manager_test_dispose;
458 object_class->constructed = meta_monitor_manager_test_constructed;
459
460 manager_class->ensure_initial_config = meta_monitor_manager_test_ensure_initial_config;
461 manager_class->apply_monitors_config = meta_monitor_manager_test_apply_monitors_config;
462 manager_class->tiled_monitor_added = meta_monitor_manager_test_tiled_monitor_added;
463 manager_class->tiled_monitor_removed = meta_monitor_manager_test_tiled_monitor_removed;
464 manager_class->is_transform_handled = meta_monitor_manager_test_is_transform_handled;
465 manager_class->calculate_monitor_mode_scale = meta_monitor_manager_test_calculate_monitor_mode_scale;
466 manager_class->calculate_supported_scales = meta_monitor_manager_test_calculate_supported_scales;
467 manager_class->get_capabilities = meta_monitor_manager_test_get_capabilities;
468 manager_class->get_max_screen_size = meta_monitor_manager_test_get_max_screen_size;
469 manager_class->get_default_layout_mode = meta_monitor_manager_test_get_default_layout_mode;
470 }
471
472 static void
meta_output_test_init(MetaOutputTest * output_test)473 meta_output_test_init (MetaOutputTest *output_test)
474 {
475 output_test->scale = 1;
476 }
477
478 static void
meta_output_test_class_init(MetaOutputTestClass * klass)479 meta_output_test_class_init (MetaOutputTestClass *klass)
480 {
481 }
482
483 static void
meta_crtc_test_init(MetaCrtcTest * crtc_test)484 meta_crtc_test_init (MetaCrtcTest *crtc_test)
485 {
486 }
487
488 static void
meta_crtc_test_class_init(MetaCrtcTestClass * klass)489 meta_crtc_test_class_init (MetaCrtcTestClass *klass)
490 {
491 }
492