chromium/components/viz/service/display/surface_aggregator_unittest.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "components/viz/service/display/surface_aggregator.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/format_macros.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "cc/base/math_util.h"
#include "cc/test/render_pass_test_utils.h"
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/common/quads/aggregated_render_pass_draw_quad.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/compositor_render_pass.h"
#include "components/viz/common/quads/compositor_render_pass_draw_quad.h"
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/quads/yuv_video_draw_quad.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/common/surfaces/subtree_capture_id.h"
#include "components/viz/service/display/aggregated_frame.h"
#include "components/viz/service/display/display_resource_provider_software.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/pending_copy_output_request.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "components/viz/test/begin_frame_args_test.h"
#include "components/viz/test/compositor_frame_helpers.h"
#include "components/viz/test/draw_quad_matchers.h"
#include "components/viz/test/fake_compositor_frame_sink_client.h"
#include "components/viz/test/fake_surface_observer.h"
#include "components/viz/test/stub_surface_client.h"
#include "components/viz/test/test_surface_id_allocator.h"
#include "gpu/command_buffer/service/scheduler.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/video_types.h"

namespace viz {
namespace {

_;
ElementsAre;

constexpr FrameSinkId kArbitraryRootFrameSinkId(1, 1);
constexpr FrameSinkId kArbitraryFrameSinkId1(2, 2);
constexpr FrameSinkId kArbitraryFrameSinkId2(3, 3);
constexpr FrameSinkId kArbitraryMiddleFrameSinkId(4, 4);
constexpr FrameSinkId kArbitraryReservedFrameSinkId(5, 5);
constexpr FrameSinkId kArbitraryFrameSinkId3(6, 6);
constexpr FrameSinkId kArbitraryFrameSinkId4(7, 7);
constexpr FrameSinkId kArbitraryFrameSinkId5(8, 8);

constexpr gfx::Size kSurfaceSize(100, 100);
constexpr gfx::Rect kEmptyDamage(0, 0);

class MockAggregatedDamageCallback {};

class DisplayTimeSource {};

}  // namespace

class SurfaceAggregatorTest : public testing::Test, public DisplayTimeSource {};

class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {};

// This test is parameterized on a boolean value to allow the
// SurfaceDrawQuad(s) in the test to merge the root render pass of its embedded
// surface to its parent render pass.
class SurfaceAggregatorValidSurfaceWithMergingPassesTest
    : public SurfaceAggregatorValidSurfaceTest,
      public testing::WithParamInterface<bool> {};

// Tests that a very simple frame containing only two solid color quads makes it
// through the aggregator correctly.
TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {}

// Tests that SharedElement quads are skipped during aggregation.
TEST_F(SurfaceAggregatorValidSurfaceTest, SharedElementQuad) {}

// Test that when surface is translucent and we need the render surface to apply
// the opacity, we would keep the render surface.
TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {}

// Test that when surface is rotated and we need the render surface to apply the
// clip, we would keep the render surface.
TEST_F(SurfaceAggregatorValidSurfaceTest, RotatedClip) {}

// Validate that implicit clipping when quads are drawn to an intermediate
// render pass texture the same size as the render pass output_rect is
// maintained even if the root render pass for a surface is merged into the
// embedding render pass and there is no intermediate texture.
TEST_F(SurfaceAggregatorValidSurfaceTest, ClipMergedPasses) {}

TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {}

// Ensure that the render pass ID map properly keeps and deletes entries.
TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassDeallocation) {}

// Ensure that the render pass ID map properly keeps and deletes entries.
TEST_F(SurfaceAggregatorValidSurfaceTest, MultiSurfacePassDeallocation) {}

// This tests very simple embedding. root_surface has a frame containing a few
// solid color quads and a surface quad referencing embedded_surface.
// embedded_surface has a frame containing only a solid color quad. The solid
// color quad should be aggregated into the final frame.
TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {}

class TestVizClient {};

TEST_F(SurfaceAggregatorValidSurfaceTest, UndrawnSurfaces) {}

TEST_F(SurfaceAggregatorValidSurfaceTest, UndrawnSurfacesWithCopyRequests) {}

TEST_F(SurfaceAggregatorValidSurfaceTest,
       SurfacesWithMultipleEmbeddersBothVisibleAndInvisible) {}

