chromium/cc/trees/draw_properties_unittest.cc

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

#include <stddef.h>

#include <algorithm>
#include <memory>
#include <set>
#include <tuple>
#include <vector>

#include "base/containers/contains.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/test/scoped_feature_list.h"
#include "cc/animation/animation.h"
#include "cc/animation/animation_host.h"
#include "cc/animation/animation_id_provider.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/effect_tree_layer_list_iterator.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/render_surface_impl.h"
#include "cc/test/animation_test_common.h"
#include "cc/test/fake_content_layer_client.h"
#include "cc/test/fake_picture_layer.h"
#include "cc/test/fake_picture_layer_impl.h"
#include "cc/test/layer_tree_impl_test_base.h"
#include "cc/test/property_tree_test_utils.h"
#include "cc/trees/clip_node.h"
#include "cc/trees/draw_property_utils.h"
#include "cc/trees/effect_node.h"
#include "cc/trees/scroll_node.h"
#include "cc/trees/transform_node.h"
#include "components/viz/common/features.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/animation/keyframe/keyframed_animation_curve.h"
#include "ui/gfx/geometry/linear_gradient.h"
#include "ui/gfx/geometry/quad_f.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/test/geometry_util.h"
#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/geometry/transform_operations.h"
#include "ui/gfx/geometry/transform_util.h"
#include "ui/gfx/geometry/vector2d_conversions.h"

