1 // Copyright 2015 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 "ui/ozone/platform/drm/gpu/drm_overlay_validator.h"
6 
7 #include <drm_fourcc.h>
8 #include <xf86drm.h>
9 
10 #include <memory>
11 #include <utility>
12 
13 #include "base/files/platform_file.h"
14 #include "base/test/task_environment.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "ui/gfx/geometry/rect_conversions.h"
17 #include "ui/gfx/gpu_fence.h"
18 #include "ui/gfx/linux/drm_util_linux.h"
19 #include "ui/gfx/linux/gbm_buffer.h"
20 #include "ui/gfx/linux/test/mock_gbm_device.h"
21 #include "ui/ozone/platform/drm/common/drm_util.h"
22 #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
23 #include "ui/ozone/platform/drm/gpu/drm_device_generator.h"
24 #include "ui/ozone/platform/drm/gpu/drm_device_manager.h"
25 #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h"
26 #include "ui/ozone/platform/drm/gpu/drm_window.h"
27 #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
28 #include "ui/ozone/platform/drm/gpu/mock_drm_device.h"
29 #include "ui/ozone/platform/drm/gpu/screen_manager.h"
30 
31 namespace {
32 
33 // Mode of size 12x8.
34 const drmModeModeInfo kDefaultMode = {0, 12, 0, 0, 0, 0, 8,     0,
35                                       0, 0,  0, 0, 0, 0, {'\0'}};
36 
37 const gfx::AcceleratedWidget kDefaultWidgetHandle = 1;
38 constexpr uint32_t kCrtcIdBase = 1;
39 constexpr uint32_t kConnectorIdBase = 100;
40 constexpr uint32_t kPlaneIdBase = 200;
41 constexpr uint32_t kInFormatsBlobPropIdBase = 400;
42 
43 constexpr uint32_t kTypePropId = 3010;
44 constexpr uint32_t kInFormatsPropId = 3011;
45 
46 }  // namespace
47 
48 class DrmOverlayValidatorTest : public testing::Test {
49  public:
50   DrmOverlayValidatorTest() = default;
51 
52   void SetUp() override;
53   void TearDown() override;
54 
OnSwapBuffers(gfx::SwapResult result)55   void OnSwapBuffers(gfx::SwapResult result) {
56     on_swap_buffers_count_++;
57     last_swap_buffers_result_ = result;
58   }
59 
ReturnNullBuffer(const gfx::Size & size,uint32_t format)60   scoped_refptr<ui::DrmFramebuffer> ReturnNullBuffer(const gfx::Size& size,
61                                                      uint32_t format) {
62     return nullptr;
63   }
64 
65   void AddPlane(const ui::OverlaySurfaceCandidate& params);
66 
CreateBuffer()67   scoped_refptr<ui::DrmFramebuffer> CreateBuffer() {
68     auto gbm_buffer = drm_->gbm_device()->CreateBuffer(
69         DRM_FORMAT_XRGB8888, primary_rect_.size(), GBM_BO_USE_SCANOUT);
70     return ui::DrmFramebuffer::AddFramebuffer(drm_, gbm_buffer.get(),
71                                               primary_rect_.size());
72   }
73 
CreateOverlayBuffer(uint32_t format,const gfx::Size & size)74   scoped_refptr<ui::DrmFramebuffer> CreateOverlayBuffer(uint32_t format,
75                                                         const gfx::Size& size) {
76     auto gbm_buffer =
77         drm_->gbm_device()->CreateBuffer(format, size, GBM_BO_USE_SCANOUT);
78     return ui::DrmFramebuffer::AddFramebuffer(drm_, gbm_buffer.get(), size);
79   }
80 
ModesetController(ui::HardwareDisplayController * controller)81   bool ModesetController(ui::HardwareDisplayController* controller) {
82     ui::CommitRequest commit_request;
83 
84     ui::DrmOverlayPlane plane(CreateBuffer(), nullptr);
85 
86     controller->GetModesetProps(&commit_request, plane, kDefaultMode);
87     ui::CommitRequest request_for_update = commit_request;
88     bool status = drm_->plane_manager()->Commit(std::move(commit_request),
89                                                 DRM_MODE_ATOMIC_ALLOW_MODESET);
90     controller->UpdateState(
91         /*enable_requested=*/true,
92         ui::DrmOverlayPlane::GetPrimaryPlane(request_for_update[0].overlays()));
93 
94     return status;
95   }
96 
97  protected:
98   struct PlaneState {
99     std::vector<uint32_t> formats;
100   };
101 
102   struct CrtcState {
103     std::vector<PlaneState> planes;
104   };
105 
106   void InitDrmStatesAndControllers(const std::vector<CrtcState>& crtc_states);
107 
108   base::test::SingleThreadTaskEnvironment task_environment_{
109       base::test::SingleThreadTaskEnvironment::MainThreadType::UI};
110   scoped_refptr<ui::MockDrmDevice> drm_;
111   ui::MockGbmDevice* gbm_ = nullptr;
112   std::unique_ptr<ui::ScreenManager> screen_manager_;
113   std::unique_ptr<ui::DrmDeviceManager> drm_device_manager_;
114   ui::DrmWindow* window_;
115   std::unique_ptr<ui::DrmOverlayValidator> overlay_validator_;
116   std::vector<ui::OverlaySurfaceCandidate> overlay_params_;
117   ui::DrmOverlayPlaneList plane_list_;
118 
119   int on_swap_buffers_count_;
120   gfx::SwapResult last_swap_buffers_result_;
121   gfx::Rect overlay_rect_;
122   gfx::Rect primary_rect_;
123 
124  private:
125   void SetupControllers();
126 
127   DISALLOW_COPY_AND_ASSIGN(DrmOverlayValidatorTest);
128 };
129 
SetUp()130 void DrmOverlayValidatorTest::SetUp() {
131   on_swap_buffers_count_ = 0;
132   last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED;
133 
134   auto gbm = std::make_unique<ui::MockGbmDevice>();
135   gbm_ = gbm.get();
136   drm_ = new ui::MockDrmDevice(std::move(gbm));
137 }
138 
InitDrmStatesAndControllers(const std::vector<CrtcState> & crtc_states)139 void DrmOverlayValidatorTest::InitDrmStatesAndControllers(
140     const std::vector<CrtcState>& crtc_states) {
141   std::vector<ui::MockDrmDevice::CrtcProperties> crtc_properties(
142       crtc_states.size());
143   std::map<uint32_t, std::string> crtc_property_names = {
144       {1000, "ACTIVE"},
145       {1001, "MODE_ID"},
146   };
147 
148   std::vector<ui::MockDrmDevice::ConnectorProperties> connector_properties(2);
149   std::map<uint32_t, std::string> connector_property_names = {
150       {2000, "CRTC_ID"},
151   };
152   for (size_t i = 0; i < connector_properties.size(); ++i) {
153     connector_properties[i].id = kConnectorIdBase + i;
154     for (const auto& pair : connector_property_names) {
155       connector_properties[i].properties.push_back(
156           {/* .id = */ pair.first, /* .value = */ 0});
157     }
158   }
159 
160   std::vector<ui::MockDrmDevice::PlaneProperties> plane_properties;
161   std::map<uint32_t, std::string> plane_property_names = {
162       // Add all required properties.
163       {3000, "CRTC_ID"},
164       {3001, "CRTC_X"},
165       {3002, "CRTC_Y"},
166       {3003, "CRTC_W"},
167       {3004, "CRTC_H"},
168       {3005, "FB_ID"},
169       {3006, "SRC_X"},
170       {3007, "SRC_Y"},
171       {3008, "SRC_W"},
172       {3009, "SRC_H"},
173       // Defines some optional properties we use for convenience.
174       {kTypePropId, "type"},
175       {kInFormatsPropId, "IN_FORMATS"},
176   };
177 
178   uint32_t plane_id = kPlaneIdBase;
179   uint32_t property_id = kInFormatsBlobPropIdBase;
180 
181   for (size_t crtc_idx = 0; crtc_idx < crtc_states.size(); ++crtc_idx) {
182     crtc_properties[crtc_idx].id = kCrtcIdBase + crtc_idx;
183     for (const auto& pair : crtc_property_names) {
184       crtc_properties[crtc_idx].properties.push_back(
185           {/* .id = */ pair.first, /* .value = */ 0});
186     }
187 
188     std::vector<ui::MockDrmDevice::PlaneProperties> crtc_plane_properties(
189         crtc_states[crtc_idx].planes.size());
190     for (size_t plane_idx = 0; plane_idx < crtc_states[crtc_idx].planes.size();
191          ++plane_idx) {
192       crtc_plane_properties[plane_idx].id = plane_id++;
193       crtc_plane_properties[plane_idx].crtc_mask = 1 << crtc_idx;
194 
195       for (const auto& pair : plane_property_names) {
196         uint64_t value = 0;
197         if (pair.first == kTypePropId) {
198           value =
199               plane_idx == 0 ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
200         } else if (pair.first == kInFormatsPropId) {
201           value = property_id++;
202           drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob(
203               value, crtc_states[crtc_idx].planes[plane_idx].formats,
204               std::vector<drm_format_modifier>()));
205         }
206 
207         crtc_plane_properties[plane_idx].properties.push_back(
208             {/* .id = */ pair.first, /* .value = */ value});
209       }
210     }
211 
212     plane_properties.insert(plane_properties.end(),
213                             crtc_plane_properties.begin(),
214                             crtc_plane_properties.end());
215   }
216 
217   std::map<uint32_t, std::string> property_names;
218   property_names.insert(crtc_property_names.begin(), crtc_property_names.end());
219   property_names.insert(connector_property_names.begin(),
220                         connector_property_names.end());
221   property_names.insert(plane_property_names.begin(),
222                         plane_property_names.end());
223   drm_->InitializeState(crtc_properties, connector_properties, plane_properties,
224                         property_names,
225                         /* use_atomic= */ true);
226 
227   SetupControllers();
228 }
229 
SetupControllers()230 void DrmOverlayValidatorTest::SetupControllers() {
231   screen_manager_ = std::make_unique<ui::ScreenManager>();
232   screen_manager_->AddDisplayController(drm_, kCrtcIdBase, kConnectorIdBase);
233   std::vector<ui::ScreenManager::ControllerConfigParams> controllers_to_enable;
234   controllers_to_enable.emplace_back(
235       1 /*display_id*/, drm_, kCrtcIdBase, kConnectorIdBase, gfx::Point(),
236       std::make_unique<drmModeModeInfo>(kDefaultMode));
237   screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
238 
239   drm_device_manager_ = std::make_unique<ui::DrmDeviceManager>(nullptr);
240 
241   std::unique_ptr<ui::DrmWindow> window(new ui::DrmWindow(
242       kDefaultWidgetHandle, drm_device_manager_.get(), screen_manager_.get()));
243   window->Initialize();
244   window->SetBounds(
245       gfx::Rect(gfx::Size(kDefaultMode.hdisplay, kDefaultMode.vdisplay)));
246   screen_manager_->AddWindow(kDefaultWidgetHandle, std::move(window));
247   window_ = screen_manager_->GetWindow(kDefaultWidgetHandle);
248   overlay_validator_ = std::make_unique<ui::DrmOverlayValidator>(window_);
249 
250   overlay_rect_ =
251       gfx::Rect(0, 0, kDefaultMode.hdisplay / 2, kDefaultMode.vdisplay / 2);
252 
253   primary_rect_ = gfx::Rect(0, 0, kDefaultMode.hdisplay, kDefaultMode.vdisplay);
254 
255   ui::OverlaySurfaceCandidate primary_candidate;
256   primary_candidate.buffer_size = primary_rect_.size();
257   primary_candidate.display_rect = gfx::RectF(primary_rect_);
258   primary_candidate.is_opaque = true;
259   primary_candidate.format = gfx::BufferFormat::BGRX_8888;
260   primary_candidate.overlay_handled = true;
261   overlay_params_.push_back(primary_candidate);
262   AddPlane(primary_candidate);
263 
264   ui::OverlaySurfaceCandidate overlay_candidate;
265   overlay_candidate.buffer_size = overlay_rect_.size();
266   overlay_candidate.display_rect = gfx::RectF(overlay_rect_);
267   overlay_candidate.plane_z_order = 1;
268   primary_candidate.is_opaque = true;
269   overlay_candidate.format = gfx::BufferFormat::BGRX_8888;
270   overlay_candidate.overlay_handled = true;
271   overlay_params_.push_back(overlay_candidate);
272   AddPlane(overlay_candidate);
273 }
274 
AddPlane(const ui::OverlaySurfaceCandidate & params)275 void DrmOverlayValidatorTest::AddPlane(
276     const ui::OverlaySurfaceCandidate& params) {
277   scoped_refptr<ui::DrmDevice> drm = window_->GetController()->GetDrmDevice();
278 
279   scoped_refptr<ui::DrmFramebuffer> drm_framebuffer = CreateOverlayBuffer(
280       ui::GetFourCCFormatFromBufferFormat(params.format), params.buffer_size);
281   plane_list_.push_back(ui::DrmOverlayPlane(
282       std::move(drm_framebuffer), params.plane_z_order, params.transform,
283       gfx::ToNearestRect(params.display_rect), params.crop_rect, true,
284       nullptr));
285 }
286 
TearDown()287 void DrmOverlayValidatorTest::TearDown() {
288   std::unique_ptr<ui::DrmWindow> window =
289       screen_manager_->RemoveWindow(kDefaultWidgetHandle);
290   window->Shutdown();
291 }
292 
TEST_F(DrmOverlayValidatorTest,WindowWithNoController)293 TEST_F(DrmOverlayValidatorTest, WindowWithNoController) {
294   CrtcState crtc_state = {/* .planes = */ {
295       {/* .formats = */ {DRM_FORMAT_XRGB8888}},
296   }};
297   InitDrmStatesAndControllers({crtc_state});
298 
299   // We should never promote layers to overlay when controller is not
300   // present.
301   ui::HardwareDisplayController* controller = window_->GetController();
302   window_->SetController(nullptr);
303   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
304       overlay_params_, ui::DrmOverlayPlaneList());
305   EXPECT_EQ(returns.front(), ui::OVERLAY_STATUS_NOT);
306   EXPECT_EQ(returns.back(), ui::OVERLAY_STATUS_NOT);
307   window_->SetController(controller);
308 }
309 
TEST_F(DrmOverlayValidatorTest,DontPromoteMoreLayersThanAvailablePlanes)310 TEST_F(DrmOverlayValidatorTest, DontPromoteMoreLayersThanAvailablePlanes) {
311   CrtcState crtc_state = {/* .planes = */ {
312       {/* .formats = */ {DRM_FORMAT_XRGB8888}},
313   }};
314   InitDrmStatesAndControllers({crtc_state});
315 
316   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
317       overlay_params_, ui::DrmOverlayPlaneList());
318   EXPECT_EQ(returns.front(), ui::OVERLAY_STATUS_ABLE);
319   EXPECT_EQ(returns.back(), ui::OVERLAY_STATUS_NOT);
320 }
321 
TEST_F(DrmOverlayValidatorTest,DontCollapseOverlayToPrimaryInFullScreen)322 TEST_F(DrmOverlayValidatorTest, DontCollapseOverlayToPrimaryInFullScreen) {
323   CrtcState crtc_state = {/* .planes = */ {
324       {/* .formats = */ {DRM_FORMAT_XRGB8888}},
325   }};
326   InitDrmStatesAndControllers({crtc_state});
327 
328   // Overlay Validator should not collapse planes during validation.
329   overlay_params_.back().buffer_size = primary_rect_.size();
330   overlay_params_.back().display_rect = gfx::RectF(primary_rect_);
331   plane_list_.back().display_bounds = primary_rect_;
332 
333   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
334       overlay_params_, ui::DrmOverlayPlaneList());
335   // Second candidate should be marked as Invalid as we have only one plane
336   // per CRTC.
337   EXPECT_EQ(returns.front(), ui::OVERLAY_STATUS_ABLE);
338   EXPECT_EQ(returns.back(), ui::OVERLAY_STATUS_NOT);
339 }
340 
TEST_F(DrmOverlayValidatorTest,OverlayFormat_XRGB)341 TEST_F(DrmOverlayValidatorTest, OverlayFormat_XRGB) {
342   // This test checks for optimal format in case of non full screen video case.
343   // This should be XRGB when overlay doesn't support YUV.
344   CrtcState state = {
345       /*  .planes = */
346       {
347           {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
348           {/* .formats = */ {DRM_FORMAT_XRGB8888}},
349       },
350   };
351   InitDrmStatesAndControllers(std::vector<CrtcState>(1, state));
352 
353   overlay_params_.back().buffer_size = overlay_rect_.size();
354   overlay_params_.back().display_rect = gfx::RectF(overlay_rect_);
355   plane_list_.back().display_bounds = overlay_rect_;
356 
357   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
358       overlay_params_, ui::DrmOverlayPlaneList());
359   EXPECT_EQ(2u, returns.size());
360   for (const auto& param : returns)
361     EXPECT_EQ(param, ui::OVERLAY_STATUS_ABLE);
362 }
363 
TEST_F(DrmOverlayValidatorTest,OverlayFormat_YUV)364 TEST_F(DrmOverlayValidatorTest, OverlayFormat_YUV) {
365   // This test checks for optimal format in case of non full screen video case.
366   // Prefer YUV as optimal format when Overlay supports it and scaling is
367   // needed.
368   CrtcState state = {
369       /* .planes = */
370       {
371           {/* .formats = */ {DRM_FORMAT_XRGB8888}},
372           {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
373       },
374   };
375   InitDrmStatesAndControllers(std::vector<CrtcState>(1, state));
376 
377   gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
378   overlay_params_.back().buffer_size = overlay_rect_.size();
379   overlay_params_.back().display_rect = gfx::RectF(overlay_rect_);
380   overlay_params_.back().crop_rect = crop_rect;
381   overlay_params_.back().is_opaque = false;
382   overlay_params_.back().format = gfx::BufferFormat::YUV_420_BIPLANAR;
383   plane_list_.pop_back();
384   AddPlane(overlay_params_.back());
385 
386   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
387       overlay_params_, ui::DrmOverlayPlaneList());
388   EXPECT_EQ(2u, returns.size());
389   for (const auto& param : returns)
390     EXPECT_EQ(param, ui::OVERLAY_STATUS_ABLE);
391 }
392 
TEST_F(DrmOverlayValidatorTest,RejectYUVBuffersIfNotSupported)393 TEST_F(DrmOverlayValidatorTest, RejectYUVBuffersIfNotSupported) {
394   // Check case where buffer storage format is already YUV 420 but planes don't
395   // support it.
396   CrtcState state = {
397       /* .planes = */
398       {
399           {/* .formats = */ {DRM_FORMAT_XRGB8888}},
400           {/* .formats = */ {DRM_FORMAT_XRGB8888}},
401       },
402   };
403   InitDrmStatesAndControllers(std::vector<CrtcState>(1, state));
404 
405   overlay_params_.back().buffer_size = overlay_rect_.size();
406   overlay_params_.back().display_rect = gfx::RectF(overlay_rect_);
407   overlay_params_.back().format = gfx::BufferFormat::YUV_420_BIPLANAR;
408   plane_list_.pop_back();
409   AddPlane(overlay_params_.back());
410 
411   std::vector<ui::OverlaySurfaceCandidate> validated_params = overlay_params_;
412   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
413       validated_params, ui::DrmOverlayPlaneList());
414   EXPECT_EQ(2u, returns.size());
415   EXPECT_EQ(returns.back(), ui::OVERLAY_STATUS_NOT);
416 }
417 
TEST_F(DrmOverlayValidatorTest,RejectYUVBuffersIfNotSupported_MirroredControllers)418 TEST_F(DrmOverlayValidatorTest,
419        RejectYUVBuffersIfNotSupported_MirroredControllers) {
420   std::vector<CrtcState> crtc_states = {
421       {
422           /* .planes = */
423           {
424               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
425               {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
426           },
427       },
428       {
429           /* .planes = */
430           {
431               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
432               {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
433           },
434       },
435   };
436   InitDrmStatesAndControllers(crtc_states);
437 
438   ui::HardwareDisplayController* controller = window_->GetController();
439   controller->AddCrtc(std::make_unique<ui::CrtcController>(
440       drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1));
441   EXPECT_TRUE(ModesetController(controller));
442 
443   gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
444   overlay_params_.back().buffer_size = overlay_rect_.size();
445   overlay_params_.back().display_rect = gfx::RectF(overlay_rect_);
446   overlay_params_.back().crop_rect = crop_rect;
447   plane_list_.back().display_bounds = overlay_rect_;
448   plane_list_.back().crop_rect = crop_rect;
449 
450   std::vector<ui::OverlaySurfaceCandidate> validated_params = overlay_params_;
451   validated_params.back().format = gfx::BufferFormat::YUV_420_BIPLANAR;
452   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
453       validated_params, ui::DrmOverlayPlaneList());
454   EXPECT_EQ(2u, returns.size());
455   EXPECT_EQ(returns.back(), ui::OVERLAY_STATUS_ABLE);
456 }
457 
TEST_F(DrmOverlayValidatorTest,RejectYUVBuffersIfNotSupported_NoPackedFormatsInMirroredCrtc)458 TEST_F(DrmOverlayValidatorTest,
459        RejectYUVBuffersIfNotSupported_NoPackedFormatsInMirroredCrtc) {
460   // This configuration should not be promoted to Overlay when either of the
461   // controllers don't support YUV 420 format.
462 
463   std::vector<CrtcState> crtc_states = {
464       {
465           /* .planes = */
466           {
467               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
468               {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
469           },
470       },
471       {
472           /* .planes = */
473           {
474               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
475               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
476           },
477       },
478   };
479   InitDrmStatesAndControllers(crtc_states);
480 
481   ui::HardwareDisplayController* controller = window_->GetController();
482   controller->AddCrtc(std::make_unique<ui::CrtcController>(
483       drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1));
484   EXPECT_TRUE(ModesetController(controller));
485 
486   gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
487   overlay_params_.back().buffer_size = overlay_rect_.size();
488   overlay_params_.back().display_rect = gfx::RectF(overlay_rect_);
489   overlay_params_.back().crop_rect = crop_rect;
490   plane_list_.back().display_bounds = overlay_rect_;
491   plane_list_.back().crop_rect = crop_rect;
492 
493   std::vector<ui::OverlaySurfaceCandidate> validated_params = overlay_params_;
494   validated_params.back().format = gfx::BufferFormat::YUV_420_BIPLANAR;
495   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
496       validated_params, ui::DrmOverlayPlaneList());
497   EXPECT_EQ(2u, returns.size());
498   EXPECT_EQ(returns.back(), ui::OVERLAY_STATUS_NOT);
499 }
500 
TEST_F(DrmOverlayValidatorTest,RejectYUVBuffersIfNotSupported_NoPackedFormatsInPrimaryDisplay)501 TEST_F(DrmOverlayValidatorTest,
502        RejectYUVBuffersIfNotSupported_NoPackedFormatsInPrimaryDisplay) {
503   std::vector<CrtcState> crtc_states = {
504       {
505           /* .planes = */
506           {
507               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
508               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
509           },
510       },
511       {
512           /* .planes = */
513           {
514               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
515               {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
516           },
517       },
518   };
519   InitDrmStatesAndControllers(crtc_states);
520 
521   ui::HardwareDisplayController* controller = window_->GetController();
522   controller->AddCrtc(std::make_unique<ui::CrtcController>(
523       drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1));
524   EXPECT_TRUE(ModesetController(controller));
525 
526   gfx::RectF crop_rect = gfx::RectF(0, 0, 0.5, 0.5);
527   overlay_params_.back().buffer_size = overlay_rect_.size();
528   overlay_params_.back().display_rect = gfx::RectF(overlay_rect_);
529   overlay_params_.back().crop_rect = crop_rect;
530   plane_list_.back().display_bounds = overlay_rect_;
531   plane_list_.back().crop_rect = crop_rect;
532 
533   std::vector<ui::OverlaySurfaceCandidate> validated_params = overlay_params_;
534   validated_params.back().format = gfx::BufferFormat::YUV_420_BIPLANAR;
535 
536   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
537       validated_params, ui::DrmOverlayPlaneList());
538   EXPECT_EQ(2u, returns.size());
539   EXPECT_EQ(returns.back(), ui::OVERLAY_STATUS_NOT);
540 }
541 
TEST_F(DrmOverlayValidatorTest,OptimalFormatXRGB_MirroredControllers)542 TEST_F(DrmOverlayValidatorTest, OptimalFormatXRGB_MirroredControllers) {
543   std::vector<CrtcState> crtc_states = {
544       {
545           /* .planes = */
546           {
547               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
548               {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
549           },
550       },
551       {
552           /* .planes = */
553           {
554               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
555               {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
556           },
557       },
558   };
559   InitDrmStatesAndControllers(crtc_states);
560 
561   ui::HardwareDisplayController* controller = window_->GetController();
562   controller->AddCrtc(std::make_unique<ui::CrtcController>(
563       drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1));
564   EXPECT_TRUE(ModesetController(controller));
565 
566   overlay_params_.back().buffer_size = overlay_rect_.size();
567   overlay_params_.back().display_rect = gfx::RectF(overlay_rect_);
568   plane_list_.back().display_bounds = overlay_rect_;
569 
570   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
571       overlay_params_, ui::DrmOverlayPlaneList());
572   EXPECT_EQ(2u, returns.size());
573   EXPECT_EQ(returns.back(), ui::OVERLAY_STATUS_ABLE);
574 }
575 
TEST_F(DrmOverlayValidatorTest,OptimalFormatXRGB_NoPackedFormatInMirroredCrtc)576 TEST_F(DrmOverlayValidatorTest,
577        OptimalFormatXRGB_NoPackedFormatInMirroredCrtc) {
578   std::vector<CrtcState> crtc_states = {
579       {
580           /* .planes = */
581           {
582               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
583               {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
584           },
585       },
586       {
587           /* .planes = */
588           {
589               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
590               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
591           },
592       },
593   };
594   InitDrmStatesAndControllers(crtc_states);
595 
596   ui::HardwareDisplayController* controller = window_->GetController();
597   controller->AddCrtc(std::make_unique<ui::CrtcController>(
598       drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1));
599   EXPECT_TRUE(ModesetController(controller));
600 
601   overlay_params_.back().buffer_size = overlay_rect_.size();
602   overlay_params_.back().display_rect = gfx::RectF(overlay_rect_);
603   plane_list_.back().display_bounds = overlay_rect_;
604 
605   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
606       overlay_params_, ui::DrmOverlayPlaneList());
607   EXPECT_EQ(returns.back(), ui::OVERLAY_STATUS_ABLE);
608 }
609 
TEST_F(DrmOverlayValidatorTest,OptimalFormatXRGB_NoPackedFormatInPrimaryDisplay)610 TEST_F(DrmOverlayValidatorTest,
611        OptimalFormatXRGB_NoPackedFormatInPrimaryDisplay) {
612   std::vector<CrtcState> crtc_states = {
613       {
614           /* .planes = */
615           {
616               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
617               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
618           },
619       },
620       {
621           /* .planes = */
622           {
623               {/* .formats = */ {DRM_FORMAT_XRGB8888}},
624               {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
625           },
626       },
627   };
628   InitDrmStatesAndControllers(crtc_states);
629 
630   ui::HardwareDisplayController* controller = window_->GetController();
631   controller->AddCrtc(std::make_unique<ui::CrtcController>(
632       drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1));
633   EXPECT_TRUE(ModesetController(controller));
634 
635   overlay_params_.back().buffer_size = overlay_rect_.size();
636   overlay_params_.back().display_rect = gfx::RectF(overlay_rect_);
637   plane_list_.back().display_bounds = overlay_rect_;
638 
639   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
640       overlay_params_, ui::DrmOverlayPlaneList());
641   EXPECT_EQ(2u, returns.size());
642   EXPECT_EQ(returns.back(), ui::OVERLAY_STATUS_ABLE);
643 }
644 
TEST_F(DrmOverlayValidatorTest,RejectBufferAllocationFail)645 TEST_F(DrmOverlayValidatorTest, RejectBufferAllocationFail) {
646   CrtcState crtc_state = {/* .planes = */ {
647       {/* .formats = */ {DRM_FORMAT_XRGB8888}},
648   }};
649   InitDrmStatesAndControllers({crtc_state});
650 
651   // Buffer allocation for scanout might fail.
652   // In that case we should reject the overlay candidate.
653   gbm_->set_allocation_failure(true);
654 
655   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
656       overlay_params_, ui::DrmOverlayPlaneList());
657   EXPECT_EQ(2u, returns.size());
658   EXPECT_EQ(returns.front(), ui::OVERLAY_STATUS_NOT);
659 }
660 
661 // This test verifies that the Ozone/DRM implementation does not reject overlay
662 // candidates purely on the basis of having non-integer bounds. Instead, they
663 // should be rounded to the nearest integer.
TEST_F(DrmOverlayValidatorTest,NonIntegerDisplayRect)664 TEST_F(DrmOverlayValidatorTest, NonIntegerDisplayRect) {
665   CrtcState state = {
666       /* .planes = */
667       {
668           {/* .formats = */ {DRM_FORMAT_XRGB8888}},
669           {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
670       },
671   };
672   InitDrmStatesAndControllers(std::vector<CrtcState>(1, state));
673 
674   overlay_params_.back().display_rect.Inset(0.005f, 0.005f);
675   plane_list_.pop_back();
676   AddPlane(overlay_params_.back());
677 
678   std::vector<ui::OverlayStatus> returns = overlay_validator_->TestPageFlip(
679       overlay_params_, ui::DrmOverlayPlaneList());
680   EXPECT_EQ(2u, returns.size());
681   for (const auto& param : returns)
682     EXPECT_EQ(param, ui::OVERLAY_STATUS_ABLE);
683 }
684