1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
3 /*
4 * Copyright (C) 2017 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/monitor-test-utils.h"
23
24 #include <float.h>
25
26 #include "backends/meta-backend-private.h"
27 #include "backends/meta-crtc.h"
28 #include "backends/meta-logical-monitor.h"
29 #include "backends/meta-monitor-config-manager.h"
30 #include "backends/meta-monitor-config-store.h"
31 #include "backends/meta-output.h"
32 #include "tests/meta-test-utils.h"
33 #include "meta-backend-test.h"
34
35 MetaGpu *
test_get_gpu(void)36 test_get_gpu (void)
37 {
38 return META_GPU (meta_backend_get_gpus (meta_get_backend ())->data);
39 }
40
41 void
set_custom_monitor_config(const char * filename)42 set_custom_monitor_config (const char *filename)
43 {
44 MetaBackend *backend = meta_get_backend ();
45 MetaMonitorManager *monitor_manager =
46 meta_backend_get_monitor_manager (backend);
47 MetaMonitorConfigManager *config_manager = monitor_manager->config_manager;
48 MetaMonitorConfigStore *config_store;
49 GError *error = NULL;
50 const char *path;
51
52 g_assert_nonnull (config_manager);
53
54 config_store = meta_monitor_config_manager_get_store (config_manager);
55
56 path = g_test_get_filename (G_TEST_DIST, "tests", "monitor-configs",
57 filename, NULL);
58 if (!meta_monitor_config_store_set_custom (config_store, path, NULL,
59 &error))
60 g_error ("Failed to set custom config: %s", error->message);
61 }
62
63 char *
read_file(const char * file_path)64 read_file (const char *file_path)
65 {
66 g_autoptr (GFile) file = NULL;
67 g_autoptr (GFileInputStream) input_stream = NULL;
68 g_autoptr (GFileInfo) file_info = NULL;
69 goffset file_size;
70 gsize bytes_read;
71 g_autofree char *buffer = NULL;
72 GError *error = NULL;
73
74 file = g_file_new_for_path (file_path);
75 input_stream = g_file_read (file, NULL, &error);
76 if (!input_stream)
77 g_error ("Failed to read migrated config file: %s", error->message);
78
79 file_info = g_file_input_stream_query_info (input_stream,
80 G_FILE_ATTRIBUTE_STANDARD_SIZE,
81 NULL, &error);
82 if (!file_info)
83 g_error ("Failed to read file info: %s", error->message);
84
85 file_size = g_file_info_get_size (file_info);
86 buffer = g_malloc0 (file_size + 1);
87
88 if (!g_input_stream_read_all (G_INPUT_STREAM (input_stream),
89 buffer, file_size, &bytes_read, NULL, &error))
90 g_error ("Failed to read file content: %s", error->message);
91 g_assert_cmpint ((goffset) bytes_read, ==, file_size);
92
93 return g_steal_pointer (&buffer);
94 }
95
96 static MetaOutput *
output_from_winsys_id(MetaBackend * backend,uint64_t output_id)97 output_from_winsys_id (MetaBackend *backend,
98 uint64_t output_id)
99 {
100 MetaGpu *gpu = meta_backend_test_get_gpu (META_BACKEND_TEST (backend));
101 GList *l;
102
103 for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
104 {
105 MetaOutput *output = l->data;
106
107 if (meta_output_get_id (output) == output_id)
108 return output;
109 }
110
111 return NULL;
112 }
113
114 typedef struct _CheckMonitorModeData
115 {
116 MetaBackend *backend;
117 MetaTestCaseMonitorCrtcMode *expect_crtc_mode_iter;
118 } CheckMonitorModeData;
119
120 static gboolean
check_monitor_mode(MetaMonitor * monitor,MetaMonitorMode * mode,MetaMonitorCrtcMode * monitor_crtc_mode,gpointer user_data,GError ** error)121 check_monitor_mode (MetaMonitor *monitor,
122 MetaMonitorMode *mode,
123 MetaMonitorCrtcMode *monitor_crtc_mode,
124 gpointer user_data,
125 GError **error)
126 {
127 CheckMonitorModeData *data = user_data;
128 MetaBackend *backend = data->backend;
129 MetaOutput *output;
130 MetaCrtcMode *crtc_mode;
131 int expect_crtc_mode_index;
132
133 output = output_from_winsys_id (backend,
134 data->expect_crtc_mode_iter->output);
135 g_assert (monitor_crtc_mode->output == output);
136
137 expect_crtc_mode_index = data->expect_crtc_mode_iter->crtc_mode;
138 if (expect_crtc_mode_index == -1)
139 {
140 crtc_mode = NULL;
141 }
142 else
143 {
144 MetaGpu *gpu = meta_output_get_gpu (output);
145
146 crtc_mode = g_list_nth_data (meta_gpu_get_modes (gpu),
147 expect_crtc_mode_index);
148 }
149 g_assert (monitor_crtc_mode->crtc_mode == crtc_mode);
150
151 if (crtc_mode)
152 {
153 const MetaCrtcModeInfo *crtc_mode_info =
154 meta_crtc_mode_get_info (crtc_mode);
155 float refresh_rate;
156 MetaCrtcModeFlag flags;
157
158 refresh_rate = meta_monitor_mode_get_refresh_rate (mode);
159 flags = meta_monitor_mode_get_flags (mode);
160
161 g_assert_cmpfloat (refresh_rate, ==, crtc_mode_info->refresh_rate);
162 g_assert_cmpint (flags, ==, (crtc_mode_info->flags &
163 HANDLED_CRTC_MODE_FLAGS));
164 }
165
166 data->expect_crtc_mode_iter++;
167
168 return TRUE;
169 }
170
171 static gboolean
check_current_monitor_mode(MetaMonitor * monitor,MetaMonitorMode * mode,MetaMonitorCrtcMode * monitor_crtc_mode,gpointer user_data,GError ** error)172 check_current_monitor_mode (MetaMonitor *monitor,
173 MetaMonitorMode *mode,
174 MetaMonitorCrtcMode *monitor_crtc_mode,
175 gpointer user_data,
176 GError **error)
177 {
178 CheckMonitorModeData *data = user_data;
179 MetaBackend *backend = data->backend;
180 MetaOutput *output;
181 MetaCrtc *crtc;
182
183 output = output_from_winsys_id (backend,
184 data->expect_crtc_mode_iter->output);
185 crtc = meta_output_get_assigned_crtc (output);
186
187 if (data->expect_crtc_mode_iter->crtc_mode == -1)
188 {
189 g_assert_null (crtc);
190 }
191 else
192 {
193 const MetaCrtcConfig *crtc_config;
194 MetaLogicalMonitor *logical_monitor;
195
196 g_assert_nonnull (crtc);
197
198 crtc_config = meta_crtc_get_config (crtc);
199 g_assert_nonnull (crtc_config);
200
201 g_assert (monitor_crtc_mode->crtc_mode == crtc_config->mode);
202
203 logical_monitor = meta_monitor_get_logical_monitor (monitor);
204 g_assert_nonnull (logical_monitor);
205 }
206
207
208 data->expect_crtc_mode_iter++;
209
210 return TRUE;
211 }
212
213 static MetaLogicalMonitor *
logical_monitor_from_layout(MetaMonitorManager * monitor_manager,MetaRectangle * layout)214 logical_monitor_from_layout (MetaMonitorManager *monitor_manager,
215 MetaRectangle *layout)
216 {
217 GList *l;
218
219 for (l = monitor_manager->logical_monitors; l; l = l->next)
220 {
221 MetaLogicalMonitor *logical_monitor = l->data;
222
223 if (meta_rectangle_equal (layout, &logical_monitor->rect))
224 return logical_monitor;
225 }
226
227 return NULL;
228 }
229
230 static void
check_logical_monitor(MetaMonitorManager * monitor_manager,MonitorTestCaseLogicalMonitor * test_logical_monitor,GList ** all_crtcs)231 check_logical_monitor (MetaMonitorManager *monitor_manager,
232 MonitorTestCaseLogicalMonitor *test_logical_monitor,
233 GList **all_crtcs)
234 {
235 MetaLogicalMonitor *logical_monitor;
236 MetaOutput *primary_output;
237 GList *monitors;
238 GList *l;
239 int i;
240
241 logical_monitor = logical_monitor_from_layout (monitor_manager,
242 &test_logical_monitor->layout);
243 g_assert_nonnull (logical_monitor);
244
245 g_assert_cmpint (logical_monitor->rect.x,
246 ==,
247 test_logical_monitor->layout.x);
248 g_assert_cmpint (logical_monitor->rect.y,
249 ==,
250 test_logical_monitor->layout.y);
251 g_assert_cmpint (logical_monitor->rect.width,
252 ==,
253 test_logical_monitor->layout.width);
254 g_assert_cmpint (logical_monitor->rect.height,
255 ==,
256 test_logical_monitor->layout.height);
257 g_assert_cmpfloat (logical_monitor->scale,
258 ==,
259 test_logical_monitor->scale);
260 g_assert_cmpuint (logical_monitor->transform,
261 ==,
262 test_logical_monitor->transform);
263
264 if (logical_monitor == monitor_manager->primary_logical_monitor)
265 g_assert (meta_logical_monitor_is_primary (logical_monitor));
266
267 primary_output = NULL;
268 monitors = meta_logical_monitor_get_monitors (logical_monitor);
269 g_assert_cmpint ((int) g_list_length (monitors),
270 ==,
271 test_logical_monitor->n_monitors);
272
273 for (i = 0; i < test_logical_monitor->n_monitors; i++)
274 {
275 MetaMonitor *monitor =
276 g_list_nth (monitor_manager->monitors,
277 test_logical_monitor->monitors[i])->data;
278
279 g_assert_nonnull (g_list_find (monitors, monitor));
280 }
281
282 for (l = monitors; l; l = l->next)
283 {
284 MetaMonitor *monitor = l->data;
285 GList *outputs;
286 GList *l_output;
287
288 outputs = meta_monitor_get_outputs (monitor);
289 for (l_output = outputs; l_output; l_output = l_output->next)
290 {
291 MetaOutput *output = l_output->data;
292 MetaCrtc *crtc;
293
294 g_assert (meta_output_get_monitor (output) == monitor);
295
296 if (meta_output_is_primary (output))
297 {
298 g_assert_null (primary_output);
299 primary_output = output;
300 }
301
302 crtc = meta_output_get_assigned_crtc (output);
303 if (crtc)
304 {
305 g_assert (meta_monitor_get_logical_monitor (monitor) ==
306 logical_monitor);
307 g_assert (g_list_find ((GList *) meta_crtc_get_outputs (crtc),
308 output));
309 *all_crtcs = g_list_remove (*all_crtcs, crtc);
310 }
311 else
312 {
313 g_assert_null (crtc);
314 }
315
316 g_assert_cmpint (logical_monitor->is_presentation,
317 ==,
318 meta_output_is_presentation (output));
319 }
320 }
321
322 if (logical_monitor == monitor_manager->primary_logical_monitor)
323 g_assert_nonnull (primary_output);
324 }
325
326 void
check_monitor_configuration(MonitorTestCaseExpect * expect)327 check_monitor_configuration (MonitorTestCaseExpect *expect)
328 {
329 MetaBackend *backend = meta_get_backend ();
330 MetaRenderer *renderer = meta_backend_get_renderer (backend);
331 MetaMonitorManager *monitor_manager =
332 meta_backend_get_monitor_manager (backend);
333 MetaMonitorManagerTest *monitor_manager_test =
334 META_MONITOR_MANAGER_TEST (monitor_manager);
335 MetaGpu *gpu = meta_backend_test_get_gpu (META_BACKEND_TEST (backend));
336 int tiled_monitor_count;
337 GList *monitors;
338 GList *crtcs;
339 int n_logical_monitors;
340 GList *all_crtcs;
341 GList *l;
342 int i;
343
344 g_assert_cmpint (monitor_manager->screen_width,
345 ==,
346 expect->screen_width);
347 g_assert_cmpint (monitor_manager->screen_height,
348 ==,
349 expect->screen_height);
350 g_assert_cmpint ((int) g_list_length (meta_gpu_get_outputs (gpu)),
351 ==,
352 expect->n_outputs);
353 g_assert_cmpint ((int) g_list_length (meta_gpu_get_crtcs (gpu)),
354 ==,
355 expect->n_crtcs);
356
357 tiled_monitor_count =
358 meta_monitor_manager_test_get_tiled_monitor_count (monitor_manager_test);
359 g_assert_cmpint (tiled_monitor_count,
360 ==,
361 expect->n_tiled_monitors);
362
363 monitors = meta_monitor_manager_get_monitors (monitor_manager);
364 g_assert_cmpint ((int) g_list_length (monitors),
365 ==,
366 expect->n_monitors);
367 for (l = monitors, i = 0; l; l = l->next, i++)
368 {
369 MetaMonitor *monitor = l->data;
370 MetaOutput *main_output;
371 const MetaOutputInfo *main_output_info;
372 GList *outputs;
373 GList *l_output;
374 int j;
375 int width_mm, height_mm;
376 GList *modes;
377 GList *l_mode;
378 MetaMonitorMode *current_mode;
379 int expected_current_mode_index;
380 MetaMonitorMode *expected_current_mode;
381
382 outputs = meta_monitor_get_outputs (monitor);
383 g_debug ("Checking monitor %d", i);
384
385 g_assert_cmpint ((int) g_list_length (outputs),
386 ==,
387 expect->monitors[i].n_outputs);
388
389 for (l_output = outputs, j = 0; l_output; l_output = l_output->next, j++)
390 {
391 MetaOutput *output = l_output->data;
392 uint64_t winsys_id = expect->monitors[i].outputs[j];
393
394 g_assert (output == output_from_winsys_id (backend, winsys_id));
395 g_assert_cmpint (expect->monitors[i].is_underscanning,
396 ==,
397 meta_output_is_underscanning (output));
398 }
399
400 meta_monitor_get_physical_dimensions (monitor, &width_mm, &height_mm);
401 g_assert_cmpint (width_mm,
402 ==,
403 expect->monitors[i].width_mm);
404 g_assert_cmpint (height_mm,
405 ==,
406 expect->monitors[i].height_mm);
407
408 main_output = meta_monitor_get_main_output (monitor);
409 main_output_info = meta_output_get_info (main_output);
410 g_assert_cmpstr (meta_monitor_get_connector (monitor), ==,
411 main_output_info->name);
412 g_assert_cmpstr (meta_monitor_get_vendor (monitor), ==,
413 main_output_info->vendor);
414 g_assert_cmpstr (meta_monitor_get_product (monitor), ==,
415 main_output_info->product);
416 g_assert_cmpstr (meta_monitor_get_serial (monitor), ==,
417 main_output_info->serial);
418 g_assert_cmpint (meta_monitor_get_connector_type (monitor), ==,
419 main_output_info->connector_type);
420
421 modes = meta_monitor_get_modes (monitor);
422 g_assert_cmpint (g_list_length (modes),
423 ==,
424 expect->monitors[i].n_modes);
425
426 for (l_mode = modes, j = 0; l_mode; l_mode = l_mode->next, j++)
427 {
428 MetaMonitorMode *mode = l_mode->data;
429 int width;
430 int height;
431 float refresh_rate;
432 MetaCrtcModeFlag flags;
433 CheckMonitorModeData data;
434
435 meta_monitor_mode_get_resolution (mode, &width, &height);
436 refresh_rate = meta_monitor_mode_get_refresh_rate (mode);
437 flags = meta_monitor_mode_get_flags (mode);
438
439 g_debug ("Checking mode %dx%d @ %f", width, height, refresh_rate);
440
441 g_assert_cmpint (width,
442 ==,
443 expect->monitors[i].modes[j].width);
444 g_assert_cmpint (height,
445 ==,
446 expect->monitors[i].modes[j].height);
447 g_assert_cmpfloat (refresh_rate,
448 ==,
449 expect->monitors[i].modes[j].refresh_rate);
450 g_assert_cmpint (flags,
451 ==,
452 expect->monitors[i].modes[j].flags);
453
454 data = (CheckMonitorModeData) {
455 .backend = backend,
456 .expect_crtc_mode_iter =
457 expect->monitors[i].modes[j].crtc_modes
458 };
459 meta_monitor_mode_foreach_output (monitor, mode,
460 check_monitor_mode,
461 &data,
462 NULL);
463 }
464
465 current_mode = meta_monitor_get_current_mode (monitor);
466 expected_current_mode_index = expect->monitors[i].current_mode;
467 if (expected_current_mode_index == -1)
468 expected_current_mode = NULL;
469 else
470 expected_current_mode = g_list_nth (modes,
471 expected_current_mode_index)->data;
472
473 g_assert (current_mode == expected_current_mode);
474 if (current_mode)
475 g_assert (meta_monitor_is_active (monitor));
476 else
477 g_assert (!meta_monitor_is_active (monitor));
478
479 if (current_mode)
480 {
481 CheckMonitorModeData data;
482
483 data = (CheckMonitorModeData) {
484 .backend = backend,
485 .expect_crtc_mode_iter =
486 expect->monitors[i].modes[expected_current_mode_index].crtc_modes
487 };
488 meta_monitor_mode_foreach_output (monitor, expected_current_mode,
489 check_current_monitor_mode,
490 &data,
491 NULL);
492 }
493
494 meta_monitor_derive_current_mode (monitor);
495 g_assert (current_mode == meta_monitor_get_current_mode (monitor));
496 }
497
498 n_logical_monitors =
499 meta_monitor_manager_get_num_logical_monitors (monitor_manager);
500 g_assert_cmpint (n_logical_monitors,
501 ==,
502 expect->n_logical_monitors);
503
504 /*
505 * Check that we have a primary logical monitor (except for headless),
506 * and that the main output of the first monitor is the only output
507 * that is marked as primary (further below). Note: outputs being primary or
508 * not only matters on X11.
509 */
510 if (expect->primary_logical_monitor == -1)
511 {
512 g_assert_null (monitor_manager->primary_logical_monitor);
513 g_assert_null (monitor_manager->logical_monitors);
514 }
515 else
516 {
517 MonitorTestCaseLogicalMonitor *test_logical_monitor =
518 &expect->logical_monitors[expect->primary_logical_monitor];
519 MetaLogicalMonitor *logical_monitor;
520
521 logical_monitor =
522 logical_monitor_from_layout (monitor_manager,
523 &test_logical_monitor->layout);
524 g_assert (logical_monitor == monitor_manager->primary_logical_monitor);
525 }
526
527 all_crtcs = NULL;
528 for (l = meta_backend_get_gpus (backend); l; l = l->next)
529 {
530 MetaGpu *gpu = l->data;
531
532 all_crtcs = g_list_concat (all_crtcs,
533 g_list_copy (meta_gpu_get_crtcs (gpu)));
534 }
535
536 for (i = 0; i < expect->n_logical_monitors; i++)
537 {
538 MonitorTestCaseLogicalMonitor *test_logical_monitor =
539 &expect->logical_monitors[i];
540
541 check_logical_monitor (monitor_manager, test_logical_monitor, &all_crtcs);
542 }
543 g_assert_cmpint (n_logical_monitors, ==, i);
544
545 for (l = all_crtcs; l; l = l->next)
546 {
547 MetaCrtc *crtc = l->data;
548
549 g_assert_null (meta_crtc_get_outputs (crtc));
550 }
551 g_list_free (all_crtcs);
552
553 crtcs = meta_gpu_get_crtcs (gpu);
554 for (l = crtcs, i = 0; l; l = l->next, i++)
555 {
556 MetaCrtc *crtc = l->data;
557 const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc);
558
559 g_debug ("Checking CRTC %d", i);
560
561 if (expect->crtcs[i].current_mode == -1)
562 {
563 g_assert_null (meta_crtc_get_outputs (crtc));
564 g_assert_null (crtc_config);
565 }
566 else
567 {
568 MetaCrtcMode *expected_current_mode;
569 const GList *outputs = meta_crtc_get_outputs (crtc);
570 const GList *l_output;
571 MetaRendererView *view;
572 cairo_rectangle_int_t view_layout;
573
574 for (l_output = outputs;
575 l_output;
576 l_output = l_output->next)
577 {
578 MetaOutput *output = l_output->data;
579
580 g_debug ("Checking CRTC Output %d",
581 g_list_index ((GList *) outputs, output));
582
583 g_assert (meta_output_get_assigned_crtc (output) == crtc);
584 g_assert_null (g_list_find (l_output->next, output));
585 }
586
587 g_assert_nonnull (crtc_config);
588
589 expected_current_mode =
590 g_list_nth_data (meta_gpu_get_modes (gpu),
591 expect->crtcs[i].current_mode);
592 g_assert (crtc_config->mode == expected_current_mode);
593
594 g_assert_cmpuint (crtc_config->transform,
595 ==,
596 expect->crtcs[i].transform);
597
598 g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.x,
599 expect->crtcs[i].x,
600 FLT_EPSILON);
601 g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.y,
602 expect->crtcs[i].y,
603 FLT_EPSILON);
604
605 view = meta_renderer_get_view_for_crtc (renderer, crtc);
606 g_assert_nonnull (view);
607 clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view),
608 &view_layout);
609 g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.x,
610 view_layout.x,
611 FLT_EPSILON);
612 g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.y,
613 view_layout.y,
614 FLT_EPSILON);
615 g_assert_cmpfloat_with_epsilon (crtc_config->layout.size.width,
616 view_layout.width,
617 FLT_EPSILON);
618 g_assert_cmpfloat_with_epsilon (crtc_config->layout.size.height,
619 view_layout.height,
620 FLT_EPSILON);
621 }
622 }
623 }
624
625 MetaMonitorTestSetup *
create_monitor_test_setup(MonitorTestCaseSetup * setup,MonitorTestFlag flags)626 create_monitor_test_setup (MonitorTestCaseSetup *setup,
627 MonitorTestFlag flags)
628 {
629 MetaMonitorTestSetup *test_setup;
630 int i;
631 int n_laptop_panels = 0;
632 int n_normal_panels = 0;
633
634 test_setup = g_new0 (MetaMonitorTestSetup, 1);
635
636 test_setup->modes = NULL;
637 for (i = 0; i < setup->n_modes; i++)
638 {
639 g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL;
640 MetaCrtcMode *mode;
641
642 crtc_mode_info = meta_crtc_mode_info_new ();
643 crtc_mode_info->width = setup->modes[i].width;
644 crtc_mode_info->height = setup->modes[i].height;
645 crtc_mode_info->refresh_rate = setup->modes[i].refresh_rate;
646 crtc_mode_info->flags = setup->modes[i].flags;
647
648 mode = g_object_new (META_TYPE_CRTC_MODE,
649 "id", (uint64_t) i,
650 "info", crtc_mode_info,
651 NULL);
652
653 test_setup->modes = g_list_append (test_setup->modes, mode);
654 }
655
656 test_setup->crtcs = NULL;
657 for (i = 0; i < setup->n_crtcs; i++)
658 {
659 MetaCrtc *crtc;
660
661 crtc = g_object_new (META_TYPE_CRTC_TEST,
662 "id", (uint64_t) i + 1,
663 "gpu", test_get_gpu (),
664 NULL);
665
666 test_setup->crtcs = g_list_append (test_setup->crtcs, crtc);
667 }
668
669 test_setup->outputs = NULL;
670 for (i = 0; i < setup->n_outputs; i++)
671 {
672 MetaOutput *output;
673 MetaOutputTest *output_test;
674 int crtc_index;
675 MetaCrtc *crtc;
676 int preferred_mode_index;
677 MetaCrtcMode *preferred_mode;
678 MetaCrtcMode **modes;
679 int n_modes;
680 int j;
681 MetaCrtc **possible_crtcs;
682 int n_possible_crtcs;
683 int scale;
684 gboolean is_laptop_panel;
685 const char *serial;
686 g_autoptr (MetaOutputInfo) output_info = NULL;
687
688 crtc_index = setup->outputs[i].crtc;
689 if (crtc_index == -1)
690 crtc = NULL;
691 else
692 crtc = g_list_nth_data (test_setup->crtcs, crtc_index);
693
694 preferred_mode_index = setup->outputs[i].preferred_mode;
695 if (preferred_mode_index == -1)
696 preferred_mode = NULL;
697 else
698 preferred_mode = g_list_nth_data (test_setup->modes,
699 preferred_mode_index);
700
701 n_modes = setup->outputs[i].n_modes;
702 modes = g_new0 (MetaCrtcMode *, n_modes);
703 for (j = 0; j < n_modes; j++)
704 {
705 int mode_index;
706
707 mode_index = setup->outputs[i].modes[j];
708 modes[j] = g_list_nth_data (test_setup->modes, mode_index);
709 }
710
711 n_possible_crtcs = setup->outputs[i].n_possible_crtcs;
712 possible_crtcs = g_new0 (MetaCrtc *, n_possible_crtcs);
713 for (j = 0; j < n_possible_crtcs; j++)
714 {
715 int possible_crtc_index;
716
717 possible_crtc_index = setup->outputs[i].possible_crtcs[j];
718 possible_crtcs[j] = g_list_nth_data (test_setup->crtcs,
719 possible_crtc_index);
720 }
721
722 scale = setup->outputs[i].scale;
723 if (scale < 1)
724 scale = 1;
725
726 is_laptop_panel = setup->outputs[i].is_laptop_panel;
727
728 serial = setup->outputs[i].serial;
729 if (!serial)
730 serial = "0x123456";
731
732 output_info = meta_output_info_new ();
733
734 output_info->name = (is_laptop_panel
735 ? g_strdup_printf ("eDP-%d", ++n_laptop_panels)
736 : g_strdup_printf ("DP-%d", ++n_normal_panels));
737 output_info->vendor = g_strdup ("MetaProduct's Inc.");
738 output_info->product = g_strdup ("MetaMonitor");
739 output_info->serial = g_strdup (serial);
740 if (setup->outputs[i].hotplug_mode)
741 {
742 output_info->hotplug_mode_update = TRUE;
743 output_info->suggested_x = setup->outputs[i].suggested_x;
744 output_info->suggested_y = setup->outputs[i].suggested_y;
745 }
746 else if (flags & MONITOR_TEST_FLAG_NO_STORED)
747 {
748 output_info->hotplug_mode_update = TRUE;
749 output_info->suggested_x = -1;
750 output_info->suggested_y = -1;
751 }
752 output_info->width_mm = setup->outputs[i].width_mm;
753 output_info->height_mm = setup->outputs[i].height_mm;
754 output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
755 output_info->preferred_mode = preferred_mode;
756 output_info->n_modes = n_modes;
757 output_info->modes = modes;
758 output_info->n_possible_crtcs = n_possible_crtcs;
759 output_info->possible_crtcs = possible_crtcs;
760 output_info->n_possible_clones = 0;
761 output_info->possible_clones = NULL;
762 output_info->connector_type = (is_laptop_panel ? META_CONNECTOR_TYPE_eDP
763 : META_CONNECTOR_TYPE_DisplayPort);
764 output_info->tile_info = setup->outputs[i].tile_info;
765 output_info->panel_orientation_transform =
766 setup->outputs[i].panel_orientation_transform;
767
768 output = g_object_new (META_TYPE_OUTPUT_TEST,
769 "id", (uint64_t) i,
770 "gpu", test_get_gpu (),
771 "info", output_info,
772 NULL);
773
774 output_test = META_OUTPUT_TEST (output);
775 output_test->scale = scale;
776
777 if (crtc)
778 {
779 MetaOutputAssignment output_assignment;
780
781 output_assignment = (MetaOutputAssignment) {
782 .is_underscanning = setup->outputs[i].is_underscanning,
783 };
784 meta_output_assign_crtc (output, crtc, &output_assignment);
785 }
786
787 test_setup->outputs = g_list_append (test_setup->outputs, output);
788 }
789
790 return test_setup;
791 }
792
793 static void
check_expected_scales(MetaMonitor * monitor,MetaMonitorMode * monitor_mode,MetaMonitorScalesConstraint constraints,int n_expected_scales,float * expected_scales)794 check_expected_scales (MetaMonitor *monitor,
795 MetaMonitorMode *monitor_mode,
796 MetaMonitorScalesConstraint constraints,
797 int n_expected_scales,
798 float *expected_scales)
799 {
800 g_autofree float *scales = NULL;
801 int n_supported_scales;
802 int width, height;
803 int i;
804
805 scales = meta_monitor_calculate_supported_scales (monitor, monitor_mode,
806 constraints,
807 &n_supported_scales);
808 g_assert_cmpint (n_expected_scales, ==, n_supported_scales);
809
810 meta_monitor_mode_get_resolution (monitor_mode, &width, &height);
811
812 for (i = 0; i < n_supported_scales; i++)
813 {
814 g_assert_cmpfloat (scales[i], >, 0.0);
815 g_assert_cmpfloat_with_epsilon (scales[i], expected_scales[i], 0.000001);
816
817 if (!(constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC))
818 {
819 /* Also ensure that the scale will generate an integral resolution */
820 g_assert_cmpfloat (fmodf (width / scales[i], 1.0), ==, 0.0);
821 g_assert_cmpfloat (fmodf (height / scales[i], 1.0), ==, 0.0);
822 }
823
824 if (i > 0)
825 {
826 /* And that scales are sorted and unique */
827 g_assert_cmpfloat (scales[i], >, scales[i-1]);
828 g_assert_false (G_APPROX_VALUE (scales[i], scales[i-1], 0.000001));
829 }
830 }
831 }
832
check_monitor_scales(MonitorTestCaseExpect * expect,MetaMonitorScalesConstraint scales_constraints)833 void check_monitor_scales (MonitorTestCaseExpect *expect,
834 MetaMonitorScalesConstraint scales_constraints)
835 {
836 MetaBackend *backend = meta_get_backend ();
837 MetaMonitorManager *monitor_manager =
838 meta_backend_get_monitor_manager (backend);
839
840 GList *monitors;
841 GList *l;
842 int i;
843
844 monitors = meta_monitor_manager_get_monitors (monitor_manager);
845 g_assert_cmpuint (g_list_length (monitors), ==, expect->n_monitors);
846
847 for (l = monitors, i = 0; l; l = l->next, i++)
848 {
849 MetaMonitor *monitor = l->data;
850 MonitorTestCaseMonitor *expected_monitor = &expect->monitors[i];
851 GList *modes = meta_monitor_get_modes (monitor);
852 GList *k;
853 int j;
854
855 g_debug ("Checking monitor %d", i);
856 g_assert_cmpuint (g_list_length (modes), ==, expected_monitor->n_modes);
857
858 for (j = 0, k = modes; k; k = k->next, j++)
859 {
860 MetaMonitorMode *monitor_mode = k->data;
861 MetaMonitorTestCaseMonitorMode *expected_mode =
862 &expected_monitor->modes[j];
863 int width, height;
864
865 meta_monitor_mode_get_resolution (monitor_mode, &width, &height);
866 g_debug ("Checking %s scaling values for mode %dx%d",
867 (scales_constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC) ?
868 "integer" : "fractional", width, height);
869
870 g_assert_cmpint (width, ==, expected_mode->width);
871 g_assert_cmpint (height, ==, expected_mode->height);
872
873 check_expected_scales (monitor, monitor_mode, scales_constraints,
874 expected_mode->n_scales,
875 expected_mode->scales);
876 }
877 }
878 }
879