// Verify that when the parent and child surface have different device scale
// factors both the damage_rect and aggregated quads from the child surface are
// scaled appropriately. https://crbug.com/1115896 was caused by a mismatch in
// the scaling of quads and damage from a child surface.
TEST_F(SurfaceAggregatorValidSurfaceTest, ScaleForDeviceScaleFactor) {}

// Verify that layer_ids are deduplicated in the final AggregatedFrame
// correctly.
TEST_F(SurfaceAggregatorValidSurfaceTest, LayerIds) {}

// This test verifies that the appropriate transform will be applied to a
// surface embedded by a parent SurfaceDrawQuad marked as
// stretch_content_to_fill_bounds.
TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillBounds) {}

// This test verifies that the appropriate transform will be applied to a
// surface embedded by a parent SurfaceDrawQuad marked as
// stretch_content_to_fill_bounds when the device_scale_factor is
// greater than 1.
TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillStretchedBounds) {}

// This test verifies that the appropriate transform will be applied to a
// surface embedded by a parent SurfaceDrawQuad marked as
// stretch_content_to_fill_bounds when the device_scale_factor is
// less than 1.
TEST_F(SurfaceAggregatorValidSurfaceTest, StretchContentToFillSquashedBounds) {}

// Verify that a reflected SurfaceDrawQuad with scaling won't have the surfaces
// root RenderPass merged with the RenderPass that embeds it. This ensures the
// reflected pixels can be scaled with AA enabled.
TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadScaled) {}

// Verify that a reflected SurfaceDrawQuad with no scaling has the surfaces root
// RenderPass merged with the RenderPass that embeds it.
TEST_F(SurfaceAggregatorValidSurfaceTest, ReflectedSurfaceDrawQuadNotScaled) {}

// This test verifies that in the presence of both primary Surface and fallback
// Surface, the fallback will not be used.
TEST_F(SurfaceAggregatorValidSurfaceTest, FallbackSurfaceReferenceWithPrimary) {}

TEST_F(SurfaceAggregatorValidSurfaceTest, CopyRequest) {}

TEST_F(SurfaceAggregatorValidSurfaceTest,
       ShouldNotTakeCopyRequestIfTakeCopyRequestIsFalse) {}

// Check that a copy request does not prevent protected quads from being
// displayed. Protected quads must merge to the root render pass to be
// considered for overlay promotion, which is required for their display.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       CopyRequestOnEmbeddedSurfaceWithProtectedQuads) {}

// This is the same test as CopyRequestOnEmbeddedSurfaceWithProtectedQuads, but
// ensures that we can still merge the render pass with the copy request even if
// it does not directly contain the protected quad and transitively embeds it.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       CopyRequestOnSurfaceEmbeddingSurfaceWithProtectedQuads) {}

// Root surface may contain copy requests.
TEST_F(SurfaceAggregatorValidSurfaceTest, RootCopyRequest) {}

TEST_F(SurfaceAggregatorValidSurfaceTest,
       ShouldNotTakeRootCopyRequestIfTakeCopyRequestIsFalse) {}

TEST_F(SurfaceAggregatorValidSurfaceTest, VideoCapturePreventsMerge) {}

TEST_F(SurfaceAggregatorValidSurfaceTest, UnreferencedSurface) {}

// This tests referencing a surface that has multiple render passes.
TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {}

// Tests an invalid surface reference in a frame. The surface quad should just
// be dropped.
TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {}

// Tests a reference to a valid surface with no submitted frame. A
// SolidColorDrawQuad should be placed in lieu of a frame.
TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {}

// Tests a reference to a valid primary surface and a fallback surface
// with no submitted frame. A SolidColorDrawQuad should be placed in lieu of a
// frame.
TEST_F(SurfaceAggregatorValidSurfaceTest, ValidFallbackWithNoFrame) {}

// Tests a surface quad referencing itself, generating a trivial cycle.
// The quad creating the cycle should be dropped from the final frame.
TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {}

// Tests a more complex cycle with one intermediate surface.
TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {}

// Tests that we map render pass IDs from different surfaces into a unified
// namespace and update CompositorRenderPassDrawQuad's id references to match.
TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {}

