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.
7 #include "base/memory/scoped_ptr.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
10 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
11 #include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
12 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
13 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h"
14 #include "ui/ozone/platform/drm/gpu/overlay_plane.h"
15 #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
16 #include "ui/ozone/platform/drm/test/mock_drm_device.h"
20 struct FakePlaneInfo
{
22 uint32_t allowed_crtc_mask
;
25 const FakePlaneInfo kOnePlanePerCrtc
[] = {{10, 1}, {20, 2}};
26 const FakePlaneInfo kTwoPlanesPerCrtc
[] = {{10, 1}, {11, 1}, {20, 2}, {21, 2}};
27 const FakePlaneInfo kOnePlanePerCrtcWithShared
[] = {{10, 1}, {20, 2}, {50, 3}};
29 class FakeScanoutBuffer
: public ui::ScanoutBuffer
{
31 FakeScanoutBuffer() {}
34 uint32_t GetFramebufferId() const override
{ return 1; }
35 uint32_t GetHandle() const override
{ return 0; }
36 gfx::Size
GetSize() const override
{ return gfx::Size(1, 1); }
39 ~FakeScanoutBuffer() override
{}
42 class FakePlaneManager
: public ui::HardwareDisplayPlaneManager
{
44 FakePlaneManager() : plane_count_(0) {}
45 ~FakePlaneManager() override
{}
47 // Normally we'd use DRM to figure out the controller configuration. But we
48 // can't use DRM in unit tests, so we just create a fake configuration.
49 void InitForTest(const FakePlaneInfo
* planes
,
51 const std::vector
<uint32_t>& crtcs
) {
53 for (size_t i
= 0; i
< count
; i
++) {
54 planes_
.push_back(new ui::HardwareDisplayPlane(
55 planes
[i
].id
, planes
[i
].allowed_crtc_mask
));
57 // The real HDPM uses sorted planes, so sort them for consistency.
58 std::sort(planes_
.begin(), planes_
.end(),
59 [](ui::HardwareDisplayPlane
* l
, ui::HardwareDisplayPlane
* r
) {
60 return l
->plane_id() < r
->plane_id();
64 bool Commit(ui::HardwareDisplayPlaneList
* plane_list
,
66 bool test_only
) override
{
70 bool SetPlaneData(ui::HardwareDisplayPlaneList
* plane_list
,
71 ui::HardwareDisplayPlane
* hw_plane
,
72 const ui::OverlayPlane
& overlay
,
74 const gfx::Rect
& src_rect
,
75 ui::CrtcController
* crtc
) override
{
76 // Check that the chosen plane is a legal choice for the crtc.
77 EXPECT_NE(-1, LookupCrtcIndex(crtc_id
));
78 EXPECT_TRUE(hw_plane
->CanUseForCrtc(LookupCrtcIndex(crtc_id
)));
79 EXPECT_FALSE(hw_plane
->in_use());
84 int plane_count() const { return plane_count_
; }
87 DISALLOW_COPY_AND_ASSIGN(FakePlaneManager
);
92 class HardwareDisplayPlaneManagerTest
: public testing::Test
{
94 HardwareDisplayPlaneManagerTest() {}
96 void SetUp() override
;
99 scoped_ptr
<FakePlaneManager
> plane_manager_
;
100 ui::HardwareDisplayPlaneList state_
;
101 std::vector
<uint32_t> default_crtcs_
;
102 scoped_refptr
<ui::ScanoutBuffer
> fake_buffer_
;
105 DISALLOW_COPY_AND_ASSIGN(HardwareDisplayPlaneManagerTest
);
108 void HardwareDisplayPlaneManagerTest::SetUp() {
109 fake_buffer_
= new FakeScanoutBuffer();
110 plane_manager_
.reset(new FakePlaneManager());
111 default_crtcs_
.push_back(100);
112 default_crtcs_
.push_back(200);
115 TEST_F(HardwareDisplayPlaneManagerTest
, SinglePlaneAssignment
) {
116 ui::OverlayPlaneList assigns
;
117 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
118 plane_manager_
->InitForTest(kOnePlanePerCrtc
, arraysize(kOnePlanePerCrtc
),
120 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
121 default_crtcs_
[0], nullptr));
122 EXPECT_EQ(1, plane_manager_
->plane_count());
125 TEST_F(HardwareDisplayPlaneManagerTest
, BadCrtc
) {
126 ui::OverlayPlaneList assigns
;
127 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
128 plane_manager_
->InitForTest(kOnePlanePerCrtc
, arraysize(kOnePlanePerCrtc
),
131 plane_manager_
->AssignOverlayPlanes(&state_
, assigns
, 1, nullptr));
134 TEST_F(HardwareDisplayPlaneManagerTest
, MultiplePlaneAssignment
) {
135 ui::OverlayPlaneList assigns
;
136 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
137 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
138 plane_manager_
->InitForTest(kTwoPlanesPerCrtc
, arraysize(kTwoPlanesPerCrtc
),
140 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
141 default_crtcs_
[0], nullptr));
142 EXPECT_EQ(2, plane_manager_
->plane_count());
145 TEST_F(HardwareDisplayPlaneManagerTest
, NotEnoughPlanes
) {
146 ui::OverlayPlaneList assigns
;
147 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
148 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
149 plane_manager_
->InitForTest(kOnePlanePerCrtc
, arraysize(kOnePlanePerCrtc
),
152 EXPECT_FALSE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
153 default_crtcs_
[0], nullptr));
156 TEST_F(HardwareDisplayPlaneManagerTest
, MultipleCrtcs
) {
157 ui::OverlayPlaneList assigns
;
158 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
159 plane_manager_
->InitForTest(kOnePlanePerCrtc
, arraysize(kOnePlanePerCrtc
),
162 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
163 default_crtcs_
[0], nullptr));
164 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
165 default_crtcs_
[1], nullptr));
166 EXPECT_EQ(2, plane_manager_
->plane_count());
169 TEST_F(HardwareDisplayPlaneManagerTest
, MultiplePlanesAndCrtcs
) {
170 ui::OverlayPlaneList assigns
;
171 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
172 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
173 plane_manager_
->InitForTest(kTwoPlanesPerCrtc
, arraysize(kTwoPlanesPerCrtc
),
175 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
176 default_crtcs_
[0], nullptr));
177 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
178 default_crtcs_
[1], nullptr));
179 EXPECT_EQ(4, plane_manager_
->plane_count());
182 TEST_F(HardwareDisplayPlaneManagerTest
, MultipleFrames
) {
183 ui::OverlayPlaneList assigns
;
184 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
185 plane_manager_
->InitForTest(kTwoPlanesPerCrtc
, arraysize(kTwoPlanesPerCrtc
),
188 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
189 default_crtcs_
[0], nullptr));
190 EXPECT_EQ(1, plane_manager_
->plane_count());
191 // Pretend we committed the frame.
192 state_
.plane_list
.swap(state_
.old_plane_list
);
193 plane_manager_
->BeginFrame(&state_
);
194 ui::HardwareDisplayPlane
* old_plane
= state_
.old_plane_list
[0];
195 // The same plane should be used.
196 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
197 default_crtcs_
[0], nullptr));
198 EXPECT_EQ(2, plane_manager_
->plane_count());
199 EXPECT_EQ(state_
.plane_list
[0], old_plane
);
202 TEST_F(HardwareDisplayPlaneManagerTest
, MultipleFramesDifferentPlanes
) {
203 ui::OverlayPlaneList assigns
;
204 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
205 plane_manager_
->InitForTest(kTwoPlanesPerCrtc
, arraysize(kTwoPlanesPerCrtc
),
208 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
209 default_crtcs_
[0], nullptr));
210 EXPECT_EQ(1, plane_manager_
->plane_count());
211 // The other plane should be used.
212 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
213 default_crtcs_
[0], nullptr));
214 EXPECT_EQ(2, plane_manager_
->plane_count());
215 EXPECT_NE(state_
.plane_list
[0], state_
.plane_list
[1]);
218 TEST_F(HardwareDisplayPlaneManagerTest
, SharedPlanes
) {
219 ui::OverlayPlaneList assigns
;
220 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
221 assigns
.push_back(ui::OverlayPlane(fake_buffer_
));
222 plane_manager_
->InitForTest(kOnePlanePerCrtcWithShared
,
223 arraysize(kOnePlanePerCrtcWithShared
),
226 EXPECT_TRUE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
227 default_crtcs_
[1], nullptr));
228 EXPECT_EQ(2, plane_manager_
->plane_count());
229 // The shared plane is now unavailable for use by the other CRTC.
230 EXPECT_FALSE(plane_manager_
->AssignOverlayPlanes(&state_
, assigns
,
231 default_crtcs_
[0], nullptr));
234 TEST(HardwareDisplayPlaneManagerLegacyTest
, UnusedPlanesAreReleased
) {
235 std::vector
<uint32_t> crtcs
;
236 crtcs
.push_back(100);
237 scoped_refptr
<ui::MockDrmDevice
> drm
= new ui::MockDrmDevice(false, crtcs
, 2);
238 ui::OverlayPlaneList assigns
;
239 scoped_refptr
<FakeScanoutBuffer
> fake_buffer
= new FakeScanoutBuffer();
240 assigns
.push_back(ui::OverlayPlane(fake_buffer
));
241 assigns
.push_back(ui::OverlayPlane(fake_buffer
));
242 ui::HardwareDisplayPlaneList hdpl
;
243 ui::CrtcController
crtc(drm
, crtcs
[0], 0);
244 drm
->plane_manager()->BeginFrame(&hdpl
);
245 EXPECT_TRUE(drm
->plane_manager()->AssignOverlayPlanes(&hdpl
, assigns
,
247 EXPECT_TRUE(drm
->plane_manager()->Commit(&hdpl
, false, false));
249 assigns
.push_back(ui::OverlayPlane(fake_buffer
));
250 drm
->plane_manager()->BeginFrame(&hdpl
);
251 EXPECT_TRUE(drm
->plane_manager()->AssignOverlayPlanes(&hdpl
, assigns
,
253 EXPECT_EQ(0, drm
->get_overlay_clear_call_count());
254 EXPECT_TRUE(drm
->plane_manager()->Commit(&hdpl
, false, false));
255 EXPECT_EQ(1, drm
->get_overlay_clear_call_count());