[go: nahoru, domu]

Replace vector<display::GammaRampRGBEntry> with display::GammaCurve

This should have no functional changes.

By using the display::GammaCurve::Sample function we can simplify
the code that sends the LUTs that are sent to DRM (resampling directly
in place and not having to special case the identity function unless
desired).

This will also allow us to transparently support parametric transfer
functions (which are often specified in display color profiles).

This will also allow us to be more intentional about the different
gamma curves that will be specified (those for a color profile
versus those for adjusting brightness as in the chromecast usage).

Bug: 1505062
Change-Id: I860e0e6988591d59c94728c54e3c492778aca966
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5057558
Reviewed-by: Ahmed Fakhry <afakhry@chromium.org>
Reviewed-by: danakj <danakj@chromium.org>
Commit-Queue: ccameron chromium <ccameron@chromium.org>
Reviewed-by: Sean Topping <seantopping@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1230474}
diff --git a/ash/display/display_color_manager.cc b/ash/display/display_color_manager.cc
index 6526fbf..561f5a31 100644
--- a/ash/display/display_color_manager.cc
+++ b/ash/display/display_color_manager.cc
@@ -63,11 +63,15 @@
       return nullptr;
     }
 
-    data->gamma_lut.resize(vcgt_channel_length);
-    for (size_t i = 0; i < vcgt_channel_length; ++i) {
-      data->gamma_lut[i].r = vcgt_data[i];
-      data->gamma_lut[i].g = vcgt_data[vcgt_channel_length + i];
-      data->gamma_lut[i].b = vcgt_data[(vcgt_channel_length * 2) + i];
+    {
+      std::vector<display::GammaRampRGBEntry> gamma_lut;
+      gamma_lut.resize(vcgt_channel_length);
+      for (size_t i = 0; i < vcgt_channel_length; ++i) {
+        gamma_lut[i].r = vcgt_data[i];
+        gamma_lut[i].g = vcgt_data[vcgt_channel_length + i];
+        gamma_lut[i].b = vcgt_data[(vcgt_channel_length * 2) + i];
+      }
+      data->gamma_curve = display::GammaCurve(gamma_lut);
     }
   } else {
     VLOG(1) << "Using full degamma/gamma/CTM from profile.";
@@ -121,18 +125,26 @@
     qcms_transform_get_output_trc_rgba(transform, display_profile,
                                        QCMS_TRC_USHORT, &gamma_data[0]);
 
-    data->degamma_lut.resize(degamma_size);
-    for (size_t i = 0; i < degamma_size; ++i) {
-      data->degamma_lut[i].r = degamma_data[i * 4];
-      data->degamma_lut[i].g = degamma_data[(i * 4) + 1];
-      data->degamma_lut[i].b = degamma_data[(i * 4) + 2];
+    {
+      std::vector<display::GammaRampRGBEntry> degamma_lut;
+      degamma_lut.resize(degamma_size);
+      for (size_t i = 0; i < degamma_size; ++i) {
+        degamma_lut[i].r = degamma_data[i * 4];
+        degamma_lut[i].g = degamma_data[(i * 4) + 1];
+        degamma_lut[i].b = degamma_data[(i * 4) + 2];
+      }
+      data->degamma_curve = display::GammaCurve(degamma_lut);
     }
 
-    data->gamma_lut.resize(gamma_size);
-    for (size_t i = 0; i < gamma_size; ++i) {
-      data->gamma_lut[i].r = gamma_data[i * 4];
-      data->gamma_lut[i].g = gamma_data[(i * 4) + 1];
-      data->gamma_lut[i].b = gamma_data[(i * 4) + 2];
+    {
+      std::vector<display::GammaRampRGBEntry> gamma_lut;
+      gamma_lut.resize(gamma_size);
+      for (size_t i = 0; i < gamma_size; ++i) {
+        gamma_lut[i].r = gamma_data[i * 4];
+        gamma_lut[i].g = gamma_data[(i * 4) + 1];
+        gamma_lut[i].b = gamma_data[(i * 4) + 2];
+      }
+      data->gamma_curve = display::GammaCurve(gamma_lut);
     }
 
     data->correction_matrix.resize(9);
@@ -329,8 +341,8 @@
   }
 
   if (!configurator_->SetGammaCorrection(display_id,
-                                         calibration_data.degamma_lut,
-                                         calibration_data.gamma_lut)) {
+                                         calibration_data.degamma_curve,
+                                         calibration_data.gamma_curve)) {
     LOG(WARNING) << "Error applying gamma correction data.";
   }
 }
diff --git a/ash/display/display_color_manager.h b/ash/display/display_color_manager.h
index e8a19ed..d53b300 100644
--- a/ash/display/display_color_manager.h
+++ b/ash/display/display_color_manager.h
@@ -19,6 +19,7 @@
 #include "third_party/skia/include/core/SkM44.h"
 #include "ui/display/display_observer.h"
 #include "ui/display/manager/display_configurator.h"
+#include "ui/display/types/display_color_management.h"
 #include "ui/display/types/display_constants.h"
 
 namespace base {
@@ -27,7 +28,6 @@
 
 namespace display {
 class DisplaySnapshot;
-struct GammaRampRGBEntry;
 }  // namespace display
 
 namespace ash {
@@ -89,8 +89,8 @@
     ColorCalibrationData();
     ~ColorCalibrationData();
 
-    std::vector<display::GammaRampRGBEntry> degamma_lut;
-    std::vector<display::GammaRampRGBEntry> gamma_lut;
+    display::GammaCurve degamma_curve;
+    display::GammaCurve gamma_curve;
     // Initialized to identity to reset color correction.
     std::vector<float> correction_matrix;
   };
diff --git a/chromecast/browser/cast_display_configurator.cc b/chromecast/browser/cast_display_configurator.cc
index a49c0bff..d284efd 100644
--- a/chromecast/browser/cast_display_configurator.cc
+++ b/chromecast/browser/cast_display_configurator.cc
@@ -176,12 +176,12 @@
 }
 
 void CastDisplayConfigurator::SetGammaCorrection(
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
+    const display::GammaCurve& degamma,
+    const display::GammaCurve& gamma) {
   if (!delegate_ || !display_)
     return;
 
-  delegate_->SetGammaCorrection(display_->display_id(), degamma_lut, gamma_lut);
+  delegate_->SetGammaCorrection(display_->display_id(), degamma, gamma);
   NotifyObservers();
 }
 