// This tests that we update shared quad state pointers correctly within
// aggregated passes.  The shared quad state list on the aggregated pass will
// include the shared quad states from each pass in one list so the quads will
// end up pointed to shared quad state objects at different offsets. This test
// uses the blend_mode value stored on the shared quad state to track the shared
// quad state, but anything saved on the shared quad state would work.
//
// This test has 4 surfaces in the following structure:
// root_surface -> quad with kClear_Mode,
//                 [child_one_surface],
//                 quad with kDstOver_Mode,
//                 [child_two_surface],
//                 quad with kDstIn_Mode
// child_one_surface -> quad with kSrc_Mode,
//                      [grandchild_surface],
//                      quad with kSrcOver_Mode
// child_two_surface -> quad with kSrcIn_Mode
// grandchild_surface -> quad with kDst_Mode
//
// Resulting in the following aggregated pass:
//  quad_root_0       - blend_mode kClear_Mode
//  quad_child_one_0  - blend_mode kSrc_Mode
//  quad_grandchild_0 - blend_mode kDst_Mode
//  quad_child_one_1  - blend_mode kSrcOver_Mode
//  quad_root_1       - blend_mode kDstOver_Mode
//  quad_child_two_0  - blend_mode kSrcIn_Mode
//  quad_root_2       - blend_mode kDstIn_Mode
TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {}

// This tests that we update shared quad state pointers for rounded corner
// bounds correctly within aggregated passes. In case of fast rounded corners or
// rounded corners that fit parent pass' rounded corners, the surface aggregator
// tries to optimize by merging the the surface quads instead of keeping the
// surface render pass.
//
// This test has 4 surfaces in the following structure:
// root_surface         -> [child_root_surface] has fast rounded corner [1],
// child_root_surface   -> [child_one_surface],
//                         [child_two_surface],
//                         quad (a),
// child_one_surface    -> quad (b),
//                         [child three surface],
//                         [child four surface]
// child_two_surface    -> quad (c),
//                      -> quad (d) has fast rounded corner [2]
//                      -> [child_five_surface]
// child_three_surface  -> quad (e),
// child_four_surface   -> quad (f) has fast rounded corner [3]
// child_five_surface   -> quad (g) has rounded corner [4]
//
// Resulting in the following aggregated pass:
// Root Pass:
//  quad (b)          - fast rounded corner [1]
//  quad (e)          - fast rounded corner [1]
//  render pass quad  - fast rounded corner [1]
//  render pass quad  - fast rounded corner [1]
//  quad (c)          - fast rounded corner [1]
//  quad (d)          - rounded corner [2]
//  quad (a)          - fast rounded corner [1]
// Render pass for child_four_surface:
//  quad (f)          - fast rounded corner [3]
// Render pass for child_five_surface:
//  quad (g)          - rounded corner [4]
TEST_F(SurfaceAggregatorValidSurfaceTest,
       AggregateSharedQuadStateRoundedCornerBounds) {}

// Same as above, but with clipping applied. The embedding render pass will have
// mask and clip that are either smaller, equal, or bigger when combined than
// the mask of a render pass where the SurfaceAggregator will try to merge that
// embedding pass in.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       AggregateSharedQuadStateRoundedCornerBoundsClipping) {}

// Tests that transforms are properly handled.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       AggregateSharedQuadStateRoundedCornerBounds2) {}

// This tests that when aggregating a frame with multiple render passes that we
// map the transforms for the root pass but do not modify the transform on child
// passes.
//
// The root surface has one pass with a surface quad transformed by +10 in the y
// direction.
//
// The middle surface has one pass with a surface quad scaled by 2 in the x
// and 3 in the y directions.
//
// The child surface has two passes. The first pass has a quad with a transform
// of +5 in the x direction. The second pass has a reference to the first pass'
// pass id and a transform of +8 in the x direction.
//
// After aggregation, the child surface's root pass quad should have all
// transforms concatenated for a total transform of +23 x, +10 y. The
// contributing render pass' transform in the aggregate frame should not be
// affected.
TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {}

// This test verifies that in the absence of a primary Surface,
// SurfaceAggregator will embed a fallback Surface, if available. If the primary
// surface is available, though, the fallback will not be used.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       FallbackSurfaceReference) {}

