1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <drm_fourcc.h>
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <xf86drm.h>
9 #include <memory>
10 #include <utility>
11
12 #include "base/callback_helpers.h"
13 #include "base/files/platform_file.h"
14 #include "base/macros.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/gfx/geometry/point.h"
17 #include "ui/gfx/gpu_fence.h"
18 #include "ui/gfx/linux/gbm_buffer.h"
19 #include "ui/gfx/linux/test/mock_gbm_device.h"
20 #include "ui/ozone/platform/drm/common/drm_util.h"
21 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
22 #include "ui/ozone/platform/drm/gpu/drm_device_generator.h"
23 #include "ui/ozone/platform/drm/gpu/drm_device_manager.h"
24 #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h"
25 #include "ui/ozone/platform/drm/gpu/drm_window.h"
26 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
27 #include "ui/ozone/platform/drm/gpu/mock_drm_device.h"
28 #include "ui/ozone/platform/drm/gpu/screen_manager.h"
29
30 namespace ui {
31 namespace {
32
33 // Create a basic mode for a 6x4 screen.
34 const drmModeModeInfo kDefaultMode = {0, 6, 0, 0, 0, 0, 4, 0,
35 0, 0, 0, 0, 0, 0, {'\0'}};
36
37 const uint32_t kPrimaryDisplayId = 1;
38 const uint32_t kSecondaryDisplayId = 2;
39
40 constexpr uint32_t kCrtcIdBase = 100;
41 constexpr uint32_t kPrimaryCrtc = kCrtcIdBase;
42 constexpr uint32_t kSecondaryCrtc = kCrtcIdBase + 1;
43
44 constexpr uint32_t kConnectorIdBase = 200;
45 constexpr uint32_t kPrimaryConnector = kConnectorIdBase;
46 constexpr uint32_t kSecondaryConnector = kConnectorIdBase + 1;
47 constexpr uint32_t kPlaneIdBase = 300;
48 constexpr uint32_t kInFormatsBlobPropIdBase = 400;
49
50 constexpr uint32_t kTypePropId = 3010;
51 constexpr uint32_t kInFormatsPropId = 3011;
52
ConstructMode(uint16_t hdisplay,uint16_t vdisplay)53 drmModeModeInfo ConstructMode(uint16_t hdisplay, uint16_t vdisplay) {
54 return {0, hdisplay, 0, 0, 0, 0, vdisplay, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
55 }
56
57 } // namespace
58
59 class ScreenManagerTest : public testing::Test {
60 public:
61 struct PlaneState {
62 std::vector<uint32_t> formats;
63 };
64
65 struct CrtcState {
66 std::vector<PlaneState> planes;
67 };
68
69 ScreenManagerTest() = default;
70 ~ScreenManagerTest() override = default;
71
GetPrimaryBounds() const72 gfx::Rect GetPrimaryBounds() const {
73 return gfx::Rect(0, 0, kDefaultMode.hdisplay, kDefaultMode.vdisplay);
74 }
75
76 // Secondary is in extended mode, right-of primary.
GetSecondaryBounds() const77 gfx::Rect GetSecondaryBounds() const {
78 return gfx::Rect(kDefaultMode.hdisplay, 0, kDefaultMode.hdisplay,
79 kDefaultMode.vdisplay);
80 }
81
InitializeDrmState(ui::MockDrmDevice * drm,const std::vector<CrtcState> & crtc_states,bool is_atomic=true)82 void InitializeDrmState(ui::MockDrmDevice* drm,
83 const std::vector<CrtcState>& crtc_states,
84 bool is_atomic = true) {
85 std::vector<ui::MockDrmDevice::CrtcProperties> crtc_properties(
86 crtc_states.size());
87 std::map<uint32_t, std::string> crtc_property_names = {
88 {1000, "ACTIVE"},
89 {1001, "MODE_ID"},
90 };
91
92 std::vector<ui::MockDrmDevice::ConnectorProperties> connector_properties(3);
93 std::map<uint32_t, std::string> connector_property_names = {
94 {2000, "CRTC_ID"},
95 };
96 for (size_t i = 0; i < connector_properties.size(); ++i) {
97 connector_properties[i].id = kPrimaryConnector + i;
98 for (const auto& pair : connector_property_names) {
99 connector_properties[i].properties.push_back(
100 {/* .id = */ pair.first, /* .value = */ 0});
101 }
102 }
103
104 std::vector<ui::MockDrmDevice::PlaneProperties> plane_properties;
105 std::map<uint32_t, std::string> plane_property_names = {
106 // Add all required properties.
107 {3000, "CRTC_ID"},
108 {3001, "CRTC_X"},
109 {3002, "CRTC_Y"},
110 {3003, "CRTC_W"},
111 {3004, "CRTC_H"},
112 {3005, "FB_ID"},
113 {3006, "SRC_X"},
114 {3007, "SRC_Y"},
115 {3008, "SRC_W"},
116 {3009, "SRC_H"},
117 // Defines some optional properties we use for convenience.
118 {kTypePropId, "type"},
119 {kInFormatsPropId, "IN_FORMATS"},
120 };
121
122 uint32_t plane_id = kPlaneIdBase;
123 uint32_t property_id = kInFormatsBlobPropIdBase;
124
125 for (size_t crtc_idx = 0; crtc_idx < crtc_states.size(); ++crtc_idx) {
126 crtc_properties[crtc_idx].id = kPrimaryCrtc + crtc_idx;
127 for (const auto& pair : crtc_property_names) {
128 crtc_properties[crtc_idx].properties.push_back(
129 {/* .id = */ pair.first, /* .value = */ 0});
130 }
131
132 std::vector<ui::MockDrmDevice::PlaneProperties> crtc_plane_properties(
133 crtc_states[crtc_idx].planes.size());
134 for (size_t plane_idx = 0;
135 plane_idx < crtc_states[crtc_idx].planes.size(); ++plane_idx) {
136 crtc_plane_properties[plane_idx].id = plane_id++;
137 crtc_plane_properties[plane_idx].crtc_mask = 1 << crtc_idx;
138
139 for (const auto& pair : plane_property_names) {
140 uint64_t value = 0;
141 if (pair.first == kTypePropId) {
142 value = plane_idx == 0 ? DRM_PLANE_TYPE_PRIMARY
143 : DRM_PLANE_TYPE_OVERLAY;
144 } else if (pair.first == kInFormatsPropId) {
145 value = property_id++;
146 drm->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob(
147 value, crtc_states[crtc_idx].planes[plane_idx].formats,
148 std::vector<drm_format_modifier>()));
149 }
150
151 crtc_plane_properties[plane_idx].properties.push_back(
152 {/* .id = */ pair.first, /* .value = */ value});
153 }
154 }
155
156 plane_properties.insert(plane_properties.end(),
157 crtc_plane_properties.begin(),
158 crtc_plane_properties.end());
159 }
160
161 std::map<uint32_t, std::string> property_names;
162 property_names.insert(crtc_property_names.begin(),
163 crtc_property_names.end());
164 property_names.insert(connector_property_names.begin(),
165 connector_property_names.end());
166 property_names.insert(plane_property_names.begin(),
167 plane_property_names.end());
168 drm->InitializeState(crtc_properties, connector_properties,
169 plane_properties, property_names, is_atomic);
170 }
171
InitializeDrmStateWithDefault(ui::MockDrmDevice * drm,bool is_atomic=true)172 void InitializeDrmStateWithDefault(ui::MockDrmDevice* drm,
173 bool is_atomic = true) {
174 // A Sample of CRTC states.
175 std::vector<CrtcState> crtc_states = {
176 {/* .planes = */
177 {
178 {/* .formats = */ {DRM_FORMAT_XRGB8888}},
179 }},
180 {/* .planes = */
181 {
182 {/* .formats = */ {DRM_FORMAT_XRGB8888}},
183 }},
184 };
185 InitializeDrmState(drm, crtc_states, is_atomic);
186 }
187
SetUp()188 void SetUp() override {
189 auto gbm = std::make_unique<ui::MockGbmDevice>();
190 drm_ = new ui::MockDrmDevice(std::move(gbm));
191 device_manager_ = std::make_unique<ui::DrmDeviceManager>(nullptr);
192 screen_manager_ = std::make_unique<ui::ScreenManager>();
193 }
194
TearDown()195 void TearDown() override {
196 screen_manager_.reset();
197 drm_ = nullptr;
198 }
199
CreateBuffer(uint32_t format,const gfx::Size & size)200 scoped_refptr<DrmFramebuffer> CreateBuffer(uint32_t format,
201 const gfx::Size& size) {
202 return CreateBufferWithModifier(format, DRM_FORMAT_MOD_NONE, size);
203 }
204
CreateBufferWithModifier(uint32_t format,uint64_t format_modifier,const gfx::Size & size)205 scoped_refptr<DrmFramebuffer> CreateBufferWithModifier(
206 uint32_t format,
207 uint64_t format_modifier,
208 const gfx::Size& size) {
209 std::vector<uint64_t> modifiers;
210 if (format_modifier != DRM_FORMAT_MOD_NONE)
211 modifiers.push_back(format_modifier);
212 auto buffer = drm_->gbm_device()->CreateBufferWithModifiers(
213 format, size, GBM_BO_USE_SCANOUT, modifiers);
214 return DrmFramebuffer::AddFramebuffer(drm_, buffer.get(), size, modifiers);
215 }
216
217 protected:
218 scoped_refptr<ui::MockDrmDevice> drm_;
219 std::unique_ptr<ui::DrmDeviceManager> device_manager_;
220 std::unique_ptr<ui::ScreenManager> screen_manager_;
221
222 private:
223 DISALLOW_COPY_AND_ASSIGN(ScreenManagerTest);
224 };
225
TEST_F(ScreenManagerTest,CheckWithNoControllers)226 TEST_F(ScreenManagerTest, CheckWithNoControllers) {
227 EXPECT_FALSE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
228 EXPECT_EQ(drm_->get_test_modeset_count(), 0);
229 EXPECT_EQ(drm_->get_commit_modeset_count(), 0);
230 EXPECT_EQ(drm_->get_commit_count(), 0);
231 }
232
TEST_F(ScreenManagerTest,CheckWithValidController)233 TEST_F(ScreenManagerTest, CheckWithValidController) {
234 InitializeDrmStateWithDefault(drm_.get());
235
236 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
237
238 ScreenManager::ControllerConfigsList controllers_to_enable;
239 controllers_to_enable.emplace_back(
240 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
241 GetPrimaryBounds().origin(),
242 std::make_unique<drmModeModeInfo>(kDefaultMode));
243 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
244 EXPECT_EQ(drm_->get_test_modeset_count(), 1);
245 EXPECT_EQ(drm_->get_commit_modeset_count(), 1);
246
247 ui::HardwareDisplayController* controller =
248 screen_manager_->GetDisplayController(GetPrimaryBounds());
249
250 EXPECT_TRUE(controller);
251 EXPECT_TRUE(controller->HasCrtc(drm_, kPrimaryCrtc));
252 }
253
TEST_F(ScreenManagerTest,CheckWithInvalidBounds)254 TEST_F(ScreenManagerTest, CheckWithInvalidBounds) {
255 InitializeDrmStateWithDefault(drm_.get());
256
257 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
258
259 ScreenManager::ControllerConfigsList controllers_to_enable;
260 controllers_to_enable.emplace_back(
261 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
262 GetPrimaryBounds().origin(),
263 std::make_unique<drmModeModeInfo>(kDefaultMode));
264 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
265
266 EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
267 EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
268 }
269
TEST_F(ScreenManagerTest,CheckForSecondValidController)270 TEST_F(ScreenManagerTest, CheckForSecondValidController) {
271 InitializeDrmStateWithDefault(drm_.get());
272
273 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
274 screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
275 kSecondaryConnector);
276
277 ScreenManager::ControllerConfigsList controllers_to_enable;
278 controllers_to_enable.emplace_back(
279 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
280 GetPrimaryBounds().origin(),
281 std::make_unique<drmModeModeInfo>(kDefaultMode));
282 drmModeModeInfo secondary_mode = kDefaultMode;
283 controllers_to_enable.emplace_back(
284 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
285 GetSecondaryBounds().origin(),
286 std::make_unique<drmModeModeInfo>(secondary_mode));
287 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
288
289 EXPECT_EQ(drm_->get_test_modeset_count(), 1);
290 EXPECT_EQ(drm_->get_commit_modeset_count(), 2);
291
292 EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
293 EXPECT_TRUE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
294 }
295
TEST_F(ScreenManagerTest,CheckControllerAfterItIsRemoved)296 TEST_F(ScreenManagerTest, CheckControllerAfterItIsRemoved) {
297 InitializeDrmStateWithDefault(drm_.get());
298
299 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
300
301 ScreenManager::ControllerConfigsList controllers_to_enable;
302 controllers_to_enable.emplace_back(
303 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
304 GetPrimaryBounds().origin(),
305 std::make_unique<drmModeModeInfo>(kDefaultMode));
306 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
307
308 EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
309
310 ScreenManager::CrtcsWithDrmList controllers_to_remove;
311 controllers_to_remove.emplace_back(kPrimaryCrtc, drm_);
312 screen_manager_->RemoveDisplayControllers(controllers_to_remove);
313 EXPECT_FALSE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
314 }
315
TEST_F(ScreenManagerTest,CheckControllerAfterDisabled)316 TEST_F(ScreenManagerTest, CheckControllerAfterDisabled) {
317 InitializeDrmStateWithDefault(drm_.get());
318 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
319
320 // Enable
321 {
322 ScreenManager::ControllerConfigsList controllers_to_enable;
323 controllers_to_enable.emplace_back(
324 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
325 GetPrimaryBounds().origin(),
326 std::make_unique<drmModeModeInfo>(kDefaultMode));
327 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
328 }
329
330 int test_modeset_count_before_disable = drm_->get_test_modeset_count();
331 int commit_modeset_count_before_disable = drm_->get_commit_modeset_count();
332 // Disable
333 ScreenManager::ControllerConfigsList controllers_to_enable;
334 controllers_to_enable.emplace_back(kPrimaryDisplayId, drm_, kPrimaryCrtc,
335 kPrimaryConnector, gfx::Point(), nullptr);
336 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
337
338 EXPECT_EQ(drm_->get_test_modeset_count(),
339 test_modeset_count_before_disable + 1);
340 EXPECT_EQ(drm_->get_commit_modeset_count(),
341 commit_modeset_count_before_disable + 1);
342
343 EXPECT_FALSE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
344 }
345
TEST_F(ScreenManagerTest,CheckMultipleControllersAfterBeingRemoved)346 TEST_F(ScreenManagerTest, CheckMultipleControllersAfterBeingRemoved) {
347 InitializeDrmStateWithDefault(drm_.get());
348
349 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
350 screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
351 kSecondaryConnector);
352
353 ScreenManager::ControllerConfigsList controllers_to_enable;
354 controllers_to_enable.emplace_back(
355 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
356 GetPrimaryBounds().origin(),
357 std::make_unique<drmModeModeInfo>(kDefaultMode));
358 controllers_to_enable.emplace_back(
359 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
360 GetSecondaryBounds().origin(),
361 std::make_unique<drmModeModeInfo>(kDefaultMode));
362 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
363
364 int modeset_count_after_enable = drm_->get_commit_modeset_count();
365 ScreenManager::CrtcsWithDrmList controllers_to_remove;
366 controllers_to_remove.emplace_back(kPrimaryCrtc, drm_);
367 controllers_to_remove.emplace_back(kSecondaryCrtc, drm_);
368 screen_manager_->RemoveDisplayControllers(controllers_to_remove);
369
370 // Removed displays are disabled in only 1 modeset commit.
371 EXPECT_EQ(drm_->get_commit_modeset_count(), modeset_count_after_enable + 1);
372
373 EXPECT_FALSE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
374 EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
375 }
376
TEST_F(ScreenManagerTest,CheckMultipleControllersAfterBeingDisabled)377 TEST_F(ScreenManagerTest, CheckMultipleControllersAfterBeingDisabled) {
378 InitializeDrmStateWithDefault(drm_.get());
379 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
380 screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
381 kSecondaryConnector);
382 // Enable
383 {
384 ScreenManager::ControllerConfigsList controllers_to_enable;
385 controllers_to_enable.emplace_back(
386 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
387 GetPrimaryBounds().origin(),
388 std::make_unique<drmModeModeInfo>(kDefaultMode));
389 controllers_to_enable.emplace_back(
390 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
391 GetSecondaryBounds().origin(),
392 std::make_unique<drmModeModeInfo>(kDefaultMode));
393 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
394 }
395
396 int test_modeset_count_before_disable = drm_->get_test_modeset_count();
397 int commit_modeset_count_before_disable = drm_->get_commit_modeset_count();
398 // Disable
399 ScreenManager::ControllerConfigsList controllers_to_enable;
400 controllers_to_enable.emplace_back(kPrimaryDisplayId, drm_, kPrimaryCrtc,
401 kPrimaryConnector, gfx::Point(), nullptr);
402 controllers_to_enable.emplace_back(kSecondaryDisplayId, drm_, kSecondaryCrtc,
403 kSecondaryConnector, gfx::Point(),
404 nullptr);
405 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
406
407 EXPECT_EQ(drm_->get_test_modeset_count(),
408 test_modeset_count_before_disable + 1);
409 EXPECT_EQ(drm_->get_commit_modeset_count(),
410 commit_modeset_count_before_disable + 2);
411
412 EXPECT_FALSE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
413 EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
414 }
415
TEST_F(ScreenManagerTest,CheckDuplicateConfiguration)416 TEST_F(ScreenManagerTest, CheckDuplicateConfiguration) {
417 InitializeDrmStateWithDefault(drm_.get(), /*is_atomic*/ false);
418
419 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
420
421 ScreenManager::ControllerConfigsList controllers_to_enable;
422 controllers_to_enable.emplace_back(
423 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
424 GetPrimaryBounds().origin(),
425 std::make_unique<drmModeModeInfo>(kDefaultMode));
426 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
427
428 uint32_t framebuffer = drm_->current_framebuffer();
429
430 controllers_to_enable.clear();
431 controllers_to_enable.emplace_back(
432 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
433 GetPrimaryBounds().origin(),
434 std::make_unique<drmModeModeInfo>(kDefaultMode));
435 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
436
437 // Should not hold onto buffers.
438 EXPECT_NE(framebuffer, drm_->current_framebuffer());
439
440 EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
441 EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
442 }
443
TEST_F(ScreenManagerTest,CheckChangingMode)444 TEST_F(ScreenManagerTest, CheckChangingMode) {
445 InitializeDrmStateWithDefault(drm_.get());
446
447 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
448
449 // Modeset with default mode.
450 {
451 ScreenManager::ControllerConfigsList controllers_to_enable;
452 controllers_to_enable.emplace_back(
453 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
454 GetPrimaryBounds().origin(),
455 std::make_unique<drmModeModeInfo>(kDefaultMode));
456 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
457 }
458 auto new_mode = kDefaultMode;
459 new_mode.vdisplay = new_mode.vdisplay++;
460 // Modeset with a changed Mode.
461 {
462 ScreenManager::ControllerConfigsList controllers_to_enable;
463 controllers_to_enable.emplace_back(
464 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
465 GetPrimaryBounds().origin(),
466 std::make_unique<drmModeModeInfo>(new_mode));
467 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
468 }
469
470 gfx::Rect new_bounds(0, 0, new_mode.hdisplay, new_mode.vdisplay);
471 EXPECT_TRUE(screen_manager_->GetDisplayController(new_bounds));
472 EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
473 drmModeModeInfo mode = screen_manager_->GetDisplayController(new_bounds)
474 ->crtc_controllers()[0]
475 ->mode();
476 EXPECT_EQ(new_mode.vdisplay, mode.vdisplay);
477 EXPECT_EQ(new_mode.hdisplay, mode.hdisplay);
478 }
479
TEST_F(ScreenManagerTest,CheckForControllersInMirroredMode)480 TEST_F(ScreenManagerTest, CheckForControllersInMirroredMode) {
481 InitializeDrmStateWithDefault(drm_.get());
482
483 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
484 screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
485 kSecondaryConnector);
486
487 ScreenManager::ControllerConfigsList controllers_to_enable;
488 controllers_to_enable.emplace_back(
489 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
490 GetPrimaryBounds().origin(),
491 std::make_unique<drmModeModeInfo>(kDefaultMode));
492 drmModeModeInfo secondary_mode = kDefaultMode;
493 controllers_to_enable.emplace_back(
494 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
495 GetPrimaryBounds().origin(),
496 std::make_unique<drmModeModeInfo>(secondary_mode));
497 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
498
499 EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
500 EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
501 }
502
TEST_F(ScreenManagerTest,CheckMirrorModeTransitions)503 TEST_F(ScreenManagerTest, CheckMirrorModeTransitions) {
504 std::vector<CrtcState> crtc_states = {
505 {
506 /* .planes = */
507 {
508 {/* .formats = */ {DRM_FORMAT_XRGB8888}},
509 {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
510 },
511 },
512 {
513 /* .planes = */
514 {
515 {/* .formats = */ {DRM_FORMAT_XRGB8888}},
516 {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
517 },
518 },
519 };
520 InitializeDrmState(drm_.get(), crtc_states);
521
522 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
523 screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
524 kSecondaryConnector);
525
526 ScreenManager::ControllerConfigsList controllers_to_enable;
527 controllers_to_enable.emplace_back(
528 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
529 GetPrimaryBounds().origin(),
530 std::make_unique<drmModeModeInfo>(kDefaultMode));
531 drmModeModeInfo secondary_mode = kDefaultMode;
532 controllers_to_enable.emplace_back(
533 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
534 GetSecondaryBounds().origin(),
535 std::make_unique<drmModeModeInfo>(secondary_mode));
536 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
537
538 EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
539 EXPECT_TRUE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
540
541 controllers_to_enable.clear();
542 drmModeModeInfo transition1_primary_mode = kDefaultMode;
543 controllers_to_enable.emplace_back(
544 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
545 GetPrimaryBounds().origin(),
546 std::make_unique<drmModeModeInfo>(transition1_primary_mode));
547 drmModeModeInfo transition1_secondary_mode = kDefaultMode;
548 controllers_to_enable.emplace_back(
549 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
550 GetPrimaryBounds().origin(),
551 std::make_unique<drmModeModeInfo>(transition1_secondary_mode));
552 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
553
554 EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
555 EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
556
557 controllers_to_enable.clear();
558 drmModeModeInfo transition2_primary_mode = kDefaultMode;
559 controllers_to_enable.emplace_back(
560 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
561 GetSecondaryBounds().origin(),
562 std::make_unique<drmModeModeInfo>(transition2_primary_mode));
563 drmModeModeInfo transition2_secondary_mode = kDefaultMode;
564 controllers_to_enable.emplace_back(
565 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
566 GetPrimaryBounds().origin(),
567 std::make_unique<drmModeModeInfo>(transition2_secondary_mode));
568 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
569
570 EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
571 EXPECT_TRUE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
572 }
573
574 // Make sure we're using each display's mode when doing mirror mode otherwise
575 // the timings may be off.
TEST_F(ScreenManagerTest,CheckMirrorModeModesettingWithDisplaysMode)576 TEST_F(ScreenManagerTest, CheckMirrorModeModesettingWithDisplaysMode) {
577 InitializeDrmStateWithDefault(drm_.get());
578
579 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
580 screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
581 kSecondaryConnector);
582
583 ScreenManager::ControllerConfigsList controllers_to_enable;
584 controllers_to_enable.emplace_back(
585 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
586 GetPrimaryBounds().origin(),
587 std::make_unique<drmModeModeInfo>(kDefaultMode));
588 // Copy the mode and use the copy so we can tell what mode the CRTC was
589 // configured with. The clock value is modified so we can tell which mode is
590 // being used.
591 drmModeModeInfo secondary_mode = kDefaultMode;
592 secondary_mode.clock++;
593 controllers_to_enable.emplace_back(
594 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
595 GetPrimaryBounds().origin(),
596 std::make_unique<drmModeModeInfo>(secondary_mode));
597 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
598
599 ui::HardwareDisplayController* controller =
600 screen_manager_->GetDisplayController(GetPrimaryBounds());
601 for (const auto& crtc : controller->crtc_controllers()) {
602 if (crtc->crtc() == kPrimaryCrtc)
603 EXPECT_EQ(kDefaultMode.clock, crtc->mode().clock);
604 else if (crtc->crtc() == kSecondaryCrtc)
605 EXPECT_EQ(secondary_mode.clock, crtc->mode().clock);
606 else
607 NOTREACHED();
608 }
609 }
610
TEST_F(ScreenManagerTest,MonitorGoneInMirrorMode)611 TEST_F(ScreenManagerTest, MonitorGoneInMirrorMode) {
612 InitializeDrmStateWithDefault(drm_.get());
613
614 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
615 screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
616 kSecondaryConnector);
617
618 ScreenManager::ControllerConfigsList controllers_to_enable;
619 controllers_to_enable.emplace_back(
620 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
621 GetPrimaryBounds().origin(),
622 std::make_unique<drmModeModeInfo>(kDefaultMode));
623 drmModeModeInfo secondary_mode = kDefaultMode;
624 controllers_to_enable.emplace_back(
625 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
626 GetPrimaryBounds().origin(),
627 std::make_unique<drmModeModeInfo>(secondary_mode));
628 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
629
630 ScreenManager::CrtcsWithDrmList controllers_to_remove;
631 controllers_to_remove.emplace_back(kSecondaryCrtc, drm_);
632 screen_manager_->RemoveDisplayControllers(controllers_to_remove);
633
634 ui::HardwareDisplayController* controller =
635 screen_manager_->GetDisplayController(GetPrimaryBounds());
636 EXPECT_TRUE(controller);
637 EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
638
639 EXPECT_TRUE(controller->HasCrtc(drm_, kPrimaryCrtc));
640 EXPECT_FALSE(controller->HasCrtc(drm_, kSecondaryCrtc));
641 }
642
TEST_F(ScreenManagerTest,MonitorDisabledInMirrorMode)643 TEST_F(ScreenManagerTest, MonitorDisabledInMirrorMode) {
644 InitializeDrmStateWithDefault(drm_.get());
645
646 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
647 screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
648 kSecondaryConnector);
649
650 ScreenManager::ControllerConfigsList controllers_to_enable;
651 controllers_to_enable.emplace_back(
652 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
653 GetPrimaryBounds().origin(),
654 std::make_unique<drmModeModeInfo>(kDefaultMode));
655 drmModeModeInfo secondary_mode = kDefaultMode;
656 controllers_to_enable.emplace_back(
657 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
658 GetPrimaryBounds().origin(),
659 std::make_unique<drmModeModeInfo>(secondary_mode));
660 // Disable display Controller.
661 controllers_to_enable.emplace_back(0, drm_, kSecondaryCrtc, 0, gfx::Point(),
662 nullptr);
663 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
664
665 ui::HardwareDisplayController* controller =
666 screen_manager_->GetDisplayController(GetPrimaryBounds());
667 EXPECT_TRUE(controller);
668 EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
669
670 EXPECT_TRUE(controller->HasCrtc(drm_, kPrimaryCrtc));
671 EXPECT_FALSE(controller->HasCrtc(drm_, kSecondaryCrtc));
672 }
673
TEST_F(ScreenManagerTest,DoNotEnterMirrorModeUnlessSameBounds)674 TEST_F(ScreenManagerTest, DoNotEnterMirrorModeUnlessSameBounds) {
675 InitializeDrmStateWithDefault(drm_.get());
676
677 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
678 screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
679 kSecondaryConnector);
680
681 // Configure displays in extended mode.
682 {
683 ScreenManager::ControllerConfigsList controllers_to_enable;
684 controllers_to_enable.emplace_back(
685 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
686 GetPrimaryBounds().origin(),
687 std::make_unique<drmModeModeInfo>(kDefaultMode));
688 drmModeModeInfo secondary_mode = kDefaultMode;
689 controllers_to_enable.emplace_back(
690 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
691 GetSecondaryBounds().origin(),
692 std::make_unique<drmModeModeInfo>(secondary_mode));
693 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
694 }
695
696 {
697 auto new_mode = std::make_unique<drmModeModeInfo>(kDefaultMode);
698 new_mode->vdisplay = 10;
699 // Shouldn't enter mirror mode unless the display bounds are the same.
700 ScreenManager::ControllerConfigsList controllers_to_enable;
701 controllers_to_enable.emplace_back(
702 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
703 GetPrimaryBounds().origin(), std::move(new_mode));
704 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
705 }
706
707 EXPECT_FALSE(
708 screen_manager_->GetDisplayController(GetPrimaryBounds())->IsMirrored());
709 }
710
TEST_F(ScreenManagerTest,ReuseFramebufferIfDisabledThenReEnabled)711 TEST_F(ScreenManagerTest, ReuseFramebufferIfDisabledThenReEnabled) {
712 InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/false);
713
714 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
715 ScreenManager::ControllerConfigsList controllers_to_enable;
716 controllers_to_enable.emplace_back(
717 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
718 GetPrimaryBounds().origin(),
719 std::make_unique<drmModeModeInfo>(kDefaultMode));
720 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
721
722 uint32_t framebuffer = drm_->current_framebuffer();
723
724 controllers_to_enable.clear();
725 // Disable display controller.
726 controllers_to_enable.emplace_back(0, drm_, kPrimaryCrtc, 0, gfx::Point(),
727 nullptr);
728 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
729 EXPECT_EQ(0u, drm_->current_framebuffer());
730
731 controllers_to_enable.clear();
732 drmModeModeInfo reenable_mode = kDefaultMode;
733 controllers_to_enable.emplace_back(
734 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
735 GetPrimaryBounds().origin(),
736 std::make_unique<drmModeModeInfo>(reenable_mode));
737 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
738
739 // Buffers are released when disabled.
740 EXPECT_NE(framebuffer, drm_->current_framebuffer());
741 }
742
TEST_F(ScreenManagerTest,CheckMirrorModeAfterBeginReEnabled)743 TEST_F(ScreenManagerTest, CheckMirrorModeAfterBeginReEnabled) {
744 InitializeDrmStateWithDefault(drm_.get());
745
746 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
747 screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
748 kSecondaryConnector);
749 {
750 ScreenManager::ControllerConfigsList controllers_to_enable;
751 controllers_to_enable.emplace_back(
752 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
753 GetPrimaryBounds().origin(),
754 std::make_unique<drmModeModeInfo>(kDefaultMode));
755 drmModeModeInfo secondary_mode = kDefaultMode;
756 controllers_to_enable.emplace_back(
757 kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
758 GetPrimaryBounds().origin(),
759 std::make_unique<drmModeModeInfo>(secondary_mode));
760 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
761 }
762 {
763 ScreenManager::ControllerConfigsList controllers_to_enable;
764 controllers_to_enable.emplace_back(0, drm_, kPrimaryCrtc, 0, gfx::Point(),
765 nullptr);
766 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
767 }
768
769 ui::HardwareDisplayController* controller =
770 screen_manager_->GetDisplayController(GetPrimaryBounds());
771 EXPECT_TRUE(controller);
772 EXPECT_FALSE(controller->IsMirrored());
773
774 {
775 ScreenManager::ControllerConfigsList controllers_to_enable;
776 drmModeModeInfo reenable_mode = kDefaultMode;
777 controllers_to_enable.emplace_back(
778 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
779 GetPrimaryBounds().origin(),
780 std::make_unique<drmModeModeInfo>(reenable_mode));
781 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
782 }
783
784 EXPECT_TRUE(controller);
785 EXPECT_TRUE(controller->IsMirrored());
786 }
787
TEST_F(ScreenManagerTest,ConfigureOnDifferentDrmDevices)788 TEST_F(ScreenManagerTest, ConfigureOnDifferentDrmDevices) {
789 auto gbm_device = std::make_unique<ui::MockGbmDevice>();
790 scoped_refptr<ui::MockDrmDevice> drm2 =
791 new ui::MockDrmDevice(std::move(gbm_device));
792
793 InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/false);
794 std::vector<CrtcState> crtc_states = {
795 {/* .planes = */
796 {
797 {/* .formats = */ {DRM_FORMAT_XRGB8888}},
798 }},
799 {/* .planes = */
800 {
801 {/* .formats = */ {DRM_FORMAT_XRGB8888}},
802 }},
803 {/* .planes = */
804 {
805 {/* .formats = */ {DRM_FORMAT_XRGB8888}},
806 }}};
807 InitializeDrmState(drm2.get(), crtc_states, /*is_atomic=*/false);
808
809 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
810 screen_manager_->AddDisplayController(drm2, kSecondaryCrtc,
811 kSecondaryConnector);
812 screen_manager_->AddDisplayController(drm2, kSecondaryCrtc + 1,
813 kSecondaryConnector + 1);
814
815 ScreenManager::ControllerConfigsList controllers_to_enable;
816 controllers_to_enable.emplace_back(
817 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
818 GetPrimaryBounds().origin(),
819 std::make_unique<drmModeModeInfo>(kDefaultMode));
820 drmModeModeInfo secondary_mode = kDefaultMode;
821 controllers_to_enable.emplace_back(
822 kSecondaryDisplayId, drm2, kSecondaryCrtc, kSecondaryConnector,
823 GetSecondaryBounds().origin(),
824 std::make_unique<drmModeModeInfo>(secondary_mode));
825 drmModeModeInfo secondary_mode2 = kDefaultMode;
826 controllers_to_enable.emplace_back(
827 kSecondaryDisplayId + 1, drm2, kSecondaryCrtc + 1,
828 kSecondaryConnector + 1, GetSecondaryBounds().origin(),
829 std::make_unique<drmModeModeInfo>(secondary_mode2));
830 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
831
832 EXPECT_EQ(drm_->get_set_crtc_call_count(), 1);
833 EXPECT_EQ(drm2->get_set_crtc_call_count(), 2);
834 }
835
TEST_F(ScreenManagerTest,CheckProperConfigurationWithDifferentDeviceAndSameCrtc)836 TEST_F(ScreenManagerTest,
837 CheckProperConfigurationWithDifferentDeviceAndSameCrtc) {
838 auto gbm_device = std::make_unique<ui::MockGbmDevice>();
839 scoped_refptr<ui::MockDrmDevice> drm2 =
840 new ui::MockDrmDevice(std::move(gbm_device));
841
842 InitializeDrmStateWithDefault(drm_.get());
843 InitializeDrmStateWithDefault(drm2.get());
844
845 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
846 screen_manager_->AddDisplayController(drm2, kPrimaryCrtc, kPrimaryConnector);
847
848 ScreenManager::ControllerConfigsList controllers_to_enable;
849 controllers_to_enable.emplace_back(
850 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
851 GetPrimaryBounds().origin(),
852 std::make_unique<drmModeModeInfo>(kDefaultMode));
853 drmModeModeInfo secondary_mode = kDefaultMode;
854 controllers_to_enable.emplace_back(
855 kSecondaryDisplayId, drm2, kPrimaryCrtc, kPrimaryConnector,
856 GetSecondaryBounds().origin(),
857 std::make_unique<drmModeModeInfo>(secondary_mode));
858 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
859
860 ui::HardwareDisplayController* controller1 =
861 screen_manager_->GetDisplayController(GetPrimaryBounds());
862 ui::HardwareDisplayController* controller2 =
863 screen_manager_->GetDisplayController(GetSecondaryBounds());
864
865 EXPECT_NE(controller1, controller2);
866 EXPECT_EQ(drm_, controller1->crtc_controllers()[0]->drm());
867 EXPECT_EQ(drm2, controller2->crtc_controllers()[0]->drm());
868 }
869
TEST_F(ScreenManagerTest,CheckControllerToWindowMappingWithSameBounds)870 TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithSameBounds) {
871 InitializeDrmStateWithDefault(drm_.get());
872
873 std::unique_ptr<ui::DrmWindow> window(
874 new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
875 window->Initialize();
876 window->SetBounds(GetPrimaryBounds());
877 screen_manager_->AddWindow(1, std::move(window));
878
879 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
880 ScreenManager::ControllerConfigsList controllers_to_enable;
881 controllers_to_enable.emplace_back(
882 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
883 GetPrimaryBounds().origin(),
884 std::make_unique<drmModeModeInfo>(kDefaultMode));
885 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
886
887 EXPECT_TRUE(screen_manager_->GetWindow(1)->GetController());
888
889 window = screen_manager_->RemoveWindow(1);
890 window->Shutdown();
891 }
892
TEST_F(ScreenManagerTest,CheckControllerToWindowMappingWithDifferentBounds)893 TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithDifferentBounds) {
894 InitializeDrmStateWithDefault(drm_.get());
895
896 std::unique_ptr<ui::DrmWindow> window(
897 new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
898 window->Initialize();
899 gfx::Rect new_bounds = GetPrimaryBounds();
900 new_bounds.Inset(0, 0, 1, 1);
901 window->SetBounds(new_bounds);
902 screen_manager_->AddWindow(1, std::move(window));
903
904 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
905 ScreenManager::ControllerConfigsList controllers_to_enable;
906 controllers_to_enable.emplace_back(
907 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
908 GetPrimaryBounds().origin(),
909 std::make_unique<drmModeModeInfo>(kDefaultMode));
910 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
911
912 EXPECT_FALSE(screen_manager_->GetWindow(1)->GetController());
913
914 window = screen_manager_->RemoveWindow(1);
915 window->Shutdown();
916 }
917
TEST_F(ScreenManagerTest,CheckControllerToWindowMappingWithOverlappingWindows)918 TEST_F(ScreenManagerTest,
919 CheckControllerToWindowMappingWithOverlappingWindows) {
920 InitializeDrmStateWithDefault(drm_.get());
921
922 const size_t kWindowCount = 2;
923 for (size_t i = 1; i < kWindowCount + 1; ++i) {
924 std::unique_ptr<ui::DrmWindow> window(
925 new ui::DrmWindow(i, device_manager_.get(), screen_manager_.get()));
926 window->Initialize();
927 window->SetBounds(GetPrimaryBounds());
928 screen_manager_->AddWindow(i, std::move(window));
929 }
930
931 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
932 ScreenManager::ControllerConfigsList controllers_to_enable;
933 controllers_to_enable.emplace_back(
934 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
935 GetPrimaryBounds().origin(),
936 std::make_unique<drmModeModeInfo>(kDefaultMode));
937 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
938
939 bool window1_has_controller = screen_manager_->GetWindow(1)->GetController();
940 bool window2_has_controller = screen_manager_->GetWindow(2)->GetController();
941 // Only one of the windows can have a controller.
942 EXPECT_TRUE(window1_has_controller ^ window2_has_controller);
943
944 for (size_t i = 1; i < kWindowCount + 1; ++i) {
945 std::unique_ptr<ui::DrmWindow> window = screen_manager_->RemoveWindow(i);
946 window->Shutdown();
947 }
948 }
949
TEST_F(ScreenManagerTest,ShouldDissociateWindowOnControllerRemoval)950 TEST_F(ScreenManagerTest, ShouldDissociateWindowOnControllerRemoval) {
951 InitializeDrmStateWithDefault(drm_.get());
952
953 gfx::AcceleratedWidget window_id = 1;
954 std::unique_ptr<ui::DrmWindow> window(new ui::DrmWindow(
955 window_id, device_manager_.get(), screen_manager_.get()));
956 window->Initialize();
957 window->SetBounds(GetPrimaryBounds());
958 screen_manager_->AddWindow(window_id, std::move(window));
959
960 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
961 ScreenManager::ControllerConfigsList controllers_to_enable;
962 controllers_to_enable.emplace_back(
963 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
964 GetPrimaryBounds().origin(),
965 std::make_unique<drmModeModeInfo>(kDefaultMode));
966 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
967
968 EXPECT_TRUE(screen_manager_->GetWindow(window_id)->GetController());
969
970 ScreenManager::CrtcsWithDrmList controllers_to_remove;
971 controllers_to_remove.emplace_back(kPrimaryCrtc, drm_);
972 screen_manager_->RemoveDisplayControllers(controllers_to_remove);
973
974 EXPECT_FALSE(screen_manager_->GetWindow(window_id)->GetController());
975
976 window = screen_manager_->RemoveWindow(1);
977 window->Shutdown();
978 }
979
TEST_F(ScreenManagerTest,EnableControllerWhenWindowHasNoBuffer)980 TEST_F(ScreenManagerTest, EnableControllerWhenWindowHasNoBuffer) {
981 InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/false);
982
983 std::unique_ptr<ui::DrmWindow> window(
984 new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
985 window->Initialize();
986 window->SetBounds(GetPrimaryBounds());
987 screen_manager_->AddWindow(1, std::move(window));
988
989 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
990 ScreenManager::ControllerConfigsList controllers_to_enable;
991 controllers_to_enable.emplace_back(
992 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
993 GetPrimaryBounds().origin(),
994 std::make_unique<drmModeModeInfo>(kDefaultMode));
995 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
996
997 EXPECT_TRUE(screen_manager_->GetWindow(1)->GetController());
998 // There is a buffer after initial config.
999 uint32_t framebuffer = drm_->current_framebuffer();
1000 EXPECT_NE(0U, framebuffer);
1001
1002 controllers_to_enable.clear();
1003 controllers_to_enable.emplace_back(
1004 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
1005 GetPrimaryBounds().origin(),
1006 std::make_unique<drmModeModeInfo>(kDefaultMode));
1007 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
1008
1009 // There is a new buffer after we configured with the same mode but no
1010 // pending frames on the window.
1011 EXPECT_NE(framebuffer, drm_->current_framebuffer());
1012
1013 window = screen_manager_->RemoveWindow(1);
1014 window->Shutdown();
1015 }
1016
TEST_F(ScreenManagerTest,EnableControllerWhenWindowHasBuffer)1017 TEST_F(ScreenManagerTest, EnableControllerWhenWindowHasBuffer) {
1018 InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/false);
1019
1020 std::unique_ptr<ui::DrmWindow> window(
1021 new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
1022 window->Initialize();
1023 window->SetBounds(GetPrimaryBounds());
1024 scoped_refptr<DrmFramebuffer> buffer =
1025 CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
1026 ui::DrmOverlayPlaneList planes;
1027 planes.push_back(ui::DrmOverlayPlane(buffer, nullptr));
1028 window->SchedulePageFlip(std::move(planes), base::DoNothing(),
1029 base::DoNothing());
1030 screen_manager_->AddWindow(1, std::move(window));
1031
1032 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
1033 ScreenManager::ControllerConfigsList controllers_to_enable;
1034 controllers_to_enable.emplace_back(
1035 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
1036 GetPrimaryBounds().origin(),
1037 std::make_unique<drmModeModeInfo>(kDefaultMode));
1038 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
1039
1040 EXPECT_EQ(buffer->opaque_framebuffer_id(), drm_->current_framebuffer());
1041
1042 window = screen_manager_->RemoveWindow(1);
1043 window->Shutdown();
1044 }
1045
1046 // See crbug.com/868010
TEST_F(ScreenManagerTest,DISABLED_RejectBufferWithIncompatibleModifiers)1047 TEST_F(ScreenManagerTest, DISABLED_RejectBufferWithIncompatibleModifiers) {
1048 std::unique_ptr<ui::DrmWindow> window(
1049 new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
1050 window->Initialize();
1051 window->SetBounds(GetPrimaryBounds());
1052 auto buffer = CreateBufferWithModifier(
1053 DRM_FORMAT_XRGB8888, I915_FORMAT_MOD_X_TILED, GetPrimaryBounds().size());
1054 ui::DrmOverlayPlaneList planes;
1055 planes.push_back(ui::DrmOverlayPlane(buffer, nullptr));
1056 window->SchedulePageFlip(std::move(planes), base::DoNothing(),
1057 base::DoNothing());
1058 screen_manager_->AddWindow(1, std::move(window));
1059
1060 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
1061 ScreenManager::ControllerConfigsList controllers_to_enable;
1062 controllers_to_enable.emplace_back(
1063 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
1064 GetPrimaryBounds().origin(),
1065 std::make_unique<drmModeModeInfo>(kDefaultMode));
1066 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
1067
1068 // ScreenManager::GetModesetBuffer (called to get a buffer to
1069 // modeset the new controller) should reject the buffer with
1070 // I915_FORMAT_MOD_X_TILED modifier we created above and the two
1071 // framebuffer IDs should be different.
1072 EXPECT_NE(buffer->framebuffer_id(), drm_->current_framebuffer());
1073 EXPECT_NE(buffer->opaque_framebuffer_id(), drm_->current_framebuffer());
1074
1075 window = screen_manager_->RemoveWindow(1);
1076 window->Shutdown();
1077 }
1078
TEST_F(ScreenManagerTest,ConfigureDisplayControllerShouldModesetOnce)1079 TEST_F(ScreenManagerTest, ConfigureDisplayControllerShouldModesetOnce) {
1080 InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/false);
1081
1082 std::unique_ptr<ui::DrmWindow> window(
1083 new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
1084 window->Initialize();
1085 window->SetBounds(GetPrimaryBounds());
1086 screen_manager_->AddWindow(1, std::move(window));
1087
1088 screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
1089 ScreenManager::ControllerConfigsList controllers_to_enable;
1090 controllers_to_enable.emplace_back(
1091 kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
1092 GetPrimaryBounds().origin(),
1093 std::make_unique<drmModeModeInfo>(kDefaultMode));
1094 screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
1095
1096 // When a window that had no controller becomes associated with a new
1097 // controller, expect the crtc to be modeset once.
1098 EXPECT_EQ(drm_->get_set_crtc_call_count(), 1);
1099
1100 window = screen_manager_->RemoveWindow(1);
1101 window->Shutdown();
1102 }
1103
TEST_F(ScreenManagerTest,ShouldNotHardwareMirrorDifferentDrmDevices)1104 TEST_F(ScreenManagerTest, ShouldNotHardwareMirrorDifferentDrmDevices) {
1105 auto gbm_device1 = std::make_unique<MockGbmDevice>();
1106 auto drm_device1 =
1107 base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device1));
1108 InitializeDrmStateWithDefault(drm_device1.get());
1109
1110 auto gbm_device2 = std::make_unique<MockGbmDevice>();
1111 auto drm_device2 =
1112 base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device2));
1113 InitializeDrmStateWithDefault(drm_device2.get());
1114
1115 DrmDeviceManager drm_device_manager(nullptr);
1116 ScreenManager screen_manager;
1117
1118 constexpr uint32_t kCrtc1 = kPrimaryCrtc;
1119 constexpr uint32_t kConnector1 = kPrimaryConnector;
1120 constexpr uint32_t kCrtc2 = kSecondaryCrtc;
1121 constexpr uint32_t kConnector2 = kSecondaryConnector;
1122
1123 drmModeModeInfo k1920x1080Screen = ConstructMode(1920, 1080);
1124 std::unique_ptr<drmModeModeInfo> primary_mode =
1125 std::make_unique<drmModeModeInfo>(k1920x1080Screen);
1126 std::unique_ptr<drmModeModeInfo> secondary_mode =
1127 std::make_unique<drmModeModeInfo>(k1920x1080Screen);
1128
1129 // Two displays on different DRM devices must not join a mirror pair.
1130 //
1131 // However, they may have the same bounds in a transitional state.
1132 //
1133 // This scenario generates the same sequence of display configuration
1134 // events as a panther (kernel 3.8.11) chromebox with two identical
1135 // 1080p displays connected, one of them via a DisplayLink adapter.
1136
1137 // Both displays connect at startup.
1138 {
1139 auto window1 =
1140 std::make_unique<DrmWindow>(1, &drm_device_manager, &screen_manager);
1141 window1->Initialize();
1142 screen_manager.AddWindow(1, std::move(window1));
1143 screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 0, 1920, 1080));
1144 screen_manager.AddDisplayController(drm_device1, kCrtc1, kConnector1);
1145 screen_manager.AddDisplayController(drm_device2, kCrtc2, kConnector2);
1146
1147 ScreenManager::ControllerConfigsList controllers_to_enable;
1148 std::unique_ptr<drmModeModeInfo> primary_mode =
1149 std::make_unique<drmModeModeInfo>(k1920x1080Screen);
1150 std::unique_ptr<drmModeModeInfo> secondary_mode =
1151 std::make_unique<drmModeModeInfo>(k1920x1080Screen);
1152 controllers_to_enable.emplace_back(kPrimaryDisplayId, drm_device1, kCrtc1,
1153 kConnector1, gfx::Point(0, 0),
1154 std::move(primary_mode));
1155 controllers_to_enable.emplace_back(kSecondaryDisplayId, drm_device2, kCrtc2,
1156 kConnector2, gfx::Point(0, 1140),
1157 std::move(secondary_mode));
1158 screen_manager.ConfigureDisplayControllers(controllers_to_enable);
1159
1160 auto window2 =
1161 std::make_unique<DrmWindow>(2, &drm_device_manager, &screen_manager);
1162 window2->Initialize();
1163 screen_manager.AddWindow(2, std::move(window2));
1164 screen_manager.GetWindow(2)->SetBounds(gfx::Rect(0, 1140, 1920, 1080));
1165 }
1166
1167 // Displays are stacked vertically, window per display.
1168 {
1169 HardwareDisplayController* controller1 =
1170 screen_manager.GetWindow(1)->GetController();
1171 HardwareDisplayController* controller2 =
1172 screen_manager.GetWindow(2)->GetController();
1173 EXPECT_NE(controller1, controller2);
1174 EXPECT_TRUE(controller1->HasCrtc(drm_device1, kCrtc1));
1175 EXPECT_TRUE(controller2->HasCrtc(drm_device2, kCrtc2));
1176 }
1177
1178 // Disconnect first display. Second display moves to origin.
1179 {
1180 ScreenManager::CrtcsWithDrmList controllers_to_remove;
1181 controllers_to_remove.emplace_back(kCrtc1, drm_device1);
1182 screen_manager.RemoveDisplayControllers(controllers_to_remove);
1183
1184 ScreenManager::ControllerConfigsList controllers_to_enable;
1185 std::unique_ptr<drmModeModeInfo> secondary_mode =
1186 std::make_unique<drmModeModeInfo>(k1920x1080Screen);
1187 controllers_to_enable.emplace_back(kSecondaryDisplayId, drm_device2, kCrtc2,
1188 kConnector2, gfx::Point(0, 0),
1189 std::move(secondary_mode));
1190 screen_manager.ConfigureDisplayControllers(controllers_to_enable);
1191
1192 screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 0, 1920, 1080));
1193 screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 0, 1920, 1080));
1194 screen_manager.RemoveWindow(2)->Shutdown();
1195 }
1196
1197 // Reconnect first display. Original configuration restored.
1198 {
1199 screen_manager.AddDisplayController(drm_device1, kCrtc1, kConnector1);
1200 ScreenManager::ControllerConfigsList controllers_to_enable;
1201 std::unique_ptr<drmModeModeInfo> primary_mode =
1202 std::make_unique<drmModeModeInfo>(k1920x1080Screen);
1203 controllers_to_enable.emplace_back(kPrimaryDisplayId, drm_device1, kCrtc1,
1204 kConnector1, gfx::Point(0, 0),
1205 std::move(primary_mode));
1206 screen_manager.ConfigureDisplayControllers(controllers_to_enable);
1207 // At this point, both displays are in the same location.
1208 {
1209 HardwareDisplayController* controller =
1210 screen_manager.GetWindow(1)->GetController();
1211 EXPECT_FALSE(controller->IsMirrored());
1212 // We don't really care which crtc it has, but it should have just
1213 EXPECT_EQ(1U, controller->crtc_controllers().size());
1214 EXPECT_TRUE(controller->HasCrtc(drm_device1, kCrtc1) ||
1215 controller->HasCrtc(drm_device2, kCrtc2));
1216 }
1217 controllers_to_enable.clear();
1218 std::unique_ptr<drmModeModeInfo> secondary_mode =
1219 std::make_unique<drmModeModeInfo>(k1920x1080Screen);
1220 controllers_to_enable.emplace_back(kSecondaryDisplayId, drm_device2, kCrtc2,
1221 kConnector2, gfx::Point(0, 1140),
1222 std::move(secondary_mode));
1223 screen_manager.ConfigureDisplayControllers(controllers_to_enable);
1224 auto window3 =
1225 std::make_unique<DrmWindow>(3, &drm_device_manager, &screen_manager);
1226 window3->Initialize();
1227 screen_manager.AddWindow(3, std::move(window3));
1228 screen_manager.GetWindow(3)->SetBounds(gfx::Rect(0, 0, 1920, 1080));
1229 screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 1140, 1920, 1080));
1230 screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 0, 1920, 1080));
1231 screen_manager.GetWindow(3)->SetBounds(gfx::Rect(0, 1140, 1920, 1080));
1232 }
1233
1234 // Everything is restored.
1235 {
1236 HardwareDisplayController* controller1 =
1237 screen_manager.GetWindow(1)->GetController();
1238 HardwareDisplayController* controller3 =
1239 screen_manager.GetWindow(3)->GetController();
1240 EXPECT_NE(controller1, controller3);
1241 EXPECT_TRUE(controller1->HasCrtc(drm_device1, kCrtc1));
1242 EXPECT_TRUE(controller3->HasCrtc(drm_device2, kCrtc2));
1243 }
1244
1245 // Cleanup.
1246 screen_manager.RemoveWindow(1)->Shutdown();
1247 screen_manager.RemoveWindow(3)->Shutdown();
1248 }
1249
1250 // crbug.com/888553
TEST_F(ScreenManagerTest,ShouldNotUnbindFramebufferOnJoiningMirror)1251 TEST_F(ScreenManagerTest, ShouldNotUnbindFramebufferOnJoiningMirror) {
1252 auto gbm_device = std::make_unique<MockGbmDevice>();
1253 auto drm_device = base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device));
1254 InitializeDrmStateWithDefault(drm_device.get(), /*is_atomic=*/false);
1255
1256 DrmDeviceManager drm_device_manager(nullptr);
1257 ScreenManager screen_manager;
1258
1259 constexpr uint32_t kCrtc1 = kPrimaryCrtc;
1260 constexpr uint32_t kConnector1 = kPrimaryConnector;
1261 constexpr uint32_t kCrtc2 = kSecondaryCrtc;
1262 constexpr uint32_t kConnector2 = kSecondaryConnector;
1263
1264 constexpr drmModeModeInfo k1080p60Screen = {
1265 /* clock= */ 148500,
1266 /* hdisplay= */ 1920,
1267 /* hsync_start= */ 2008,
1268 /* hsync_end= */ 2052,
1269 /* htotal= */ 2200,
1270 /* hskew= */ 0,
1271 /* vdisplay= */ 1080,
1272 /* vsync_start= */ 1084,
1273 /* vsync_end= */ 1089,
1274 /* vtotal= */ 1125,
1275 /* vscan= */ 0,
1276 /* vrefresh= */ 60,
1277 /* flags= */ 0xa,
1278 /* type= */ 64,
1279 /* name= */ "1920x1080",
1280 };
1281
1282 // Both displays connect at startup.
1283 {
1284 auto window1 =
1285 std::make_unique<DrmWindow>(1, &drm_device_manager, &screen_manager);
1286 window1->Initialize();
1287 screen_manager.AddWindow(1, std::move(window1));
1288 screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 0, 1920, 1080));
1289 screen_manager.AddDisplayController(drm_device, kCrtc1, kConnector1);
1290 screen_manager.AddDisplayController(drm_device, kCrtc2, kConnector2);
1291
1292 ScreenManager::ControllerConfigsList controllers_to_enable;
1293 std::unique_ptr<drmModeModeInfo> primary_mode =
1294 std::make_unique<drmModeModeInfo>(k1080p60Screen);
1295 std::unique_ptr<drmModeModeInfo> secondary_mode =
1296 std::make_unique<drmModeModeInfo>(k1080p60Screen);
1297 controllers_to_enable.emplace_back(kPrimaryDisplayId, drm_device, kCrtc1,
1298 kConnector1, gfx::Point(0, 0),
1299 std::move(primary_mode));
1300 controllers_to_enable.emplace_back(kSecondaryDisplayId, drm_device, kCrtc2,
1301 kConnector2, gfx::Point(0, 0),
1302 std::move(secondary_mode));
1303 screen_manager.ConfigureDisplayControllers(controllers_to_enable);
1304 }
1305
1306 EXPECT_NE(0u, drm_device->GetFramebufferForCrtc(kCrtc1));
1307 EXPECT_NE(0u, drm_device->GetFramebufferForCrtc(kCrtc2));
1308
1309 // Cleanup.
1310 screen_manager.RemoveWindow(1)->Shutdown();
1311 }
1312
1313 } // namespace ui
1314