diff --git a/chromecast/browser/cast_display_configurator.h b/chromecast/browser/cast_display_configurator.h
index e9de1553..4d16e7cc 100644
--- a/chromecast/browser/cast_display_configurator.h
+++ b/chromecast/browser/cast_display_configurator.h
@@ -18,7 +18,7 @@
 namespace display {
 class DisplayMode;
 class DisplaySnapshot;
-struct GammaRampRGBEntry;
+class GammaCurve;
 }  // namespace display
 
 namespace gfx {
@@ -64,9 +64,8 @@
 
   void ConfigureDisplayFromCommandLine();
   void SetColorMatrix(const std::vector<float>& color_matrix);
-  void SetGammaCorrection(
-      const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut);
+  void SetGammaCorrection(const display::GammaCurve& degamma,
+                          const display::GammaCurve& gamma);
 
  private:
   void ForceInitialConfigure();
diff --git a/chromecast/ui/display_settings/gamma_configurator.cc b/chromecast/ui/display_settings/gamma_configurator.cc
index c69d0af..56781ea 100644
--- a/chromecast/ui/display_settings/gamma_configurator.cc
+++ b/chromecast/ui/display_settings/gamma_configurator.cc
@@ -59,9 +59,11 @@
 
 void GammaConfigurator::ApplyGammaLut() {
   if (is_inverted_)
-    display_configurator_->SetGammaCorrection({}, InvertGammaLut(gamma_lut_));
+    display_configurator_->SetGammaCorrection(
+        {}, display::GammaCurve(InvertGammaLut(gamma_lut_)));
   else
-    display_configurator_->SetGammaCorrection({}, gamma_lut_);
+    display_configurator_->SetGammaCorrection({},
+                                              display::GammaCurve(gamma_lut_));
 }
 
 void GammaConfigurator::SetColorInversion(bool invert) {
diff --git a/chromecast/ui/display_settings/gamma_configurator.h b/chromecast/ui/display_settings/gamma_configurator.h
index 0386250..d05d975d 100644
--- a/chromecast/ui/display_settings/gamma_configurator.h
+++ b/chromecast/ui/display_settings/gamma_configurator.h
@@ -7,7 +7,7 @@
 
 #include <vector>
 
-#include "ui/display/types/gamma_ramp_rgb_entry.h"
+#include "ui/display/types/display_color_management.h"
 
 namespace chromecast {
 
diff --git a/ui/display/manager/display_configurator.cc b/ui/display/manager/display_configurator.cc
index 35202de..425fff9 100644
--- a/ui/display/manager/display_configurator.cc
+++ b/ui/display/manager/display_configurator.cc
@@ -799,14 +799,13 @@
   return native_display_delegate_->SetColorMatrix(display_id, color_matrix);
 }
 
-bool DisplayConfigurator::SetGammaCorrection(
-    int64_t display_id,
-    const std::vector<GammaRampRGBEntry>& degamma_lut,
-    const std::vector<GammaRampRGBEntry>& gamma_lut) {
+bool DisplayConfigurator::SetGammaCorrection(int64_t display_id,
+                                             const GammaCurve& degamma,
+                                             const GammaCurve& gamma) {
   if (!IsDisplayIdInDisplayStateList(display_id, cached_displays_))
     return false;
-  return native_display_delegate_->SetGammaCorrection(display_id, degamma_lut,
-                                                      gamma_lut);
+  return native_display_delegate_->SetGammaCorrection(display_id, degamma,
+                                                      gamma);
 }
 
 void DisplayConfigurator::SetPrivacyScreen(int64_t display_id,
diff --git a/ui/display/manager/display_configurator.h b/ui/display/manager/display_configurator.h
index 32ce4de..2d4ce75 100644
--- a/ui/display/manager/display_configurator.h
+++ b/ui/display/manager/display_configurator.h
@@ -30,12 +30,11 @@
 class ContentProtectionManager;
 class DisplayMode;
 class DisplaySnapshot;
+class GammaCurve;
 class ManagedDisplayMode;
 class NativeDisplayDelegate;
 class UpdateDisplayConfigurationTask;
 
-struct GammaRampRGBEntry;
-
 namespace test {
 class DisplayManagerTestApi;
 }  // namespace test
@@ -274,8 +273,8 @@
   // Sets the given |gamma_lut| and |degamma_lut| on the display with
   // |display_id|.
   bool SetGammaCorrection(int64_t display_id,
-                          const std::vector<GammaRampRGBEntry>& degamma_lut,
-                          const std::vector<GammaRampRGBEntry>& gamma_lut);
+                          const GammaCurve& degamma,
+                          const GammaCurve& gamma);
 
   // Enable/disable the privacy screen on display with |display_id|.
   // For this to succeed, privacy screen must be supported by the display.
diff --git a/ui/display/manager/test/action_logger_util.cc b/ui/display/manager/test/action_logger_util.cc
index 82f60996..a733229 100644
--- a/ui/display/manager/test/action_logger_util.cc
+++ b/ui/display/manager/test/action_logger_util.cc
@@ -8,9 +8,9 @@
 
 #include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
+#include "ui/display/types/display_color_management.h"
 #include "ui/display/types/display_mode.h"
 #include "ui/display/types/display_snapshot.h"
-#include "ui/display/types/gamma_ramp_rgb_entry.h"
 #include "ui/display/types/native_display_delegate.h"
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/size.h"
@@ -51,26 +51,13 @@
                             ctm.c_str());
 }
 
-std::string SetGammaCorrectionAction(
-    int64_t display_id,
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
-  std::string degamma_table;
-  for (size_t i = 0; i < degamma_lut.size(); ++i) {
-    degamma_table += base::StringPrintf(",degamma[%" PRIuS "]=%04x%04x%04x", i,
-                                        degamma_lut[i].r, degamma_lut[i].g,
-                                        degamma_lut[i].b);
-  }
-  std::string gamma_table;
-  for (size_t i = 0; i < gamma_lut.size(); ++i) {
-    gamma_table +=
-        base::StringPrintf(",gamma[%" PRIuS "]=%04x%04x%04x", i, gamma_lut[i].r,
-                           gamma_lut[i].g, gamma_lut[i].b);
-  }
-
+std::string SetGammaCorrectionAction(int64_t display_id,
+                                     const display::GammaCurve& degamma,
+                                     const display::GammaCurve& gamma) {
   return base::StringPrintf("set_gamma_correction(id=%" PRId64 "%s%s)",
-                            display_id, degamma_table.c_str(),
-                            gamma_table.c_str());
+                            display_id,
+                            degamma.ToActionString("degamma").c_str(),
+                            gamma.ToActionString("gamma").c_str());
 }
 
 std::string SetPrivacyScreenAction(int64_t display_id, bool enabled) {
diff --git a/ui/display/manager/test/action_logger_util.h b/ui/display/manager/test/action_logger_util.h
index 3bddd6e..772ed68 100644
--- a/ui/display/manager/test/action_logger_util.h
+++ b/ui/display/manager/test/action_logger_util.h
@@ -15,7 +15,7 @@
 
 namespace display {
 
-struct GammaRampRGBEntry;
+class GammaCurve;
 struct DisplayConfigurationParams;
 
 namespace test {
@@ -51,10 +51,9 @@
 
 // Returns a string describing a TestNativeDisplayDelegate::SetGammaCorrection()
 // call.
-std::string SetGammaCorrectionAction(
-    int64_t display_id,
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut);
+std::string SetGammaCorrectionAction(int64_t display_id,
+                                     const display::GammaCurve& degamma,
+                                     const display::GammaCurve& gamma);
 
 // Returns a string describing a TestNativeDisplayDelegate::SetPrivacyScreen()
 // call.
diff --git a/ui/display/manager/test/fake_display_delegate.cc b/ui/display/manager/test/fake_display_delegate.cc
index 5eb8982..697411b 100644
--- a/ui/display/manager/test/fake_display_delegate.cc
+++ b/ui/display/manager/test/fake_display_delegate.cc
@@ -197,10 +197,9 @@
   return false;
 }
 
-bool FakeDisplayDelegate::SetGammaCorrection(
-    int64_t display_id,
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
+bool FakeDisplayDelegate::SetGammaCorrection(int64_t display_id,
+                                             const display::GammaCurve& degamma,
+                                             const display::GammaCurve& gamma) {
   return false;
 }
 
diff --git a/ui/display/manager/test/fake_display_delegate.h b/ui/display/manager/test/fake_display_delegate.h
index 909f7d8..7c9392c 100644
--- a/ui/display/manager/test/fake_display_delegate.h
+++ b/ui/display/manager/test/fake_display_delegate.h
@@ -100,10 +100,9 @@
                     SetHDCPStateCallback callback) override;
   bool SetColorMatrix(int64_t display_id,
                       const std::vector<float>& color_matrix) override;
-  bool SetGammaCorrection(
-      int64_t display_id,
-      const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut) override;
+  bool SetGammaCorrection(int64_t display_id,
+                          const display::GammaCurve& degamma,
+                          const display::GammaCurve& gamma) override;
   void SetPrivacyScreen(int64_t display_id,
                         bool enabled,
                         SetPrivacyScreenCallback callback) override;
diff --git a/ui/display/manager/test/test_native_display_delegate.cc b/ui/display/manager/test/test_native_display_delegate.cc
index 62399c4c..70120e7 100644
--- a/ui/display/manager/test/test_native_display_delegate.cc
+++ b/ui/display/manager/test/test_native_display_delegate.cc
@@ -229,10 +229,9 @@
 
 bool TestNativeDisplayDelegate::SetGammaCorrection(
     int64_t display_id,
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
-  log_->AppendAction(
-      SetGammaCorrectionAction(display_id, degamma_lut, gamma_lut));
+    const display::GammaCurve& degamma,
+    const display::GammaCurve& gamma) {
+  log_->AppendAction(SetGammaCorrectionAction(display_id, degamma, gamma));
   return true;
 }
 
diff --git a/ui/display/manager/test/test_native_display_delegate.h b/ui/display/manager/test/test_native_display_delegate.h
index 6750f3b6..63cc243 100644
--- a/ui/display/manager/test/test_native_display_delegate.h
+++ b/ui/display/manager/test/test_native_display_delegate.h
@@ -96,10 +96,9 @@
                     SetHDCPStateCallback callback) override;
   bool SetColorMatrix(int64_t display_id,
                       const std::vector<float>& color_matrix) override;
-  bool SetGammaCorrection(
-      int64_t display_id,
-      const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut) override;
+  bool SetGammaCorrection(int64_t display_id,
+                          const display::GammaCurve& degamma,
+                          const display::GammaCurve& gamma) override;
   void SetPrivacyScreen(int64_t display_id,
                         bool enabled,
                         SetPrivacyScreenCallback callback) override;
diff --git a/ui/display/types/native_display_delegate.h b/ui/display/types/native_display_delegate.h
index 0b669c7..9ad022e 100644
--- a/ui/display/types/native_display_delegate.h
+++ b/ui/display/types/native_display_delegate.h
@@ -17,9 +17,9 @@
 
 namespace display {
 class DisplaySnapshot;
+class GammaCurve;
 class NativeDisplayObserver;
 
-struct GammaRampRGBEntry;
 struct DisplayConfigurationParams;
 
 using GetDisplaysCallback =
@@ -87,10 +87,9 @@
   // Sets the given |gamma_lut| and |degamma_lut| on the display with
   // |display_id|. Returns true if the given tables were sent to the GPU process
   // successfully.
-  virtual bool SetGammaCorrection(
-      int64_t display_id,
-      const std::vector<GammaRampRGBEntry>& degamma_lut,
-      const std::vector<GammaRampRGBEntry>& gamma_lut) = 0;
+  virtual bool SetGammaCorrection(int64_t display_id,
+                                  const GammaCurve& degamma,
+                                  const GammaCurve& gamma) = 0;
 
   // Sets the privacy screen state on the display with |display_id|.
   virtual void SetPrivacyScreen(int64_t display_id,
diff --git a/ui/ozone/platform/drm/common/drm_wrapper.cc b/ui/ozone/platform/drm/common/drm_wrapper.cc
index 5673fa3e..6e8c3f4 100644
--- a/ui/ozone/platform/drm/common/drm_wrapper.cc
+++ b/ui/ozone/platform/drm/common/drm_wrapper.cc
@@ -17,7 +17,7 @@
 #include "base/trace_event/trace_event.h"
 #include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
 #include "third_party/skia/include/core/SkImageInfo.h"
-#include "ui/display/types/gamma_ramp_rgb_entry.h"
+#include "ui/display/types/display_color_management.h"
 #include "ui/ozone/platform/drm/common/drm_util.h"
 
 namespace ui {
@@ -293,13 +293,12 @@
  * Gamma
  *******/
 
-bool DrmWrapper::SetGammaRamp(
-    uint32_t crtc_id,
-    const std::vector<display::GammaRampRGBEntry>& lut) {
+bool DrmWrapper::SetGammaRamp(uint32_t crtc_id,
+                              const display::GammaCurve& curve) {
   ScopedDrmCrtcPtr crtc = GetCrtc(crtc_id);
   size_t gamma_size = static_cast<size_t>(crtc->gamma_size);
 
-  if (gamma_size == 0 && lut.empty()) {
+  if (gamma_size == 0 && curve.IsDefaultIdentity()) {
     return true;
   }
 
@@ -308,33 +307,12 @@
     return false;
   }
 
-  // TODO(robert.bradford) resample the incoming ramp to match what the kernel
-  // expects.
-  if (!lut.empty() && gamma_size != lut.size()) {
-    LOG(ERROR) << "Gamma table size mismatch: supplied " << lut.size()
-               << " expected " << gamma_size;
-    return false;
-  }
-
   std::vector<uint16_t> r, g, b;
-  r.reserve(gamma_size);
-  g.reserve(gamma_size);
-  b.reserve(gamma_size);
-
-  if (lut.empty()) {
-    // Create a linear gamma ramp table to deactivate the feature.
-    for (size_t i = 0; i < gamma_size; ++i) {
-      uint16_t value = (i * ((1 << 16) - 1)) / (gamma_size - 1);
-      r.push_back(value);
-      g.push_back(value);
-      b.push_back(value);
-    }
-  } else {
-    for (size_t i = 0; i < gamma_size; ++i) {
-      r.push_back(lut[i].r);
-      g.push_back(lut[i].g);
-      b.push_back(lut[i].b);
-    }
+  r.resize(gamma_size);
+  g.resize(gamma_size);
+  b.resize(gamma_size);
+  for (size_t i = 0; i < gamma_size; ++i) {
+    curve.Evaluate(i / (gamma_size - 1.f), r[i], g[i], b[i]);
   }
 
   DCHECK(drm_fd_.is_valid());
diff --git a/ui/ozone/platform/drm/common/drm_wrapper.h b/ui/ozone/platform/drm/common/drm_wrapper.h
index 723b787..1a1c1c0 100644
--- a/ui/ozone/platform/drm/common/drm_wrapper.h
+++ b/ui/ozone/platform/drm/common/drm_wrapper.h
@@ -27,7 +27,7 @@
 struct SkImageInfo;
 
 namespace display {
-struct GammaRampRGBEntry;
+class GammaCurve;
 }  // namespace display
 
 namespace ui {
@@ -181,8 +181,7 @@
    * Gamma
    *******/
 
-  virtual bool SetGammaRamp(uint32_t crtc_id,
-                            const std::vector<display::GammaRampRGBEntry>& lut);
+  virtual bool SetGammaRamp(uint32_t crtc_id, const display::GammaCurve& lut);
 
   /********
    * Planes
diff --git a/ui/ozone/platform/drm/gpu/drm_display.cc b/ui/ozone/platform/drm/gpu/drm_display.cc
index 2920003..e8ac17b 100644
--- a/ui/ozone/platform/drm/gpu/drm_display.cc
+++ b/ui/ozone/platform/drm/gpu/drm_display.cc
@@ -13,8 +13,8 @@
 #include "base/trace_event/trace_event.h"
 #include "build/chromeos_buildflags.h"
 #include "ui/display/display_features.h"
+#include "ui/display/types/display_color_management.h"
 #include "ui/display/types/display_snapshot.h"
-#include "ui/display/types/gamma_ramp_rgb_entry.h"
 #include "ui/gfx/color_space.h"
 #include "ui/ozone/platform/drm/common/drm_util.h"
 #include "ui/ozone/platform/drm/gpu/drm_device.h"
@@ -322,18 +322,19 @@
   drm_->plane_manager()->SetBackgroundColor(crtc_, background_color);
 }
 
-void DrmDisplay::SetGammaCorrection(
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
-  // When both |degamma_lut| and |gamma_lut| are empty they are interpreted as
+void DrmDisplay::SetGammaCorrection(const display::GammaCurve& degamma,
+                                    const display::GammaCurve& gamma) {
+  // When both |degamma| and |gamma| are empty they are interpreted as
   // "linear/pass-thru" [1]. If the display |is_hdr_capable_| we have to make
   // sure the |current_color_space_| is considered properly.
   // [1]
   // https://www.kernel.org/doc/html/v4.19/gpu/drm-kms.html#color-management-properties
-  if (degamma_lut.empty() && gamma_lut.empty() && is_hdr_capable_)
+  if (degamma.IsDefaultIdentity() && gamma.IsDefaultIdentity() &&
+      is_hdr_capable_) {
     SetColorSpace(current_color_space_);
-  else
-    CommitGammaCorrection(degamma_lut, gamma_lut);
+  } else {
+    CommitGammaCorrection(degamma, gamma);
+  }
 }
 
 bool DrmDisplay::SetPrivacyScreen(bool enabled) {
@@ -460,10 +461,8 @@
   // is interpreted as "linear/pass-thru", see [1]. However when we have an SDR
   // |color_space|, we need to write a scaled down |gamma| function to prevent
   // the mode change brightness to be visible.
-  std::vector<display::GammaRampRGBEntry> degamma;
-  std::vector<display::GammaRampRGBEntry> gamma;
   if (current_color_space_.IsHDR())
-    return CommitGammaCorrection(degamma, gamma);
+    return CommitGammaCorrection({}, {});
 
   // TODO(mcasas) This should be the inverse value of DisplayChangeObservers's
   // FillDisplayColorSpaces's kHDRLevel, move to a common place.
@@ -474,15 +473,17 @@
   // Only using kSDRLevel of the available values shifts the contrast ratio, we
   // restore it via a smaller local gamma correction using this exponent.
   constexpr float kExponent = 1.2;
-  FillPowerFunctionValues(&gamma, kNumGammaSamples, kSDRLevel, kExponent);
-  CommitGammaCorrection(degamma, gamma);
+  std::vector<display::GammaRampRGBEntry> gamma_entries;
+  FillPowerFunctionValues(&gamma_entries, kNumGammaSamples, kSDRLevel,
+                          kExponent);
+  CommitGammaCorrection({}, display::GammaCurve(gamma_entries));
 }
 
-void DrmDisplay::CommitGammaCorrection(
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
-  if (!drm_->plane_manager()->SetGammaCorrection(crtc_, degamma_lut, gamma_lut))
+void DrmDisplay::CommitGammaCorrection(const display::GammaCurve& degamma,
+                                       const display::GammaCurve& gamma) {
+  if (!drm_->plane_manager()->SetGammaCorrection(crtc_, degamma, gamma)) {
     LOG(ERROR) << "Failed to set gamma tables for display: crtc_id = " << crtc_;
+  }
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/drm_display.h b/ui/ozone/platform/drm/gpu/drm_display.h
index bc895fad..ff5798a 100644
--- a/ui/ozone/platform/drm/gpu/drm_display.h
+++ b/ui/ozone/platform/drm/gpu/drm_display.h
@@ -22,7 +22,7 @@
 
 namespace display {
 class DisplaySnapshot;
-struct GammaRampRGBEntry;
+class GammaCurve;
 }  // namespace display
 
 namespace ui {
@@ -87,9 +87,8 @@
                     display::ContentProtectionMethod protection_method);
   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);
+  void SetGammaCorrection(const display::GammaCurve& degamma,
+                          const display::GammaCurve& gamma);
   bool SetPrivacyScreen(bool enabled);
   bool SetHdrOutputMetadata(const gfx::ColorSpace color_space);
   bool SetColorspaceProperty(const gfx::ColorSpace color_space);
@@ -98,9 +97,8 @@
   void set_is_hdr_capable_for_testing(bool value) { is_hdr_capable_ = value; }
 
  private:
-  void CommitGammaCorrection(
-      const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut);
+  void CommitGammaCorrection(const display::GammaCurve& degamma,
+                             const display::GammaCurve& gamma);
   gfx::HDRStaticMetadata::Eotf GetEotf(
       const gfx::ColorSpace::TransferID transfer_id);
 
diff --git a/ui/ozone/platform/drm/gpu/drm_display_unittest.cc b/ui/ozone/platform/drm/gpu/drm_display_unittest.cc
index e93ddf2..f03679a1 100644
--- a/ui/ozone/platform/drm/gpu/drm_display_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/drm_display_unittest.cc
@@ -10,6 +10,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/manager/test/fake_display_snapshot.h"
+#include "ui/display/types/display_color_management.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/linux/test/mock_gbm_device.h"
 #include "ui/ozone/platform/drm/common/drm_util.h"
@@ -62,19 +63,27 @@
 // Verifies that the argument goes from 0 to the maximum uint16_t times |scale|
 // following a power function with |exponent|.
 MATCHER_P2(MatchesPowerFunction, scale, exponent, "") {
-  EXPECT_FALSE(arg.empty());
+  EXPECT_FALSE(arg.IsDefaultIdentity());
 
-  const uint16_t max_value = std::numeric_limits<uint16_t>::max() * scale;
+  const uint16_t kMaxValue = std::numeric_limits<uint16_t>::max() * scale;
+  const uint16_t kEpsilon = std::numeric_limits<uint16_t>::max() * 0.02f;
 
-  float i = 1.0;
-  for (const auto rgb_value : arg) {
-    const uint16_t expected_value = max_value * pow(i / arg.size(), exponent);
-    i++;
-    EXPECT_NEAR(rgb_value.r, expected_value, 1.0);
-    EXPECT_NEAR(rgb_value.g, expected_value, 1.0);
-    EXPECT_NEAR(rgb_value.b, expected_value, 1.0);
+  const size_t kSize = 10;
+  for (size_t i = 0; i < kSize; ++i) {
+    float x = i / (kSize - 1.f);
+    uint16_t r, g, b;
+    arg.Evaluate(x, r, g, b);
+
+    const uint16_t expected_value = kMaxValue * pow(x, exponent);
+    EXPECT_NEAR(r, expected_value, kEpsilon);
+    EXPECT_NEAR(g, expected_value, kEpsilon);
+    EXPECT_NEAR(b, expected_value, kEpsilon);
   }
+  return true;
+}
 
+MATCHER(IsDefaultIdentity, "") {
+  EXPECT_TRUE(arg.IsDefaultIdentity());
   return true;
 }
 
@@ -87,8 +96,8 @@
   MOCK_METHOD(bool,
               SetGammaCorrection,
               (uint32_t crtc_id,
-               const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-               const std::vector<display::GammaRampRGBEntry>& gamma_lut),
+               const display::GammaCurve& degamma,
+               const display::GammaCurve& gamma),
               (override));
 
   bool Commit(CommitRequest commit_request, uint32_t flags) override {
@@ -181,18 +190,19 @@
   MockHardwareDisplayPlaneManager* plane_manager =
       AddMockHardwareDisplayPlaneManager();
 
-  ON_CALL(*plane_manager, SetGammaCorrection(_, SizeIs(0), _))
+  ON_CALL(*plane_manager, SetGammaCorrection(_, IsDefaultIdentity(), _))
       .WillByDefault(::testing::Return(true));
 
   const auto kHDRColorSpace = gfx::ColorSpace::CreateHDR10();
-  EXPECT_CALL(*plane_manager, SetGammaCorrection(_, SizeIs(0), SizeIs(0)));
+  EXPECT_CALL(*plane_manager,
+              SetGammaCorrection(_, IsDefaultIdentity(), IsDefaultIdentity()));
   drm_display_->SetColorSpace(kHDRColorSpace);
 
   const auto kSDRColorSpace = gfx::ColorSpace::CreateREC709();
   constexpr float kSDRLevel = 0.85;
   constexpr float kExponent = 1.2;
   EXPECT_CALL(*plane_manager,
-              SetGammaCorrection(_, SizeIs(0),
+              SetGammaCorrection(_, IsDefaultIdentity(),
                                  MatchesPowerFunction(kSDRLevel, kExponent)));
   drm_display_->SetColorSpace(kSDRColorSpace);
 }
@@ -204,9 +214,9 @@
   ON_CALL(*plane_manager, SetGammaCorrection(_, _, _))
       .WillByDefault(::testing::Return(true));
 
-  EXPECT_CALL(*plane_manager, SetGammaCorrection(_, SizeIs(0), SizeIs(0)));
-  drm_display_->SetGammaCorrection(std::vector<display::GammaRampRGBEntry>(),
-                                   std::vector<display::GammaRampRGBEntry>());
+  EXPECT_CALL(*plane_manager,
+              SetGammaCorrection(_, IsDefaultIdentity(), IsDefaultIdentity()));
+  drm_display_->SetGammaCorrection({}, {});
 }
 
 TEST_F(DrmDisplayTest, SetEmptyGammaCorrectionHDRDisplay) {
@@ -220,10 +230,9 @@
   constexpr float kSDRLevel = 0.85;
   constexpr float kExponent = 1.2;
   EXPECT_CALL(*plane_manager,
-              SetGammaCorrection(_, SizeIs(0),
+              SetGammaCorrection(_, IsDefaultIdentity(),
                                  MatchesPowerFunction(kSDRLevel, kExponent)));
-  drm_display_->SetGammaCorrection(std::vector<display::GammaRampRGBEntry>(),
-                                   std::vector<display::GammaRampRGBEntry>());
+  drm_display_->SetGammaCorrection({}, {});
 }
 
 }  // namespace ui
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 3662aaf..3eefa83 100644
--- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
+++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
@@ -432,14 +432,14 @@
 
 void DrmGpuDisplayManager::SetGammaCorrection(
     int64_t display_id,
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
+    const display::GammaCurve& degamma,
+    const display::GammaCurve& gamma) {
   DrmDisplay* display = FindDisplay(display_id);
   if (!display) {
     LOG(WARNING) << __func__ << ": there is no display with ID " << display_id;
     return;
   }
-  display->SetGammaCorrection(degamma_lut, gamma_lut);
+  display->SetGammaCorrection(degamma, gamma);
 }
 
 bool DrmGpuDisplayManager::SetPrivacyScreen(int64_t display_id, bool enabled) {
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 bf7eb491..4a47222 100644
--- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
+++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
@@ -18,7 +18,7 @@
 using drmModeModeInfo = struct _drmModeModeInfo;
 
 namespace display {
-struct GammaRampRGBEntry;
+class GammaCurve;
 }  // namespace display
 
 namespace gfx {
@@ -71,10 +71,9 @@
   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,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut);
+  void SetGammaCorrection(int64_t display_id,
+                          const display::GammaCurve& degamma,
+                          const display::GammaCurve& gamma);
   bool SetPrivacyScreen(int64_t display_id, bool enabled);
 
   void SetColorSpace(int64_t crtc_id, const gfx::ColorSpace& color_space);
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_util.cc b/ui/ozone/platform/drm/gpu/drm_gpu_util.cc
index 9cf6e8f..e7516ea1 100644
--- a/ui/ozone/platform/drm/gpu/drm_gpu_util.cc
+++ b/ui/ozone/platform/drm/gpu/drm_gpu_util.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/trace_event/trace_event.h"
 #include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
+#include "ui/display/types/display_color_management.h"
 #include "ui/display/types/gamma_ramp_rgb_entry.h"
 
 namespace ui {
@@ -51,19 +52,20 @@
   return true;
 }
 
-ScopedDrmColorLutPtr CreateLutBlob(
-    const std::vector<display::GammaRampRGBEntry>& source) {
+ScopedDrmColorLutPtr CreateLutBlob(const display::GammaCurve& source,
+                                   size_t size) {
   TRACE_EVENT0("drm", "CreateLutBlob");
-  if (source.empty())
+  if (source.IsDefaultIdentity()) {
     return nullptr;
+  }
 
-  ScopedDrmColorLutPtr lut(static_cast<drm_color_lut*>(
-      malloc(sizeof(drm_color_lut) * source.size())));
+  ScopedDrmColorLutPtr lut(
+      static_cast<drm_color_lut*>(malloc(sizeof(drm_color_lut) * size)));
   drm_color_lut* p = lut.get();
-  for (size_t i = 0; i < source.size(); ++i) {
-    p[i].red = source[i].r;
-    p[i].green = source[i].g;
-    p[i].blue = source[i].b;
+  for (size_t i = 0; i < size; ++i) {
+    // Be robust to `size` being 1, since some tests do this.
+    source.Evaluate(i / std::max(size - 1.f, 1.f), p[i].red, p[i].green,
+                    p[i].blue);
   }
   return lut;
 }
@@ -115,40 +117,6 @@
   return dmg_rect;
 }
 
-std::vector<display::GammaRampRGBEntry> ResampleLut(
-    const std::vector<display::GammaRampRGBEntry>& lut_in,
-    size_t desired_size) {
-  TRACE_EVENT1("drm", "ResampleLut", "desired_size", desired_size);
-  if (lut_in.empty())
-    return std::vector<display::GammaRampRGBEntry>();
-
-  if (lut_in.size() == desired_size)
-    return lut_in;
-
-  std::vector<display::GammaRampRGBEntry> result;
-  result.resize(desired_size);
-
-  for (size_t i = 0; i < desired_size; ++i) {
-    size_t base_index = lut_in.size() * i / desired_size;
-    size_t remaining = lut_in.size() * i % desired_size;
-    if (base_index < lut_in.size() - 1) {
-      result[i].r = lut_in[base_index].r +
-                    (lut_in[base_index + 1].r - lut_in[base_index].r) *
-                        remaining / desired_size;
-      result[i].g = lut_in[base_index].g +
-                    (lut_in[base_index + 1].g - lut_in[base_index].g) *
-                        remaining / desired_size;
-      result[i].b = lut_in[base_index].b +
-                    (lut_in[base_index + 1].b - lut_in[base_index].b) *
-                        remaining / desired_size;
-    } else {
-      result[i] = lut_in.back();
-    }
-  }
-
-  return result;
-}
-
 HardwareDisplayControllerInfoList GetDisplayInfosAndUpdateCrtcs(
     DrmWrapper& drm) {
   auto [displays, invalid_crtcs] = GetDisplayInfosAndInvalidCrtcs(drm);
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_util.h b/ui/ozone/platform/drm/gpu/drm_gpu_util.h
index 0cd903f..4ee764f 100644
--- a/ui/ozone/platform/drm/gpu/drm_gpu_util.h
+++ b/ui/ozone/platform/drm/gpu/drm_gpu_util.h
@@ -24,9 +24,9 @@
                         uint32_t object_id,
                         const DrmWrapper::Property& property);
 
-// Transforms the gamma ramp entries into the drm_color_lut format.
-ScopedDrmColorLutPtr CreateLutBlob(
-    const std::vector<display::GammaRampRGBEntry>& source);
+// Transforms the gamma curve into the drm_color_lut format with `size` entries.
+ScopedDrmColorLutPtr CreateLutBlob(const display::GammaCurve& source,
+                                   size_t size);
 
 // Converts |color_matrix| to a drm_color_ctm in U31.32 format where the most
 // significant bit is the sign.
@@ -36,12 +36,6 @@
 // Creates a FB Damage Clip Blob
 ScopedDrmModeRectPtr CreateDCBlob(const gfx::Rect& rect);
 
-// Creates a new look-up table of the desired size to fit the expectations of
-// the DRM driver.
-std::vector<display::GammaRampRGBEntry> ResampleLut(
-    const std::vector<display::GammaRampRGBEntry>& lut_in,
-    size_t desired_size);
-
 // Returns the display infos parsed in
 // |GetDisplayInfosAndInvalidCrtcs| and disables the invalid CRTCs
 // that weren't picked as preferred CRTCs.
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.cc b/ui/ozone/platform/drm/gpu/drm_thread.cc
index 2348af2..0647c0d 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -471,12 +471,11 @@
   display_manager_->SetColorMatrix(display_id, color_matrix);
 }
 
-void DrmThread::SetGammaCorrection(
-    int64_t display_id,
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
+void DrmThread::SetGammaCorrection(int64_t display_id,
+                                   const display::GammaCurve& degamma,
+                                   const display::GammaCurve& gamma) {
   TRACE_EVENT0("drm", "DrmThread::SetGammaCorrection");
-  display_manager_->SetGammaCorrection(display_id, degamma_lut, gamma_lut);
+  display_manager_->SetGammaCorrection(display_id, degamma, gamma);
 }
 
 void DrmThread::SetPrivacyScreen(int64_t display_id,
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.h b/ui/ozone/platform/drm/gpu/drm_thread.h
index f104ff4c..df06e8ab 100644
--- a/ui/ozone/platform/drm/gpu/drm_thread.h
+++ b/ui/ozone/platform/drm/gpu/drm_thread.h
@@ -34,7 +34,7 @@
 }  // namespace base
 
 namespace display {
-struct GammaRampRGBEntry;
+class GammaCurve;
 }  // namespace display
 
 namespace gfx {
@@ -182,10 +182,9 @@
                     base::OnceCallback<void(int64_t, bool)> callback) override;
   void SetColorMatrix(int64_t display_id,
                       const std::vector<float>& color_matrix) override;
-  void SetGammaCorrection(
-      int64_t display_id,
-      const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut) override;
+  void SetGammaCorrection(int64_t display_id,
+                          const display::GammaCurve& degamma,
+                          const display::GammaCurve& gamma) override;
   void SetPrivacyScreen(int64_t display_id,
                         bool enabled,
                         base::OnceCallback<void(bool)> callback) override;
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 7003dc2..e23d42a 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
@@ -15,6 +15,7 @@
 #include "base/logging.h"
 #include "base/ranges/algorithm.h"
 #include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
+#include "ui/display/types/display_color_management.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/ozone/platform/drm/common/drm_util.h"
@@ -333,8 +334,8 @@
 
 bool HardwareDisplayPlaneManager::SetGammaCorrection(
     uint32_t crtc_id,
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
+    const display::GammaCurve& degamma_curve,
+    const display::GammaCurve& gamma_curve) {
   const auto crtc_index = LookupCrtcIndex(crtc_id);
   if (!crtc_index) {
     LOG(ERROR) << "Unknown CRTC ID=" << crtc_id;
@@ -344,23 +345,25 @@
   CrtcState* crtc_state = &crtc_state_[*crtc_index];
   CrtcProperties* crtc_props = &crtc_state->properties;
 
-  if (!degamma_lut.empty() &&
-      (!crtc_props->degamma_lut.id || !crtc_props->degamma_lut_size.id))
+  if (!degamma_curve.IsDefaultIdentity() &&
+      (!crtc_props->degamma_lut.id || !crtc_props->degamma_lut_size.id)) {
     return false;
+  }
 
   if (!crtc_props->gamma_lut.id || !crtc_props->gamma_lut_size.id) {
-    if (degamma_lut.empty())
-      return drm_->SetGammaRamp(crtc_id, gamma_lut);
+    if (degamma_curve.IsDefaultIdentity()) {
+      return drm_->SetGammaRamp(crtc_id, gamma_curve);
+    }
 
     // We're missing either degamma or gamma lut properties. We shouldn't try to
     // set just one of them.
     return false;
   }
 
-  ScopedDrmColorLutPtr degamma_blob_data = CreateLutBlob(
-      ResampleLut(degamma_lut, crtc_props->degamma_lut_size.value));
+  ScopedDrmColorLutPtr degamma_blob_data =
+      CreateLutBlob(degamma_curve, crtc_props->degamma_lut_size.value);
   ScopedDrmColorLutPtr gamma_blob_data =
-      CreateLutBlob(ResampleLut(gamma_lut, crtc_props->gamma_lut_size.value));
+      CreateLutBlob(gamma_curve, crtc_props->gamma_lut_size.value);
 
   if (degamma_blob_data) {
     crtc_state->degamma_lut_blob = drm_->CreatePropertyBlob(
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 92c349e..c934e676 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
+++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
@@ -141,10 +141,9 @@
   void SetBackgroundColor(uint32_t crtc_id, const uint64_t background_color);
 
   // Sets the degamma/gamma luts on the CRTC object with ID |crtc_id|.
-  virtual bool SetGammaCorrection(
-      uint32_t crtc_id,
-      const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut);
+  virtual bool SetGammaCorrection(uint32_t crtc_id,
+                                  const display::GammaCurve& degamma,
+                                  const display::GammaCurve& gamma);
 
   // Assign hardware planes from the |planes_| list to |overlay_list| entries,
   // recording the plane IDs in the |plane_list|. Only planes compatible with
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 3b7723b9..35155d9 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
@@ -18,7 +18,7 @@
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/types/gamma_ramp_rgb_entry.h"
+#include "ui/display/types/display_color_management.h"
 #include "ui/gfx/gpu_fence.h"
 #include "ui/gfx/gpu_fence_handle.h"
 #include "ui/gfx/linux/gbm_buffer.h"
@@ -37,6 +37,11 @@
 
 namespace {
 
+// TODO(https://crbug.com/1505062): These tests should not use a single-point
+// curve as the non-empty value (it is arguably not a valid input).
+const display::GammaCurve kNonemptyGammaCurve({{0, 0, 0}});
+const display::GammaCurve kEmptyGammaCurve;
+
 const gfx::Size kDefaultBufferSize(2, 2);
 // Create a basic mode for a 6x4 screen.
 drmModeModeInfo kDefaultMode = {.hdisplay = 6, .vdisplay = 4};
@@ -1095,7 +1100,7 @@
   fake_drm_->InitializeState(drm_state, use_atomic_);
 
   EXPECT_FALSE(fake_drm_->plane_manager()->SetGammaCorrection(
-      fake_drm_->crtc_property(0).id, {{0, 0, 0}}, {}));
+      fake_drm_->crtc_property(0).id, kNonemptyGammaCurve, kEmptyGammaCurve));
   if (use_atomic_) {
     HardwareDisplayPlaneList state;
     PerformPageFlip(/*crtc_idx=*/0, &state);
@@ -1110,7 +1115,7 @@
   fake_drm_->InitializeState(drm_state, use_atomic_);
 
   EXPECT_FALSE(fake_drm_->plane_manager()->SetGammaCorrection(
-      fake_drm_->crtc_property(0).id, {{0, 0, 0}}, {}));
+      fake_drm_->crtc_property(0).id, kNonemptyGammaCurve, kEmptyGammaCurve));
   if (use_atomic_) {
     HardwareDisplayPlaneList state;
     PerformPageFlip(/*crtc_idx=*/0, &state);
@@ -1129,7 +1134,7 @@
   fake_drm_->InitializeState(drm_state, use_atomic_);
 
   EXPECT_FALSE(fake_drm_->plane_manager()->SetGammaCorrection(
-      fake_drm_->crtc_property(0).id, {}, {{0, 0, 0}}));
+      fake_drm_->crtc_property(0).id, kEmptyGammaCurve, kNonemptyGammaCurve));
   if (use_atomic_) {
     HardwareDisplayPlaneList state;
     PerformPageFlip(/*crtc_idx=*/0, &state);
@@ -1145,7 +1150,7 @@
   fake_drm_->InitializeState(drm_state, use_atomic_);
 
   EXPECT_FALSE(fake_drm_->plane_manager()->SetGammaCorrection(
-      fake_drm_->crtc_property(0).id, {}, {{0, 0, 0}}));
+      fake_drm_->crtc_property(0).id, kEmptyGammaCurve, kNonemptyGammaCurve));
   if (use_atomic_) {
     HardwareDisplayPlaneList state;
     PerformPageFlip(/*crtc_idx=*/0, &state);
@@ -1163,14 +1168,14 @@
 
   fake_drm_->set_legacy_gamma_ramp_expectation(true);
   EXPECT_TRUE(fake_drm_->plane_manager()->SetGammaCorrection(
-      fake_drm_->crtc_property(0).id, {}, {{0, 0, 0}}));
+      fake_drm_->crtc_property(0).id, kEmptyGammaCurve, kNonemptyGammaCurve));
   EXPECT_EQ(1, fake_drm_->get_set_gamma_ramp_count());
   EXPECT_EQ(0, fake_drm_->get_commit_count());
   EXPECT_EQ(0, fake_drm_->get_set_object_property_count());
 
   // Ensure disabling gamma also works on legacy.
   EXPECT_TRUE(fake_drm_->plane_manager()->SetGammaCorrection(
-      fake_drm_->crtc_property(0).id, {}, {}));
+      fake_drm_->crtc_property(0).id, kEmptyGammaCurve, kEmptyGammaCurve));
   EXPECT_EQ(2, fake_drm_->get_set_gamma_ramp_count());
   EXPECT_EQ(0, fake_drm_->get_commit_count());
   EXPECT_EQ(0, fake_drm_->get_set_object_property_count());
@@ -1184,7 +1189,7 @@
   fake_drm_->InitializeState(drm_state, use_atomic_);
 
   EXPECT_FALSE(fake_drm_->plane_manager()->SetGammaCorrection(
-      fake_drm_->crtc_property(0).id, {{0, 0, 0}}, {}));
+      fake_drm_->crtc_property(0).id, kNonemptyGammaCurve, kEmptyGammaCurve));
   EXPECT_EQ(0, fake_drm_->get_commit_count());
 
   drm_state.crtc_properties[0].properties.push_back(
@@ -1217,7 +1222,8 @@
   }
 
   EXPECT_TRUE(fake_drm_->plane_manager()->SetGammaCorrection(
-      fake_drm_->crtc_property(0).id, {{0, 0, 0}}, {{0, 0, 0}}));
+      fake_drm_->crtc_property(0).id, kNonemptyGammaCurve,
+      kNonemptyGammaCurve));
   if (use_atomic_) {
     PerformPageFlip(/*crtc_idx=*/0, &state);
 #if defined(COMMIT_PROPERTIES_ON_PAGE_FLIP)
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.cc b/ui/ozone/platform/drm/gpu/mock_drm_device.cc
index 21bba1c..c8e88f8b 100644
--- a/ui/ozone/platform/drm/gpu/mock_drm_device.cc
+++ b/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -897,9 +897,8 @@
   return true;
 }
 