// Tests that damage rects are aggregated correctly when surfaces change.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       AggregateDamageRect) {}

// Tests that damage rects are aggregated correctly when surfaces stretch to
// fit and device size is less than 1.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       AggregateDamageRectWithSquashToFit) {}

// Tests that damage rects are aggregated correctly when surfaces stretch to
// fit and device size is greater than 1.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       AggregateDamageRectWithStretchToFit) {}

// Check that damage is correctly calculated for surfaces.
TEST_F(SurfaceAggregatorValidSurfaceTest, SwitchSurfaceDamage) {}

// Verifies that damage to any surface between primary and fallback damages the
// display if primary and fallback have the FrameSinkId.
TEST_F(SurfaceAggregatorValidSurfaceTest, SurfaceDamageSameFrameSinkId) {}

// Verifies that only damage to primary and fallback surfaces and nothing in
// between damages the display if primary and fallback have different
// FrameSinkIds.
TEST_F(SurfaceAggregatorValidSurfaceTest, SurfaceDamageDifferentFrameSinkId) {}

// Verifies that when only a primary surface is provided any damage to primary
// surface damages the display.
TEST_F(SurfaceAggregatorValidSurfaceTest, SurfaceDamagePrimarySurfaceOnly) {}

// Verifies that when primary and fallback ids are equal, only damage to that
// particular surface causes damage to display.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       SurfaceDamagePrimaryAndFallbackEqual) {}

// Tests the behavior of |intersects_damage_under| flag on a
// CompositorRenderPassDrawQuad, which should reset to false if the damage from
// quads below drawing to the same target intersects the RPDQ's rect, or
// otherwise remain unchanged.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       RPDQBackdropFilterCacheFlagTest1) {}

// Tests the behavior of |intersects_damage_under| flag on a
// CompositorRenderPassDrawQuad. When damage under the RPDQ is coming from quads
// that draw to a different render target, it should not affect the
// |intersects_damage_under| flag. However, if merging happens, the RPDQ on root
// render pass of the surface being merged should take damage from all quads
// under it in the same final render target.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       RPDQBackdropFilterCacheFlagTest2) {}

// Tests that RenderPassDrawQud's |intersects_damage_under| flag is updated
// correctly with surface damage.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       RPDQCanUseBackdropFilterCache) {}

// Verifies the |intersects_damage_under| flag on a CompositorRenderPassDrawQuad
// is updated correctly in cases involving a child surface that is embedded
// twice in the root surface and whose damage affects the flag.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       RPDQCanUseBackdropFilterCacheTestWithMultiplyEmbeddedSurface) {}

// Tests the behavior of pixel moving backdrop filter damage expansion when
// passes are merge and the parent surface has damage.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       PixelMovingBackdropFilterDamageExpansion) {}

// Tests the behavior of pixel moving backdrop filter damage expansion when
// passes are merged, the parent surface has damage, and the merged surface
// is set to stretch its contents to fill bounds.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       PixelMovingBackdropFilterDamageExpansionWithSurfaceStretch) {}

SurfaceAggregatorPartialSwapTest;

TEST_F(SurfaceAggregatorPartialSwapTest, ExpandByTargetDamage) {}

class SurfaceAggregatorWithResourcesTest : public SurfaceAggregatorTest {};

CompositorFrame BuildCompositorFrameWithResources(
    const std::vector<ResourceId>& resource_ids,
    bool valid,
    SurfaceId child_id) {}

void SubmitCompositorFrameWithResources(
    const std::vector<ResourceId>& resource_ids,
    bool valid,
    SurfaceId child_id,
    CompositorFrameSinkSupport* support,
    SurfaceId surface_id) {}

TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {}

// This test verifies that when a CompositorFrame is submitted to a new surface
// ID, and a new display frame is generated, then the resources of the old
// surface are returned to the appropriate client.
TEST_F(SurfaceAggregatorWithResourcesTest, ReturnResourcesAsSurfacesChange) {}

TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) {}

TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) {}

// Ensure that aggregator completely ignores Surfaces that reference invalid
// resources.
TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) {}

TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) {}

// Ensure that the render passes have correct color spaces. This test
// simulates the Windows HDR behavior.
TEST_F(SurfaceAggregatorValidSurfaceTest, ColorSpaceTestWin) {}

