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 <drm_fourcc.h>
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/skia/include/core/SkCanvas.h"
10 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
11 #include "ui/ozone/platform/drm/gpu/drm_buffer.h"
12 #include "ui/ozone/platform/drm/gpu/drm_device.h"
13 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
14 #include "ui/ozone/platform/drm/test/mock_drm_device.h"
15 #include "ui/ozone/public/native_pixmap.h"
19 // Create a basic mode for a 6x4 screen.
20 const drmModeModeInfo kDefaultMode
=
21 {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
23 const uint32_t kPrimaryCrtc
= 1;
24 const uint32_t kPrimaryConnector
= 2;
25 const uint32_t kSecondaryCrtc
= 3;
26 const uint32_t kSecondaryConnector
= 4;
27 const size_t kPlanesPerCrtc
= 2;
29 const gfx::Size
kDefaultModeSize(kDefaultMode
.hdisplay
, kDefaultMode
.vdisplay
);
30 const gfx::SizeF
kDefaultModeSizeF(1.0, 1.0);
32 class MockScanoutBuffer
: public ui::ScanoutBuffer
{
34 MockScanoutBuffer(const gfx::Size
& size
) : size_(size
) {}
37 uint32_t GetFramebufferId() const override
{ return 0; }
38 uint32_t GetHandle() const override
{ return 0; }
39 gfx::Size
GetSize() const override
{ return size_
; }
40 uint32_t GetFramebufferPixelFormat() const override
{
41 return DRM_FORMAT_XRGB8888
;
45 ~MockScanoutBuffer() override
{}
49 DISALLOW_COPY_AND_ASSIGN(MockScanoutBuffer
);
54 class HardwareDisplayControllerTest
: public testing::Test
{
56 HardwareDisplayControllerTest() : page_flips_(0) {}
57 ~HardwareDisplayControllerTest() override
{}
59 void SetUp() override
;
60 void TearDown() override
;
62 void PageFlipCallback(gfx::SwapResult
);
65 scoped_ptr
<ui::HardwareDisplayController
> controller_
;
66 scoped_refptr
<ui::MockDrmDevice
> drm_
;
71 DISALLOW_COPY_AND_ASSIGN(HardwareDisplayControllerTest
);
74 void HardwareDisplayControllerTest::SetUp() {
75 std::vector
<uint32_t> crtcs
;
76 crtcs
.push_back(kPrimaryCrtc
);
77 crtcs
.push_back(kSecondaryCrtc
);
78 drm_
= new ui::MockDrmDevice(false, crtcs
, kPlanesPerCrtc
);
79 controller_
.reset(new ui::HardwareDisplayController(
80 scoped_ptr
<ui::CrtcController
>(
81 new ui::CrtcController(drm_
.get(), kPrimaryCrtc
, kPrimaryConnector
)),
85 void HardwareDisplayControllerTest::TearDown() {
90 void HardwareDisplayControllerTest::PageFlipCallback(gfx::SwapResult
) {
94 TEST_F(HardwareDisplayControllerTest
, CheckModesettingResult
) {
95 ui::OverlayPlane
plane(scoped_refptr
<ui::ScanoutBuffer
>(
96 new MockScanoutBuffer(kDefaultModeSize
)));
98 EXPECT_TRUE(controller_
->Modeset(plane
, kDefaultMode
));
99 EXPECT_FALSE(plane
.buffer
->HasOneRef());
102 TEST_F(HardwareDisplayControllerTest
, CheckStateAfterPageFlip
) {
103 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
104 new MockScanoutBuffer(kDefaultModeSize
)));
106 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
108 ui::OverlayPlane
plane2(scoped_refptr
<ui::ScanoutBuffer
>(
109 new MockScanoutBuffer(kDefaultModeSize
)));
110 std::vector
<ui::OverlayPlane
> planes
=
111 std::vector
<ui::OverlayPlane
>(1, plane2
);
112 EXPECT_TRUE(controller_
->SchedulePageFlip(
113 planes
, false /* test_only */,
114 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
115 base::Unretained(this))));
116 drm_
->RunCallbacks();
117 EXPECT_TRUE(plane1
.buffer
->HasOneRef());
118 EXPECT_FALSE(plane2
.buffer
->HasOneRef());
120 EXPECT_EQ(1, drm_
->get_page_flip_call_count());
121 EXPECT_EQ(0, drm_
->get_overlay_flip_call_count());
124 TEST_F(HardwareDisplayControllerTest
, CheckStateIfModesetFails
) {
125 drm_
->set_set_crtc_expectation(false);
127 ui::OverlayPlane
plane(scoped_refptr
<ui::ScanoutBuffer
>(
128 new MockScanoutBuffer(kDefaultModeSize
)));
130 EXPECT_FALSE(controller_
->Modeset(plane
, kDefaultMode
));
133 TEST_F(HardwareDisplayControllerTest
, CheckStateIfPageFlipFails
) {
134 drm_
->set_page_flip_expectation(false);
136 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
137 new MockScanoutBuffer(kDefaultModeSize
)));
139 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
141 ui::OverlayPlane
plane2(scoped_refptr
<ui::ScanoutBuffer
>(
142 new MockScanoutBuffer(kDefaultModeSize
)));
143 std::vector
<ui::OverlayPlane
> planes
=
144 std::vector
<ui::OverlayPlane
>(1, plane2
);
145 EXPECT_FALSE(controller_
->SchedulePageFlip(
146 planes
, false /* test_only */,
147 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
148 base::Unretained(this))));
149 drm_
->RunCallbacks();
152 EXPECT_FALSE(plane1
.buffer
->HasOneRef());
153 EXPECT_TRUE(plane2
.buffer
->HasOneRef());
156 TEST_F(HardwareDisplayControllerTest
, CheckOverlayPresent
) {
157 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
158 new MockScanoutBuffer(kDefaultModeSize
)));
159 ui::OverlayPlane
plane2(
160 scoped_refptr
<ui::ScanoutBuffer
>(new MockScanoutBuffer(kDefaultModeSize
)),
161 1, gfx::OVERLAY_TRANSFORM_NONE
, gfx::Rect(kDefaultModeSize
),
162 gfx::RectF(kDefaultModeSizeF
));
164 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
166 std::vector
<ui::OverlayPlane
> planes
;
167 planes
.push_back(plane1
);
168 planes
.push_back(plane2
);
170 EXPECT_TRUE(controller_
->SchedulePageFlip(
171 planes
, false /* test_only */,
172 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
173 base::Unretained(this))));
174 drm_
->RunCallbacks();
175 EXPECT_EQ(1, drm_
->get_page_flip_call_count());
176 EXPECT_EQ(1, drm_
->get_overlay_flip_call_count());
179 TEST_F(HardwareDisplayControllerTest
, CheckOverlayTestMode
) {
180 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
181 new MockScanoutBuffer(kDefaultModeSize
)));
182 ui::OverlayPlane
plane2(
183 scoped_refptr
<ui::ScanoutBuffer
>(new MockScanoutBuffer(kDefaultModeSize
)),
184 1, gfx::OVERLAY_TRANSFORM_NONE
, gfx::Rect(kDefaultModeSize
),
185 gfx::RectF(kDefaultModeSizeF
));
187 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
189 std::vector
<ui::OverlayPlane
> planes
;
190 planes
.push_back(plane1
);
191 planes
.push_back(plane2
);
193 EXPECT_TRUE(controller_
->SchedulePageFlip(
194 planes
, false /* test_only */,
195 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
196 base::Unretained(this))));
197 drm_
->RunCallbacks();
198 EXPECT_EQ(1, drm_
->get_page_flip_call_count());
199 EXPECT_EQ(1, drm_
->get_overlay_flip_call_count());
201 // A test call shouldn't cause new flips, but should succeed.
202 EXPECT_TRUE(controller_
->SchedulePageFlip(
203 planes
, true, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
204 base::Unretained(this))));
205 drm_
->RunCallbacks();
206 EXPECT_EQ(1, drm_
->get_page_flip_call_count());
207 EXPECT_EQ(1, drm_
->get_overlay_flip_call_count());
209 // Regular flips should continue on normally.
210 EXPECT_TRUE(controller_
->SchedulePageFlip(
211 planes
, false /* test_only */,
212 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
213 base::Unretained(this))));
214 drm_
->RunCallbacks();
215 EXPECT_EQ(2, drm_
->get_page_flip_call_count());
216 EXPECT_EQ(2, drm_
->get_overlay_flip_call_count());
219 TEST_F(HardwareDisplayControllerTest
, RejectUnderlays
) {
220 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
221 new MockScanoutBuffer(kDefaultModeSize
)));
222 ui::OverlayPlane
plane2(
223 scoped_refptr
<ui::ScanoutBuffer
>(new MockScanoutBuffer(kDefaultModeSize
)),
224 -1, gfx::OVERLAY_TRANSFORM_NONE
, gfx::Rect(kDefaultModeSize
),
225 gfx::RectF(kDefaultModeSizeF
));
227 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
229 std::vector
<ui::OverlayPlane
> planes
;
230 planes
.push_back(plane1
);
231 planes
.push_back(plane2
);
233 EXPECT_FALSE(controller_
->SchedulePageFlip(
234 planes
, false /* test_only */,
235 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
236 base::Unretained(this))));
239 TEST_F(HardwareDisplayControllerTest
, PageflipMirroredControllers
) {
240 controller_
->AddCrtc(scoped_ptr
<ui::CrtcController
>(
241 new ui::CrtcController(drm_
.get(), kSecondaryCrtc
, kSecondaryConnector
)));
243 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
244 new MockScanoutBuffer(kDefaultModeSize
)));
245 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
246 EXPECT_EQ(2, drm_
->get_set_crtc_call_count());
248 ui::OverlayPlane
plane2(scoped_refptr
<ui::ScanoutBuffer
>(
249 new MockScanoutBuffer(kDefaultModeSize
)));
250 std::vector
<ui::OverlayPlane
> planes
=
251 std::vector
<ui::OverlayPlane
>(1, plane2
);
252 EXPECT_TRUE(controller_
->SchedulePageFlip(
253 planes
, false /* test_only */,
254 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
255 base::Unretained(this))));
256 drm_
->RunCallbacks();
257 EXPECT_EQ(2, drm_
->get_page_flip_call_count());
258 EXPECT_EQ(1, page_flips_
);
261 TEST_F(HardwareDisplayControllerTest
, PlaneStateAfterRemoveCrtc
) {
262 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
263 new MockScanoutBuffer(kDefaultModeSize
)));
264 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
265 std::vector
<ui::OverlayPlane
> planes
=
266 std::vector
<ui::OverlayPlane
>(1, plane1
);
267 EXPECT_TRUE(controller_
->SchedulePageFlip(
268 planes
, false /* test_only */,
269 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
270 base::Unretained(this))));
271 drm_
->RunCallbacks();
273 const ui::HardwareDisplayPlane
* owned_plane
= nullptr;
274 for (const auto& plane
: drm_
->plane_manager()->planes())
277 ASSERT_TRUE(owned_plane
!= nullptr);
278 EXPECT_EQ(kPrimaryCrtc
, owned_plane
->owning_crtc());
279 // Removing the crtc should not free the plane or change ownership.
280 scoped_ptr
<ui::CrtcController
> crtc
=
281 controller_
->RemoveCrtc(drm_
, kPrimaryCrtc
);
282 EXPECT_TRUE(owned_plane
->in_use());
283 EXPECT_EQ(kPrimaryCrtc
, owned_plane
->owning_crtc());
284 // Check that controller doesn't effect the state of removed plane in
285 // subsequent page flip.
286 EXPECT_TRUE(controller_
->SchedulePageFlip(
287 planes
, false /* test_only */,
288 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
289 base::Unretained(this))));
290 drm_
->RunCallbacks();
291 EXPECT_TRUE(owned_plane
->in_use());
292 EXPECT_EQ(kPrimaryCrtc
, owned_plane
->owning_crtc());
295 TEST_F(HardwareDisplayControllerTest
, PlaneStateAfterDestroyingCrtc
) {
296 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
297 new MockScanoutBuffer(kDefaultModeSize
)));
298 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
299 std::vector
<ui::OverlayPlane
> planes
=
300 std::vector
<ui::OverlayPlane
>(1, plane1
);
301 EXPECT_TRUE(controller_
->SchedulePageFlip(
302 planes
, false /* test_only */,
303 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
304 base::Unretained(this))));
305 drm_
->RunCallbacks();
307 const ui::HardwareDisplayPlane
* owned_plane
= nullptr;
308 for (const auto& plane
: drm_
->plane_manager()->planes())
311 ASSERT_TRUE(owned_plane
!= nullptr);
312 EXPECT_EQ(kPrimaryCrtc
, owned_plane
->owning_crtc());
313 scoped_ptr
<ui::CrtcController
> crtc
=
314 controller_
->RemoveCrtc(drm_
, kPrimaryCrtc
);
315 // Destroying crtc should free the plane.
317 uint32_t crtc_nullid
= 0;
318 EXPECT_FALSE(owned_plane
->in_use());
319 EXPECT_EQ(crtc_nullid
, owned_plane
->owning_crtc());
322 TEST_F(HardwareDisplayControllerTest
, PlaneStateAfterAddCrtc
) {
323 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
324 new MockScanoutBuffer(kDefaultModeSize
)));
325 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
326 std::vector
<ui::OverlayPlane
> planes
=
327 std::vector
<ui::OverlayPlane
>(1, plane1
);
328 EXPECT_TRUE(controller_
->SchedulePageFlip(
329 planes
, false /* test_only */,
330 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
331 base::Unretained(this))));
332 drm_
->RunCallbacks();
334 ui::HardwareDisplayPlane
* primary_crtc_plane
= nullptr;
335 for (const auto& plane
: drm_
->plane_manager()->planes()) {
336 if (plane
->in_use() && kPrimaryCrtc
== plane
->owning_crtc())
337 primary_crtc_plane
= plane
;
340 ASSERT_TRUE(primary_crtc_plane
!= nullptr);
342 scoped_ptr
<ui::HardwareDisplayController
> hdc_controller
;
343 hdc_controller
.reset(new ui::HardwareDisplayController(
344 controller_
->RemoveCrtc(drm_
, kPrimaryCrtc
), controller_
->origin()));
345 EXPECT_TRUE(controller_
->SchedulePageFlip(
346 planes
, false /* test_only */,
347 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
348 base::Unretained(this))));
349 drm_
->RunCallbacks();
350 EXPECT_TRUE(primary_crtc_plane
->in_use());
351 EXPECT_EQ(kPrimaryCrtc
, primary_crtc_plane
->owning_crtc());
353 // We reset state of plane here to test that the plane was actually added to
354 // hdc_controller. In which case, the right state should be set to plane
355 // after page flip call is handled by the controller.
356 primary_crtc_plane
->set_in_use(false);
357 primary_crtc_plane
->set_owning_crtc(0);
358 EXPECT_TRUE(hdc_controller
->SchedulePageFlip(
359 planes
, false /* test_only */,
360 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
361 base::Unretained(this))));
362 drm_
->RunCallbacks();
363 EXPECT_TRUE(primary_crtc_plane
->in_use());
364 EXPECT_EQ(kPrimaryCrtc
, primary_crtc_plane
->owning_crtc());
367 TEST_F(HardwareDisplayControllerTest
, ModesetWhilePageFlipping
) {
368 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
369 new MockScanoutBuffer(kDefaultModeSize
)));
370 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
371 std::vector
<ui::OverlayPlane
> planes
=
372 std::vector
<ui::OverlayPlane
>(1, plane1
);
373 EXPECT_TRUE(controller_
->SchedulePageFlip(
374 planes
, false /* test_only */,
375 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
376 base::Unretained(this))));
378 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
379 drm_
->RunCallbacks();
380 EXPECT_EQ(1, page_flips_
);
383 TEST_F(HardwareDisplayControllerTest
, AddCrtcMidPageFlip
) {
384 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
385 new MockScanoutBuffer(kDefaultModeSize
)));
386 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
387 std::vector
<ui::OverlayPlane
> planes
=
388 std::vector
<ui::OverlayPlane
>(1, plane1
);
389 EXPECT_TRUE(controller_
->SchedulePageFlip(
390 planes
, false /* test_only */,
391 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
392 base::Unretained(this))));
394 controller_
->AddCrtc(scoped_ptr
<ui::CrtcController
>(
395 new ui::CrtcController(drm_
.get(), kSecondaryCrtc
, kSecondaryConnector
)));
397 drm_
->RunCallbacks();
398 EXPECT_EQ(1, page_flips_
);
401 TEST_F(HardwareDisplayControllerTest
, RemoveCrtcMidPageFlip
) {
402 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
403 new MockScanoutBuffer(kDefaultModeSize
)));
404 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
405 std::vector
<ui::OverlayPlane
> planes
=
406 std::vector
<ui::OverlayPlane
>(1, plane1
);
407 EXPECT_TRUE(controller_
->SchedulePageFlip(
408 planes
, false /* test_only */,
409 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
410 base::Unretained(this))));
412 controller_
->RemoveCrtc(drm_
, kPrimaryCrtc
);
414 EXPECT_EQ(1, page_flips_
);
415 drm_
->RunCallbacks();
416 EXPECT_EQ(1, page_flips_
);