Set ContentColorUsage in more quad types, aggregate in prewalk

Add ContentColorUsage to the SurfaceAggregator's PrewalkResult, and
populate it during the pre-walk step.

Add implementations of the GetContentColorUsage method to
TextureLayerImpl, VideoLayerImpl. Set the corresponding
CompositorFrameMetadata for VideoResourceUpdater as well.

Bug: 955158, 976426
Change-Id: Iae00a5c413e3bb893cdc84319d8426b30b357667
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2036634
Reviewed-by: Miguel Casas <mcasas@chromium.org>
Commit-Queue: ccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738072}
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index 47de6c8..a37fa8092e 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -64,6 +64,7 @@
   void RecreateTileResources() override;
   Region GetInvalidationRegionForDebugging() override;
   gfx::Rect GetEnclosingRectInTargetSpace() const override;
+  gfx::ContentColorUsage GetContentColorUsage() const override;
 
   // PictureLayerTilingClient overrides.
   std::unique_ptr<Tile> CreateTile(const Tile::CreateInfo& info) override;
@@ -157,8 +158,6 @@
   // an animation, at which point the PaintWorklet must be re-painted.
   void InvalidatePaintWorklets(const PaintWorkletInput::PropertyKey& key);
 
-  gfx::ContentColorUsage GetContentColorUsage() const override;
-
  protected:
   PictureLayerImpl(LayerTreeImpl* tree_impl, int id);
   PictureLayerTiling* AddTiling(const gfx::AxisTransform2d& contents_transform);
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc
index 20f21f7a..d910736 100644
--- a/cc/layers/texture_layer_impl.cc
+++ b/cc/layers/texture_layer_impl.cc
@@ -200,6 +200,10 @@
   // all) instead.
 }
 
+gfx::ContentColorUsage TextureLayerImpl::GetContentColorUsage() const {
+  return transferable_resource_.color_space.GetContentColorUsage();
+}
+
 void TextureLayerImpl::SetPremultipliedAlpha(bool premultiplied_alpha) {
   premultiplied_alpha_ = premultiplied_alpha;
 }
diff --git a/cc/layers/texture_layer_impl.h b/cc/layers/texture_layer_impl.h
index a9c7733..bc34d50 100644
--- a/cc/layers/texture_layer_impl.h
+++ b/cc/layers/texture_layer_impl.h
@@ -44,6 +44,7 @@
   SimpleEnclosedRegion VisibleOpaqueRegion() const override;
   void ReleaseResources() override;
   void OnPurgeMemory() override;
+  gfx::ContentColorUsage GetContentColorUsage() const override;
 
   // These setter methods don't cause any implicit damage, so the texture client
   // must explicitly invalidate if they intend to cause a visible change in the
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc
index 905a0a5a..98124a9 100644
--- a/cc/layers/video_layer_impl.cc
+++ b/cc/layers/video_layer_impl.cc
@@ -187,6 +187,13 @@
   updater_ = nullptr;
 }
 
+gfx::ContentColorUsage VideoLayerImpl::GetContentColorUsage() const {
+  gfx::ColorSpace frame_color_space;
+  if (frame_)
+    frame_color_space = frame_->ColorSpace();
+  return frame_color_space.GetContentColorUsage();
+}
+
 void VideoLayerImpl::SetNeedsRedraw() {
   UnionUpdateRect(gfx::Rect(bounds()));
   layer_tree_impl()->SetNeedsRedraw();
diff --git a/cc/layers/video_layer_impl.h b/cc/layers/video_layer_impl.h
index 5d3aa87..e71d6ad7 100644
--- a/cc/layers/video_layer_impl.h
+++ b/cc/layers/video_layer_impl.h
@@ -45,6 +45,7 @@
   SimpleEnclosedRegion VisibleOpaqueRegion() const override;
   void DidBecomeActive() override;
   void ReleaseResources() override;
+  gfx::ContentColorUsage GetContentColorUsage() const override;
 
   void SetNeedsRedraw();
   media::VideoRotation video_rotation() const { return video_rotation_; }
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index 04754248..054bf9c 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -77,26 +77,6 @@
   return true;
 }
 
-gfx::ContentColorUsage FindWidestContentColorUsage(
-    Surface* root_surface,
-    base::flat_set<SurfaceId> referenced_surfaces,
-    const SurfaceManager& manager) {
-  gfx::ContentColorUsage result = gfx::ContentColorUsage::kSRGB;
-
-  result = std::max(
-      result, root_surface->GetActiveFrame().metadata.content_color_usage);
-
-  for (auto& referenced_surface_id : referenced_surfaces) {
-    Surface* referenced_surface =
-        manager.GetSurfaceForId(referenced_surface_id);
-    result = std::max(
-        result,
-        referenced_surface->GetActiveFrame().metadata.content_color_usage);
-  }
-
-  return result;
-}
-
 }  // namespace
 
 struct SurfaceAggregator::ClipData {
@@ -113,6 +93,7 @@
   // not included in a SurfaceDrawQuad.
   base::flat_set<SurfaceId> undrawn_surfaces;
   bool may_contain_video = false;
+  gfx::ContentColorUsage content_color_usage = gfx::ContentColorUsage::kSRGB;
 };
 
 struct SurfaceAggregator::RoundedCornerInfo {
@@ -599,7 +580,7 @@
         source.transform_to_root_target, source.filters,
         source.backdrop_filters, source.backdrop_filter_bounds,
         display_color_spaces_.GetCompositingColorSpace(
-            source.has_transparent_background, display_content_color_usage_),
+            source.has_transparent_background, root_content_color_usage_),
         source.has_transparent_background, source.cache_render_pass,
         source.has_damage_from_contributing_content, source.generate_mipmap);
 