// Ensure that the render passes have correct color spaces.
TEST_F(SurfaceAggregatorValidSurfaceTest, MetadataContentColorUsageTest) {}

// Tests that has_damage_from_contributing_content is aggregated correctly from
// child surface quads.
TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageByChangingChildSurface) {}

// Tests that has_damage_from_contributing_content is aggregated correctly from
// grand child surface quads.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       HasDamageByChangingGrandChildSurface) {}

// Tests that has_damage_from_contributing_content is aggregated correctly from
// grand child surface quads when render passes can't be merged.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       HasDamageByChangingGrandChildSurfaceNoMerge) {}

// Tests that has_damage_from_contributing_content is aggregated correctly when
// non-root pass has damage but root pass has no damage due to non-root damage
// being outside the root passes output_rect.
TEST_F(SurfaceAggregatorValidSurfaceTest, RootPassNoDamage) {}

// Tests that has_damage_from_contributing_content is aggregated correctly from
// render pass quads.
TEST_F(SurfaceAggregatorValidSurfaceTest, HasDamageFromRenderPassQuads) {}

// Tests that the first frame damage_rect of a cached render pass should be
// fully damaged.
TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectOfCachedRenderPass) {}

// Tests that the first frame damage_rect of cached render pass of a child
// surface should be fully damaged.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       DamageRectOfCachedRenderPassInChildSurface) {}

// Tests that the damage rect from a child surface is clipped before
// aggregated with the parent damage rect when clipping is on
TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithClippedChildSurface) {}

// Tests the damage rect with a invalid child frame
TEST_F(SurfaceAggregatorValidSurfaceTest, DamageRectWithInvalidChildFrame) {}

// Tests the overlay occluding damage rect
TEST_F(SurfaceAggregatorValidSurfaceTest, OverlayOccludingDamageRect) {}

// Tests the |per_quad_damage| feature by adding a few quads, flagged with
// |per_quad_damage|, and then checking the output damage after surface
// aggregation. By placing these quads in a surface we also test that the
// correct relevant transforms have been applied by examining the
// |surface_damage_rect_list_|.
TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassHasPerQuadDamage) {}

// Per quad damage can appear on quads that have the same 'shared_quad_state'.
// We need to make sure this will generate independent damage in the output
// listing.
TEST_F(SurfaceAggregatorValidSurfaceTest, PerQuadDamageSameSharedQuadState) {}

TEST_F(SurfaceAggregatorValidSurfaceTest, QuadContainsSurfaceDamageRect) {}

// Check that the overlay damage index is set for quads in non-root render
// passes. This can be useful e.g. if we want to do overlay processing even if
// the web contents surface does not merge.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       OverlayDamageIndexFromNonRootSurface) {}

// Check GetRectDamage() handles per quad damage correctly.
TEST_F(SurfaceAggregatorValidSurfaceTest, NonRootRenderPassWithPerQuadDamage) {}

// Validates that while the display transform is applied to the aggregated frame
// and its damage, its not applied to the callback to the root frame sink.
TEST_F(SurfaceAggregatorValidSurfaceTest, DisplayTransformDamageCallback) {}

// Tests that a rounded_corner_bounds field on a quad in a child
// surface gets mapped up to the space of the parent surface, due to
// change of target render surface. (rounded corner bounds are in the space
// of the render surface).
TEST_F(SurfaceAggregatorValidSurfaceTest, RoundedCornerTransformChange) {}

// Tests that the rounded corner bounds of a surface quad that gets transformed
// when drawing into an ancestor surface get properly mapped to the new
// coordinate space of its final render surface. It also tests the specific case
// where the surface is embedded in a parent surface that itself can't be
// merged into the root surface (due to opacity).
TEST_F(SurfaceAggregatorValidSurfaceTest, RoundedCornerTransformedSurfaceQuad) {}

// This is a variant of RoundedCornerTransformedSurfaceQuad that does not
// have opacity, and therefore can be merged into the root render pass.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       RoundedCornerTransformedMergedSurfaceQuad) {}

TEST_F(SurfaceAggregatorValidSurfaceTest, TransformedRoundedSurfaceQuad) {}