-bool MockDrmDevice::SetGammaRamp(
-    uint32_t crtc_id,
-    const std::vector<display::GammaRampRGBEntry>& lut) {
+bool MockDrmDevice::SetGammaRamp(uint32_t crtc_id,
+                                 const display::GammaCurve& curve) {
   set_gamma_ramp_count_++;
   return legacy_gamma_ramp_expectation_;
 }
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.h b/ui/ozone/platform/drm/gpu/mock_drm_device.h
index 513e936e..f13bbd5 100644
--- a/ui/ozone/platform/drm/gpu/mock_drm_device.h
+++ b/ui/ozone/platform/drm/gpu/mock_drm_device.h
@@ -341,9 +341,8 @@
   bool MapDumbBuffer(uint32_t handle, size_t size, void** pixels) override;
   bool UnmapDumbBuffer(void* pixels, size_t size) override;
   bool CloseBufferHandle(uint32_t handle) override;
-  bool SetGammaRamp(
-      uint32_t crtc_id,
-      const std::vector<display::GammaRampRGBEntry>& lut) override;
+  bool SetGammaRamp(uint32_t crtc_id,
+                    const display::GammaCurve& curve) override;
   bool SetCapability(uint64_t capability, uint64_t value) override;
   absl::optional<std::string> GetDriverName() const override;
   void SetDriverName(absl::optional<std::string> name);
diff --git a/ui/ozone/platform/drm/host/drm_display_host.cc b/ui/ozone/platform/drm/host/drm_display_host.cc
index 32297bac..f21d22e 100644
--- a/ui/ozone/platform/drm/host/drm_display_host.cc
+++ b/ui/ozone/platform/drm/host/drm_display_host.cc
@@ -105,11 +105,9 @@
   sender_->GpuSetColorMatrix(snapshot_->display_id(), color_matrix);
 }
 
