OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include <vector> |
| 6 |
| 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" |
| 17 |
| 18 namespace { |
| 19 |
| 20 struct FakePlaneInfo { |
| 21 uint32_t id; |
| 22 uint32_t allowed_crtc_mask; |
| 23 }; |
| 24 |
| 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}}; |
| 28 |
| 29 class FakeScanoutBuffer : public ui::ScanoutBuffer { |
| 30 public: |
| 31 FakeScanoutBuffer() {} |
| 32 |
| 33 // ui::ScanoutBuffer: |
| 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); } |
| 37 |
| 38 protected: |
| 39 ~FakeScanoutBuffer() override {} |
| 40 }; |
| 41 |
| 42 class FakePlaneManager : public ui::HardwareDisplayPlaneManager { |
| 43 public: |
| 44 FakePlaneManager() : plane_count_(0) {} |
| 45 ~FakePlaneManager() override {} |
| 46 |
| 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, |
| 50 size_t count, |
| 51 const std::vector<uint32_t>& crtcs) { |
| 52 crtcs_ = 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)); |
| 56 } |
| 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(); |
| 61 }); |
| 62 } |
| 63 |
| 64 bool Commit(ui::HardwareDisplayPlaneList* plane_list, |
| 65 bool is_sync, |
| 66 bool test_only) override { |
| 67 return false; |
| 68 } |
| 69 |
| 70 bool SetPlaneData(ui::HardwareDisplayPlaneList* plane_list, |
| 71 ui::HardwareDisplayPlane* hw_plane, |
| 72 const ui::OverlayPlane& overlay, |
| 73 uint32_t crtc_id, |
| 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()); |
| 80 plane_count_++; |
| 81 return true; |
| 82 } |
| 83 |
| 84 int plane_count() const { return plane_count_; } |
| 85 |
| 86 private: |
| 87 DISALLOW_COPY_AND_ASSIGN(FakePlaneManager); |
| 88 |
| 89 int plane_count_; |
| 90 }; |
| 91 |
| 92 class HardwareDisplayPlaneManagerTest : public testing::Test { |
| 93 public: |
| 94 HardwareDisplayPlaneManagerTest() {} |
| 95 |
| 96 void SetUp() override; |
| 97 |
| 98 protected: |
| 99 scoped_ptr<FakePlaneManager> plane_manager_; |
| 100 ui::HardwareDisplayPlaneList state_; |
| 101 std::vector<uint32_t> default_crtcs_; |
| 102 scoped_refptr<ui::ScanoutBuffer> fake_buffer_; |
| 103 |
| 104 private: |
| 105 DISALLOW_COPY_AND_ASSIGN(HardwareDisplayPlaneManagerTest); |
| 106 }; |
| 107 |
| 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); |
| 113 } |
| 114 |
| 115 TEST_F(HardwareDisplayPlaneManagerTest, SinglePlaneAssignment) { |
| 116 ui::OverlayPlaneList assigns; |
| 117 assigns.push_back(ui::OverlayPlane(fake_buffer_)); |
| 118 plane_manager_->InitForTest(kOnePlanePerCrtc, arraysize(kOnePlanePerCrtc), |
| 119 default_crtcs_); |
| 120 EXPECT_TRUE(plane_manager_->AssignOverlayPlanes(&state_, assigns, |
| 121 default_crtcs_[0], nullptr)); |
| 122 EXPECT_EQ(1, plane_manager_->plane_count()); |
| 123 } |
| 124 |
| 125 TEST_F(HardwareDisplayPlaneManagerTest, BadCrtc) { |
| 126 ui::OverlayPlaneList assigns; |
| 127 assigns.push_back(ui::OverlayPlane(fake_buffer_)); |
| 128 plane_manager_->InitForTest(kOnePlanePerCrtc, arraysize(kOnePlanePerCrtc), |
| 129 default_crtcs_); |
| 130 EXPECT_FALSE( |
| 131 plane_manager_->AssignOverlayPlanes(&state_, assigns, 1, nullptr)); |
| 132 } |
| 133 |
| 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), |
| 139 default_crtcs_); |
| 140 EXPECT_TRUE(plane_manager_->AssignOverlayPlanes(&state_, assigns, |
| 141 default_crtcs_[0], nullptr)); |
| 142 EXPECT_EQ(2, plane_manager_->plane_count()); |
| 143 } |
| 144 |
| 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), |
| 150 default_crtcs_); |
| 151 |
| 152 EXPECT_FALSE(plane_manager_->AssignOverlayPlanes(&state_, assigns, |
| 153 default_crtcs_[0], nullptr)); |
| 154 } |
| 155 |
| 156 TEST_F(HardwareDisplayPlaneManagerTest, MultipleCrtcs) { |
| 157 ui::OverlayPlaneList assigns; |
| 158 assigns.push_back(ui::OverlayPlane(fake_buffer_)); |
| 159 plane_manager_->InitForTest(kOnePlanePerCrtc, arraysize(kOnePlanePerCrtc), |
| 160 default_crtcs_); |
| 161 |
| 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()); |
| 167 } |
| 168 |
| 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), |
| 174 default_crtcs_); |
| 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()); |
| 180 } |
| 181 |
| 182 TEST_F(HardwareDisplayPlaneManagerTest, MultipleFrames) { |
| 183 ui::OverlayPlaneList assigns; |
| 184 assigns.push_back(ui::OverlayPlane(fake_buffer_)); |
| 185 plane_manager_->InitForTest(kTwoPlanesPerCrtc, arraysize(kTwoPlanesPerCrtc), |
| 186 default_crtcs_); |
| 187 |
| 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); |
| 200 } |
| 201 |
| 202 TEST_F(HardwareDisplayPlaneManagerTest, MultipleFramesDifferentPlanes) { |
| 203 ui::OverlayPlaneList assigns; |
| 204 assigns.push_back(ui::OverlayPlane(fake_buffer_)); |
| 205 plane_manager_->InitForTest(kTwoPlanesPerCrtc, arraysize(kTwoPlanesPerCrtc), |
| 206 default_crtcs_); |
| 207 |
| 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]); |
| 216 } |
| 217 |
| 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), |
| 224 default_crtcs_); |
| 225 |
| 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)); |
| 232 } |
| 233 |
| 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, |
| 246 crtcs[0], &crtc)); |
| 247 EXPECT_TRUE(drm->plane_manager()->Commit(&hdpl, false, false)); |
| 248 assigns.clear(); |
| 249 assigns.push_back(ui::OverlayPlane(fake_buffer)); |
| 250 drm->plane_manager()->BeginFrame(&hdpl); |
| 251 EXPECT_TRUE(drm->plane_manager()->AssignOverlayPlanes(&hdpl, assigns, |
| 252 crtcs[0], &crtc)); |
| 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()); |
| 256 } |
| 257 |
| 258 } // namespace |
OLD | NEW |