@@ -1184,7 +1165,7 @@
         remapped_pass_id, output_rect, damage_rect, transform_to_root_target,
         source.filters, source.backdrop_filters, source.backdrop_filter_bounds,
         display_color_spaces_.GetCompositingColorSpace(
-            source.has_transparent_background, display_content_color_usage_),
+            source.has_transparent_background, root_content_color_usage_),
         source.has_transparent_background, source.cache_render_pass,
         source.has_damage_from_contributing_content, source.generate_mipmap);
 
@@ -1538,6 +1519,8 @@
   referenced_surfaces_.erase(surface->surface_id());
   if (!damage_rect.IsEmpty() && frame.metadata.may_contain_video)
     result->may_contain_video = true;
+  result->content_color_usage =
+      std::max(result->content_color_usage, frame.metadata.content_color_usage);
 
   // Repeat this operation until no new render pass with pixel moving backdrop
   // filter intersects with the damage rect.
@@ -1685,14 +1668,12 @@
   PrewalkResult prewalk_result;
   root_damage_rect_ =
       PrewalkTree(surface, false, 0, true /* will_draw */, &prewalk_result);
+  root_content_color_usage_ = prewalk_result.content_color_usage;
 
   PropagateCopyRequestPasses();
   has_copy_requests_ = !copy_request_passes_.empty();
   frame.metadata.may_contain_video = prewalk_result.may_contain_video;
-
-  display_content_color_usage_ =
-      FindWidestContentColorUsage(surface, referenced_surfaces_, *manager_);
-  frame.metadata.content_color_usage = display_content_color_usage_;
+  frame.metadata.content_color_usage = prewalk_result.content_color_usage;
 
   CopyUndrawnSurfaces(&prewalk_result);
   referenced_surfaces_.insert(surface_id);
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h
index 788d880..2fec07a 100644
--- a/components/viz/service/display/surface_aggregator.h
+++ b/components/viz/service/display/surface_aggregator.h
@@ -305,7 +305,7 @@
   // blending color space (e.g. for HDR), then a final render pass to convert
   // between the two will be added. This space must always be valid.
   gfx::DisplayColorSpaces display_color_spaces_;
-  gfx::ContentColorUsage display_content_color_usage_;
+
   // Maximum texture size which if positive, will limit the size of render
   // passes.
   int max_texture_size_ = 0;
@@ -363,6 +363,13 @@
   // The root damage rect of the currently-aggregating frame.
   gfx::Rect root_damage_rect_;
 
+  // The aggregate color content usage of the currently-aggregating frame. This
+  // is computed by the prewalk, and is used to determine the format and color
+  // space of all render passes. Note that that is more heavy-handed than is
+  // desirable.
+  gfx::ContentColorUsage root_content_color_usage_ =
+      gfx::ContentColorUsage::kSRGB;
+
   // Occluding damage rect will be calculated for qualified candidates
   const bool needs_surface_occluding_damage_rect_;
 
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
index ece2f92..b70b20e 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -578,6 +578,8 @@
                       gfx::Transform());
 
   if (video_frame) {
+    compositor_frame.metadata.content_color_usage =
+        video_frame->ColorSpace().GetContentColorUsage();
     const bool is_opaque = media::IsOpaque(video_frame->format());
     resource_provider_->AppendQuads(render_pass.get(), std::move(video_frame),
                                     rotation_, is_opaque);
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc
index 3421538..fe4e8747 100644
--- a/ui/gfx/color_space.cc
+++ b/ui/gfx/color_space.cc
@@ -15,6 +15,7 @@
 #include "third_party/skia/include/core/SkColorSpace.h"
 #include "third_party/skia/include/core/SkData.h"
 #include "third_party/skia/include/core/SkICC.h"
+#include "ui/gfx/display_color_spaces.h"
 #include "ui/gfx/icc_profile.h"
 #include "ui/gfx/skia_color_space_util.h"
 
@@ -496,6 +497,14 @@
   return result;
 }
 
+ContentColorUsage ColorSpace::GetContentColorUsage() const {
+  if (IsHDR())
+    return ContentColorUsage::kHDR;
+  if (IsWide())
+    return ContentColorUsage::kWideColorGamut;
+  return ContentColorUsage::kSRGB;
+}
+
 ColorSpace ColorSpace::GetAsRGB() const {
   ColorSpace result(*this);
   if (IsValid())
diff --git a/ui/gfx/color_space.h b/ui/gfx/color_space.h
index b6c1ad27..6eaaea60 100644
--- a/ui/gfx/color_space.h
+++ b/ui/gfx/color_space.h
@@ -36,6 +36,8 @@
 
 namespace gfx {
 
+enum class ContentColorUsage : uint8_t;
+
 namespace mojom {
 class ColorSpaceDataView;
 }  // namespace mojom
@@ -243,6 +245,9 @@
   // Returns true if the encoded values can be outside of the 0.0-1.0 range.
   bool FullRangeEncodedValues() const;
 
+  // Returns the color space's content color usage category (sRGB, WCG, or HDR).
+  ContentColorUsage GetContentColorUsage() const;
+
   // Return this color space with any YUV to RGB conversion stripped off.
   ColorSpace GetAsRGB() const;