Add CRTC background color property and methods to get & set it

Intel GEN9+ platforms support a programmable CRTC background color
below HW planes. The background color can be seen on areas not
covered by the planes. This CL adds the background color property
exposed by kernel, and the methods to get & set the property.

BUG=chromium:894259

Change-Id: I2f43eb91e76f8d7f22faa0c75de553a066f8fdee
Reviewed-on: https://chromium-review.googlesource.com/c/1278858
Reviewed-by: Daniel Nicoara <dnicoara@chromium.org>
Reviewed-by: Dongseong Hwang <dongseong.hwang@intel.com>
Auto-Submit: Wei Li <wei.c.li@intel.com>
Commit-Queue: Daniel Nicoara <dnicoara@chromium.org>
Cr-Commit-Position: refs/heads/master@{#624781}
diff --git a/AUTHORS b/AUTHORS
index 1fe1df4..374b1a1 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -914,6 +914,7 @@
 Volker Sorge <volker.sorge@gmail.com>
 Waihung Fu <fufranci@amazon.com>
 Wanming Lin <wanming.lin@intel.com>
+Wei Li <wei.c.li@intel.com>
 WenSheng He <wensheng.he@samsung.com>
 Wesley Lancel <wesleylancel@gmail.com>
 Wesley Wigham <wwigham@gmail.com>
diff --git a/ui/ozone/platform/drm/gpu/drm_display.cc b/ui/ozone/platform/drm/gpu/drm_display.cc
index d476350..f800442 100644
--- a/ui/ozone/platform/drm/gpu/drm_display.cc
+++ b/ui/ozone/platform/drm/gpu/drm_display.cc
@@ -178,6 +178,10 @@
   }
 }
 
+void DrmDisplay::SetBackgroundColor(const uint64_t background_color) {
+  drm_->plane_manager()->SetBackgroundColor(crtc_, background_color);
+}
+
 void DrmDisplay::SetGammaCorrection(
     const std::vector<display::GammaRampRGBEntry>& degamma_lut,
     const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
diff --git a/ui/ozone/platform/drm/gpu/drm_display.h b/ui/ozone/platform/drm/gpu/drm_display.h
index 2ffc4d2..16f2dae 100644
--- a/ui/ozone/platform/drm/gpu/drm_display.h
+++ b/ui/ozone/platform/drm/gpu/drm_display.h
@@ -49,6 +49,7 @@
   bool GetHDCPState(display::HDCPState* state);
   bool SetHDCPState(display::HDCPState state);
   void SetColorMatrix(const std::vector<float>& color_matrix);
+  void SetBackgroundColor(const uint64_t background_color);
   void SetGammaCorrection(
       const std::vector<display::GammaRampRGBEntry>& degamma_lut,
       const std::vector<display::GammaRampRGBEntry>& gamma_lut);
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
index 64272d29..232ae76 100644
--- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
+++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
@@ -202,6 +202,18 @@
   display->SetColorMatrix(color_matrix);
 }
 