-void DrmDisplayHost::SetGammaCorrection(
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
-  sender_->GpuSetGammaCorrection(snapshot_->display_id(), degamma_lut,
-                                 gamma_lut);
+void DrmDisplayHost::SetGammaCorrection(const display::GammaCurve& degamma,
+                                        const display::GammaCurve& gamma) {
+  sender_->GpuSetGammaCorrection(snapshot_->display_id(), degamma, gamma);
 }
 
 void DrmDisplayHost::SetPrivacyScreen(
diff --git a/ui/ozone/platform/drm/host/drm_display_host.h b/ui/ozone/platform/drm/host/drm_display_host.h
index 5a91096..60d7b1a 100644
--- a/ui/ozone/platform/drm/host/drm_display_host.h
+++ b/ui/ozone/platform/drm/host/drm_display_host.h
@@ -43,9 +43,8 @@
                     display::ContentProtectionMethod protection_method,
                     display::SetHDCPStateCallback callback);
   void SetColorMatrix(const std::vector<float>& color_matrix);
-  void SetGammaCorrection(
-      const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut);
+  void SetGammaCorrection(const display::GammaCurve& degamma,
+                          const display::GammaCurve& gamma);
   void SetPrivacyScreen(bool enabled,
                         display::SetPrivacyScreenCallback callback);
 
diff --git a/ui/ozone/platform/drm/host/drm_native_display_delegate.cc b/ui/ozone/platform/drm/host/drm_native_display_delegate.cc
index aad9cc5..0d0ee81 100644
--- a/ui/ozone/platform/drm/host/drm_native_display_delegate.cc
+++ b/ui/ozone/platform/drm/host/drm_native_display_delegate.cc
@@ -92,10 +92,10 @@
 
 bool DrmNativeDisplayDelegate::SetGammaCorrection(
     int64_t display_id,
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
+    const display::GammaCurve& degamma,
+    const display::GammaCurve& gamma) {
   DrmDisplayHost* display = display_manager_->GetDisplay(display_id);
-  display->SetGammaCorrection(degamma_lut, gamma_lut);
+  display->SetGammaCorrection(degamma, gamma);
   return true;
 }
 
diff --git a/ui/ozone/platform/drm/host/drm_native_display_delegate.h b/ui/ozone/platform/drm/host/drm_native_display_delegate.h
index 8c11c8f..e8e2184 100644
--- a/ui/ozone/platform/drm/host/drm_native_display_delegate.h
+++ b/ui/ozone/platform/drm/host/drm_native_display_delegate.h
@@ -48,10 +48,9 @@
                     display::SetHDCPStateCallback callback) override;
   bool SetColorMatrix(int64_t display_id,
                       const std::vector<float>& color_matrix) override;