// Verifies that if a child surface is embedded twice in the root surface,
// SurfaceAggregator considers both occurrences in damage rect calculation.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       AggregateDamageRectWithMultiplyEmbeddedSurface) {}

// Verifies that if a CompositorFrame contains a render pass id cycle then the
// frame is rejected as invalid.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       AggregateDamageRectWithRenderPassCycle) {}

// Verify that a SurfaceDrawQuad with !|allow_merge| won't be merged into
// the parent renderpass.
TEST_F(SurfaceAggregatorValidSurfaceTest, AllowMerge) {}

// Check that if a non-merged surface is invisible, its entire render pass is
// skipped.
TEST_F(SurfaceAggregatorValidSurfaceTest, SkipInvisibleSurface) {}

// Verify that a SurfaceDrawQuad's root RenderPass has correct texture
// parameters if being drawn via RPDQ.
TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassDoesNotFillSurface) {}

// Tests that damage rects are aggregated correctly when surfaces change.
TEST_P(SurfaceAggregatorValidSurfaceWithMergingPassesTest,
       AggregateDamageRectWithBackdropFilter) {}

TEST_F(SurfaceAggregatorValidSurfaceTest,
       ContainedFrameSinkChangeInvalidatesHitTestData) {}

void ExpectDelegatedInkMetadataIsEqual(const gfx::DelegatedInkMetadata& lhs,
                                       const gfx::DelegatedInkMetadata& rhs) {}

// Basic test to confirm that ink metadata on a child surface will be
// transformed by the parent and only used once.
TEST_F(SurfaceAggregatorValidSurfaceTest, DelegatedInkMetadataTest) {}

// Confirm that transforms are aggregated as the tree is walked and correctly
// applied to the ink metadata.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       TransformDelegatedInkMetadataTallTree) {}

// Confirm the metadata is transformed correctly and makes it to the aggregated
// frame when there are multiple children.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       DelegatedInkMetadataMultipleChildren) {}

// Confirm the the metadata with the most recent timestamp is used when
// multiple children have delegated ink metadata.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       MultipleChildrenHaveDelegatedInkMetadata) {}

// Confirm that delegated ink metadata on an undrawn surface is not on the
// aggregated surface unless the undrawn surface contains a CopyOutputRequest.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       DelegatedInkMetadataOnUndrawnSurface) {}

TEST_F(SurfaceAggregatorValidSurfaceTest, HasUnembeddedRenderPass) {}

TEST_F(SurfaceAggregatorValidSurfaceTest,
       HasDamageFromContributingPropagatedForUnembeddedRenderPass) {}

// Tests that a CopyOutputRequest on a render pass that's not embedded from the
// root pass is recognized when copying secure texture content.
TEST_F(SurfaceAggregatorValidSurfaceTest,
       CopyRequestWithSecureOutputForUnembeddedRenderPass) {}

// Tests that changing the color usage results in full-frame damage.
TEST_F(SurfaceAggregatorValidSurfaceTest, ColorUsageChangeFullFrameDamage) {}

// Test the Clip Rect of a non-merged pass from an embedded surface.
TEST_F(SurfaceAggregatorValidSurfaceTest, ClipRectNonMergedPass) {}

INSTANTIATE_TEST_SUITE_P();

#if BUILDFLAG(IS_WIN)
// The flag |prevent_merging_surfaces_to_root_pass| prevents surfaces referenced
// by the root pass of the root surface (e.g. the web contents surface(s)) from
// merging during surface aggregation. This enables
// |kDelegatedCompositingLimitToUi| because in delegated compositing mode, those
// surfaces become RPDQ overlays.
class SurfaceAggregatorPreventMergeTest
    : public SurfaceAggregatorValidSurfaceTest {
 protected:
  SurfaceAggregatorPreventMergeTest()
      : SurfaceAggregatorValidSurfaceTest(
            SurfaceAggregator::ExtraPassForReadbackOption::kNone,
            /*prevent_merging_surfaces_to_root_pass=*/true) {}
};

