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