Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / ozone / platform / drm / gpu / hardware_display_controller_unittest.cc
blobc5eff99b18160fa301947cfea40d2a5f5851e20f
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>
7 #include "base/bind.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"
17 namespace {
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 {
33 public:
34 MockScanoutBuffer(const gfx::Size& size) : size_(size) {}
36 // ScanoutBuffer:
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;
44 private:
45 ~MockScanoutBuffer() override {}
47 gfx::Size size_;
49 DISALLOW_COPY_AND_ASSIGN(MockScanoutBuffer);
52 } // namespace
54 class HardwareDisplayControllerTest : public testing::Test {
55 public:
56 HardwareDisplayControllerTest() : page_flips_(0) {}
57 ~HardwareDisplayControllerTest() override {}
59 void SetUp() override;
60 void TearDown() override;
62 void PageFlipCallback(gfx::SwapResult);
64 protected:
65 scoped_ptr<ui::HardwareDisplayController> controller_;
66 scoped_refptr<ui::MockDrmDevice> drm_;
68 int page_flips_;
70 private:
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)),
82 gfx::Point()));
85 void HardwareDisplayControllerTest::TearDown() {
86 controller_.reset();
87 drm_ = nullptr;
90 void HardwareDisplayControllerTest::PageFlipCallback(gfx::SwapResult) {
91 page_flips_++;
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();
150 planes.clear();
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())
275 if (plane->in_use())
276 owned_plane = plane;
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())
309 if (plane->in_use())
310 owned_plane = plane;
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.
316 crtc.reset();
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_);