blob: 380703a90ed53b6f9e4eb5cf1154b4ff080e6c2e [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_PROPERTY_TREE_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_PROPERTY_TREE_MANAGER_H_
#include "base/macros.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace cc {
class ClipTree;
class EffectTree;
class Layer;
class LayerTreeHost;
class PropertyTrees;
class ScrollTree;
class TransformTree;
struct EffectNode;
struct TransformNode;
enum class RenderSurfaceReason : uint8_t;
}
namespace gfx {
class ScrollOffset;
}
namespace blink {
class ClipPaintPropertyNode;
class LayerListBuilder;
class EffectPaintPropertyNode;
class ScrollPaintPropertyNode;
class SynthesizedClip;
class TransformPaintPropertyNode;
class PropertyTreeManagerClient {
public:
virtual ~PropertyTreeManagerClient() = default;
virtual SynthesizedClip& CreateOrReuseSynthesizedClipLayer(
const ClipPaintPropertyNode&,
const TransformPaintPropertyNode&,
bool needs_layer,
CompositorElementId& mask_isolation_id,
CompositorElementId& mask_effect_id) = 0;
};
// Mutates a cc property tree to reflect Blink paint property tree
// state. Intended for use by PaintArtifactCompositor.
class PropertyTreeManager {
DISALLOW_NEW();
public:
PropertyTreeManager(PropertyTreeManagerClient&,
cc::PropertyTrees& property_trees,
cc::Layer& root_layer,
LayerListBuilder& layer_list_builder,
int new_sequence_number);
~PropertyTreeManager();
// A brief discourse on cc property tree nodes, identifiers, and current and
// future design evolution envisioned:
//
// cc property trees identify nodes by their |id|, which implementation-wise
// is actually its index in the property tree's vector of its node type. More
// recent cc code now refers to these as 'node indices', or 'property tree
// indices'. |parent_id| is the same sort of 'node index' of that node's
// parent.
//
// Note there are two other primary types of 'ids' referenced in cc property
// tree related logic: (1) ElementId, also known Blink-side as
// CompositorElementId, used by the animation system to allow tying an element
// to its respective layer, and (2) layer ids. There are other ancillary ids
// not relevant to any of the above, such as
// cc::TransformNode::sorting_context_id
// (a.k.a. blink::TransformPaintPropertyNode::renderingContextId()).
//
// There is a vision to move toward a world where cc property nodes have no
// association with layers and instead have a |stable_id|. The id could come
// from an ElementId in turn derived from the layout object responsible for
// creating the property node.
//
// We would also like to explore moving to use a single shared property tree
// representation across both cc and Blink. See
// platform/graphics/paint/README.md for more.
//
// With the above as background, we can now state more clearly a description
// of the below set of compositor node methods: they take Blink paint property
// tree nodes as input, create a corresponding compositor property tree node
// if none yet exists, and return the compositor node's 'node id', a.k.a.,
// 'node index'.
// Returns the compositor transform node id. If a compositor transform node
// does not exist, it is created. Any transforms that are for scroll offset
// translation will ensure the associated scroll node exists.
int EnsureCompositorTransformNode(const TransformPaintPropertyNode&);
int EnsureCompositorClipNode(const ClipPaintPropertyNode&);
// Ensure the compositor scroll node using the associated scroll offset
// translation.
int EnsureCompositorScrollNode(
const TransformPaintPropertyNode& scroll_offset_translation);
// Same as above but marks the scroll nodes as being the viewport.
int EnsureCompositorInnerScrollNode(
const TransformPaintPropertyNode& scroll_offset_translation);
int EnsureCompositorOuterScrollNode(
const TransformPaintPropertyNode& scroll_offset_translation);
int EnsureCompositorPageScaleTransformNode(const TransformPaintPropertyNode&);
// This function is expected to be invoked right before emitting each layer.
// It keeps track of the nesting of clip and effects, output a composited
// effect node whenever an effect is entered, or a non-trivial clip is
// entered. In the latter case, the generated composited effect node is
// called a "synthetic effect", and the corresponding clip a "synthesized
// clip". Upon exiting a synthesized clip, a mask layer will be appended,
// which will be kDstIn blended on top of contents enclosed by the synthetic
// effect, i.e. applying the clip as a mask.
int SwitchToEffectNodeWithSynthesizedClip(
const EffectPaintPropertyNode& next_effect,
const ClipPaintPropertyNode& next_clip,
bool layer_draws_content);
// Expected to be invoked after emitting the last layer. This will exit all
// effects on the effect stack, generating clip mask layers for all the
// unclosed synthesized clips.
void Finalize();
static bool DirectlyUpdateCompositedOpacityValue(
cc::LayerTreeHost&,
const EffectPaintPropertyNode&);
// Returns true if the compositor scroll offsets were updated, even if the
// values did not change. This function updates both the cc scroll tree scroll
// offset and the cc transform node's scroll offset.
static bool DirectlyUpdateScrollOffsetTransform(
cc::LayerTreeHost&,
const TransformPaintPropertyNode&);
static bool DirectlyUpdateTransform(cc::LayerTreeHost&,
const TransformPaintPropertyNode&);
static bool DirectlyUpdatePageScaleTransform(
cc::LayerTreeHost&,
const TransformPaintPropertyNode&);
// This function only updates the cc scroll tree scroll offset and does not
// update the cc transform node's scroll offset.
static void DirectlySetScrollOffset(cc::LayerTreeHost&,
CompositorElementId,
const gfx::ScrollOffset&);
// Ensures a cc::ScrollNode for all scroll translations.
void EnsureCompositorScrollNodes(
const Vector<const TransformPaintPropertyNode*>&
scroll_translation_nodes);
// Sets the cc::ScrollNode::is_composited bit to true for the node with ID
// |cc_node_id|.
void SetCcScrollNodeIsComposited(int cc_node_id);
private:
void SetupRootTransformNode();
void SetupRootClipNode();
void SetupRootEffectNode();
void SetupRootScrollNode();
// The type of operation the current cc effect node applies.
enum CcEffectType {
// The cc effect corresponds to a Blink effect node.
kEffect = 0,
// The cc effect is synthetic for a blink clip node that has to be
// rasterized because the clip is non-trivial.
kSyntheticForNonTrivialClip = 1 << 0,
// The cc effect is synthetic to create a render surface that is
// 2d-axis-aligned with a blink clip node that is non-2d-axis-aligned
// in the the original render surface. Cc requires a rectangular clip to be
// 2d-axis-aligned with the render surface to correctly apply the clip.
// TODO(crbug.com/504464): This will be changed when we move render surface
// decision logic into the cc compositor thread.
kSyntheticFor2dAxisAlignment = 1 << 1
};
static bool SupportsShaderBasedRoundedCorner(
const ClipPaintPropertyNode&,
CcEffectType type,
const EffectPaintPropertyNode* next_effect);
struct EffectState {
// The cc effect node that has the corresponding drawing state to the
// effect and clip state from the last
// SwitchToEffectNodeWithSynthesizedClip.
int effect_id;
CcEffectType effect_type;
// The effect state of the cc effect node. It's never nullptr.
const EffectPaintPropertyNode* effect;
// The clip state of the cc effect node. This value may be shallower than
// the one passed into SwitchToEffectNodeWithSynthesizedClip because not
// every clip needs to be synthesized as cc effect. Is set to output clip of
// the effect if the type is kEffect, or set to the synthesized clip node.
// It's never nullptr.
const ClipPaintPropertyNode* clip;
// The transform space of this state. It's |&effect->LocalTransformSpace()|
// if this state is of kEffect type or synthetic with backdrop filters
// moved up from the original effect.
// Otherwise it's |&clip->LocalTransformSpace()|.
const TransformPaintPropertyNode* transform;
// Whether the transform space of this state may be 2d axis misaligned to
// the containing render surface. As there may be new render surfaces
// created between this state and the current known ancestor render surface
// after this state is created, we must conservatively accumulate this flag
// from the known render surface instead of checking if the combined
// transform is 2d axis aligned, in case of:
// Effect1 (Current known render surface)
// Rotate(45deg)
// Effect2 (Not known now, but may become render surface later)
// Rotate(-45deg)
// Clip (Would be mistakenly treated as 2d axis aligned if we used
//
// It's lazily computed if it can't be trivially known when we create this
// EffectState.
enum {
kAligned,
kMisaligned,
kUnknown,
} may_be_2d_axis_misaligned_to_render_surface;
// Whether this effect or an ancestor has a synthetic rounded clip between
// self and the next render surface. This is used to force a render surface
// for all ancestor synthetic rounded clips if a descendant is found.
bool contained_by_non_render_surface_synthetic_rounded_clip;
};
void CollectAnimationElementId(CompositorElementId);
void BuildEffectNodesRecursively(const EffectPaintPropertyNode& next_effect);
void ForceRenderSurfaceIfSyntheticRoundedCornerClip(EffectState& state);
// When entering |target_clip| and |next_effect|, we may need to synthesize
// cc clips and effects for particular types of masks. See CcEffectType.
// Returns the id of the cc effect node created for |next_effect| or
// kInvalidNodeId. Normally this function doesn't create cc effect node for
// |next_effect|, thus returns kInvalidNodeId, except when |next_effect| has
// backdrop effects and we need to move the effect up to the outermost
// synthetic effect to allow the backdrop effects to access the correct
// backdrop, in which case this function returns the id of the synthetic cc
// effect node that contains the converted |next_effect| effects.
int SynthesizeCcEffectsForClipsIfNeeded(
const ClipPaintPropertyNode& target_clip,
const EffectPaintPropertyNode* next_effect);
void EmitClipMaskLayer();
void CloseCcEffect();
void PopulateCcEffectNode(cc::EffectNode&,
const EffectPaintPropertyNode& effect,
int output_clip_id);
bool IsCurrentCcEffectSynthetic() const { return current_.effect_type; }
bool IsCurrentCcEffectSyntheticForNonTrivialClip() const {
return current_.effect_type & CcEffectType::kSyntheticForNonTrivialClip;
}
bool EffectStateMayBe2dAxisMisalignedToRenderSurface(EffectState&,
wtf_size_t index);
bool CurrentEffectMayBe2dAxisMisalignedToRenderSurface();
CcEffectType SyntheticEffectType(const ClipPaintPropertyNode&);
void SetCurrentEffectState(const cc::EffectNode&,
CcEffectType,
const EffectPaintPropertyNode&,
const ClipPaintPropertyNode&,
const TransformPaintPropertyNode&);
void SetCurrentEffectRenderSurfaceReason(cc::RenderSurfaceReason);
cc::TransformTree& GetTransformTree();
cc::ClipTree& GetClipTree();
cc::EffectTree& GetEffectTree();
cc::ScrollTree& GetScrollTree();
// Should only be called from EnsureCompositorTransformNode as part of
// creating the associated scroll offset transform node.
void CreateCompositorScrollNode(
const ScrollPaintPropertyNode&,
const cc::TransformNode& scroll_offset_translation);
PropertyTreeManagerClient& client_;
// Property trees which should be updated by the manager.
cc::PropertyTrees& property_trees_;
// The special layer which is the parent of every other layers.
// This is where clip mask layers we generated for synthesized clips are
// appended into.
cc::Layer& root_layer_;
LayerListBuilder& layer_list_builder_;
int new_sequence_number_;
// The current effect state. Virtually it's the top of the effect stack if
// it and effect_stack_ are treated as a whole stack.
EffectState current_;
// This keep track of cc effect stack. Whenever a new cc effect is nested,
// a new entry is pushed, and the entry will be popped when the effect closed.
// Note: This is a "restore stack", i.e. the top element does not represent
// the current state (which is in current_), but the state prior to most
// recent push.
Vector<EffectState> effect_stack_;
// A set of synthetic clips masks which will be applied if a layer under them
// is encountered which draws content (and thus necessitates the mask).
HashSet<int> pending_synthetic_mask_layers_;
DISALLOW_COPY_AND_ASSIGN(PropertyTreeManager);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_PROPERTY_TREE_MANAGER_H_