// 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