-  bool SetGammaCorrection(
-      int64_t display_id,
-      const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut) override;
+  bool SetGammaCorrection(int64_t display_id,
+                          const display::GammaCurve& degamma,
+                          const display::GammaCurve& gamma) override;
   void SetPrivacyScreen(int64_t display_id,
                         bool enabled,
                         display::SetPrivacyScreenCallback callback) override;
diff --git a/ui/ozone/platform/drm/host/gpu_thread_adapter.h b/ui/ozone/platform/drm/host/gpu_thread_adapter.h
index a6dce54..835cfb0 100644
--- a/ui/ozone/platform/drm/host/gpu_thread_adapter.h
+++ b/ui/ozone/platform/drm/host/gpu_thread_adapter.h
@@ -62,10 +62,9 @@
       display::ContentProtectionMethod protection_method) = 0;
   virtual bool GpuSetColorMatrix(int64_t display_id,
                                  const std::vector<float>& color_matrix) = 0;
-  virtual bool GpuSetGammaCorrection(
-      int64_t display_id,
-      const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut) = 0;
+  virtual bool GpuSetGammaCorrection(int64_t display_id,
+                                     const display::GammaCurve& degamma,
+                                     const display::GammaCurve& gamma) = 0;
   virtual void GpuSetPrivacyScreen(
       int64_t display_id,
       bool enabled,
diff --git a/ui/ozone/platform/drm/host/host_drm_device.cc b/ui/ozone/platform/drm/host/host_drm_device.cc
index 7d8e915..1afcf10 100644
--- a/ui/ozone/platform/drm/host/host_drm_device.cc
+++ b/ui/ozone/platform/drm/host/host_drm_device.cc
@@ -255,8 +255,8 @@
 
 bool HostDrmDevice::GpuSetGammaCorrection(
     int64_t display_id,
-    const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-    const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
+    const display::GammaCurve& degamma_lut,
+    const display::GammaCurve& gamma_lut) {
   DCHECK_CALLED_ON_VALID_THREAD(on_ui_thread_);
   if (!IsConnected())
     return false;
diff --git a/ui/ozone/platform/drm/host/host_drm_device.h b/ui/ozone/platform/drm/host/host_drm_device.h
index 17e060b..9f21a57f 100644
--- a/ui/ozone/platform/drm/host/host_drm_device.h
+++ b/ui/ozone/platform/drm/host/host_drm_device.h
@@ -79,10 +79,9 @@
       display::ContentProtectionMethod protection_method) override;
   bool GpuSetColorMatrix(int64_t display_id,
                          const std::vector<float>& color_matrix) override;
-  bool GpuSetGammaCorrection(
-      int64_t display_id,
-      const std::vector<display::GammaRampRGBEntry>& degamma_lut,
-      const std::vector<display::GammaRampRGBEntry>& gamma_lut) override;
+  bool GpuSetGammaCorrection(int64_t display_id,
+                             const display::GammaCurve& degamma,
+                             const display::GammaCurve& gamma) override;
   void GpuSetPrivacyScreen(int64_t display_id,
                            bool enabled,
                            display::SetPrivacyScreenCallback callback) override;
diff --git a/ui/ozone/platform/drm/mojom/drm_device.mojom b/ui/ozone/platform/drm/mojom/drm_device.mojom
index 8aaa8bb..6b9d8a7 100644
--- a/ui/ozone/platform/drm/mojom/drm_device.mojom
+++ b/ui/ozone/platform/drm/mojom/drm_device.mojom
@@ -6,11 +6,11 @@
 
 import "mojo/public/mojom/base/file.mojom";
 import "mojo/public/mojom/base/file_path.mojom";
+import "ui/display/mojom/display_color_management.mojom";
 import "ui/display/mojom/display_configuration_params.mojom";
 import "ui/display/mojom/display_constants.mojom";
 import "ui/display/mojom/display_mode.mojom";
 import "ui/display/mojom/display_snapshot.mojom";
-import "ui/display/mojom/gamma_ramp_rgb_entry.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
 import "ui/gfx/mojom/accelerated_widget.mojom";
 import "ui/ozone/platform/drm/mojom/device_cursor.mojom";
@@ -89,8 +89,8 @@
 
   // Sets a color correction gamma lookup table.
   SetGammaCorrection(int64 display_id,
-                     array<display.mojom.GammaRampRGBEntry> degamma_lut,
-                     array<display.mojom.GammaRampRGBEntry> gamma_lut);
+                     display.mojom.GammaCurve degamma,
+                     display.mojom.GammaCurve gamma);
 
   // Sets the state of the privacy screen feature, returns whether or not the
   // configuration was successful.