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.
6 #include "testing/gtest/include/gtest/gtest.h"
7 #include "third_party/skia/include/core/SkCanvas.h"
8 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
9 #include "ui/ozone/platform/drm/gpu/drm_buffer.h"
10 #include "ui/ozone/platform/drm/gpu/drm_device.h"
11 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
12 #include "ui/ozone/platform/drm/test/mock_drm_device.h"
13 #include "ui/ozone/public/native_pixmap.h"
17 // Create a basic mode for a 6x4 screen.
18 const drmModeModeInfo kDefaultMode
=
19 {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
21 const uint32_t kPrimaryCrtc
= 1;
22 const uint32_t kPrimaryConnector
= 2;
23 const uint32_t kSecondaryCrtc
= 3;
24 const uint32_t kSecondaryConnector
= 4;
25 const size_t kPlanesPerCrtc
= 2;
27 const gfx::Size
kDefaultModeSize(kDefaultMode
.hdisplay
, kDefaultMode
.vdisplay
);
28 const gfx::SizeF
kDefaultModeSizeF(1.0, 1.0);
30 class MockScanoutBuffer
: public ui::ScanoutBuffer
{
32 MockScanoutBuffer(const gfx::Size
& size
) : size_(size
) {}
35 uint32_t GetFramebufferId() const override
{ return 0; }
36 uint32_t GetHandle() const override
{ return 0; }
37 gfx::Size
GetSize() const override
{ return size_
; }
40 ~MockScanoutBuffer() override
{}
44 DISALLOW_COPY_AND_ASSIGN(MockScanoutBuffer
);
49 class HardwareDisplayControllerTest
: public testing::Test
{
51 HardwareDisplayControllerTest() : page_flips_(0) {}
52 ~HardwareDisplayControllerTest() override
{}
54 void SetUp() override
;
55 void TearDown() override
;
57 void PageFlipCallback(gfx::SwapResult
);
60 scoped_ptr
<ui::HardwareDisplayController
> controller_
;
61 scoped_refptr
<ui::MockDrmDevice
> drm_
;
66 DISALLOW_COPY_AND_ASSIGN(HardwareDisplayControllerTest
);
69 void HardwareDisplayControllerTest::SetUp() {
70 std::vector
<uint32_t> crtcs
;
71 crtcs
.push_back(kPrimaryCrtc
);
72 crtcs
.push_back(kSecondaryCrtc
);
73 drm_
= new ui::MockDrmDevice(false, crtcs
, kPlanesPerCrtc
);
74 controller_
.reset(new ui::HardwareDisplayController(
75 scoped_ptr
<ui::CrtcController
>(
76 new ui::CrtcController(drm_
.get(), kPrimaryCrtc
, kPrimaryConnector
)),
80 void HardwareDisplayControllerTest::TearDown() {
85 void HardwareDisplayControllerTest::PageFlipCallback(gfx::SwapResult
) {
89 TEST_F(HardwareDisplayControllerTest
, CheckModesettingResult
) {
90 ui::OverlayPlane
plane(scoped_refptr
<ui::ScanoutBuffer
>(
91 new MockScanoutBuffer(kDefaultModeSize
)));
93 EXPECT_TRUE(controller_
->Modeset(plane
, kDefaultMode
));
94 EXPECT_FALSE(plane
.buffer
->HasOneRef());
97 TEST_F(HardwareDisplayControllerTest
, CheckStateAfterPageFlip
) {
98 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
99 new MockScanoutBuffer(kDefaultModeSize
)));
101 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
103 ui::OverlayPlane
plane2(scoped_refptr
<ui::ScanoutBuffer
>(
104 new MockScanoutBuffer(kDefaultModeSize
)));
105 std::vector
<ui::OverlayPlane
> planes
=
106 std::vector
<ui::OverlayPlane
>(1, plane2
);
107 EXPECT_TRUE(controller_
->SchedulePageFlip(
108 planes
, false, false,
109 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
110 base::Unretained(this))));
111 drm_
->RunCallbacks();
112 EXPECT_TRUE(plane1
.buffer
->HasOneRef());
113 EXPECT_FALSE(plane2
.buffer
->HasOneRef());
115 EXPECT_EQ(1, drm_
->get_page_flip_call_count());
116 EXPECT_EQ(0, drm_
->get_overlay_flip_call_count());
119 TEST_F(HardwareDisplayControllerTest
, CheckStateIfModesetFails
) {
120 drm_
->set_set_crtc_expectation(false);
122 ui::OverlayPlane
plane(scoped_refptr
<ui::ScanoutBuffer
>(
123 new MockScanoutBuffer(kDefaultModeSize
)));
125 EXPECT_FALSE(controller_
->Modeset(plane
, kDefaultMode
));
128 TEST_F(HardwareDisplayControllerTest
, CheckStateIfPageFlipFails
) {
129 drm_
->set_page_flip_expectation(false);
131 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
132 new MockScanoutBuffer(kDefaultModeSize
)));
134 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
136 ui::OverlayPlane
plane2(scoped_refptr
<ui::ScanoutBuffer
>(
137 new MockScanoutBuffer(kDefaultModeSize
)));
138 std::vector
<ui::OverlayPlane
> planes
=
139 std::vector
<ui::OverlayPlane
>(1, plane2
);
140 EXPECT_FALSE(controller_
->SchedulePageFlip(
141 planes
, false, false,
142 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
143 base::Unretained(this))));
144 drm_
->RunCallbacks();
147 EXPECT_FALSE(plane1
.buffer
->HasOneRef());
148 EXPECT_TRUE(plane2
.buffer
->HasOneRef());
151 TEST_F(HardwareDisplayControllerTest
, CheckOverlayPresent
) {
152 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
153 new MockScanoutBuffer(kDefaultModeSize
)));
154 ui::OverlayPlane
plane2(
155 scoped_refptr
<ui::ScanoutBuffer
>(new MockScanoutBuffer(kDefaultModeSize
)),
156 1, gfx::OVERLAY_TRANSFORM_NONE
, gfx::Rect(kDefaultModeSize
),
157 gfx::RectF(kDefaultModeSizeF
));
159 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
161 std::vector
<ui::OverlayPlane
> planes
;
162 planes
.push_back(plane1
);
163 planes
.push_back(plane2
);
165 EXPECT_TRUE(controller_
->SchedulePageFlip(
166 planes
, false, false,
167 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
168 base::Unretained(this))));
169 drm_
->RunCallbacks();
170 EXPECT_EQ(1, drm_
->get_page_flip_call_count());
171 EXPECT_EQ(1, drm_
->get_overlay_flip_call_count());
174 TEST_F(HardwareDisplayControllerTest
, CheckOverlayTestMode
) {
175 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
176 new MockScanoutBuffer(kDefaultModeSize
)));
177 ui::OverlayPlane
plane2(
178 scoped_refptr
<ui::ScanoutBuffer
>(new MockScanoutBuffer(kDefaultModeSize
)),
179 1, gfx::OVERLAY_TRANSFORM_NONE
, gfx::Rect(kDefaultModeSize
),
180 gfx::RectF(kDefaultModeSizeF
));
182 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
184 std::vector
<ui::OverlayPlane
> planes
;
185 planes
.push_back(plane1
);
186 planes
.push_back(plane2
);
188 EXPECT_TRUE(controller_
->SchedulePageFlip(
189 planes
, false, false,
190 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
191 base::Unretained(this))));
192 drm_
->RunCallbacks();
193 EXPECT_EQ(1, drm_
->get_page_flip_call_count());
194 EXPECT_EQ(1, drm_
->get_overlay_flip_call_count());
196 // A test call shouldn't cause new flips, but should succeed.
197 EXPECT_TRUE(controller_
->SchedulePageFlip(
199 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
200 base::Unretained(this))));
201 drm_
->RunCallbacks();
202 EXPECT_EQ(1, drm_
->get_page_flip_call_count());
203 EXPECT_EQ(1, drm_
->get_overlay_flip_call_count());
205 // Regular flips should continue on normally.
206 EXPECT_TRUE(controller_
->SchedulePageFlip(
207 planes
, false, false,
208 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
209 base::Unretained(this))));
210 drm_
->RunCallbacks();
211 EXPECT_EQ(2, drm_
->get_page_flip_call_count());
212 EXPECT_EQ(2, drm_
->get_overlay_flip_call_count());
215 TEST_F(HardwareDisplayControllerTest
, RejectUnderlays
) {
216 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
217 new MockScanoutBuffer(kDefaultModeSize
)));
218 ui::OverlayPlane
plane2(
219 scoped_refptr
<ui::ScanoutBuffer
>(new MockScanoutBuffer(kDefaultModeSize
)),
220 -1, gfx::OVERLAY_TRANSFORM_NONE
, gfx::Rect(kDefaultModeSize
),
221 gfx::RectF(kDefaultModeSizeF
));
223 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
225 std::vector
<ui::OverlayPlane
> planes
;
226 planes
.push_back(plane1
);
227 planes
.push_back(plane2
);
229 EXPECT_FALSE(controller_
->SchedulePageFlip(
230 planes
, false, false,
231 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
232 base::Unretained(this))));
235 TEST_F(HardwareDisplayControllerTest
, PageflipMirroredControllers
) {
236 controller_
->AddCrtc(scoped_ptr
<ui::CrtcController
>(
237 new ui::CrtcController(drm_
.get(), kSecondaryCrtc
, kSecondaryConnector
)));
239 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
240 new MockScanoutBuffer(kDefaultModeSize
)));
241 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
242 EXPECT_EQ(2, drm_
->get_set_crtc_call_count());
244 ui::OverlayPlane
plane2(scoped_refptr
<ui::ScanoutBuffer
>(
245 new MockScanoutBuffer(kDefaultModeSize
)));
246 std::vector
<ui::OverlayPlane
> planes
=
247 std::vector
<ui::OverlayPlane
>(1, plane2
);
248 EXPECT_TRUE(controller_
->SchedulePageFlip(
249 planes
, false, false,
250 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
251 base::Unretained(this))));
252 drm_
->RunCallbacks();
253 EXPECT_EQ(2, drm_
->get_page_flip_call_count());
254 EXPECT_EQ(1, page_flips_
);
257 TEST_F(HardwareDisplayControllerTest
, PlaneStateAfterRemoveCrtc
) {
258 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
259 new MockScanoutBuffer(kDefaultModeSize
)));
260 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
261 std::vector
<ui::OverlayPlane
> planes
=
262 std::vector
<ui::OverlayPlane
>(1, plane1
);
263 EXPECT_TRUE(controller_
->SchedulePageFlip(
264 planes
, false, false,
265 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
266 base::Unretained(this))));
267 drm_
->RunCallbacks();
269 const ui::HardwareDisplayPlane
* owned_plane
= nullptr;
270 for (const auto& plane
: drm_
->plane_manager()->planes())
273 ASSERT_TRUE(owned_plane
!= nullptr);
274 EXPECT_EQ(kPrimaryCrtc
, owned_plane
->owning_crtc());
275 // Removing the crtc should free the plane.
276 scoped_ptr
<ui::CrtcController
> crtc
=
277 controller_
->RemoveCrtc(drm_
, kPrimaryCrtc
);
278 EXPECT_FALSE(owned_plane
->in_use());
281 TEST_F(HardwareDisplayControllerTest
, ModesetWhilePageFlipping
) {
282 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
283 new MockScanoutBuffer(kDefaultModeSize
)));
284 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
285 std::vector
<ui::OverlayPlane
> planes
=
286 std::vector
<ui::OverlayPlane
>(1, plane1
);
287 EXPECT_TRUE(controller_
->SchedulePageFlip(
288 planes
, false, false,
289 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
290 base::Unretained(this))));
292 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
293 drm_
->RunCallbacks();
294 EXPECT_EQ(1, page_flips_
);
297 TEST_F(HardwareDisplayControllerTest
, AddCrtcMidPageFlip
) {
298 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
299 new MockScanoutBuffer(kDefaultModeSize
)));
300 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
301 std::vector
<ui::OverlayPlane
> planes
=
302 std::vector
<ui::OverlayPlane
>(1, plane1
);
303 EXPECT_TRUE(controller_
->SchedulePageFlip(
304 planes
, false, false,
305 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
306 base::Unretained(this))));
308 controller_
->AddCrtc(scoped_ptr
<ui::CrtcController
>(
309 new ui::CrtcController(drm_
.get(), kSecondaryCrtc
, kSecondaryConnector
)));
311 drm_
->RunCallbacks();
312 EXPECT_EQ(1, page_flips_
);
315 TEST_F(HardwareDisplayControllerTest
, RemoveCrtcMidPageFlip
) {
316 ui::OverlayPlane
plane1(scoped_refptr
<ui::ScanoutBuffer
>(
317 new MockScanoutBuffer(kDefaultModeSize
)));
318 EXPECT_TRUE(controller_
->Modeset(plane1
, kDefaultMode
));
319 std::vector
<ui::OverlayPlane
> planes
=
320 std::vector
<ui::OverlayPlane
>(1, plane1
);
321 EXPECT_TRUE(controller_
->SchedulePageFlip(
322 planes
, false, false,
323 base::Bind(&HardwareDisplayControllerTest::PageFlipCallback
,
324 base::Unretained(this))));
326 controller_
->RemoveCrtc(drm_
, kPrimaryCrtc
);
328 EXPECT_EQ(1, page_flips_
);
329 drm_
->RunCallbacks();
330 EXPECT_EQ(1, page_flips_
);