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.
5 #include "testing/gtest/include/gtest/gtest.h"
6 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
7 #include "ui/ozone/platform/drm/gpu/drm_buffer.h"
8 #include "ui/ozone/platform/drm/gpu/drm_device_generator.h"
9 #include "ui/ozone/platform/drm/gpu/drm_device_manager.h"
10 #include "ui/ozone/platform/drm/gpu/drm_window.h"
11 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
12 #include "ui/ozone/platform/drm/gpu/screen_manager.h"
13 #include "ui/ozone/platform/drm/test/mock_drm_device.h"
17 void EmptySwapCallback(gfx::SwapResult
) {
20 // Create a basic mode for a 6x4 screen.
21 const drmModeModeInfo kDefaultMode
=
22 {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
24 const uint32_t kPrimaryCrtc
= 1;
25 const uint32_t kPrimaryConnector
= 2;
26 const uint32_t kSecondaryCrtc
= 3;
27 const uint32_t kSecondaryConnector
= 4;
31 class ScreenManagerTest
: public testing::Test
{
33 ScreenManagerTest() {}
34 ~ScreenManagerTest() override
{}
36 gfx::Rect
GetPrimaryBounds() const {
37 return gfx::Rect(0, 0, kDefaultMode
.hdisplay
, kDefaultMode
.vdisplay
);
40 // Secondary is in extended mode, right-of primary.
41 gfx::Rect
GetSecondaryBounds() const {
42 return gfx::Rect(kDefaultMode
.hdisplay
, 0, kDefaultMode
.hdisplay
,
43 kDefaultMode
.vdisplay
);
46 void SetUp() override
{
47 drm_
= new ui::MockDrmDevice();
48 device_manager_
.reset(new ui::DrmDeviceManager(nullptr));
49 buffer_generator_
.reset(new ui::DrmBufferGenerator());
50 screen_manager_
.reset(new ui::ScreenManager(buffer_generator_
.get()));
52 void TearDown() override
{
53 screen_manager_
.reset();
58 scoped_refptr
<ui::MockDrmDevice
> drm_
;
59 scoped_ptr
<ui::DrmDeviceManager
> device_manager_
;
60 scoped_ptr
<ui::DrmBufferGenerator
> buffer_generator_
;
61 scoped_ptr
<ui::ScreenManager
> screen_manager_
;
64 DISALLOW_COPY_AND_ASSIGN(ScreenManagerTest
);
67 TEST_F(ScreenManagerTest
, CheckWithNoControllers
) {
68 EXPECT_FALSE(screen_manager_
->GetDisplayController(GetPrimaryBounds()));
71 TEST_F(ScreenManagerTest
, CheckWithValidController
) {
72 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
73 screen_manager_
->ConfigureDisplayController(
74 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
76 ui::HardwareDisplayController
* controller
=
77 screen_manager_
->GetDisplayController(GetPrimaryBounds());
79 EXPECT_TRUE(controller
);
80 EXPECT_TRUE(controller
->HasCrtc(drm_
, kPrimaryCrtc
));
83 TEST_F(ScreenManagerTest
, CheckWithInvalidBounds
) {
84 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
85 screen_manager_
->ConfigureDisplayController(
86 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
89 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetPrimaryBounds()));
90 EXPECT_FALSE(screen_manager_
->GetDisplayController(GetSecondaryBounds()));
93 TEST_F(ScreenManagerTest
, CheckForSecondValidController
) {
94 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
95 screen_manager_
->ConfigureDisplayController(
96 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
98 screen_manager_
->AddDisplayController(drm_
, kSecondaryCrtc
,
100 screen_manager_
->ConfigureDisplayController(
101 drm_
, kSecondaryCrtc
, kSecondaryConnector
, GetSecondaryBounds().origin(),
104 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetPrimaryBounds()));
105 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetSecondaryBounds()));
108 TEST_F(ScreenManagerTest
, CheckControllerAfterItIsRemoved
) {
109 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
110 screen_manager_
->ConfigureDisplayController(
111 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
113 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetPrimaryBounds()));
115 screen_manager_
->RemoveDisplayController(drm_
, kPrimaryCrtc
);
116 EXPECT_FALSE(screen_manager_
->GetDisplayController(GetPrimaryBounds()));
119 TEST_F(ScreenManagerTest
, CheckDuplicateConfiguration
) {
120 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
121 screen_manager_
->ConfigureDisplayController(
122 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
124 uint32_t framebuffer
= drm_
->current_framebuffer();
126 screen_manager_
->ConfigureDisplayController(
127 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
130 // Should not hold onto buffers.
131 EXPECT_NE(framebuffer
, drm_
->current_framebuffer());
133 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetPrimaryBounds()));
134 EXPECT_FALSE(screen_manager_
->GetDisplayController(GetSecondaryBounds()));
137 TEST_F(ScreenManagerTest
, CheckChangingMode
) {
138 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
139 screen_manager_
->ConfigureDisplayController(
140 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
142 drmModeModeInfo new_mode
= kDefaultMode
;
143 new_mode
.vdisplay
= 10;
144 screen_manager_
->ConfigureDisplayController(
145 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
148 gfx::Rect
new_bounds(0, 0, new_mode
.hdisplay
, new_mode
.vdisplay
);
149 EXPECT_TRUE(screen_manager_
->GetDisplayController(new_bounds
));
150 EXPECT_FALSE(screen_manager_
->GetDisplayController(GetSecondaryBounds()));
151 drmModeModeInfo mode
=
152 screen_manager_
->GetDisplayController(new_bounds
)->get_mode();
153 EXPECT_EQ(new_mode
.vdisplay
, mode
.vdisplay
);
154 EXPECT_EQ(new_mode
.hdisplay
, mode
.hdisplay
);
157 TEST_F(ScreenManagerTest
, CheckForControllersInMirroredMode
) {
158 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
159 screen_manager_
->ConfigureDisplayController(
160 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
162 screen_manager_
->AddDisplayController(drm_
, kSecondaryCrtc
,
163 kSecondaryConnector
);
164 screen_manager_
->ConfigureDisplayController(
165 drm_
, kSecondaryCrtc
, kSecondaryConnector
, GetPrimaryBounds().origin(),
168 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetPrimaryBounds()));
169 EXPECT_FALSE(screen_manager_
->GetDisplayController(GetSecondaryBounds()));
172 TEST_F(ScreenManagerTest
, CheckMirrorModeTransitions
) {
173 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
174 screen_manager_
->ConfigureDisplayController(
175 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
177 screen_manager_
->AddDisplayController(drm_
, kSecondaryCrtc
,
178 kSecondaryConnector
);
179 screen_manager_
->ConfigureDisplayController(
180 drm_
, kSecondaryCrtc
, kSecondaryConnector
, GetSecondaryBounds().origin(),
183 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetPrimaryBounds()));
184 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetSecondaryBounds()));
186 screen_manager_
->ConfigureDisplayController(
187 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
189 screen_manager_
->ConfigureDisplayController(
190 drm_
, kSecondaryCrtc
, kSecondaryConnector
, GetPrimaryBounds().origin(),
192 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetPrimaryBounds()));
193 EXPECT_FALSE(screen_manager_
->GetDisplayController(GetSecondaryBounds()));
195 screen_manager_
->ConfigureDisplayController(
196 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetSecondaryBounds().origin(),
198 screen_manager_
->ConfigureDisplayController(
199 drm_
, kSecondaryCrtc
, kSecondaryConnector
, GetPrimaryBounds().origin(),
201 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetPrimaryBounds()));
202 EXPECT_TRUE(screen_manager_
->GetDisplayController(GetSecondaryBounds()));
205 TEST_F(ScreenManagerTest
, MonitorGoneInMirrorMode
) {
206 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
207 screen_manager_
->ConfigureDisplayController(
208 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
210 screen_manager_
->AddDisplayController(drm_
, kSecondaryCrtc
,
211 kSecondaryConnector
);
212 screen_manager_
->ConfigureDisplayController(
213 drm_
, kSecondaryCrtc
, kSecondaryConnector
, GetPrimaryBounds().origin(),
216 screen_manager_
->RemoveDisplayController(drm_
, kSecondaryCrtc
);
218 ui::HardwareDisplayController
* controller
=
219 screen_manager_
->GetDisplayController(GetPrimaryBounds());
220 EXPECT_TRUE(controller
);
221 EXPECT_FALSE(screen_manager_
->GetDisplayController(GetSecondaryBounds()));
223 EXPECT_TRUE(controller
->HasCrtc(drm_
, kPrimaryCrtc
));
224 EXPECT_FALSE(controller
->HasCrtc(drm_
, kSecondaryCrtc
));
227 TEST_F(ScreenManagerTest
, MonitorDisabledInMirrorMode
) {
228 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
229 screen_manager_
->ConfigureDisplayController(
230 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
232 screen_manager_
->AddDisplayController(drm_
, kSecondaryCrtc
,
233 kSecondaryConnector
);
234 screen_manager_
->ConfigureDisplayController(
235 drm_
, kSecondaryCrtc
, kSecondaryConnector
, GetPrimaryBounds().origin(),
238 screen_manager_
->DisableDisplayController(drm_
, kSecondaryCrtc
);
240 ui::HardwareDisplayController
* controller
=
241 screen_manager_
->GetDisplayController(GetPrimaryBounds());
242 EXPECT_TRUE(controller
);
243 EXPECT_FALSE(screen_manager_
->GetDisplayController(GetSecondaryBounds()));
245 EXPECT_TRUE(controller
->HasCrtc(drm_
, kPrimaryCrtc
));
246 EXPECT_FALSE(controller
->HasCrtc(drm_
, kSecondaryCrtc
));
249 TEST_F(ScreenManagerTest
, DoNotEnterMirrorModeUnlessSameBounds
) {
250 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
251 screen_manager_
->AddDisplayController(drm_
, kSecondaryCrtc
,
252 kSecondaryConnector
);
254 // Configure displays in extended mode.
255 screen_manager_
->ConfigureDisplayController(
256 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
258 screen_manager_
->ConfigureDisplayController(
259 drm_
, kSecondaryCrtc
, kSecondaryConnector
, GetSecondaryBounds().origin(),
262 drmModeModeInfo new_mode
= kDefaultMode
;
263 new_mode
.vdisplay
= 10;
264 // Shouldn't enter mirror mode unless the display bounds are the same.
265 screen_manager_
->ConfigureDisplayController(
266 drm_
, kSecondaryCrtc
, kSecondaryConnector
, GetPrimaryBounds().origin(),
270 screen_manager_
->GetDisplayController(GetPrimaryBounds())->IsMirrored());
273 TEST_F(ScreenManagerTest
, ReuseFramebufferIfDisabledThenReEnabled
) {
274 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
275 screen_manager_
->ConfigureDisplayController(
276 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
278 uint32_t framebuffer
= drm_
->current_framebuffer();
280 screen_manager_
->DisableDisplayController(drm_
, kPrimaryCrtc
);
281 EXPECT_EQ(0u, drm_
->current_framebuffer());
283 screen_manager_
->ConfigureDisplayController(
284 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
287 // Buffers are released when disabled.
288 EXPECT_NE(framebuffer
, drm_
->current_framebuffer());
291 TEST_F(ScreenManagerTest
, CheckMirrorModeAfterBeginReEnabled
) {
292 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
293 screen_manager_
->ConfigureDisplayController(
294 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
296 screen_manager_
->DisableDisplayController(drm_
, kPrimaryCrtc
);
298 screen_manager_
->AddDisplayController(drm_
, kSecondaryCrtc
,
299 kSecondaryConnector
);
300 screen_manager_
->ConfigureDisplayController(
301 drm_
, kSecondaryCrtc
, kSecondaryConnector
, GetPrimaryBounds().origin(),
304 ui::HardwareDisplayController
* controller
=
305 screen_manager_
->GetDisplayController(GetPrimaryBounds());
306 EXPECT_TRUE(controller
);
307 EXPECT_FALSE(controller
->IsMirrored());
309 screen_manager_
->ConfigureDisplayController(
310 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
312 EXPECT_TRUE(controller
);
313 EXPECT_TRUE(controller
->IsMirrored());
316 TEST_F(ScreenManagerTest
,
317 CheckProperConfigurationWithDifferentDeviceAndSameCrtc
) {
318 scoped_refptr
<ui::MockDrmDevice
> drm2
= new ui::MockDrmDevice();
320 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
321 screen_manager_
->AddDisplayController(drm2
, kPrimaryCrtc
, kPrimaryConnector
);
323 screen_manager_
->ConfigureDisplayController(
324 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
326 screen_manager_
->ConfigureDisplayController(
327 drm2
, kPrimaryCrtc
, kPrimaryConnector
, GetSecondaryBounds().origin(),
330 ui::HardwareDisplayController
* controller1
=
331 screen_manager_
->GetDisplayController(GetPrimaryBounds());
332 ui::HardwareDisplayController
* controller2
=
333 screen_manager_
->GetDisplayController(GetSecondaryBounds());
335 EXPECT_NE(controller1
, controller2
);
336 EXPECT_EQ(drm_
, controller1
->crtc_controllers()[0]->drm());
337 EXPECT_EQ(drm2
, controller2
->crtc_controllers()[0]->drm());
340 TEST_F(ScreenManagerTest
, CheckControllerToWindowMappingWithSameBounds
) {
341 scoped_ptr
<ui::DrmWindow
> window(
342 new ui::DrmWindow(1, device_manager_
.get(), screen_manager_
.get()));
343 window
->Initialize();
344 window
->OnBoundsChanged(GetPrimaryBounds());
345 screen_manager_
->AddWindow(1, window
.Pass());
347 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
348 screen_manager_
->ConfigureDisplayController(
349 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
352 EXPECT_TRUE(screen_manager_
->GetWindow(1)->GetController());
354 window
= screen_manager_
->RemoveWindow(1);
358 TEST_F(ScreenManagerTest
, CheckControllerToWindowMappingWithDifferentBounds
) {
359 scoped_ptr
<ui::DrmWindow
> window(
360 new ui::DrmWindow(1, device_manager_
.get(), screen_manager_
.get()));
361 window
->Initialize();
362 gfx::Rect new_bounds
= GetPrimaryBounds();
363 new_bounds
.Inset(0, 0, 1, 1);
364 window
->OnBoundsChanged(new_bounds
);
365 screen_manager_
->AddWindow(1, window
.Pass());
367 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
368 screen_manager_
->ConfigureDisplayController(
369 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
372 EXPECT_FALSE(screen_manager_
->GetWindow(1)->GetController());
374 window
= screen_manager_
->RemoveWindow(1);
378 TEST_F(ScreenManagerTest
,
379 CheckControllerToWindowMappingWithOverlappingWindows
) {
380 const size_t kWindowCount
= 2;
381 for (size_t i
= 1; i
< kWindowCount
+ 1; ++i
) {
382 scoped_ptr
<ui::DrmWindow
> window(
383 new ui::DrmWindow(i
, device_manager_
.get(), screen_manager_
.get()));
384 window
->Initialize();
385 window
->OnBoundsChanged(GetPrimaryBounds());
386 screen_manager_
->AddWindow(i
, window
.Pass());
389 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
390 screen_manager_
->ConfigureDisplayController(
391 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
394 bool window1_has_controller
= screen_manager_
->GetWindow(1)->GetController();
395 bool window2_has_controller
= screen_manager_
->GetWindow(2)->GetController();
396 // Only one of the windows can have a controller.
397 EXPECT_TRUE(window1_has_controller
^ window2_has_controller
);
399 for (size_t i
= 1; i
< kWindowCount
+ 1; ++i
) {
400 scoped_ptr
<ui::DrmWindow
> window
= screen_manager_
->RemoveWindow(i
);
405 TEST_F(ScreenManagerTest
, ShouldDissociateWindowOnControllerRemoval
) {
406 gfx::AcceleratedWidget window_id
= 1;
407 scoped_ptr
<ui::DrmWindow
> window(new ui::DrmWindow(
408 window_id
, device_manager_
.get(), screen_manager_
.get()));
409 window
->Initialize();
410 window
->OnBoundsChanged(GetPrimaryBounds());
411 screen_manager_
->AddWindow(window_id
, window
.Pass());
413 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
414 screen_manager_
->ConfigureDisplayController(
415 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
418 EXPECT_TRUE(screen_manager_
->GetWindow(window_id
)->GetController());
420 screen_manager_
->RemoveDisplayController(drm_
, kPrimaryCrtc
);
422 EXPECT_FALSE(screen_manager_
->GetWindow(window_id
)->GetController());
424 window
= screen_manager_
->RemoveWindow(1);
428 TEST_F(ScreenManagerTest
, EnableControllerWhenWindowHasNoBuffer
) {
429 scoped_ptr
<ui::DrmWindow
> window(
430 new ui::DrmWindow(1, device_manager_
.get(), screen_manager_
.get()));
431 window
->Initialize();
432 window
->OnBoundsChanged(GetPrimaryBounds());
433 screen_manager_
->AddWindow(1, window
.Pass());
435 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
436 screen_manager_
->ConfigureDisplayController(
437 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
440 EXPECT_TRUE(screen_manager_
->GetWindow(1)->GetController());
441 // There is a buffer after initial config.
442 uint32_t framebuffer
= drm_
->current_framebuffer();
443 EXPECT_NE(0U, framebuffer
);
445 screen_manager_
->ConfigureDisplayController(
446 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
449 // There is a new buffer after we configured with the same mode but no
450 // pending frames on the window.
451 EXPECT_NE(framebuffer
, drm_
->current_framebuffer());
453 window
= screen_manager_
->RemoveWindow(1);
457 TEST_F(ScreenManagerTest
, EnableControllerWhenWindowHasBuffer
) {
458 scoped_ptr
<ui::DrmWindow
> window(
459 new ui::DrmWindow(1, device_manager_
.get(), screen_manager_
.get()));
460 window
->Initialize();
461 window
->OnBoundsChanged(GetPrimaryBounds());
462 scoped_refptr
<ui::ScanoutBuffer
> buffer
=
463 buffer_generator_
->Create(drm_
, GetPrimaryBounds().size());
464 window
->QueueOverlayPlane(ui::OverlayPlane(buffer
));
465 window
->SchedulePageFlip(false /* is_sync */, base::Bind(&EmptySwapCallback
));
466 screen_manager_
->AddWindow(1, window
.Pass());
468 screen_manager_
->AddDisplayController(drm_
, kPrimaryCrtc
, kPrimaryConnector
);
469 screen_manager_
->ConfigureDisplayController(
470 drm_
, kPrimaryCrtc
, kPrimaryConnector
, GetPrimaryBounds().origin(),
473 EXPECT_EQ(buffer
->GetFramebufferId(), drm_
->current_framebuffer());
475 window
= screen_manager_
->RemoveWindow(1);