viz: Make OverlayCandidateFactory::IsOccluded*() static functions

IsOccluded and IsOccludedByFilteredQuad do not depend on members of
OverlayCandidateFactory. This CL makes them static and also take a
DrawQuad instead of a OverlayCandidate, since it just needs the target
rect which can be calculated from either.

Change-Id: If2533b3bbdfbfd13c5c17fb383979e19bff9f658
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6261410
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Commit-Queue: Michael Tang <tangm@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1420204}
diff --git a/components/viz/service/display/overlay_candidate_factory.cc b/components/viz/service/display/overlay_candidate_factory.cc
index 983b88c..11142ee 100644
--- a/components/viz/service/display/overlay_candidate_factory.cc
+++ b/components/viz/service/display/overlay_candidate_factory.cc
@@ -285,15 +285,17 @@
       0.f, quad_damage.size().GetArea() - occluded_damage_estimate_total);
 }
 
+// static
 bool OverlayCandidateFactory::IsOccludedByFilteredQuad(
-    const OverlayCandidate& candidate,
+    const DrawQuad& quad,
     QuadList::ConstIterator quad_list_begin,
     QuadList::ConstIterator quad_list_end,
     const base::flat_map<AggregatedRenderPassId,
                          raw_ptr<cc::FilterOperations, CtnExperimental>>&
-        render_pass_backdrop_filters) const {
-  gfx::RectF target_rect =
-      OverlayCandidate::DisplayRectInTargetSpace(candidate);
+        render_pass_backdrop_filters) {
+  const gfx::RectF target_rect =
+      quad.shared_quad_state->quad_to_target_transform.MapRect(
+          gfx::RectF(quad.visible_rect));
   for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end;
        ++overlap_iter) {
     if (auto* render_pass_draw_quad =
@@ -312,14 +314,16 @@
   return false;
 }
 
+// static
 bool OverlayCandidateFactory::IsOccluded(
-    const OverlayCandidate& candidate,
+    const DrawQuad& quad,
     QuadList::ConstIterator quad_list_begin,
-    QuadList::ConstIterator quad_list_end) const {
+    QuadList::ConstIterator quad_list_end) {
   // The rects are rounded as they're snapped by the compositor to pixel unless
   // it is AA'ed, in which case, it won't be overlaid.
-  gfx::Rect target_rect =
-      gfx::ToRoundedRect(OverlayCandidate::DisplayRectInTargetSpace(candidate));
+  const gfx::Rect target_rect = gfx::ToRoundedRect(
+      quad.shared_quad_state->quad_to_target_transform.MapRect(
+          gfx::RectF(quad.visible_rect)));
 
   // Check that no visible quad overlaps the candidate.
   for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end;
diff --git a/components/viz/service/display/overlay_candidate_factory.h b/components/viz/service/display/overlay_candidate_factory.h
index 05d4081..4f05e07e 100644
--- a/components/viz/service/display/overlay_candidate_factory.h
+++ b/components/viz/service/display/overlay_candidate_factory.h
@@ -98,20 +98,24 @@
                               QuadList::ConstIterator quad_list_end) const;
 
   // Returns true if any of the quads in the list given by |quad_list_begin|
-  // and |quad_list_end| have an associated filter and occlude |candidate|.
-  bool IsOccludedByFilteredQuad(
-      const OverlayCandidate& candidate,
+  // and |quad_list_end| have an associated filter and occlude |quad|.
+  // |quad| should normally be at |quad_list_end| since we only want to check
+  // for occlusion with quads above it.
+  static bool IsOccludedByFilteredQuad(
+      const DrawQuad& quad,
       QuadList::ConstIterator quad_list_begin,
       QuadList::ConstIterator quad_list_end,
       const base::flat_map<AggregatedRenderPassId,
                            raw_ptr<cc::FilterOperations, CtnExperimental>>&
-          render_pass_backdrop_filters) const;
+          render_pass_backdrop_filters);
 
   // Returns true if any of the quads in the list given by |quad_list_begin|
-  // and |quad_list_end| occlude |candidate|.
-  bool IsOccluded(const OverlayCandidate& candidate,
-                  QuadList::ConstIterator quad_list_begin,
-                  QuadList::ConstIterator quad_list_end) const;
+  // and |quad_list_end| occlude |quad|.
+  // |quad| should normally be at |quad_list_end| since we only want to check
+  // for occlusion with quads above it.
+  static bool IsOccluded(const DrawQuad& quad,
+                         QuadList::ConstIterator quad_list_begin,
+                         QuadList::ConstIterator quad_list_end);
 
   gfx::Rect GetUnassignedDamage() { return unassigned_surface_damage_; }
 
diff --git a/components/viz/service/display/overlay_candidate_factory_unittest.cc b/components/viz/service/display/overlay_candidate_factory_unittest.cc
index 529d541a..95df66b 100644
--- a/components/viz/service/display/overlay_candidate_factory_unittest.cc
+++ b/components/viz/service/display/overlay_candidate_factory_unittest.cc
@@ -27,6 +27,7 @@
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/test/geometry_util.h"
+#include "ui/gfx/geometry/transform_util.h"
 #include "ui/gfx/overlay_transform_utils.h"
 #include "ui/gfx/video_types.h"
 
@@ -248,13 +249,17 @@
   return rpdq;
 }
 