+void DrmGpuDisplayManager::SetBackgroundColor(
+    int64_t display_id,
+    const uint64_t background_color) {
+  DrmDisplay* display = FindDisplay(display_id);
+  if (!display) {
+    LOG(ERROR) << "There is no display with ID" << display_id;
+    return;
+  }
+
+  display->SetBackgroundColor(background_color);
+}
+
 void DrmGpuDisplayManager::SetGammaCorrection(
     int64_t display_id,
     const std::vector<display::GammaRampRGBEntry>& degamma_lut,
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
index 8e0a1a8..4a7669f 100644
--- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
+++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
@@ -48,6 +48,8 @@
   bool SetHDCPState(int64_t display_id, display::HDCPState state);
   void SetColorMatrix(int64_t display_id,
                       const std::vector<float>& color_matrix);
+  void SetBackgroundColor(int64_t display_id,
+                          const uint64_t background_color);
   void SetGammaCorrection(
       int64_t display_id,
       const std::vector<display::GammaRampRGBEntry>& degamma_lut,
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
index 69a2c6b..bb8799b 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
@@ -250,6 +250,16 @@
   return CommitColorMatrix(crtc_state->properties);
 }
 
+void HardwareDisplayPlaneManager::SetBackgroundColor(
+    uint32_t crtc_id,
+    const uint64_t background_color) {
+  const int crtc_index = LookupCrtcIndex(crtc_id);
+  DCHECK_GE(crtc_index, 0);
+  CrtcState* crtc_state = &crtc_state_[crtc_index];
+
+  crtc_state->properties.background_color.value = background_color;
+}
+
 bool HardwareDisplayPlaneManager::SetGammaCorrection(
     uint32_t crtc_id,
     const std::vector<display::GammaRampRGBEntry>& degamma_lut,
@@ -336,6 +346,8 @@
                           &state.properties.degamma_lut_size);
     GetDrmPropertyForName(drm_, props.get(), "OUT_FENCE_PTR",
                           &state.properties.out_fence_ptr);
+    GetDrmPropertyForName(drm_, props.get(), "BACKGROUND_COLOR",
+                          &state.properties.background_color);
 
     num_crtcs_with_out_fence_ptr += (state.properties.out_fence_ptr.id != 0);
 
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
index e4de8f55..45cd06c 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
@@ -71,6 +71,9 @@
   // on the CRTC with ID |crtc_id|.
   bool SetColorMatrix(uint32_t crtc_id, const std::vector<float>& color_matrix);
 
+  // Sets the background color on the CRTC object with ID |crtc_id|.
+  void SetBackgroundColor(uint32_t crtc_id, const uint64_t background_color);
+
   // Sets the degamma/gamma luts on the CRTC object with ID |crtc_id|.
   bool SetGammaCorrection(
       uint32_t crtc_id,
@@ -141,6 +144,7 @@
     DrmDevice::Property degamma_lut;
     DrmDevice::Property degamma_lut_size;
     DrmDevice::Property out_fence_ptr;
+    DrmDevice::Property background_color;
   };
 
   struct CrtcState {
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
index 3d1083b..c1868d0f9 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
@@ -83,23 +83,26 @@
       crtcs.push_back(atomic_plane->crtc());
   }
 
-#if defined(COMMIT_PROPERTIES_ON_PAGE_FLIP)
   drmModeAtomicReqPtr request = plane_list->atomic_property_set.get();
-
-  // Apply all CRTC properties in the page-flip so we don't block the swap chain
-  // for a vsync.
-  // TODO(dnicoara): See if we can apply these properties async using
-  // DRM_MODE_ATOMIC_ASYNC_UPDATE flag when committing.
   for (auto* const crtc : crtcs) {
     int idx = LookupCrtcIndex(crtc->crtc());
+
+#if defined(COMMIT_PROPERTIES_ON_PAGE_FLIP)
+    // Apply all CRTC properties in the page-flip so we don't block the
+    // swap chain for a vsync.
+    // TODO(dnicoara): See if we can apply these properties async using
+    // DRM_MODE_ATOMIC_ASYNC_UPDATE flag when committing.
     AddPropertyIfValid(request, crtc->crtc(),
                        crtc_state_[idx].properties.degamma_lut);
     AddPropertyIfValid(request, crtc->crtc(),
                        crtc_state_[idx].properties.gamma_lut);
     AddPropertyIfValid(request, crtc->crtc(), crtc_state_[idx].properties.ctm);
-  }
 #endif
 
+    AddPropertyIfValid(request, crtc->crtc(),
+                       crtc_state_[idx].properties.background_color);
+  }
+
   if (test_only) {
     for (HardwareDisplayPlane* plane : plane_list->plane_list) {
       plane->set_in_use(false);
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
index ded5335..6103f40 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
@@ -40,6 +40,7 @@
 constexpr uint32_t kDegammaLutSizePropId = 307;
 constexpr uint32_t kOutFencePtrPropId = 308;
 constexpr uint32_t kInFormatsBlobPropId = 400;
+constexpr uint32_t kBackgroundColorPropId = 401;
 
 const gfx::Size kDefaultBufferSize(2, 2);
 
@@ -164,6 +165,7 @@
   property_names_.insert({kDegammaLutPropId, "DEGAMMA_LUT"});
   property_names_.insert({kDegammaLutSizePropId, "DEGAMMA_LUT_SIZE"});
   property_names_.insert({kOutFencePtrPropId, "OUT_FENCE_PTR"});
+  property_names_.insert({kBackgroundColorPropId, "BACKGROUND_COLOR"});
 }
 
 void HardwareDisplayPlaneManagerTest::PerformPageFlip(
@@ -686,6 +688,39 @@
   }
 }
 
+TEST_P(HardwareDisplayPlaneManagerTest, SetBackgroundColor_Success) {
+  InitializeDrmState(/*crtc_count=*/1, /*planes_per_crtc=*/1);
+  crtc_properties_[0].properties.push_back(
+      {/* .id = */ kBackgroundColorPropId, /* .value = */ 0});
+  fake_drm_->InitializeState(crtc_properties_, plane_properties_,
+                             property_names_, use_atomic_);
+  fake_drm_->plane_manager()->SetBackgroundColor(crtc_properties_[0].id, 0);
+  if (use_atomic_) {
+    ui::HardwareDisplayPlaneList state;
+    PerformPageFlip(/*crtc_idx=*/0, &state);
+    EXPECT_EQ(1, fake_drm_->get_commit_count());
+    EXPECT_EQ(0u, GetCrtcPropertyValue(crtc_properties_[0].id,
+                                       "BACKGROUND_COLOR"));
+  } else {
+    EXPECT_EQ(0, fake_drm_->get_set_object_property_count());
+  }
+
+  crtc_properties_[0].properties.push_back(
+      {/* .id = */ kBackgroundColorPropId, /* .value = */ 1});
+  fake_drm_->InitializeState(crtc_properties_, plane_properties_,
+                             property_names_, use_atomic_);
+  fake_drm_->plane_manager()->SetBackgroundColor(crtc_properties_[0].id, 1);
+  if (use_atomic_) {
+    ui::HardwareDisplayPlaneList state;
+    PerformPageFlip(/*crtc_idx=*/0, &state);
+    EXPECT_EQ(2, fake_drm_->get_commit_count());
+    EXPECT_EQ(1u, GetCrtcPropertyValue(crtc_properties_[0].id,
+                                       "BACKGROUND_COLOR"));
+  } else {
+    EXPECT_EQ(0, fake_drm_->get_set_object_property_count());
+  }
+}
+
 TEST_P(HardwareDisplayPlaneManagerAtomicTest,
        CommitReturnsNullOutFenceIfOutFencePtrNotSupported) {
   scoped_refptr<ui::DrmFramebuffer> fake_buffer2 =