// Check that surfaces in the root pass are not allowed to merge.
TEST_F(SurfaceAggregatorPreventMergeTest, PreventMerge) {
  const gfx::Rect child_rect(5, 5);

  TestVizClient child(this, &manager_, kArbitraryFrameSinkId1, child_rect);
  child.SubmitCompositorFrame(SkColors::kGreen);

  // Submit a SurfaceDrawQuad that allows merging, but will be prevented.
  {
    std::vector<Quad> root_quads = {
        Quad::SurfaceQuad(SurfaceRange(std::nullopt, child.surface_id()),
                          SkColors::kWhite, child_rect, false, true)};
    std::vector<Pass> root_passes = {
        Pass(root_quads, CompositorRenderPassId{1}, kSurfaceSize)};

    CompositorFrame frame = MakeEmptyCompositorFrame();
    AddPasses(&frame.render_pass_list, root_passes,
              &frame.metadata.referenced_surfaces);

    root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
                                      std::move(frame));
  }

  auto aggregated_frame = AggregateFrame(root_surface_id_);

  // We expect |child| to be prevented from merging.
  EXPECT_EQ(2u, aggregated_frame.render_pass_list.size());
}

TEST_F(SurfaceAggregatorPreventMergeTest, NonRootSurfacesCanMerge) {
  const gfx::Rect child_rect(5, 5);

  // Submit a leaf surface that does not contain other surfaces. This should be
  // merged into |child_surface_id| because |child_surface_id| is not the root.
  TestVizClient inner_child(this, &manager_, kArbitraryFrameSinkId1,
                            child_rect);
  inner_child.SubmitCompositorFrame(SkColors::kBlue);

  // Submit an intermediate surface that embeds the leaf and will be embedded by
  // the root.
  TestSurfaceIdAllocator child_surface_id(child_sink_->frame_sink_id());
  {
    std::vector<Quad> child_quads = {
        Quad::SurfaceQuad(SurfaceRange(std::nullopt, inner_child.surface_id()),
                          SkColors::kGreen, child_rect, false, true)};
    std::vector<Pass> child_passes = {
        Pass(child_quads, CompositorRenderPassId{1}, kSurfaceSize)};

    CompositorFrame child_frame = MakeEmptyCompositorFrame();
    AddPasses(&child_frame.render_pass_list, child_passes,
              &child_frame.metadata.referenced_surfaces);

    child_sink_->SubmitCompositorFrame(child_surface_id.local_surface_id(),
                                       std::move(child_frame));
  }

  // Submit a SurfaceDrawQuad that allows merging, but will be prevented.
  {
    std::vector<Quad> root_quads = {
        Quad::SurfaceQuad(SurfaceRange(std::nullopt, child_surface_id),
                          SkColors::kWhite, child_rect, false, true)};
    std::vector<Pass> root_passes = {
        Pass(root_quads, CompositorRenderPassId{1}, kSurfaceSize)};

    CompositorFrame frame = MakeEmptyCompositorFrame();
    AddPasses(&frame.render_pass_list, root_passes,
              &frame.metadata.referenced_surfaces);

    root_sink_->SubmitCompositorFrame(root_surface_id_.local_surface_id(),
                                      std::move(frame));
  }

  auto aggregated_frame = AggregateFrame(root_surface_id_);

  // We expect |inner_child| to merge into |child_surface_id|, but not for
  // |child_surface_id| to merge into |root_surface_id_|.
  EXPECT_EQ(2u, aggregated_frame.render_pass_list.size());
}
#endif

class SurfaceAggregatorVulkanSecondaryCB
    : public SurfaceAggregatorValidSurfaceTest {};

TEST_F(SurfaceAggregatorVulkanSecondaryCB, AppendPassForFrameWithFilter) {}

TEST_F(SurfaceAggregatorVulkanSecondaryCB,
       DoNotAppendPassForFrameWithoutReadback) {}

namespace {

// Blocks until `OnScreenshotCaptured()` is called.
class OnScreenshotCapturedWaiter : public mojom::FrameSinkManagerClient {};

class SurfaceAggregatorCopyRequestAgainstPreviousSurfaceTest
    : public SurfaceAggregatorValidSurfaceTest,
      public ::testing::WithParamInterface<bool> {};

std::string DescribeParam(const ::testing::TestParamInfo<bool>& info) {}

}  // namespace

TEST_P(SurfaceAggregatorCopyRequestAgainstPreviousSurfaceTest,
       CopyAgainstPreviousSurface) {}

INSTANTIATE_TEST_SUITE_P();

}  // namespace viz