-OverlayCandidate CreateCandidate(float left,
-                                 float top,
-                                 float right,
-                                 float bottom) {
-  OverlayCandidate candidate;
-  candidate.display_rect.SetRect(left, top, right - left, bottom - top);
-  return candidate;
+const SolidColorDrawQuad& CreateDrawQuadWithBounds(
+    float left,
+    float top,
+    float right,
+    float bottom,
+    AggregatedRenderPass* render_pass) {
+  const gfx::Rect quad_rect(1, 1);
+  const gfx::RectF target_rect(left, top, right - left, bottom - top);
+  return *AddQuad(
+      quad_rect, gfx::TransformBetweenRects(gfx::RectF(quad_rect), target_rect),
+      render_pass);
 }
 
 using OverlayCandidateFactoryTest = OverlayCandidateFactoryTestBase;
@@ -276,24 +281,27 @@
   AddQuad(gfx::Rect(10, 0, 1, 10), identity, &render_pass);
   AddQuad(gfx::Rect(0, 10, 10, 1), identity, &render_pass);
 
-  EXPECT_FALSE(factory.IsOccluded(CreateCandidate(0.5f, 0.5f, 10.49f, 10.49f),
-                                  render_pass.quad_list.begin(),
-                                  render_pass.quad_list.end()));
-
-  EXPECT_TRUE(factory.IsOccluded(CreateCandidate(0.49f, 0.5f, 10.49f, 10.49f),
-                                 render_pass.quad_list.begin(),
-                                 render_pass.quad_list.end()));
-
-  EXPECT_TRUE(factory.IsOccluded(CreateCandidate(0.5f, 0.49f, 10.50f, 10.5f),
-                                 render_pass.quad_list.begin(),
-                                 render_pass.quad_list.end()));
-  EXPECT_TRUE(factory.IsOccluded(CreateCandidate(0.5f, 0.5f, 10.5f, 10.49f),
-                                 render_pass.quad_list.begin(),
-                                 render_pass.quad_list.end()));
-
-  EXPECT_TRUE(factory.IsOccluded(CreateCandidate(0.5f, 0.5f, 10.49f, 10.5f),
-                                 render_pass.quad_list.begin(),
-                                 render_pass.quad_list.end()));
+  AggregatedRenderPass test_quad_render_pass;
+  EXPECT_FALSE(OverlayCandidateFactory::IsOccluded(
+      CreateDrawQuadWithBounds(0.5f, 0.5f, 10.49f, 10.49f,
+                               &test_quad_render_pass),
+      render_pass.quad_list.begin(), render_pass.quad_list.end()));
+  EXPECT_TRUE(OverlayCandidateFactory::IsOccluded(
+      CreateDrawQuadWithBounds(0.49f, 0.5f, 10.49f, 10.49f,
+                               &test_quad_render_pass),
+      render_pass.quad_list.begin(), render_pass.quad_list.end()));
+  EXPECT_TRUE(OverlayCandidateFactory::IsOccluded(
+      CreateDrawQuadWithBounds(0.5f, 0.49f, 10.50f, 10.5f,
+                               &test_quad_render_pass),
+      render_pass.quad_list.begin(), render_pass.quad_list.end()));
+  EXPECT_TRUE(OverlayCandidateFactory::IsOccluded(
+      CreateDrawQuadWithBounds(0.5f, 0.5f, 10.5f, 10.49f,
+                               &test_quad_render_pass),
+      render_pass.quad_list.begin(), render_pass.quad_list.end()));
+  EXPECT_TRUE(OverlayCandidateFactory::IsOccluded(
+      CreateDrawQuadWithBounds(0.5f, 0.5f, 10.49f, 10.5f,
+                               &test_quad_render_pass),
+      render_pass.quad_list.begin(), render_pass.quad_list.end()));
 }
 
 TEST_F(OverlayCandidateFactoryTest, IsOccludedScaled) {
@@ -313,21 +321,22 @@
   AddQuad(gfx::Rect(9, 0, 1, 10), quad_to_target_transform, &render_pass);
   AddQuad(gfx::Rect(0, 11, 10, 1), quad_to_target_transform, &render_pass);
 
-  EXPECT_FALSE(factory.IsOccluded(CreateCandidate(2.f, 3.f, 14.f, 17.f),
-                                  render_pass.quad_list.begin(),
-                                  render_pass.quad_list.end()));
-  EXPECT_TRUE(factory.IsOccluded(CreateCandidate(1.f, 3.f, 14.f, 17.f),
-                                 render_pass.quad_list.begin(),
-                                 render_pass.quad_list.end()));
-  EXPECT_TRUE(factory.IsOccluded(CreateCandidate(2.f, 2.f, 14.f, 17.f),
-                                 render_pass.quad_list.begin(),
-                                 render_pass.quad_list.end()));
-  EXPECT_TRUE(factory.IsOccluded(CreateCandidate(2.f, 3.f, 15.f, 17.f),
-                                 render_pass.quad_list.begin(),
-                                 render_pass.quad_list.end()));
-  EXPECT_TRUE(factory.IsOccluded(CreateCandidate(2.f, 3.f, 15.f, 18.f),
-                                 render_pass.quad_list.begin(),
-                                 render_pass.quad_list.end()));
+  AggregatedRenderPass test_quad_render_pass;
+  EXPECT_FALSE(OverlayCandidateFactory::IsOccluded(
+      CreateDrawQuadWithBounds(2.f, 3.f, 14.f, 17.f, &test_quad_render_pass),
+      render_pass.quad_list.begin(), render_pass.quad_list.end()));
+  EXPECT_TRUE(OverlayCandidateFactory::IsOccluded(
+      CreateDrawQuadWithBounds(1.f, 3.f, 14.f, 17.f, &test_quad_render_pass),
+      render_pass.quad_list.begin(), render_pass.quad_list.end()));
+  EXPECT_TRUE(OverlayCandidateFactory::IsOccluded(
+      CreateDrawQuadWithBounds(2.f, 2.f, 14.f, 17.f, &test_quad_render_pass),
+      render_pass.quad_list.begin(), render_pass.quad_list.end()));
+  EXPECT_TRUE(OverlayCandidateFactory::IsOccluded(
+      CreateDrawQuadWithBounds(2.f, 3.f, 15.f, 17.f, &test_quad_render_pass),
+      render_pass.quad_list.begin(), render_pass.quad_list.end()));
+  EXPECT_TRUE(OverlayCandidateFactory::IsOccluded(
+      CreateDrawQuadWithBounds(2.f, 3.f, 15.f, 18.f, &test_quad_render_pass),
+      render_pass.quad_list.begin(), render_pass.quad_list.end()));
 }
 
 TEST_F(OverlayCandidateFactoryTest, RoundedCorner) {
@@ -669,8 +678,8 @@
     OverlayCandidate::CandidateStatus result =
         factory.FromDrawQuad(&quad, candidate);
     ASSERT_EQ(result, OverlayCandidate::CandidateStatus::kSuccess);
-    EXPECT_FALSE(factory.IsOccludedByFilteredQuad(candidate, quad_list.begin(),
-                                                  quad_list.end(), filter_map));
+    EXPECT_FALSE(OverlayCandidateFactory::IsOccludedByFilteredQuad(
+        quad, quad_list.begin(), quad_list.end(), filter_map));
   }
 
   // Check that a transformed 1x1 quad intersects with the filtered RPDQ.
