[go: up one dir, main page]

[merge m76] Switch default HDR color space back to SCRGB linear

We switched to HDR10 color space with RGB10A2 backbuffers to workaround
a DWM/driver bug when Chrome is fullscreen.  It looks like that bug was
present in RS3 but has been fixed in RS5.  MS has recommended not using
HDR10 color space in general so we'll switch back to SCRGB linear with
RGBAF16 backbuffers.

This CL also allows choosing HDR10 color space in chrome://flags for
testing or as a workaround.

(cherry picked from commit 71e474a84342725845b5e05aed9c941cfa1ac88c)

Bug: 937108
Change-Id: I2b97afc0a302b687d672217f085897e7de7f290a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1646540
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: ccameron <ccameron@chromium.org>
Reviewed-by: Robert Liao <robliao@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#667846}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1665230
Reviewed-by: Sunny Sachanandani <sunnyps@chromium.org>
Cr-Commit-Position: refs/branch-heads/3809@{#427}
Cr-Branched-From: d82dec1a818f378c464ba307ddd9c92133eac355-refs/heads/master@{#665002}
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index c4949aae..222950f4 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -542,8 +542,10 @@
      switches::kForceDisplayColorProfile, "display-p3-d65"},
     {flag_descriptions::kForceColorProfileColorSpin,
      switches::kForceDisplayColorProfile, "color-spin-gamma24"},
-    {flag_descriptions::kForceColorProfileHdr,
+    {flag_descriptions::kForceColorProfileSCRGBLinear,
      switches::kForceDisplayColorProfile, "scrgb-linear"},
+    {flag_descriptions::kForceColorProfileHDR10,
+     switches::kForceDisplayColorProfile, "hdr10"},
 };
 
 const FeatureEntry::Choice kForceEffectiveConnectionTypeChoices[] = {
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 6b11b86..fe57ff6b 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -269,7 +269,9 @@
 const char kForceColorProfileSRGB[] = "sRGB";
 const char kForceColorProfileP3[] = "Display P3 D65";
 const char kForceColorProfileColorSpin[] = "Color spin with gamma 2.4";
-const char kForceColorProfileHdr[] = "scRGB linear (HDR where available)";
+const char kForceColorProfileSCRGBLinear[] =
+    "scRGB linear (HDR where available)";
+const char kForceColorProfileHDR10[] = "HDR10 (HDR where available)";
 
 const char kForceColorProfileName[] = "Force color profile";
 const char kForceColorProfileDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index e404338..233ecb5 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -192,7 +192,8 @@
 extern const char kForceColorProfileSRGB[];
 extern const char kForceColorProfileP3[];
 extern const char kForceColorProfileColorSpin[];
-extern const char kForceColorProfileHdr[];
+extern const char kForceColorProfileSCRGBLinear[];
+extern const char kForceColorProfileHDR10[];
 
 extern const char kForceColorProfileName[];
 extern const char kForceColorProfileDescription[];
diff --git a/ui/aura/window_tree_host_unittest.cc b/ui/aura/window_tree_host_unittest.cc
index cd73b939..46e15ec5 100644
--- a/ui/aura/window_tree_host_unittest.cc
+++ b/ui/aura/window_tree_host_unittest.cc
@@ -97,7 +97,7 @@
 
   // UI compositor overrides HDR color space based on whether alpha blending is
   // needed or not.
-  test_screen()->SetColorSpace(gfx::ColorSpace::CreateSCRGBLinear());
+  test_screen()->SetColorSpace(gfx::ColorSpace::CreateHDR10());
   host()->compositor()->SetBackgroundColor(SK_ColorBLACK);
   EXPECT_EQ(gfx::ColorSpace::CreateHDR10(),
             host()->compositor()->output_color_space());
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index 15c98e2b..0b6b01d 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -414,12 +414,11 @@
   gfx::ColorSpace output_color_space = color_space;
 
 #if defined(OS_WIN)
-  // Ensure output color space for HDR is linear if we need alpha blending, and
-  // HDR10 (BT.2020 primaries with PQ transfer function) otherwise.
   if (color_space.IsHDR()) {
     bool transparent = SkColorGetA(host_->background_color()) != SK_AlphaOPAQUE;
-    output_color_space = transparent ? gfx::ColorSpace::CreateSCRGBLinear()
-                                     : gfx::ColorSpace::CreateHDR10();
+    // Ensure output color space for HDR is linear if we need alpha blending.
+    if (transparent)
+      output_color_space = gfx::ColorSpace::CreateSCRGBLinear();
     output_color_space = output_color_space.GetScaledColorSpace(
         gfx::ColorSpace::kDefaultSDRWhiteLevel / sdr_white_level);
   }
@@ -456,7 +455,12 @@
 void Compositor::SetBackgroundColor(SkColor color) {
   host_->set_background_color(color);
   // Update color space based on whether background color is transparent.
-  SetDisplayColorSpace(output_color_space_, sdr_white_level_);
+  if (output_color_space_.IsHDR()) {
+    gfx::ColorSpace unscaled_color_space =
+        output_color_space_.GetScaledColorSpace(
+            sdr_white_level_ / gfx::ColorSpace::kDefaultSDRWhiteLevel);
+    SetDisplayColorSpace(unscaled_color_space, sdr_white_level_);
+  }
   ScheduleDraw();
 }
 
diff --git a/ui/display/display.cc b/ui/display/display.cc
index e7778157..f2153337b 100644
--- a/ui/display/display.cc
+++ b/ui/display/display.cc
@@ -21,12 +21,14 @@
 namespace display {
 namespace {
 
-constexpr int DEFAULT_BITS_PER_PIXEL = 24;
-constexpr int DEFAULT_BITS_PER_COMPONENT = 8;
+constexpr int kDefaultBitsPerPixel = 24;
+constexpr int kDefaultBitsPerComponent = 8;
 
-// Assuming HDR10 color space with RGB10A2 backbuffer.
-constexpr int HDR_BITS_PER_PIXEL = 30;
-constexpr int HDR_BITS_PER_COMPONENT = 10;
+constexpr int kHDR10BitsPerPixel = 30;
+constexpr int kHDR10BitsPerComponent = 10;
+
+constexpr int kSCRGBLinearBitsPerPixel = 48;
+constexpr int kSCRGBLinearBitsPerComponent = 16;
 
 // This variable tracks whether the forced device scale factor switch needs to
 // be read from the command line, i.e. if it is set to -1 then the command line
@@ -66,6 +68,8 @@
     return gfx::ColorSpace::CreateDisplayP3D65();
   if (value == "scrgb-linear")
     return gfx::ColorSpace::CreateSCRGBLinear();
+  if (value == "hdr10")
+    return gfx::ColorSpace::CreateHDR10();
   if (value == "extended-srgb")
     return gfx::ColorSpace::CreateExtendedSRGB();
   if (value == "generic-rgb") {
@@ -211,9 +215,12 @@
       bounds_(bounds),
       work_area_(bounds),
       device_scale_factor_(GetForcedDeviceScaleFactor()) {
-  SetColorSpaceAndDepth(HasForceDisplayColorProfile()
-                            ? GetForcedDisplayColorProfile()
-                            : gfx::ColorSpace::CreateSRGB());
+  gfx::ColorSpace color_space = HasForceDisplayColorProfile()
+                                    ? GetForcedDisplayColorProfile()
+                                    : gfx::ColorSpace::CreateSRGB();
+  float sdr_white_level =
+      color_space.IsHDR() ? 200.f : gfx::ColorSpace::kDefaultSDRWhiteLevel;
+  SetColorSpaceAndDepth(color_space, sdr_white_level);
 #if defined(USE_AURA)
   SetScaleAndBounds(device_scale_factor_, bounds);
 #endif
@@ -301,13 +308,15 @@
                                     float sdr_white_level) {
   color_space_ = color_space;
   sdr_white_level_ = sdr_white_level;
-  // Assuming HDR10 color space and buffer format.
-  if (color_space_.IsHDR()) {
-    color_depth_ = HDR_BITS_PER_PIXEL;
-    depth_per_component_ = HDR_BITS_PER_COMPONENT;
+  if (color_space_ == gfx::ColorSpace::CreateHDR10()) {
+    color_depth_ = kHDR10BitsPerPixel;
+    depth_per_component_ = kHDR10BitsPerComponent;
+  } else if (color_space == gfx::ColorSpace::CreateSCRGBLinear()) {
+    color_depth_ = kSCRGBLinearBitsPerPixel;
+    depth_per_component_ = kSCRGBLinearBitsPerComponent;
   } else {
-    color_depth_ = DEFAULT_BITS_PER_PIXEL;
-    depth_per_component_ = DEFAULT_BITS_PER_COMPONENT;
+    color_depth_ = kDefaultBitsPerPixel;
+    depth_per_component_ = kDefaultBitsPerComponent;
   }
 }
 
diff --git a/ui/display/display_unittest.cc b/ui/display/display_unittest.cc
index d90c990..836f283 100644
--- a/ui/display/display_unittest.cc
+++ b/ui/display/display_unittest.cc
@@ -76,14 +76,13 @@
   EXPECT_EQ(24, display.color_depth());
   EXPECT_EQ(8, display.depth_per_component());
 
-  // All HDR color spaces report the same bit depth as HDR10.
   display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateHDR10());
   EXPECT_EQ(30, display.color_depth());
   EXPECT_EQ(10, display.depth_per_component());
 
   display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateSCRGBLinear());
-  EXPECT_EQ(30, display.color_depth());
-  EXPECT_EQ(10, display.depth_per_component());
+  EXPECT_EQ(48, display.color_depth());
+  EXPECT_EQ(16, display.depth_per_component());
 
   display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateSRGB());
   EXPECT_EQ(24, display.color_depth());
diff --git a/ui/display/win/screen_win.cc b/ui/display/win/screen_win.cc
index 15e4bbd1..0998b14 100644
--- a/ui/display/win/screen_win.cc
+++ b/ui/display/win/screen_win.cc
@@ -14,6 +14,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/stl_util.h"
 #include "base/win/win_util.h"
+#include "base/win/windows_version.h"
 #include "ui/display/display.h"
 #include "ui/display/display_layout.h"
 #include "ui/display/display_layout_builder.h"
@@ -210,9 +211,13 @@
   display.set_display_frequency(display_info.display_frequency());
   if (!Display::HasForceDisplayColorProfile()) {
     if (hdr_enabled) {
-      // It doesn't matter what HDR color space we set since UI compositor will
-      // override it to HDR10 if opaque or SCRGB linear if translucent.
-      display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateHDR10(),
+      // Using RGBA F16 backbuffers required by SCRGB linear causes stuttering
+      // on Windows RS3, but RGB10A2 with HDR10 color space works fine.
+      gfx::ColorSpace hdr_color_space =
+          base::win::GetVersion() > base::win::Version::WIN10_RS3
+              ? gfx::ColorSpace::CreateSCRGBLinear()
+              : gfx::ColorSpace::CreateHDR10();
+      display.SetColorSpaceAndDepth(hdr_color_space,
                                     display_info.sdr_white_level());
     } else {
       display.SetColorSpaceAndDepth(