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/monitor-store-unit-tests.h"
23
24 #include "backends/meta-backend-private.h"
25 #include "backends/meta-monitor-config-store.h"
26 #include "backends/meta-monitor-config-manager.h"
27 #include "backends/meta-monitor-manager-private.h"
28 #include "tests/monitor-test-utils.h"
29
30 #define MAX_N_MONITORS 10
31 #define MAX_N_LOGICAL_MONITORS 10
32 #define MAX_N_CONFIGURATIONS 10
33
34 typedef struct _MonitorStoreTestCaseMonitorMode
35 {
36 int width;
37 int height;
38 float refresh_rate;
39 MetaCrtcModeFlag flags;
40 } MonitorStoreTestCaseMonitorMode;
41
42 typedef struct _MonitorStoreTestCaseMonitor
43 {
44 const char *connector;
45 const char *vendor;
46 const char *product;
47 const char *serial;
48 MonitorStoreTestCaseMonitorMode mode;
49 gboolean is_underscanning;
50 } MonitorStoreTestCaseMonitor;
51
52 typedef struct _MonitorStoreTestCaseLogicalMonitor
53 {
54 MetaRectangle layout;
55 float scale;
56 MetaMonitorTransform transform;
57 gboolean is_primary;
58 gboolean is_presentation;
59 MonitorStoreTestCaseMonitor monitors[MAX_N_MONITORS];
60 int n_monitors;
61 } MonitorStoreTestCaseLogicalMonitor;
62
63 typedef struct _MonitorStoreTestConfiguration
64 {
65 MonitorStoreTestCaseLogicalMonitor logical_monitors[MAX_N_LOGICAL_MONITORS];
66 int n_logical_monitors;
67 } MonitorStoreTestConfiguration;
68
69 typedef struct _MonitorStoreTestExpect
70 {
71 MonitorStoreTestConfiguration configurations[MAX_N_CONFIGURATIONS];
72 int n_configurations;
73 } MonitorStoreTestExpect;
74
75 static MetaMonitorsConfigKey *
create_config_key_from_expect(MonitorStoreTestConfiguration * expect_config)76 create_config_key_from_expect (MonitorStoreTestConfiguration *expect_config)
77 {
78 MetaMonitorsConfigKey *config_key;
79 GList *monitor_specs;
80 int i;
81
82 monitor_specs = NULL;
83 for (i = 0; i < expect_config->n_logical_monitors; i++)
84 {
85 int j;
86
87 for (j = 0; j < expect_config->logical_monitors[i].n_monitors; j++)
88 {
89 MetaMonitorSpec *monitor_spec;
90 MonitorStoreTestCaseMonitor *test_monitor =
91 &expect_config->logical_monitors[i].monitors[j];
92
93 monitor_spec = g_new0 (MetaMonitorSpec, 1);
94
95 monitor_spec->connector = g_strdup (test_monitor->connector);
96 monitor_spec->vendor = g_strdup (test_monitor->vendor);
97 monitor_spec->product = g_strdup (test_monitor->product);
98 monitor_spec->serial = g_strdup (test_monitor->serial);
99
100 monitor_specs = g_list_prepend (monitor_specs, monitor_spec);
101 }
102 }
103
104 g_assert_nonnull (monitor_specs);
105
106 monitor_specs = g_list_sort (monitor_specs,
107 (GCompareFunc) meta_monitor_spec_compare);
108
109 config_key = g_new0 (MetaMonitorsConfigKey, 1);
110 *config_key = (MetaMonitorsConfigKey) {
111 .monitor_specs = monitor_specs
112 };
113
114 return config_key;
115 }
116
117 static void
check_monitor_store_configuration(MetaMonitorConfigStore * config_store,MonitorStoreTestConfiguration * config_expect)118 check_monitor_store_configuration (MetaMonitorConfigStore *config_store,
119 MonitorStoreTestConfiguration *config_expect)
120 {
121 MetaMonitorsConfigKey *config_key;
122 MetaMonitorsConfig *config;
123 GList *l;
124 int i;
125
126 config_key = create_config_key_from_expect (config_expect);
127 config = meta_monitor_config_store_lookup (config_store, config_key);
128 g_assert_nonnull (config);
129
130 g_assert (meta_monitors_config_key_equal (config->key, config_key));
131 meta_monitors_config_key_free (config_key);
132
133 g_assert_cmpuint (g_list_length (config->logical_monitor_configs),
134 ==,
135 config_expect->n_logical_monitors);
136
137 for (l = config->logical_monitor_configs, i = 0; l; l = l->next, i++)
138 {
139 MetaLogicalMonitorConfig *logical_monitor_config = l->data;
140 GList *k;
141 int j;
142
143 g_assert (meta_rectangle_equal (&logical_monitor_config->layout,
144 &config_expect->logical_monitors[i].layout));
145 g_assert_cmpfloat (logical_monitor_config->scale,
146 ==,
147 config_expect->logical_monitors[i].scale);
148 g_assert_cmpint (logical_monitor_config->transform,
149 ==,
150 config_expect->logical_monitors[i].transform);
151 g_assert_cmpint (logical_monitor_config->is_primary,
152 ==,
153 config_expect->logical_monitors[i].is_primary);
154 g_assert_cmpint (logical_monitor_config->is_presentation,
155 ==,
156 config_expect->logical_monitors[i].is_presentation);
157
158 g_assert_cmpint ((int) g_list_length (logical_monitor_config->monitor_configs),
159 ==,
160 config_expect->logical_monitors[i].n_monitors);
161
162 for (k = logical_monitor_config->monitor_configs, j = 0;
163 k;
164 k = k->next, j++)
165 {
166 MetaMonitorConfig *monitor_config = k->data;
167 MonitorStoreTestCaseMonitor *test_monitor =
168 &config_expect->logical_monitors[i].monitors[j];
169
170 g_assert_cmpstr (monitor_config->monitor_spec->connector,
171 ==,
172 test_monitor->connector);
173 g_assert_cmpstr (monitor_config->monitor_spec->vendor,
174 ==,
175 test_monitor->vendor);
176 g_assert_cmpstr (monitor_config->monitor_spec->product,
177 ==,
178 test_monitor->product);
179 g_assert_cmpstr (monitor_config->monitor_spec->serial,
180 ==,
181 test_monitor->serial);
182
183 g_assert_cmpint (monitor_config->mode_spec->width,
184 ==,
185 test_monitor->mode.width);
186 g_assert_cmpint (monitor_config->mode_spec->height,
187 ==,
188 test_monitor->mode.height);
189 g_assert_cmpfloat (monitor_config->mode_spec->refresh_rate,
190 ==,
191 test_monitor->mode.refresh_rate);
192 g_assert_cmpint (monitor_config->mode_spec->flags,
193 ==,
194 test_monitor->mode.flags);
195 g_assert_cmpint (monitor_config->enable_underscanning,
196 ==,
197 test_monitor->is_underscanning);
198 }
199 }
200 }
201
202 static void
check_monitor_store_configurations(MonitorStoreTestExpect * expect)203 check_monitor_store_configurations (MonitorStoreTestExpect *expect)
204 {
205 MetaBackend *backend = meta_get_backend ();
206 MetaMonitorManager *monitor_manager =
207 meta_backend_get_monitor_manager (backend);
208 MetaMonitorConfigManager *config_manager = monitor_manager->config_manager;
209 MetaMonitorConfigStore *config_store =
210 meta_monitor_config_manager_get_store (config_manager);
211 int i;
212
213 g_assert_cmpint (meta_monitor_config_store_get_config_count (config_store),
214 ==,
215 expect->n_configurations);
216
217 for (i = 0; i < expect->n_configurations; i++)
218 check_monitor_store_configuration (config_store, &expect->configurations[i]);
219 }
220
221 static void
meta_test_monitor_store_single(void)222 meta_test_monitor_store_single (void)
223 {
224 MonitorStoreTestExpect expect = {
225 .configurations = {
226 {
227 .logical_monitors = {
228 {
229 .layout = {
230 .x = 0,
231 .y = 0,
232 .width = 1920,
233 .height = 1080
234 },
235 .scale = 1,
236 .is_primary = TRUE,
237 .is_presentation = FALSE,
238 .monitors = {
239 {
240 .connector = "DP-1",
241 .vendor = "MetaProduct's Inc.",
242 .product = "MetaMonitor",
243 .serial = "0x123456",
244 .mode = {
245 .width = 1920,
246 .height = 1080,
247 .refresh_rate = 60.000495910644531
248 }
249 }
250 },
251 .n_monitors = 1,
252 }
253 },
254 .n_logical_monitors = 1
255 }
256 },
257 .n_configurations = 1
258 };
259
260 set_custom_monitor_config ("single.xml");
261
262 check_monitor_store_configurations (&expect);
263 }
264
265 static void
meta_test_monitor_store_vertical(void)266 meta_test_monitor_store_vertical (void)
267 {
268 MonitorStoreTestExpect expect = {
269 .configurations = {
270 {
271 .logical_monitors = {
272 {
273 .layout = {
274 .x = 0,
275 .y = 0,
276 .width = 1024,
277 .height = 768
278 },
279 .scale = 1,
280 .is_primary = TRUE,
281 .is_presentation = FALSE,
282 .monitors = {
283 {
284 .connector = "DP-1",
285 .vendor = "MetaProduct's Inc.",
286 .product = "MetaMonitor",
287 .serial = "0x123456",
288 .mode = {
289 .width = 1024,
290 .height = 768,
291 .refresh_rate = 60.000495910644531
292 }
293 }
294 },
295 .n_monitors = 1,
296 },
297 {
298 .layout = {
299 .x = 0,
300 .y = 768,
301 .width = 800,
302 .height = 600
303 },
304 .scale = 1,
305 .is_primary = FALSE,
306 .is_presentation = FALSE,
307 .monitors = {
308 {
309 .connector = "DP-2",
310 .vendor = "MetaProduct's Inc.",
311 .product = "MetaMonitor",
312 .serial = "0x123456",
313 .mode = {
314 .width = 800,
315 .height = 600,
316 .refresh_rate = 60.000495910644531
317 }
318 }
319 },
320 .n_monitors = 1,
321 }
322 },
323 .n_logical_monitors = 2
324 }
325 },
326 .n_configurations = 1
327 };
328
329 set_custom_monitor_config ("vertical.xml");
330
331 check_monitor_store_configurations (&expect);
332 }
333
334 static void
meta_test_monitor_store_primary(void)335 meta_test_monitor_store_primary (void)
336 {
337 MonitorStoreTestExpect expect = {
338 .configurations = {
339 {
340 .logical_monitors = {
341 {
342 .layout = {
343 .x = 0,
344 .y = 0,
345 .width = 1024,
346 .height = 768
347 },
348 .scale = 1,
349 .is_primary = FALSE,
350 .is_presentation = FALSE,
351 .monitors = {
352 {
353 .connector = "DP-1",
354 .vendor = "MetaProduct's Inc.",
355 .product = "MetaMonitor",
356 .serial = "0x123456",
357 .mode = {
358 .width = 1024,
359 .height = 768,
360 .refresh_rate = 60.000495910644531
361 }
362 }
363 },
364 .n_monitors = 1,
365 },
366 {
367 .layout = {
368 .x = 1024,
369 .y = 0,
370 .width = 800,
371 .height = 600
372 },
373 .scale = 1,
374 .is_primary = TRUE,
375 .is_presentation = FALSE,
376 .monitors = {
377 {
378 .connector = "DP-2",
379 .vendor = "MetaProduct's Inc.",
380 .product = "MetaMonitor",
381 .serial = "0x123456",
382 .mode = {
383 .width = 800,
384 .height = 600,
385 .refresh_rate = 60.000495910644531
386 }
387 }
388 },
389 .n_monitors = 1,
390 }
391 },
392 .n_logical_monitors = 2
393 }
394 },
395 .n_configurations = 1
396 };
397
398 set_custom_monitor_config ("primary.xml");
399
400 check_monitor_store_configurations (&expect);
401 }
402
403 static void
meta_test_monitor_store_underscanning(void)404 meta_test_monitor_store_underscanning (void)
405 {
406 MonitorStoreTestExpect expect = {
407 .configurations = {
408 {
409 .logical_monitors = {
410 {
411 .layout = {
412 .x = 0,
413 .y = 0,
414 .width = 1024,
415 .height = 768
416 },
417 .scale = 1,
418 .is_primary = TRUE,
419 .is_presentation = FALSE,
420 .monitors = {
421 {
422 .connector = "DP-1",
423 .vendor = "MetaProduct's Inc.",
424 .product = "MetaMonitor",
425 .serial = "0x123456",
426 .is_underscanning = TRUE,
427 .mode = {
428 .width = 1024,
429 .height = 768,
430 .refresh_rate = 60.000495910644531
431 }
432 }
433 },
434 .n_monitors = 1,
435 },
436 },
437 .n_logical_monitors = 1
438 }
439 },
440 .n_configurations = 1
441 };
442
443 set_custom_monitor_config ("underscanning.xml");
444
445 check_monitor_store_configurations (&expect);
446 }
447
448 static void
meta_test_monitor_store_scale(void)449 meta_test_monitor_store_scale (void)
450 {
451 MonitorStoreTestExpect expect = {
452 .configurations = {
453 {
454 .logical_monitors = {
455 {
456 .layout = {
457 .x = 0,
458 .y = 0,
459 .width = 960,
460 .height = 540
461 },
462 .scale = 2,
463 .is_primary = TRUE,
464 .is_presentation = FALSE,
465 .monitors = {
466 {
467 .connector = "DP-1",
468 .vendor = "MetaProduct's Inc.",
469 .product = "MetaMonitor",
470 .serial = "0x123456",
471 .mode = {
472 .width = 1920,
473 .height = 1080,
474 .refresh_rate = 60.000495910644531
475 }
476 }
477 },
478 .n_monitors = 1,
479 }
480 },
481 .n_logical_monitors = 1
482 }
483 },
484 .n_configurations = 1
485 };
486
487 if (!meta_is_stage_views_enabled ())
488 {
489 g_test_skip ("Not using stage views");
490 return;
491 }
492
493 set_custom_monitor_config ("scale.xml");
494
495 check_monitor_store_configurations (&expect);
496 }
497
498 static void
meta_test_monitor_store_fractional_scale(void)499 meta_test_monitor_store_fractional_scale (void)
500 {
501 MonitorStoreTestExpect expect = {
502 .configurations = {
503 {
504 .logical_monitors = {
505 {
506 .layout = {
507 .x = 0,
508 .y = 0,
509 .width = 800,
510 .height = 600
511 },
512 .scale = 1.5,
513 .is_primary = TRUE,
514 .is_presentation = FALSE,
515 .monitors = {
516 {
517 .connector = "DP-1",
518 .vendor = "MetaProduct's Inc.",
519 .product = "MetaMonitor",
520 .serial = "0x123456",
521 .mode = {
522 .width = 1200,
523 .height = 900,
524 .refresh_rate = 60.000495910644531
525 }
526 }
527 },
528 .n_monitors = 1,
529 }
530 },
531 .n_logical_monitors = 1
532 }
533 },
534 .n_configurations = 1
535 };
536
537 if (!meta_is_stage_views_enabled ())
538 {
539 g_test_skip ("Not using stage views");
540 return;
541 }
542
543 set_custom_monitor_config ("fractional-scale.xml");
544
545 check_monitor_store_configurations (&expect);
546 }
547
548 static void
meta_test_monitor_store_high_precision_fractional_scale(void)549 meta_test_monitor_store_high_precision_fractional_scale (void)
550 {
551 MonitorStoreTestExpect expect = {
552 .configurations = {
553 {
554 .logical_monitors = {
555 {
556 .layout = {
557 .x = 0,
558 .y = 0,
559 .width = 744,
560 .height = 558
561 },
562 .scale = 1.3763440847396851,
563 .is_primary = TRUE,
564 .is_presentation = FALSE,
565 .monitors = {
566 {
567 .connector = "DP-1",
568 .vendor = "MetaProduct's Inc.",
569 .product = "MetaMonitor",
570 .serial = "0x123456",
571 .mode = {
572 .width = 1024,
573 .height = 768,
574 .refresh_rate = 60.000495910644531
575 }
576 }
577 },
578 .n_monitors = 1,
579 }
580 },
581 .n_logical_monitors = 1
582 }
583 },
584 .n_configurations = 1
585 };
586
587 if (!meta_is_stage_views_enabled ())
588 {
589 g_test_skip ("Not using stage views");
590 return;
591 }
592
593 set_custom_monitor_config ("high-precision-fractional-scale.xml");
594
595 check_monitor_store_configurations (&expect);
596 }
597
598 static void
meta_test_monitor_store_mirrored(void)599 meta_test_monitor_store_mirrored (void)
600 {
601 MonitorStoreTestExpect expect = {
602 .configurations = {
603 {
604 .logical_monitors = {
605 {
606 .layout = {
607 .x = 0,
608 .y = 0,
609 .width = 800,
610 .height = 600
611 },
612 .scale = 1,
613 .is_primary = TRUE,
614 .monitors = {
615 {
616 .connector = "DP-1",
617 .vendor = "MetaProduct's Inc.",
618 .product = "MetaMonitor",
619 .serial = "0x123456",
620 .mode = {
621 .width = 800,
622 .height = 600,
623 .refresh_rate = 60.000495910644531
624 }
625 },
626 {
627 .connector = "DP-2",
628 .vendor = "MetaProduct's Inc.",
629 .product = "MetaMonitor",
630 .serial = "0x123456",
631 .mode = {
632 .width = 800,
633 .height = 600,
634 .refresh_rate = 60.000495910644531
635 }
636 }
637 },
638 .n_monitors = 2,
639 }
640 },
641 .n_logical_monitors = 1
642 }
643 },
644 .n_configurations = 1
645 };
646
647 set_custom_monitor_config ("mirrored.xml");
648
649 check_monitor_store_configurations (&expect);
650 }
651
652 static void
meta_test_monitor_store_first_rotated(void)653 meta_test_monitor_store_first_rotated (void)
654 {
655 MonitorStoreTestExpect expect = {
656 .configurations = {
657 {
658 .logical_monitors = {
659 {
660 .layout = {
661 .x = 0,
662 .y = 0,
663 .width = 768,
664 .height = 1024
665 },
666 .scale = 1,
667 .transform = META_MONITOR_TRANSFORM_270,
668 .is_primary = TRUE,
669 .is_presentation = FALSE,
670 .monitors = {
671 {
672 .connector = "DP-1",
673 .vendor = "MetaProduct's Inc.",
674 .product = "MetaMonitor",
675 .serial = "0x123456",
676 .mode = {
677 .width = 1024,
678 .height = 768,
679 .refresh_rate = 60.000495910644531
680 }
681 }
682 },
683 .n_monitors = 1,
684 },
685 {
686 .layout = {
687 .x = 768,
688 .y = 0,
689 .width = 1024,
690 .height = 768
691 },
692 .scale = 1,
693 .transform = META_MONITOR_TRANSFORM_NORMAL,
694 .is_primary = FALSE,
695 .is_presentation = FALSE,
696 .monitors = {
697 {
698 .connector = "DP-2",
699 .vendor = "MetaProduct's Inc.",
700 .product = "MetaMonitor",
701 .serial = "0x123456",
702 .mode = {
703 .width = 1024,
704 .height = 768,
705 .refresh_rate = 60.000495910644531
706 }
707 }
708 },
709 .n_monitors = 1,
710 }
711 },
712 .n_logical_monitors = 2
713 }
714 },
715 .n_configurations = 1
716 };
717
718 set_custom_monitor_config ("first-rotated.xml");
719
720 check_monitor_store_configurations (&expect);
721 }
722
723 static void
meta_test_monitor_store_second_rotated(void)724 meta_test_monitor_store_second_rotated (void)
725 {
726 MonitorStoreTestExpect expect = {
727 .configurations = {
728 {
729 .logical_monitors = {
730 {
731 .layout = {
732 .x = 0,
733 .y = 256,
734 .width = 1024,
735 .height = 768
736 },
737 .scale = 1,
738 .transform = META_MONITOR_TRANSFORM_NORMAL,
739 .is_primary = TRUE,
740 .is_presentation = FALSE,
741 .monitors = {
742 {
743 .connector = "DP-1",
744 .vendor = "MetaProduct's Inc.",
745 .product = "MetaMonitor",
746 .serial = "0x123456",
747 .mode = {
748 .width = 1024,
749 .height = 768,
750 .refresh_rate = 60.000495910644531
751 }
752 }
753 },
754 .n_monitors = 1,
755 },
756 {
757 .layout = {
758 .x = 1024,
759 .y = 0,
760 .width = 768,
761 .height = 1024
762 },
763 .scale = 1,
764 .transform = META_MONITOR_TRANSFORM_90,
765 .is_primary = FALSE,
766 .is_presentation = FALSE,
767 .monitors = {
768 {
769 .connector = "DP-2",
770 .vendor = "MetaProduct's Inc.",
771 .product = "MetaMonitor",
772 .serial = "0x123456",
773 .mode = {
774 .width = 1024,
775 .height = 768,
776 .refresh_rate = 60.000495910644531
777 }
778 }
779 },
780 .n_monitors = 1,
781 }
782 },
783 .n_logical_monitors = 2
784 }
785 },
786 .n_configurations = 1
787 };
788
789 set_custom_monitor_config ("second-rotated.xml");
790
791 check_monitor_store_configurations (&expect);
792 }
793
794 static void
meta_test_monitor_store_interlaced(void)795 meta_test_monitor_store_interlaced (void)
796 {
797 MonitorStoreTestExpect expect = {
798 .configurations = {
799 {
800 .logical_monitors = {
801 {
802 .layout = {
803 .x = 0,
804 .y = 0,
805 .width = 1024,
806 .height = 768
807 },
808 .scale = 1,
809 .is_primary = TRUE,
810 .is_presentation = FALSE,
811 .monitors = {
812 {
813 .connector = "DP-1",
814 .vendor = "MetaProduct's Inc.",
815 .product = "MetaMonitor",
816 .serial = "0x123456",
817 .mode = {
818 .width = 1024,
819 .height = 768,
820 .refresh_rate = 60.000495910644531,
821 .flags = META_CRTC_MODE_FLAG_INTERLACE,
822 }
823 }
824 },
825 .n_monitors = 1,
826 },
827 },
828 .n_logical_monitors = 1
829 }
830 },
831 .n_configurations = 1
832 };
833
834 set_custom_monitor_config ("interlaced.xml");
835
836 check_monitor_store_configurations (&expect);
837 }
838
839 void
init_monitor_store_tests(void)840 init_monitor_store_tests (void)
841 {
842 g_test_add_func ("/backends/monitor-store/single",
843 meta_test_monitor_store_single);
844 g_test_add_func ("/backends/monitor-store/vertical",
845 meta_test_monitor_store_vertical);
846 g_test_add_func ("/backends/monitor-store/primary",
847 meta_test_monitor_store_primary);
848 g_test_add_func ("/backends/monitor-store/underscanning",
849 meta_test_monitor_store_underscanning);
850 g_test_add_func ("/backends/monitor-store/scale",
851 meta_test_monitor_store_scale);
852 g_test_add_func ("/backends/monitor-store/fractional-scale",
853 meta_test_monitor_store_fractional_scale);
854 g_test_add_func ("/backends/monitor-store/high-precision-fractional-scale",
855 meta_test_monitor_store_high_precision_fractional_scale);
856 g_test_add_func ("/backends/monitor-store/mirrored",
857 meta_test_monitor_store_mirrored);
858 g_test_add_func ("/backends/monitor-store/first-rotated",
859 meta_test_monitor_store_first_rotated);
860 g_test_add_func ("/backends/monitor-store/second-rotated",
861 meta_test_monitor_store_second_rotated);
862 g_test_add_func ("/backends/monitor-store/interlaced",
863 meta_test_monitor_store_interlaced);
864 }
865