@@ -684,8 +693,8 @@
     OverlayCandidate::CandidateStatus result =
         factory.FromDrawQuad(&quad, candidate);
     ASSERT_EQ(result, OverlayCandidate::CandidateStatus::kSuccess);
-    EXPECT_TRUE(factory.IsOccludedByFilteredQuad(candidate, quad_list.begin(),
-                                                 quad_list.end(), filter_map));
+    EXPECT_TRUE(OverlayCandidateFactory::IsOccludedByFilteredQuad(
+        quad, quad_list.begin(), quad_list.end(), filter_map));
   }
 }
 
diff --git a/components/viz/service/display/overlay_processor_win.cc b/components/viz/service/display/overlay_processor_win.cc
index 9d36cae..1c9d4ea 100644
--- a/components/viz/service/display/overlay_processor_win.cc
+++ b/components/viz/service/display/overlay_processor_win.cc
@@ -518,6 +518,12 @@
 
   // Try to promote all the quads in the root pass to overlay.
   for (const auto* quad : root_render_pass->quad_list.BackToFront()) {
+    if (OverlayCandidateFactory::IsOccludedByFilteredQuad(
+            *quad, root_render_pass->quad_list.begin(),
+            root_render_pass->quad_list.end(), render_pass_backdrop_filters)) {
+      return base::unexpected(DelegationStatus::kCompositedBackdropFilter);
+    }
+
     std::optional<OverlayCandidate> dc_layer;
     if (is_full_delegated_compositing) {
       // Try to promote videos like DCLayerOverlay does first, then fall back to
@@ -551,12 +557,6 @@
       }
     }
 
