summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorjaydasika <jaydasika@chromium.org>2016-01-27 09:05:07 -0800
committerCommit bot <commit-bot@chromium.org>2016-01-27 17:06:16 +0000
commit8665451221d678b75feeebbea51fd780148aa2cc (patch)
treed8bb9febcf7a2dd13d4a8075a54c1c9168947c4d /cc
parent477b16c4b0051e183d22d3705faeebcb2cc0cc42 (diff)
downloadchromium_src-8665451221d678b75feeebbea51fd780148aa2cc.zip
chromium_src-8665451221d678b75feeebbea51fd780148aa2cc.tar.gz
chromium_src-8665451221d678b75feeebbea51fd780148aa2cc.tar.bz2
cc :: Reland compute if layer is drawn from property trees
This CL : * deletes is_hidden * computes if a layer is drawn using the effect tree BUG=575413 CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel patch from issue 1588093004 at patchset 250001 (http://crrev.com/1588093004#ps250001) Review URL: https://codereview.chromium.org/1633203002 Cr-Commit-Position: refs/heads/master@{#371807}
Diffstat (limited to 'cc')
-rw-r--r--cc/layers/layer.cc8
-rw-r--r--cc/layers/layer.h8
-rw-r--r--cc/layers/layer_impl.cc23
-rw-r--r--cc/layers/layer_impl.h10
-rw-r--r--cc/proto/property_tree.proto10
-rw-r--r--cc/trees/draw_property_utils.cc23
-rw-r--r--cc/trees/layer_tree_host_common.cc60
-rw-r--r--cc/trees/layer_tree_host_common_unittest.cc114
-rw-r--r--cc/trees/occlusion_tracker.cc2
-rw-r--r--cc/trees/property_tree.cc58
-rw-r--r--cc/trees/property_tree.h7
-rw-r--r--cc/trees/property_tree_builder.cc26
12 files changed, 238 insertions, 111 deletions
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index 10a75d8..b3dca99 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -100,8 +100,7 @@ Layer::Layer(const LayerSettings& settings)
replica_layer_(nullptr),
client_(nullptr),
num_unclipped_descendants_(0),
- frame_timing_requests_dirty_(false),
- is_hidden_from_property_trees_(false) {
+ frame_timing_requests_dirty_(false) {
if (!settings.use_compositor_animation_timelines) {
layer_animation_controller_ = LayerAnimationController::Create(layer_id_);
layer_animation_controller_->AddValueObserver(this);
@@ -539,6 +538,10 @@ void Layer::SetOpacity(float opacity) {
SetNeedsCommit();
}
+float Layer::EffectiveOpacity() const {
+ return hide_layer_and_subtree_ ? 0.f : opacity_;
+}
+
bool Layer::OpacityIsAnimating() const {
DCHECK(layer_tree_host_);
return layer_animation_controller_
@@ -1241,7 +1244,6 @@ void Layer::PushPropertiesTo(LayerImpl* layer) {
layer->set_user_scrollable_vertical(user_scrollable_vertical_);
layer->SetElementId(element_id_);
layer->SetMutableProperties(mutable_properties_);
- layer->set_is_hidden_from_property_trees(is_hidden_from_property_trees_);
LayerImpl* scroll_parent = nullptr;
if (scroll_parent_) {
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index e009169..1ddb5e8 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -141,6 +141,7 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
void SetOpacity(float opacity);
float opacity() const { return opacity_; }
+ float EffectiveOpacity() const;
bool OpacityIsAnimating() const;
bool HasPotentiallyRunningOpacityAnimation() const;
virtual bool OpacityCanAnimateOnImplThread() const;
@@ -560,12 +561,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
bool layer_or_descendant_is_drawn();
void set_sorted_for_recursion(bool sorted_for_recursion);
bool sorted_for_recursion();
- void set_is_hidden_from_property_trees(bool is_hidden) {
- if (is_hidden == is_hidden_from_property_trees_)
- return;
- is_hidden_from_property_trees_ = is_hidden;
- SetNeedsPushProperties();
- }
// LayerAnimationValueProvider implementation.
gfx::ScrollOffset ScrollOffsetForAnimation() const override;
@@ -792,7 +787,6 @@ class CC_EXPORT Layer : public base::RefCounted<Layer>,
std::vector<FrameTimingRequest> frame_timing_requests_;
bool frame_timing_requests_dirty_;
- bool is_hidden_from_property_trees_;
DISALLOW_COPY_AND_ASSIGN(Layer);
};
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 57b62f8..f585bde 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -100,8 +100,7 @@ LayerImpl::LayerImpl(LayerTreeImpl* tree_impl,
visited_(false),
layer_or_descendant_is_drawn_(false),
layer_or_descendant_has_input_handler_(false),
- sorted_for_recursion_(false),
- is_hidden_from_property_trees_(false) {
+ sorted_for_recursion_(false) {
DCHECK_GT(layer_id_, 0);
DCHECK(layer_tree_impl_);
layer_tree_impl_->RegisterLayer(this);
@@ -659,7 +658,6 @@ void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
layer->SetClipTreeIndex(clip_tree_index_);
layer->SetEffectTreeIndex(effect_tree_index_);
layer->set_offset_to_transform_parent(offset_to_transform_parent_);
- layer->set_is_hidden_from_property_trees(is_hidden_from_property_trees_);
LayerImpl* scroll_parent = nullptr;
if (scroll_parent_) {
@@ -962,7 +960,7 @@ void LayerImpl::UpdatePropertyTreeOpacity() {
// started, but might have finished since then on the compositor thread.
if (node->owner_id != id())
return;
- node->data.opacity = opacity_;
+ node->data.opacity = EffectiveOpacity();
effect_tree.set_needs_update(true);
}
}
@@ -991,7 +989,10 @@ void LayerImpl::OnFilterAnimated(const FilterOperations& filters) {
void LayerImpl::OnOpacityAnimated(float opacity) {
SetOpacity(opacity);
- UpdatePropertyTreeOpacity();
+ // When hide_layer_and_subtree is true, the effective opacity is zero and we
+ // need not update the opacity on property trees.
+ if (!hide_layer_and_subtree_)
+ UpdatePropertyTreeOpacity();
}
void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) {
@@ -1248,6 +1249,10 @@ void LayerImpl::SetOpacity(float opacity) {
NoteLayerPropertyChangedForSubtree();
}
+float LayerImpl::EffectiveOpacity() const {
+ return hide_layer_and_subtree_ ? 0.f : opacity_;
+}
+
bool LayerImpl::OpacityIsAnimating() const {
LayerAnimationController::ObserverType observer_type =
IsActive() ? LayerAnimationController::ObserverType::ACTIVE
@@ -1923,11 +1928,13 @@ gfx::Rect LayerImpl::GetScaledEnclosingRectInTargetSpace(float scale) const {
gfx::Rect(scaled_bounds));
}
-bool LayerImpl::LayerIsHidden() const {
+bool LayerImpl::IsHidden() const {
if (layer_tree_impl()->settings().use_property_trees) {
- return is_hidden_from_property_trees_;
+ EffectTree& effect_tree = layer_tree_impl_->property_trees()->effect_tree;
+ EffectNode* node = effect_tree.Node(effect_tree_index_);
+ return node->data.screen_space_opacity == 0.f;
} else {
- return hide_layer_and_subtree_ || (parent() && parent()->LayerIsHidden());
+ return EffectiveOpacity() == 0.f || (parent() && parent()->IsHidden());
}
}
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index 12ee4c0..e3d0c87 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -321,6 +321,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
void SetOpacity(float opacity);
float opacity() const { return opacity_; }
+ float EffectiveOpacity() const;
bool OpacityIsAnimating() const;
bool HasPotentiallyRunningOpacityAnimation() const;
bool OpacityIsAnimatingOnImplOnly() const;
@@ -685,13 +686,7 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
void UpdatePropertyTreeForScrollingAndAnimationIfNeeded();
- void set_is_hidden_from_property_trees(bool is_hidden) {
- if (is_hidden == is_hidden_from_property_trees_)
- return;
- is_hidden_from_property_trees_ = is_hidden;
- SetNeedsPushProperties();
- }
- bool LayerIsHidden() const;
+ bool IsHidden() const;
float GetIdealContentsScale() const;
@@ -895,7 +890,6 @@ class CC_EXPORT LayerImpl : public LayerAnimationValueObserver,
// If true, the layer or one of its descendants has a wheel or touch handler.
bool layer_or_descendant_has_input_handler_;
bool sorted_for_recursion_;
- bool is_hidden_from_property_trees_;
DISALLOW_COPY_AND_ASSIGN(LayerImpl);
};
diff --git a/cc/proto/property_tree.proto b/cc/proto/property_tree.proto
index 50cfb45..d35f264 100644
--- a/cc/proto/property_tree.proto
+++ b/cc/proto/property_tree.proto
@@ -81,9 +81,13 @@ message EffectNodeData {
optional float opacity = 1;
optional float screen_space_opacity = 2;
optional bool has_render_surface = 3;
- optional int64 num_copy_requests_in_subtree = 4;
- optional int64 transform_id = 5;
- optional int64 clip_id = 6;
+ optional bool has_copy_request = 4;
+ optional bool has_background_filters = 5;
+ optional bool is_drawn = 6;
+ optional bool screen_space_opacity_is_animating = 7;
+ optional int64 num_copy_requests_in_subtree = 8;
+ optional int64 transform_id = 9;
+ optional int64 clip_id = 10;
}
message ScrollNodeData {
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc
index fa52236..6899816 100644
--- a/cc/trees/draw_property_utils.cc
+++ b/cc/trees/draw_property_utils.cc
@@ -344,7 +344,7 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
// The opacity of a layer always applies to its children (either implicitly
// via a render surface or explicitly if the parent preserves 3D), so the
// entire subtree can be skipped if this layer is fully transparent.
- return !layer->opacity();
+ return !layer->EffectiveOpacity();
}
static inline bool SubtreeShouldBeSkipped(Layer* layer,
@@ -380,7 +380,8 @@ static inline bool SubtreeShouldBeSkipped(Layer* layer,
// In particular, it should not cause the subtree to be skipped.
// Similarly, for layers that might animate opacity using an impl-only
// animation, their subtree should also not be skipped.
- return !layer->opacity() && !layer->HasPotentiallyRunningOpacityAnimation() &&
+ return !layer->EffectiveOpacity() &&
+ !layer->HasPotentiallyRunningOpacityAnimation() &&
!layer->OpacityCanAnimateOnImplThread();
}
@@ -430,18 +431,19 @@ static bool LayerShouldBeSkipped(LayerType* layer,
template <typename LayerType>
void FindLayersThatNeedUpdates(
LayerType* layer,
- const TransformTree& tree,
- bool subtree_is_visible_from_ancestor,
+ const TransformTree& transform_tree,
+ const EffectTree& effect_tree,
typename LayerType::LayerListType* update_layer_list,
std::vector<LayerType*>* visible_layer_list) {
+ DCHECK_GE(layer->effect_tree_index(), 0);
bool layer_is_drawn =
- layer->HasCopyRequest() ||
- (subtree_is_visible_from_ancestor && !layer->hide_layer_and_subtree());
+ effect_tree.Node(layer->effect_tree_index())->data.is_drawn;
- if (layer->parent() && SubtreeShouldBeSkipped(layer, layer_is_drawn, tree))
+ if (layer->parent() &&
+ SubtreeShouldBeSkipped(layer, layer_is_drawn, transform_tree))
return;
- if (!LayerShouldBeSkipped(layer, layer_is_drawn, tree)) {
+ if (!LayerShouldBeSkipped(layer, layer_is_drawn, transform_tree)) {
visible_layer_list->push_back(layer);
update_layer_list->push_back(layer);
}
@@ -457,7 +459,7 @@ void FindLayersThatNeedUpdates(
}
for (size_t i = 0; i < layer->children().size(); ++i) {
- FindLayersThatNeedUpdates(layer->child_at(i), tree, layer_is_drawn,
+ FindLayersThatNeedUpdates(layer->child_at(i), transform_tree, effect_tree,
update_layer_list, visible_layer_list);
}
}
@@ -679,9 +681,8 @@ static void ComputeVisibleRectsUsingPropertyTreesInternal(
can_render_to_separate_surface);
ComputeEffects(&property_trees->effect_tree);
- const bool subtree_is_visible_from_ancestor = true;
FindLayersThatNeedUpdates(root_layer, property_trees->transform_tree,
- subtree_is_visible_from_ancestor, update_layer_list,
+ property_trees->effect_tree, update_layer_list,
visible_layer_list);
CalculateVisibleRects<LayerType>(
*visible_layer_list, property_trees->clip_tree,
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index 76c91a0..1414918 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -668,7 +668,7 @@ static inline bool SubtreeShouldBeSkipped(LayerImpl* layer,
// The opacity of a layer always applies to its children (either implicitly
// via a render surface or explicitly if the parent preserves 3D), so the
// entire subtree can be skipped if this layer is fully transparent.
- return !layer->opacity();
+ return !layer->EffectiveOpacity();
}
static inline void SavePaintPropertiesLayer(LayerImpl* layer) {}
@@ -1515,7 +1515,7 @@ static void CalculateDrawPropertiesInternal(
// the right results.
const bool layer_is_visible =
data_from_ancestor.subtree_is_visible_from_ancestor &&
- !layer->hide_layer_and_subtree();
+ layer->EffectiveOpacity() != 0;
const bool layer_is_drawn = layer_is_visible || layer->HasCopyRequest();
// The root layer cannot skip CalcDrawProperties.
@@ -2327,11 +2327,21 @@ enum PropertyTreeOption {
};
void CalculateRenderTargetInternal(LayerImpl* layer,
+ PropertyTrees* property_trees,
bool subtree_visible_from_ancestor,
- bool can_render_to_separate_surface) {
- const bool layer_is_visible =
- subtree_visible_from_ancestor && !layer->hide_layer_and_subtree();
- const bool layer_is_drawn = layer_is_visible || layer->HasCopyRequest();
+ bool can_render_to_separate_surface,
+ bool use_property_trees) {
+ bool layer_is_drawn;
+ if (use_property_trees) {
+ DCHECK_GE(layer->effect_tree_index(), 0);
+ layer_is_drawn =
+ property_trees->effect_tree.Node(layer->effect_tree_index())
+ ->data.is_drawn;
+ } else {
+ layer_is_drawn =
+ (subtree_visible_from_ancestor && layer->EffectiveOpacity() != 0) ||
+ layer->HasCopyRequest();
+ }
// The root layer cannot be skipped.
if (!IsRootLayer(layer) && SubtreeShouldBeSkipped(layer, layer_is_drawn)) {
@@ -2364,7 +2374,8 @@ void CalculateRenderTargetInternal(LayerImpl* layer,
for (size_t i = 0; i < layer->children().size(); ++i) {
CalculateRenderTargetInternal(
LayerTreeHostCommon::get_layer_as_raw_ptr(layer->children(), i),
- layer_is_drawn, can_render_to_separate_surface);
+ property_trees, layer_is_drawn, can_render_to_separate_surface,
+ use_property_trees);
}
}
@@ -2395,14 +2406,17 @@ void CalculateRenderSurfaceLayerListInternal(
// |can_render_to_separate_surface| and |current_render_surface_layer_list_id|
// are settings that should stay the same during recursion.
-
- // Layers that are marked as hidden will hide themselves and their subtree.
- // Exception: Layers with copy requests, whether hidden or not, must be drawn
- // anyway. In this case, we will inform their subtree they are visible to get
- // the right results.
- const bool layer_is_visible =
- subtree_visible_from_ancestor && !layer->hide_layer_and_subtree();
- const bool layer_is_drawn = layer_is_visible || layer->HasCopyRequest();
+ bool layer_is_drawn = false;
+ if (use_property_trees) {
+ DCHECK_GE(layer->effect_tree_index(), 0);
+ layer_is_drawn =
+ property_trees->effect_tree.Node(layer->effect_tree_index())
+ ->data.is_drawn;
+ } else {
+ layer_is_drawn =
+ (subtree_visible_from_ancestor && layer->EffectiveOpacity() != 0) ||
+ layer->HasCopyRequest();
+ }
// The root layer cannot be skipped.
if (!IsRootLayer(layer) && SubtreeShouldBeSkipped(layer, layer_is_drawn)) {
@@ -2451,10 +2465,14 @@ void CalculateRenderSurfaceLayerListInternal(
// target.
layer->render_surface()->set_contributes_to_drawn_surface(false);
} else {
- // Even if the |layer_is_drawn|, it only contributes to a drawn surface
- // when the |layer_is_visible|.
+ bool contributes_to_drawn_surface =
+ use_property_trees
+ ? property_trees->effect_tree.ContributesToDrawnSurface(
+ layer->effect_tree_index())
+ : subtree_visible_from_ancestor &&
+ layer->EffectiveOpacity() != 0.f;
layer->render_surface()->set_contributes_to_drawn_surface(
- layer_is_visible);
+ contributes_to_drawn_surface);
}
// Ignore occlusion from outside the surface when surface contents need to
@@ -2619,8 +2637,10 @@ void CalculateRenderSurfaceLayerListInternal(
void CalculateRenderTarget(
LayerTreeHostCommon::CalcDrawPropsImplInputs* inputs) {
- CalculateRenderTargetInternal(inputs->root_layer, true,
- inputs->can_render_to_separate_surface);
+ CalculateRenderTargetInternal(
+ inputs->root_layer, inputs->property_trees, true,
+ inputs->can_render_to_separate_surface,
+ inputs->verify_property_trees || inputs->use_property_trees);
}
void CalculateRenderSurfaceLayerList(
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index f4e5b60..3a426ec 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -150,7 +150,10 @@ TEST_F(LayerTreeHostCommonTest, TransformsForNoOpLayer) {
grand_child->screen_space_transform());
}
-TEST_F(LayerTreeHostCommonTest, DoNotSkipLayersWithHandlers) {
+TEST_F(LayerTreeHostCommonTest,
+ ScreenSpaceTransformOfSkippedLayersWithHandlers) {
+ // Even for layers that are skipped, we need to compute the correct screen
+ // space transform because it is used during hit testing.
LayerImpl* parent = root_layer();
LayerImpl* child = AddChild<LayerImpl>(parent);
LayerImpl* grand_child = AddChild<LayerImpl>(child);
@@ -163,9 +166,7 @@ TEST_F(LayerTreeHostCommonTest, DoNotSkipLayersWithHandlers) {
SetLayerPropertiesForTesting(child, identity_matrix, gfx::Point3F(),
gfx::PointF(10, 10), gfx::Size(100, 100), true,
false);
- // This would have previously caused us to skip our subtree, but this would be
- // wrong; we need up-to-date draw properties to do hit testing on the layers
- // with handlers.
+ // This will cause the subtree to be skipped.
child->SetOpacity(0.f);
SetLayerPropertiesForTesting(grand_child, identity_matrix, gfx::Point3F(),
gfx::PointF(10, 10), gfx::Size(100, 100), true,
@@ -178,10 +179,8 @@ TEST_F(LayerTreeHostCommonTest, DoNotSkipLayersWithHandlers) {
EXPECT_FALSE(grand_child->has_render_surface());
// Check that we've computed draw properties for the subtree rooted at
// |child|.
- EXPECT_TRUE(child->draw_properties().target_space_transform.IsIdentity());
- EXPECT_FALSE(child->render_surface()->draw_transform().IsIdentity());
- EXPECT_FALSE(
- grand_child->draw_properties().target_space_transform.IsIdentity());
+ EXPECT_FALSE(child->render_surface()->screen_space_transform().IsIdentity());
+ EXPECT_FALSE(grand_child->ScreenSpaceTransform().IsIdentity());
}
TEST_F(LayerTreeHostCommonTest, EffectTreeTransformIdTest) {
@@ -1341,6 +1340,8 @@ TEST_F(LayerTreeHostCommonTest,
gfx::PointF(), gfx::Size(10, 10), true, false,
false);
render_surface1->SetOpacity(0.f);
+ render_surface1->SetDrawsContent(true);
+ child->SetDrawsContent(true);
FilterOperations filters;
filters.Append(FilterOperation::CreateBlurFilter(1.5f));
render_surface1->SetBackgroundFilters(filters);
@@ -5184,6 +5185,23 @@ TEST_F(LayerTreeHostCommonTest, OpacityAnimatingOnPendingTree) {
// layer should be included even though it is transparent.
ASSERT_EQ(1u, render_surface_layer_list.size());
ASSERT_EQ(2u, root->render_surface()->layer_list().size());
+
+ // If the root itself is hidden, the child should not be drawn even if it has
+ // an animating opacity.
+ root->SetOpacity(0.f);
+ root->layer_tree_impl()->property_trees()->needs_rebuild = true;
+ LayerImplList render_surface_layer_list2;
+ root->layer_tree_impl()->IncrementRenderSurfaceListIdForTesting();
+ LayerTreeHostCommon::CalcDrawPropsImplInputsForTesting inputs2(
+ root.get(), root->bounds(), &render_surface_layer_list2,
+ root->layer_tree_impl()->current_render_surface_list_id());
+ inputs2.can_adjust_raster_scales = true;
+ LayerTreeHostCommon::CalculateDrawProperties(&inputs2);
+
+ LayerImpl* child_ptr = root->layer_tree_impl()->LayerById(2);
+ EffectTree tree = root->layer_tree_impl()->property_trees()->effect_tree;
+ EffectNode* node = tree.Node(child_ptr->effect_tree_index());
+ EXPECT_FALSE(node->data.is_drawn);
}
class LayerTreeSettingsForLCDTextTest : public LayerTreeSettings {
@@ -5582,8 +5600,16 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) {
copy_child->SetDrawsContent(true);
LayerImpl* copy_child_layer = copy_child.get();
- scoped_ptr<LayerImpl> copy_grand_parent_sibling_before =
+ scoped_ptr<LayerImpl> copy_grand_child =
LayerImpl::Create(host_impl.pending_tree(), 6);
+ SetLayerPropertiesForTesting(copy_grand_child.get(), identity_matrix,
+ gfx::Point3F(), gfx::PointF(), gfx::Size(20, 20),
+ true, false, false);
+ copy_child->SetDrawsContent(true);
+ LayerImpl* copy_grand_child_layer = copy_grand_child.get();
+
+ scoped_ptr<LayerImpl> copy_grand_parent_sibling_before =
+ LayerImpl::Create(host_impl.pending_tree(), 7);
SetLayerPropertiesForTesting(copy_grand_parent_sibling_before.get(),
identity_matrix, gfx::Point3F(), gfx::PointF(),
gfx::Size(40, 40), true, false, false);
@@ -5592,7 +5618,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) {
copy_grand_parent_sibling_before.get();
scoped_ptr<LayerImpl> copy_grand_parent_sibling_after =
- LayerImpl::Create(host_impl.pending_tree(), 7);
+ LayerImpl::Create(host_impl.pending_tree(), 8);
SetLayerPropertiesForTesting(copy_grand_parent_sibling_after.get(),
identity_matrix, gfx::Point3F(), gfx::PointF(),
gfx::Size(40, 40), true, false, false);
@@ -5600,6 +5626,7 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) {
LayerImpl* copy_grand_parent_sibling_after_layer =
copy_grand_parent_sibling_after.get();
+ copy_child->AddChild(std::move(copy_grand_child));
copy_request->AddChild(std::move(copy_child));
copy_parent->AddChild(std::move(copy_request));
copy_grand_parent->AddChild(std::move(copy_parent));
@@ -5608,10 +5635,12 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) {
root->AddChild(std::move(copy_grand_parent_sibling_after));
// Hide the copy_grand_parent and its subtree. But make a copy request in that
- // hidden subtree on copy_layer.
+ // hidden subtree on copy_layer. Also hide the copy grand child and its
+ // subtree.
copy_grand_parent_layer->SetHideLayerAndSubtree(true);
copy_grand_parent_sibling_before_layer->SetHideLayerAndSubtree(true);
copy_grand_parent_sibling_after_layer->SetHideLayerAndSubtree(true);
+ copy_grand_child_layer->SetHideLayerAndSubtree(true);
std::vector<scoped_ptr<CopyOutputRequest>> copy_requests;
copy_requests.push_back(
@@ -5632,27 +5661,27 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) {
EXPECT_GT(copy_parent_layer->num_copy_requests_in_target_subtree(), 0);
EXPECT_GT(copy_layer->num_copy_requests_in_target_subtree(), 0);
- // We should have three render surfaces, one for the root, one for the parent
+ // We should have four render surfaces, one for the root, one for the grand
+ // parent since it has opacity and two drawing descendants, one for the parent
// since it owns a surface, and one for the copy_layer.
- ASSERT_EQ(3u, render_surface_layer_list.size());
+ ASSERT_EQ(4u, render_surface_layer_list.size());
EXPECT_EQ(root->id(), render_surface_layer_list.at(0)->id());
- EXPECT_EQ(copy_parent_layer->id(), render_surface_layer_list.at(1)->id());
- EXPECT_EQ(copy_layer->id(), render_surface_layer_list.at(2)->id());
+ EXPECT_EQ(copy_grand_parent_layer->id(),
+ render_surface_layer_list.at(1)->id());
+ EXPECT_EQ(copy_parent_layer->id(), render_surface_layer_list.at(2)->id());
+ EXPECT_EQ(copy_layer->id(), render_surface_layer_list.at(3)->id());
- // The root render surface should have 2 contributing layers. The
- // copy_grand_parent is hidden along with its siblings, but the copy_parent
- // will appear since something in its subtree needs to be drawn for a copy
- // request.
+ // The root render surface should have 2 contributing layers.
ASSERT_EQ(2u, root->render_surface()->layer_list().size());
EXPECT_EQ(root->id(), root->render_surface()->layer_list().at(0)->id());
- EXPECT_EQ(copy_parent_layer->id(),
+ EXPECT_EQ(copy_grand_parent_layer->id(),
root->render_surface()->layer_list().at(1)->id());
// Nothing actually draws into the copy parent, so only the copy_layer will
// appear in its list, since it needs to be drawn for the copy request.
ASSERT_EQ(1u, copy_parent_layer->render_surface()->layer_list().size());
EXPECT_EQ(copy_layer->id(),
- copy_parent_layer->render_surface()->layer_list().at(0)->id());
+ copy_layer->render_surface()->layer_list().at(0)->id());
// The copy_layer's render surface should have two contributing layers.
ASSERT_EQ(2u, copy_layer->render_surface()->layer_list().size());
@@ -5660,6 +5689,26 @@ TEST_F(LayerTreeHostCommonTest, SubtreeHiddenWithCopyRequest) {
copy_layer->render_surface()->layer_list().at(0)->id());
EXPECT_EQ(copy_child_layer->id(),
copy_layer->render_surface()->layer_list().at(1)->id());
+
+ // copy_grand_parent, copy_parent shouldn't be drawn because they are hidden,
+ // but the copy_layer and copy_child should be drawn for the copy request.
+ // copy grand child should not be drawn as its hidden even in the copy
+ // request.
+ EffectTree tree = root->layer_tree_impl()->property_trees()->effect_tree;
+ EffectNode* node = tree.Node(copy_grand_parent_layer->effect_tree_index());
+ EXPECT_FALSE(node->data.is_drawn);
+ node = tree.Node(copy_parent_layer->effect_tree_index());
+ EXPECT_FALSE(node->data.is_drawn);
+ node = tree.Node(copy_layer->effect_tree_index());
+ EXPECT_TRUE(node->data.is_drawn);
+ node = tree.Node(copy_child_layer->effect_tree_index());
+ EXPECT_TRUE(node->data.is_drawn);
+ node = tree.Node(copy_grand_child_layer->effect_tree_index());
+ EXPECT_FALSE(node->data.is_drawn);
+
+ // Though copy_layer is drawn, it shouldn't contribute to drawn surface as its
+ // actually hidden.
+ EXPECT_FALSE(copy_layer->render_surface()->contributes_to_drawn_surface());
}
TEST_F(LayerTreeHostCommonTest, ClippedOutCopyRequest) {
@@ -8840,11 +8889,11 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeMain) {
// Now, even though child has zero opacity, we will configure |grandchild| and
// |greatgrandchild| in several ways that should force the subtree to be
// processed anyhow.
- greatgrandchild->RequestCopyOfOutput(
+ grandchild->RequestCopyOfOutput(
CopyOutputRequest::CreateBitmapRequest(base::Bind(&CopyOutputCallback)));
ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_rect_from_property_trees());
- grandchild->set_visible_rect_from_property_trees(gfx::Rect());
+ greatgrandchild->set_visible_rect_from_property_trees(gfx::Rect());
// Add an opacity animation with a start delay.
animation_id = 1;
@@ -8892,15 +8941,10 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) {
SetLayerPropertiesForTesting(grandchild.get(), identity, gfx::Point3F(),
gfx::PointF(), gfx::Size(10, 10), true, false,
false);
- SetLayerPropertiesForTesting(greatgrandchild.get(), identity, gfx::Point3F(),
- gfx::PointF(), gfx::Size(10, 10), true, false,
- true);
LayerImpl* child_ptr = child.get();
LayerImpl* grandchild_ptr = grandchild.get();
- LayerImpl* greatgrandchild_ptr = greatgrandchild.get();
- grandchild->AddChild(std::move(greatgrandchild));
child->AddChild(std::move(grandchild));
root->AddChild(std::move(child));
@@ -8940,7 +8984,7 @@ TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) {
std::vector<scoped_ptr<CopyOutputRequest>> requests;
requests.push_back(CopyOutputRequest::CreateEmptyRequest());
- greatgrandchild_ptr->PassCopyRequests(&requests);
+ grandchild_ptr->PassCopyRequests(&requests);
root.get()->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawPropertiesWithPropertyTrees(root.get());
EXPECT_EQ(gfx::Rect(10, 10),
@@ -9532,7 +9576,9 @@ TEST_F(LayerTreeHostCommonTest, LayerWithInputHandlerAndZeroOpacity) {
SetLayerPropertiesForTesting(render_surface, identity_matrix, gfx::Point3F(),
gfx::PointF(), gfx::Size(30, 30), true, false,
true);
- SetLayerPropertiesForTesting(test_layer, identity_matrix, gfx::Point3F(),
+ gfx::Transform translation;
+ translation.Translate(10, 10);
+ SetLayerPropertiesForTesting(test_layer, translation, gfx::Point3F(),
gfx::PointF(), gfx::Size(20, 20), true, false,
false);
@@ -9542,9 +9588,7 @@ TEST_F(LayerTreeHostCommonTest, LayerWithInputHandlerAndZeroOpacity) {
test_layer->SetHaveWheelEventHandlers(true);
ExecuteCalculateDrawProperties(root);
- EXPECT_EQ(gfx::Rect(20, 20), test_layer->drawable_content_rect());
- EXPECT_EQ(gfx::RectF(20, 20),
- render_surface->render_surface()->DrawableContentRect());
+ EXPECT_EQ(translation, test_layer->ScreenSpaceTransform());
}
TEST_F(LayerTreeHostCommonTest, ClipChildVisibleRect) {
@@ -9627,12 +9671,12 @@ TEST_F(LayerTreeHostCommonTest, SubtreeIsHiddenTest) {
hidden->SetHideLayerAndSubtree(true);
ExecuteCalculateDrawProperties(root);
- EXPECT_TRUE(test->LayerIsHidden());
+ EXPECT_TRUE(test->IsHidden());
hidden->SetHideLayerAndSubtree(false);
root->layer_tree_impl()->property_trees()->needs_rebuild = true;
ExecuteCalculateDrawProperties(root);
- EXPECT_FALSE(test->LayerIsHidden());
+ EXPECT_FALSE(test->IsHidden());
}
TEST_F(LayerTreeHostCommonTest, TwoUnclippedRenderSurfaces) {
diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc
index 250ac4d..4bcb762 100644
--- a/cc/trees/occlusion_tracker.cc
+++ b/cc/trees/occlusion_tracker.cc
@@ -174,7 +174,7 @@ void OcclusionTracker::FinishedRenderTarget(const LayerImpl* finished_target) {
// Readbacks always happen on render targets so we only need to check
// for readbacks here.
bool target_is_only_for_copy_request =
- finished_target->HasCopyRequest() && finished_target->LayerIsHidden();
+ finished_target->HasCopyRequest() && finished_target->IsHidden();
// If the occlusion within the surface can not be applied to things outside of
// the surface's subtree, then clear the occlusion here so it won't be used.
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc
index 64209e9..aae88ae 100644
--- a/cc/trees/property_tree.cc
+++ b/cc/trees/property_tree.cc
@@ -415,6 +415,10 @@ EffectNodeData::EffectNodeData()
: opacity(1.f),
screen_space_opacity(1.f),
has_render_surface(false),
+ has_copy_request(false),
+ has_background_filters(false),
+ is_drawn(true),
+ screen_space_opacity_is_animating(false),
num_copy_requests_in_subtree(0),
transform_id(0),
clip_id(0) {}
@@ -423,6 +427,11 @@ bool EffectNodeData::operator==(const EffectNodeData& other) const {
return opacity == other.opacity &&
screen_space_opacity == other.screen_space_opacity &&
has_render_surface == other.has_render_surface &&
+ has_copy_request == other.has_copy_request &&
+ has_background_filters == other.has_background_filters &&
+ is_drawn == other.is_drawn &&
+ screen_space_opacity_is_animating ==
+ other.screen_space_opacity_is_animating &&
num_copy_requests_in_subtree == other.num_copy_requests_in_subtree &&
transform_id == other.transform_id && clip_id == other.clip_id;
}
@@ -433,6 +442,11 @@ void EffectNodeData::ToProtobuf(proto::TreeNode* proto) const {
data->set_opacity(opacity);
data->set_screen_space_opacity(screen_space_opacity);
data->set_has_render_surface(has_render_surface);
+ data->set_has_copy_request(has_copy_request);
+ data->set_has_background_filters(has_background_filters);
+ data->set_is_drawn(is_drawn);
+ data->set_screen_space_opacity_is_animating(
+ screen_space_opacity_is_animating);
data->set_num_copy_requests_in_subtree(num_copy_requests_in_subtree);
data->set_transform_id(transform_id);
data->set_clip_id(clip_id);
@@ -445,6 +459,10 @@ void EffectNodeData::FromProtobuf(const proto::TreeNode& proto) {
opacity = data.opacity();
screen_space_opacity = data.screen_space_opacity();
has_render_surface = data.has_render_surface();
+ has_copy_request = data.has_copy_request();
+ has_background_filters = data.has_background_filters();
+ is_drawn = data.is_drawn();
+ screen_space_opacity_is_animating = data.screen_space_opacity_is_animating();
num_copy_requests_in_subtree = data.num_copy_requests_in_subtree();
transform_id = data.transform_id();
clip_id = data.clip_id();
@@ -1075,16 +1093,54 @@ void EffectTree::UpdateOpacities(EffectNode* node, EffectNode* parent_node) {
node->data.screen_space_opacity *= parent_node->data.screen_space_opacity;
}
+void EffectTree::UpdateIsDrawn(EffectNode* node, EffectNode* parent_node) {
+ // Nodes that have screen space opacity 0 are hidden. So they are not drawn.
+ // Exceptions:
+ // 1) Nodes that contribute to copy requests, whether hidden or not, must be
+ // drawn.
+ // 2) Nodes that have a background filter.
+ // 3) Nodes with animating screen space opacity are drawn if their parent is
+ // drawn irrespective of their opacity.
+ if (node->data.has_copy_request || node->data.has_background_filters)
+ node->data.is_drawn = true;
+ else if (node->data.screen_space_opacity_is_animating)
+ node->data.is_drawn = parent_node ? parent_node->data.is_drawn : true;
+ else if (node->data.opacity == 0.f)
+ node->data.is_drawn = false;
+ else if (parent_node)
+ node->data.is_drawn = parent_node->data.is_drawn;
+ else
+ node->data.is_drawn = true;
+}
+
void EffectTree::UpdateEffects(int id) {
EffectNode* node = Node(id);
EffectNode* parent_node = parent(node);
UpdateOpacities(node, parent_node);
+ UpdateIsDrawn(node, parent_node);
}
void EffectTree::ClearCopyRequests() {
- for (auto& node : nodes())
+ for (auto& node : nodes()) {
node.data.num_copy_requests_in_subtree = 0;
+ node.data.has_copy_request = false;
+ }
+ set_needs_update(true);
+}
+
+bool EffectTree::ContributesToDrawnSurface(int id) {
+ // All drawn nodes contribute to drawn surface.
+ // Exception : Nodes that are hidden and are drawn only for the sake of
+ // copy requests.
+ EffectNode* node = Node(id);
+ EffectNode* parent_node = parent(node);
+ bool contributes_to_drawn_surface =
+ node->data.is_drawn &&
+ (node->data.opacity != 0.f || node->data.has_background_filters);
+ if (parent_node && !parent_node->data.is_drawn)
+ contributes_to_drawn_surface = false;
+ return contributes_to_drawn_surface;
}
void TransformTree::UpdateNodeAndAncestorsHaveIntegerTranslations(
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h
index db0396d..dc479a9 100644
--- a/cc/trees/property_tree.h
+++ b/cc/trees/property_tree.h
@@ -244,6 +244,10 @@ struct CC_EXPORT EffectNodeData {
float screen_space_opacity;
bool has_render_surface;
+ bool has_copy_request;
+ bool has_background_filters;
+ bool is_drawn;
+ bool screen_space_opacity_is_animating;
int num_copy_requests_in_subtree;
int transform_id;
int clip_id;
@@ -499,11 +503,14 @@ class CC_EXPORT EffectTree final : public PropertyTree<EffectNode> {
void ClearCopyRequests();
+ bool ContributesToDrawnSurface(int id);
+
void ToProtobuf(proto::PropertyTree* proto) const;
void FromProtobuf(const proto::PropertyTree& proto);
private:
void UpdateOpacities(EffectNode* node, EffectNode* parent_node);
+ void UpdateIsDrawn(EffectNode* node, EffectNode* parent_node);
};
class CC_EXPORT ScrollTree final : public PropertyTree<ScrollNode> {
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc
index a27bd3c..8af9eb8 100644
--- a/cc/trees/property_tree_builder.cc
+++ b/cc/trees/property_tree_builder.cc
@@ -520,7 +520,7 @@ bool ShouldCreateRenderSurface(LayerType* layer,
num_descendants_that_draw_content > 0 &&
(layer->DrawsContent() || num_descendants_that_draw_content > 1);
- if (layer->opacity() != 1.f && layer->should_flatten_transform() &&
+ if (layer->EffectiveOpacity() != 1.f && layer->should_flatten_transform() &&
at_least_two_layers_in_subtree_draw_content) {
TRACE_EVENT_INSTANT0(
"cc", "PropertyTreeBuilder::ShouldCreateRenderSurface opacity",
@@ -557,7 +557,7 @@ bool AddEffectNodeIfNeeded(
LayerType* layer,
DataForRecursion<LayerType>* data_for_children) {
const bool is_root = !layer->parent();
- const bool has_transparency = layer->opacity() != 1.f;
+ const bool has_transparency = layer->EffectiveOpacity() != 1.f;
const bool has_animated_opacity = IsAnimatingOpacity(layer);
const bool should_create_render_surface = ShouldCreateRenderSurface(
layer, data_from_ancestor.compound_transform_since_render_target,
@@ -580,9 +580,10 @@ bool AddEffectNodeIfNeeded(
EffectNode node;
node.owner_id = layer->id();
- node.data.opacity = layer->opacity();
- node.data.screen_space_opacity = layer->opacity();
+ node.data.opacity = layer->EffectiveOpacity();
node.data.has_render_surface = should_create_render_surface;
+ node.data.has_copy_request = layer->HasCopyRequest();
+ node.data.has_background_filters = !layer->background_filters().IsEmpty();
if (!is_root) {
// The effect node's transform id is used only when we create a render
@@ -597,9 +598,9 @@ bool AddEffectNodeIfNeeded(
}
node.data.clip_id = data_from_ancestor.clip_tree_parent;
- node.data.screen_space_opacity *=
- data_from_ancestor.effect_tree->Node(parent_id)
- ->data.screen_space_opacity;
+ EffectNode* parent = data_from_ancestor.effect_tree->Node(parent_id);
+ node.data.screen_space_opacity_is_animating =
+ parent->data.screen_space_opacity_is_animating || has_animated_opacity;
} else {
// Root render surface acts the unbounded and untransformed to draw content
// into. Transform node created from root layer (includes device scale
@@ -607,6 +608,7 @@ bool AddEffectNodeIfNeeded(
// to root render surface's content, but not root render surface itself.
node.data.transform_id = kRootPropertyTreeNodeId;
node.data.clip_id = kRootPropertyTreeNodeId;
+ node.data.screen_space_opacity_is_animating = has_animated_opacity;
}
data_for_children->effect_tree_parent =
data_for_children->effect_tree->Insert(node, parent_id);
@@ -646,10 +648,6 @@ void BuildPropertyTreesInternal(
AddClipNodeIfNeeded(data_from_parent, layer, created_render_surface,
created_transform_node, &data_for_children);
- data_for_children.is_hidden =
- layer->hide_layer_and_subtree() || data_from_parent.is_hidden;
- layer->set_is_hidden_from_property_trees(data_for_children.is_hidden);
-
for (size_t i = 0; i < layer->children().size(); ++i) {
if (!layer->child_at(i)->scroll_parent()) {
DataForRecursionFromChild<LayerType> data_from_child;
@@ -768,11 +766,11 @@ void BuildPropertyTreesTopLevelInternal(
property_trees->needs_rebuild = false;
// The transform tree is kept up-to-date as it is built, but the
- // combined_clips stored in the clip tree aren't computed during tree
- // building.
+ // combined_clips stored in the clip tree and the screen_space_opacity and
+ // is_drawn in the effect tree aren't computed during tree building.
property_trees->transform_tree.set_needs_update(false);
property_trees->clip_tree.set_needs_update(true);
- property_trees->effect_tree.set_needs_update(false);
+ property_trees->effect_tree.set_needs_update(true);
}
void PropertyTreeBuilder::BuildPropertyTrees(