namespace cc {
namespace {

bool LayerSubtreeHasCopyRequest(Layer* layer) {}

class DrawPropertiesTestBase : public LayerTreeImplTestBase {};

class DrawPropertiesTest : public DrawPropertiesTestBase,
                           public testing::Test {};

class DrawPropertiesTestWithLayerTree : public DrawPropertiesTestBase,
                                        public testing::Test {};

class DrawPropertiesDrawRectsTest : public DrawPropertiesTest {};

// Sanity check: For layers positioned at zero, with zero size,
// and with identity transforms, then the draw transform,
// screen space transform, and the hierarchy passed on to children
// layers should also be identity transforms.
TEST_F(DrawPropertiesTest, TransformsForNoOpLayer) {}

TEST_F(DrawPropertiesTest, TransformsForSingleLayer) {}

TEST_F(DrawPropertiesTest, TransformsAboutScrollOffset) {}

TEST_F(DrawPropertiesTest, TransformsForSimpleHierarchy) {}

TEST_F(DrawPropertiesTest, TransformsForSingleRenderSurface) {}

TEST_F(DrawPropertiesTest, TransformsForRenderSurfaceHierarchy) {}

TEST_F(DrawPropertiesTest, LayerFullyContainedWithinClipInTargetSpace) {}

TEST_F(DrawPropertiesTest, TransformsForDegenerateIntermediateLayer) {}

TEST_F(DrawPropertiesTest, RenderSurfaceWithSublayerScale) {}

TEST_F(DrawPropertiesTest, TransformAboveRootLayer) {}

TEST_F(DrawPropertiesTest, DrawableContentRectForReferenceFilter) {}

TEST_F(DrawPropertiesTest, DrawableContentRectForReferenceFilterHighDpi) {}

TEST_F(DrawPropertiesTest, VisibleLayerRectForBlurFilterUnderClip) {}

TEST_F(DrawPropertiesTest, VisibleLayerRectForReferenceFilterUnderClip) {}

TEST_F(DrawPropertiesTest, RenderSurfaceForBlendMode) {}

TEST_F(DrawPropertiesTest, RenderSurfaceDrawOpacity) {}

TEST_F(DrawPropertiesTest, ClipRectCullsRenderSurfaces) {}

TEST_F(DrawPropertiesTest, ClipRectCullsSurfaceWithoutVisibleContent) {}

TEST_F(DrawPropertiesTest, IsClippedIsSetCorrectlyLayerImpl) {}

TEST_F(DrawPropertiesTest, UpdateClipRectCorrectly) {}

TEST_F(DrawPropertiesTest, DrawableContentRectForLayers) {}

TEST_F(DrawPropertiesTest, ClipRectIsPropagatedCorrectlyToSurfaces) {}

TEST_F(DrawPropertiesTest, AnimationsForRenderSurfaceHierarchy) {}

TEST_F(DrawPropertiesTest, LargeTransforms) {}

static bool TransformIsAnimating(LayerImpl* layer) {}

static bool HasPotentiallyRunningTransformAnimation(LayerImpl* layer) {}

TEST_F(DrawPropertiesTest,
       ScreenSpaceTransformIsAnimatingWithDelayedAnimation) {}

// Test visible layer rect and drawable content rect are calculated correctly
// for identity transforms.
TEST_F(DrawPropertiesDrawRectsTest, DrawRectsForIdentityTransform) {}

// Test visible layer rect and drawable content rect are calculated correctly
// for rotations about z-axis (i.e. 2D rotations).
TEST_F(DrawPropertiesDrawRectsTest, DrawRectsFor2DRotations) {}

// Test visible layer rect and drawable content rect are calculated correctly
// for 3d transforms.
TEST_F(DrawPropertiesDrawRectsTest, DrawRectsFor3dOrthographicTransform) {}

// Test visible layer rect and drawable content rect are calculated correctly
// when the layer has a perspective projection onto the target surface.
TEST_F(DrawPropertiesDrawRectsTest, DrawRectsFor3dPerspectiveTransform) {}

// There is currently no explicit concept of an orthographic projection plane
// in our code (nor in the CSS spec to my knowledge). Therefore, layers that
// are technically behind the surface in an orthographic world should not be
// clipped when they are flattened to the surface.
TEST_F(DrawPropertiesDrawRectsTest,
       DrawRectsFor3dOrthographicIsNotClippedBehindSurface) {}

// Test visible layer rect and drawable content rect are calculated correctly
// when projecting a surface onto a layer, but the layer is partially behind
// the camera (not just behind the projection plane). In this case, the
// cartesian coordinates may seem to be valid, but actually they are not. The
// visible rect needs to be properly clipped by the w = 0 plane in homogeneous
// coordinates before converting to cartesian coordinates. The drawable
// content rect would be entire surface rect because layer is rotated at the
// camera position.
TEST_F(DrawPropertiesDrawRectsTest, DrawRectsFor3dPerspectiveWhenClippedByW) {}

static bool ProjectionClips(const gfx::Transform& map_transform,
                            const gfx::RectF& mapped_rect) {}

// To determine visible rect in layer space, there needs to be an
// un-projection from surface space to layer space. When the original
// transform was a perspective projection that was clipped, it returns a rect
// that encloses the clipped bounds.  Un-projecting this new rect may require
// clipping again.
TEST_F(DrawPropertiesDrawRectsTest, DrawRectsForPerspectiveUnprojection) {}

TEST_F(DrawPropertiesTest, DrawableAndVisibleContentRectsForSimpleLayers) {}

TEST_F(DrawPropertiesTest,
       DrawableAndVisibleContentRectsForLayersClippedByLayer) {}

TEST_F(DrawPropertiesTest, VisibleContentRectWithClippingAndScaling) {}

TEST_F(DrawPropertiesTest, ClipRectWithClipParent) {}

TEST_F(DrawPropertiesTest, ClipRectWithClippedDescendantOfFilter) {}

TEST_F(DrawPropertiesTest,
       DrawableAndVisibleContentRectsForLayersInUnclippedRenderSurface) {}

TEST_F(DrawPropertiesTest, VisibleContentRectsForClippedSurfaceWithEmptyClip) {}

TEST_F(DrawPropertiesTest,
       DrawableAndVisibleContentRectsForLayersWithUninvertibleTransform) {}

TEST_F(DrawPropertiesTest,
       VisibleContentRectForLayerWithUninvertibleDrawTransform) {}

TEST_F(DrawPropertiesTest, ClipExpanderWithUninvertibleTransform) {}

// Needs layer tree mode: mask layer.
TEST_F(DrawPropertiesTestWithLayerTree, OcclusionBySiblingOfTarget) {}

// Occlusion immune with kAllowUndamagedNonrootRenderPassToSkip enabled.
TEST_F(DrawPropertiesTestWithLayerTree, OcclusionImmuneForSiblingOfTarget) {}

TEST_F(DrawPropertiesTest, OcclusionForLayerWithUninvertibleDrawTransform) {}

TEST_F(DrawPropertiesTest,
       DrawableAndVisibleContentRectsForLayersInClippedRenderSurface) {}

// Check that clipping does not propagate down surfaces.
TEST_F(DrawPropertiesTest, DrawableAndVisibleContentRectsForSurfaceHierarchy) {}

TEST_F(DrawPropertiesTest,
       VisibleRectsForClippedDescendantsOfUnclippedSurfaces) {}

TEST_F(DrawPropertiesTest,
       VisibleRectsWhenClipChildIsBetweenTwoRenderSurfaces) {}

TEST_F(DrawPropertiesTest, ClipRectOfSurfaceWhoseParentIsAClipChild) {}

TEST_F(DrawPropertiesTest,
       RenderSurfaceCommonAncestorClipOnChangeOfChildLayerClip) {}

// Test that only drawn layers contribute to render surface content rect.
TEST_F(DrawPropertiesTest, RenderSurfaceContentRectWhenLayerNotDrawn) {}

// Tests visible rects computation when we have unclipped_surface->
// surface_with_unclipped_descendants->clipped_surface, checks that the bounds
// of surface_with_unclipped_descendants doesn't propagate to the
// clipped_surface below it.
TEST_F(DrawPropertiesTest, VisibleRectsMultipleSurfaces) {}

// Tests visible rects computation when we have unclipped_surface->
// surface_with_unclipped_descendants->clipped_surface, checks that the bounds
// of root propagate to the clipped_surface.
TEST_F(DrawPropertiesTest, RootClipPropagationToClippedSurface) {}

// Layers that have non-axis aligned bounds (due to transforms) have an
// expanded, axis-aligned DrawableContentRect and visible content rect.
TEST_F(DrawPropertiesTest,
       DrawableAndVisibleContentRectsWithTransformOnUnclippedSurface) {}

// Layers that have non-axis aligned bounds (due to transforms) have an
// expanded, axis-aligned DrawableContentRect and visible content rect.
TEST_F(DrawPropertiesTest,
       DrawableAndVisibleContentRectsWithTransformOnClippedSurface) {}

TEST_F(DrawPropertiesTest, DrawableAndVisibleContentRectsInHighDPI) {}

DrawPropertiesScalingTest;

// Verify draw and screen space transforms of layers not in a surface.
TEST_F(DrawPropertiesScalingTest, LayerTransformsInHighDPI) {}

// Verify draw and screen space transforms of layers in a surface.
TEST_F(DrawPropertiesScalingTest, SurfaceLayerTransformsInHighDPI) {}

TEST_F(DrawPropertiesScalingTest, SmallIdealScale) {}

TEST_F(DrawPropertiesScalingTest, IdealScaleForAnimatingLayer) {}

TEST_F(DrawPropertiesTest, RenderSurfaceTransformsInHighDPI) {}

TEST_F(DrawPropertiesTest,
       RenderSurfaceTransformsInHighDPIAccurateScaleZeroPosition) {}

// Needs layer tree mode: mask layer. Not using impl-side PropertyTreeBuilder.
TEST_F(DrawPropertiesTestWithLayerTree, LayerSearch) {}

TEST_F(DrawPropertiesTest, TransparentChildRenderSurfaceCreation) {}

TEST_F(DrawPropertiesTest, OpacityAnimatingOnPendingTree) {}

class BackfaceVisibilityInteropTest : public DrawPropertiesTestBase,
                                      public testing::Test {};

TEST_F(BackfaceVisibilityInteropTest, BackfaceInvisibleTransform) {}

// Needs layer tree mode: hide_layer_and_subtree.
TEST_F(DrawPropertiesTestWithLayerTree, SubtreeHidden_SingleLayerImpl) {}

// Needs layer tree mode: hide_layer_and_subtree.
TEST_F(DrawPropertiesTestWithLayerTree, SubtreeHidden_TwoLayersImpl) {}

// Needs layer tree mode: mask layer, hide_layer_and_subtree and copy request.
TEST_F(DrawPropertiesTestWithLayerTree, SubtreeHiddenWithCopyRequest) {}

// Needs layer tree mode: copy request.
TEST_F(DrawPropertiesTestWithLayerTree, ClippedOutCopyRequest) {}

// Needs layer tree mode: copy request.
TEST_F(DrawPropertiesTestWithLayerTree, SingularTransformAndCopyRequests) {}

// Needs layer tree mode: copy request.
TEST_F(DrawPropertiesTestWithLayerTree, VisibleRectInNonRootCopyRequest) {}

TEST_F(DrawPropertiesTest, TransformedClipParent) {}

TEST_F(DrawPropertiesTest, ClipParentWithInterveningRenderSurface) {}

TEST_F(DrawPropertiesTest, ClipParentScrolledInterveningLayer) {}

TEST_F(DrawPropertiesTest, DescendantsOfClipChildren) {}

TEST_F(DrawPropertiesTest,
       SurfacesShouldBeUnaffectedByNonDescendantClipChildren) {}

TEST_F(DrawPropertiesTest, TransformAnimationUpdatesBackfaceVisibility) {}

TEST_F(DrawPropertiesTest, ScrollChildAndScrollParentDifferentTargets) {}

TEST_F(DrawPropertiesTest, SingularTransformSubtreesDoNotDraw) {}

TEST_F(DrawPropertiesTest, ScrollSnapping) {}

TEST_F(DrawPropertiesTest, ScrollSnappingWithAnimatedScreenSpaceTransform) {}

TEST_F(DrawPropertiesTest, ScrollSnappingWithScrollChild) {}

class DrawPropertiesStickyPositionTest : public DrawPropertiesTest {};

TEST_F(DrawPropertiesStickyPositionTest, StickyPositionTop) {}

TEST_F(DrawPropertiesStickyPositionTest, StickyPositionTopRounded) {}

TEST_F(DrawPropertiesStickyPositionTest, StickyPositionSubpixelScroll) {}

TEST_F(DrawPropertiesStickyPositionTest, StickyPositionBottom) {}

TEST_F(DrawPropertiesStickyPositionTest, StickyPositionBottomRounded) {}

TEST_F(DrawPropertiesStickyPositionTest,
       StickyPositionBottomOuterViewportDelta) {}

TEST_F(DrawPropertiesStickyPositionTest, StickyPositionLeftRight) {}

// This test ensures that the compositor sticky position code correctly accounts
// for the element having been given a position from the main thread sticky
// position code.
TEST_F(DrawPropertiesStickyPositionTest, StickyPositionMainThreadUpdates) {}

// This tests the main thread updates with a composited sticky container. In
// this case the position received from main is relative to the container but
// the constraint rects are relative to the ancestor scroller.
TEST_F(DrawPropertiesStickyPositionTest, StickyPositionCompositedContainer) {}

// A transform on a sticky element should not affect its sticky position.
TEST_F(DrawPropertiesStickyPositionTest, StickyPositionScaledStickyBox) {}

// Tests that a transform does not affect the sticking points. The sticky
// element will however move relative to the viewport due to its transform.
TEST_F(DrawPropertiesStickyPositionTest, StickyPositionScaledContainer) {}

TEST_F(DrawPropertiesStickyPositionTest, StickyPositionNested) {}

class DrawPropertiesAnchorPositionScrollTest : public DrawPropertiesTest {};

TEST_F(DrawPropertiesAnchorPositionScrollTest, Basics) {}

TEST_F(DrawPropertiesAnchorPositionScrollTest, NestedScrollers) {}
class AnimationScaleFactorTrackingLayerImpl : public LayerImpl {};

TEST_F(DrawPropertiesTest, MaximumAnimationScaleFactor) {}

static void GatherDrawnLayers(LayerTreeImpl* tree_impl,
                              std::set<LayerImpl*>* drawn_layers) {}

// Needs layer tree mode: mask layer.
TEST_F(DrawPropertiesTestWithLayerTree, RenderSurfaceLayerListMembership) {}

// Needs layer tree mode: mask layer.
TEST_F(DrawPropertiesTestWithLayerTree, DrawPropertyDeviceScale) {}

TEST_F(DrawPropertiesTest, DrawPropertyScales) {}

TEST_F(DrawPropertiesTest, AnimationScales) {}

TEST_F(DrawPropertiesTest, AnimationScaleFromSmallToOne) {}

TEST_F(DrawPropertiesTest, VisibleContentRectInChildRenderSurface) {}

TEST_F(DrawPropertiesTest, ViewportBoundsDeltaAffectVisibleContentRect) {}

TEST_F(DrawPropertiesTest, VisibleContentRectForAnimatedLayer) {}

TEST_F(DrawPropertiesTest,
       VisibleContentRectForAnimatedLayerWithSingularTransform) {}

TEST_F(DrawPropertiesTest, ChangeTransformOrigin) {}

TEST_F(DrawPropertiesTest, UpdateScrollChildPosition) {}

// Needs layer tree mode: copy request. Not using impl-side PropertyTreeBuilder.
TEST_F(DrawPropertiesTestWithLayerTree, HasCopyRequestsInTargetSubtree) {}

// Needs layer tree mode: hide_layer_and_subtree, etc.
// Not using impl-side PropertyTreeBuilder.
TEST_F(DrawPropertiesTestWithLayerTree, SkippingSubtreeMain) {}

// Needs layer tree mode: hide_layer_and_subtree, etc.
TEST_F(DrawPropertiesTestWithLayerTree, SkippingLayerImpl) {}

// This tests for correctness of an optimization.  If a node in the tree
// maps all possible spaces to a single point (ie has a singular transform)
// we can ignore the size of all its children.  We need to make sure that
// we don't do this if an animation can replace this transform in the
// compositor without recomputing the trees.
TEST_F(DrawPropertiesTest, LayerSkippingInSubtreeOfSingularTransform) {}

// This tests that we skip computing the visible areas for the subtree
// rooted at nodes with constant zero opacity.
TEST_F(DrawPropertiesTestWithLayerTree, SkippingPendingLayerImpl) {}

// Needs layer tree mode: hide_layer_and_subtree.
TEST_F(DrawPropertiesTestWithLayerTree, SkippingLayer) {}

TEST_F(DrawPropertiesTest, TransformOfParentClipNodeAncestorOfTarget) {}

TEST_F(DrawPropertiesTest, RenderSurfaceWithUnclippedDescendantsClipsSubtree) {}

TEST_F(DrawPropertiesTest,
       RenderSurfaceWithUnclippedDescendantsButDoesntApplyOwnClip) {}

TEST_F(DrawPropertiesTest,
       RenderSurfaceClipsSubtreeAndHasUnclippedDescendants) {}

TEST_F(DrawPropertiesTest, UnclippedClipParent) {}

TEST_F(DrawPropertiesTest, RenderSurfaceContentRectWithMultipleSurfaces) {}

TEST_F(DrawPropertiesTest, ClipBetweenClipChildTargetAndClipParentTarget) {}

TEST_F(DrawPropertiesTest, VisibleRectForDescendantOfScaledSurface) {}

TEST_F(DrawPropertiesTest, LayerWithInputHandlerAndZeroOpacity) {}

TEST_F(DrawPropertiesTest, ClipParentDrawsIntoScaledRootSurface) {}

TEST_F(DrawPropertiesTest, ClipChildVisibleRect) {}

TEST_F(DrawPropertiesTest, LayerClipRectLargerThanClippingRenderSurfaceRect) {}

// Needs layer tree mode: hide_layer_and_subtree.
TEST_F(DrawPropertiesTestWithLayerTree, SubtreeIsHiddenTest) {}

TEST_F(DrawPropertiesTest, TwoUnclippedRenderSurfaces) {}

// Needs layer tree mode: mask layer.
TEST_F(DrawPropertiesTestWithLayerTree, MaskLayerDrawProperties) {}

TEST_F(DrawPropertiesTest, SublayerScaleWithTransformNodeBetweenTwoTargets) {}

TEST_F(DrawPropertiesTest, NoisyTransform) {}

TEST_F(DrawPropertiesTest, LargeTransformTest) {}

#if DCHECK_IS_ON()
class DrawPropertiesTestDoubleBlurCheck : public DrawPropertiesTestBase,
                                          public testing::Test {};

TEST_F(DrawPropertiesTestDoubleBlurCheck, CheckForNoDoubleBlurTest) {}
#endif

// In layer tree mode, not using impl-side PropertyTreeBuilder.
TEST_F(DrawPropertiesTestWithLayerTree, OpacityAnimationsTrackingTest) {}

// In layer tree mode, not using impl-side PropertyTreeBuilder.
TEST_F(DrawPropertiesTestWithLayerTree, TransformAnimationsTrackingTest) {}

// Needs layer tree mode: copy request.
TEST_F(DrawPropertiesTestWithLayerTree, CopyRequestScalingTest) {}

// Needs layer tree mode: hide_layer_and_subtree, etc.
TEST_F(DrawPropertiesTestWithLayerTree, SubtreeHiddenWithCacheRenderSurface) {}

// Needs layer tree mode: copy request.
TEST_F(DrawPropertiesTestWithLayerTree,
       VisibleRectInNonRootCacheRenderSurface) {}

// In layer tree mode, not using impl-side PropertyTreeBuilder.
TEST_F(DrawPropertiesTestWithLayerTree, CustomLayerClipBounds) {}

// In layer tree mode, not using impl-side PropertyTreeBuilder.
TEST_F(DrawPropertiesTestWithLayerTree, CustomLayerClipBoundsWithMaskToBounds) {}

struct MaskFilterTestCase {};

class DrawPropertiesWithLayerTreeTest :
    public DrawPropertiesTestWithLayerTree,
    public testing::WithParamInterface<MaskFilterTestCase> {};

// In layer tree mode, not using impl-side PropertyTreeBuilder.
TEST_P(DrawPropertiesWithLayerTreeTest, MaskFilterOnRenderSurface) {}


INSTANTIATE_TEST_SUITE_P();
}  // namespace
}  // namespace cc