-    if (factory.IsOccludedByFilteredQuad(
-            dc_layer.value(), root_render_pass->quad_list.begin(),
-            root_render_pass->quad_list.end(), render_pass_backdrop_filters)) {
-      return base::unexpected(DelegationStatus::kCompositedBackdropFilter);
-    }
-
     // Store metadata on RPDQ overlays for post-processing in
     // |UpdatePromotedRenderPassProperties| to support partially delegated
     // compositing.
diff --git a/components/viz/service/display/overlay_strategy_single_on_top.cc b/components/viz/service/display/overlay_strategy_single_on_top.cc
index 97e0e2c..ae9477c 100644
--- a/components/viz/service/display/overlay_strategy_single_on_top.cc
+++ b/components/viz/service/display/overlay_strategy_single_on_top.cc
@@ -141,12 +141,12 @@
 
       // Candidates with rounded-display masks should not overlap with any other
       // quad with rounded-display masks.
-      DCHECK(!candidate_factory.IsOccluded(candidate, quad_list->begin(),
-                                           quad_it));
+      DCHECK(!OverlayCandidateFactory::IsOccluded(**quad_it, quad_list->begin(),
+                                                  quad_it));
 
       candidates_with_masks.emplace_back(quad_it, candidate, this);
-    } else if (!candidate_factory.IsOccluded(candidate, first_non_mask_quad_it,
-                                             quad_it)) {
+    } else if (!OverlayCandidateFactory::IsOccluded(
+                   **quad_it, first_non_mask_quad_it, quad_it)) {
       // We exclude quads with rounded-display masks from the occlusion
       // calculation as they will be promoted to overlays if they occlude any
       // SingleOnTop candidate. In case these quads are not promoted, the
diff --git a/components/viz/service/display/overlay_strategy_underlay.cc b/components/viz/service/display/overlay_strategy_underlay.cc
index 3996be4..127ad1b 100644
--- a/components/viz/service/display/overlay_strategy_underlay.cc
+++ b/components/viz/service/display/overlay_strategy_underlay.cc
@@ -63,8 +63,8 @@
     // If we are requiring an overlay, then we should not block it due to this
     // condition.
     if (!candidate.requires_overlay &&
-        candidate_factory.IsOccludedByFilteredQuad(
-            candidate, quad_list.begin(), it, render_pass_backdrop_filters)) {
+        OverlayCandidateFactory::IsOccludedByFilteredQuad(
+            **it, quad_list.begin(), it, render_pass_backdrop_filters)) {
       continue;
     }