#include <algorithm>
+#include "base/atomic_sequence_num.h"
#include "base/debug/trace_event.h"
#include "base/location.h"
#include "base/metrics/histogram.h"
#include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
#include "cc/animation/animation.h"
#include "cc/animation/animation_events.h"
+#include "cc/animation/animation_registrar.h"
#include "cc/animation/keyframed_animation_curve.h"
#include "cc/animation/layer_animation_controller.h"
+#include "cc/base/simple_enclosed_region.h"
#include "cc/layers/layer_client.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/scrollbar_layer_interface.h"
namespace cc {
-static int s_next_layer_id = 1;
+base::StaticAtomicSequenceNumber g_next_layer_id;
scoped_refptr<Layer> Layer::Create() {
return make_scoped_refptr(new Layer());
: needs_push_properties_(false),
num_dependents_need_push_properties_(false),
stacking_order_changed_(false),
- layer_id_(s_next_layer_id++),
+ // Layer IDs start from 1.
+ layer_id_(g_next_layer_id.GetNext() + 1),
ignore_set_needs_commit_(false),
+ sorting_context_id_(0),
parent_(NULL),
layer_tree_host_(NULL),
scroll_clip_layer_id_(INVALID_ID),
+ num_descendants_that_draw_content_(0),
should_scroll_on_main_thread_(false),
have_wheel_event_handlers_(false),
+ have_scroll_event_handlers_(false),
user_scrollable_horizontal_(true),
user_scrollable_vertical_(true),
is_root_for_isolated_group_(false),
is_container_for_fixed_position_layers_(false),
is_drawable_(false),
+ draws_content_(false),
hide_layer_and_subtree_(false),
masks_to_bounds_(false),
contents_opaque_(false),
use_parent_backface_visibility_(false),
draw_checkerboard_for_missing_tiles_(false),
force_render_surface_(false),
- is_3d_sorted_(false),
- anchor_point_(0.5f, 0.5f),
+ transform_is_invertible_(true),
background_color_(0),
opacity_(1.f),
blend_mode_(SkXfermode::kSrcOver_Mode),
- anchor_point_z_(0.f),
scroll_parent_(NULL),
clip_parent_(NULL),
replica_layer_(NULL),
raster_scale_(0.f),
client_(NULL) {
- if (layer_id_ == INT_MAX) {
- s_next_layer_id = 1;
- }
-
layer_animation_controller_ = LayerAnimationController::Create(layer_id_);
layer_animation_controller_->AddValueObserver(this);
layer_animation_controller_->set_value_provider(this);
layer_animation_controller_->RemoveValueObserver(this);
layer_animation_controller_->remove_value_provider(this);
+ RemoveFromScrollTree();
+ RemoveFromClipTree();
+
// Remove the parent reference from all children and dependents.
RemoveAllChildren();
if (mask_layer_.get()) {
DCHECK_EQ(this, replica_layer_->parent());
replica_layer_->RemoveFromParent();
}
-
- RemoveFromScrollTree();
- RemoveFromClipTree();
}
void Layer::SetLayerTreeHost(LayerTreeHost* host) {
if (host && layer_animation_controller_->has_any_animation())
host->SetNeedsCommit();
- SetNeedsFilterContextIfNeeded();
}
void Layer::SetNeedsUpdate() {
layer_tree_host_->SetNextCommitWaitsForActivation();
}
-void Layer::SetNeedsFilterContextIfNeeded() {
- if (!layer_tree_host_)
- return;
-
- if (!filters_.IsEmpty() || !background_filters_.IsEmpty() ||
- !uses_default_blend_mode())
- layer_tree_host_->set_needs_filter_context();
-}
-
void Layer::SetNeedsPushProperties() {
if (needs_push_properties_)
return;
void Layer::InsertChild(scoped_refptr<Layer> child, size_t index) {
DCHECK(IsPropertyChangeAllowed());
child->RemoveFromParent();
+ AddDrawableDescendants(child->NumDescendantsThatDrawContent() +
+ (child->DrawsContent() ? 1 : 0));
child->SetParent(this);
child->stacking_order_changed_ = true;
continue;
child->SetParent(NULL);
+ AddDrawableDescendants(-child->NumDescendantsThatDrawContent() -
+ (child->DrawsContent() ? 1 : 0));
children_.erase(iter);
SetNeedsFullTreeSync();
return;
SetNeedsCommit();
}
-void Layer::SetAnchorPoint(const gfx::PointF& anchor_point) {
- DCHECK(IsPropertyChangeAllowed());
- if (anchor_point_ == anchor_point)
- return;
- anchor_point_ = anchor_point;
- SetNeedsCommit();
-}
-
-void Layer::SetAnchorPointZ(float anchor_point_z) {
- DCHECK(IsPropertyChangeAllowed());
- if (anchor_point_z_ == anchor_point_z)
- return;
- anchor_point_z_ = anchor_point_z;
- SetNeedsCommit();
-}
-
void Layer::SetBackgroundColor(SkColor background_color) {
DCHECK(IsPropertyChangeAllowed());
if (background_color_ == background_color)
return color;
}
-void Layer::CalculateContentsScale(
- float ideal_contents_scale,
- float device_scale_factor,
- float page_scale_factor,
- bool animating_transform_to_screen,
- float* contents_scale_x,
- float* contents_scale_y,
- gfx::Size* content_bounds) {
+void Layer::CalculateContentsScale(float ideal_contents_scale,
+ float* contents_scale_x,
+ float* contents_scale_y,
+ gfx::Size* content_bounds) {
DCHECK(layer_tree_host_);
*contents_scale_x = 1;
return;
filters_ = filters;
SetNeedsCommit();
- SetNeedsFilterContextIfNeeded();
}
bool Layer::FilterIsAnimating() const {
return;
background_filters_ = filters;
SetNeedsCommit();
- SetNeedsFilterContextIfNeeded();
}
void Layer::SetOpacity(float opacity) {
blend_mode_ = blend_mode;
SetNeedsCommit();
- SetNeedsFilterContextIfNeeded();
}
void Layer::SetIsRootForIsolatedGroup(bool root) {
if (transform_ == transform)
return;
transform_ = transform;
+ transform_is_invertible_ = transform.IsInvertible();
+ SetNeedsCommit();
+}
+
+void Layer::SetTransformOrigin(const gfx::Point3F& transform_origin) {
+ DCHECK(IsPropertyChangeAllowed());
+ if (transform_origin_ == transform_origin)
+ return;
+ transform_origin_ = transform_origin;
SetNeedsCommit();
}
// "this" may have been destroyed during the process.
}
-// TODO(wjmaclean) We should template this and put it into LayerTreeHostCommon
-// so that both Layer and LayerImpl are using the same code. In order
-// to template it we should avoid calling layer_tree_host() by giving
-// Layer/LayerImpl local accessors for page_scale_layer() and
-// page_scale_factor().
-gfx::Vector2d Layer::MaxScrollOffset() const {
- if (scroll_clip_layer_id_ == INVALID_ID)
- return gfx::Vector2d();
-
- gfx::Size scaled_scroll_bounds(bounds());
- Layer const* current_layer = this;
- Layer const* page_scale_layer = layer_tree_host()->page_scale_layer();
- float scale_factor = 1.f;
- do {
- if (current_layer == page_scale_layer) {
- scale_factor = layer_tree_host()->page_scale_factor();
- scaled_scroll_bounds.SetSize(
- scale_factor * scaled_scroll_bounds.width(),
- scale_factor * scaled_scroll_bounds.height());
- }
- current_layer = current_layer->parent();
- } while (current_layer && current_layer->id() != scroll_clip_layer_id_);
- DCHECK(current_layer);
- DCHECK(current_layer->id() == scroll_clip_layer_id_);
-
- gfx::Vector2dF max_offset(
- scaled_scroll_bounds.width() - current_layer->bounds().width(),
- scaled_scroll_bounds.height() - current_layer->bounds().height());
- // We need the final scroll offset to be in CSS coords.
- max_offset.Scale(1.f / scale_factor);
- max_offset.SetToMax(gfx::Vector2dF());
- return gfx::ToFlooredVector2d(max_offset);
-}
-
void Layer::SetScrollClipLayerId(int clip_layer_id) {
DCHECK(IsPropertyChangeAllowed());
if (scroll_clip_layer_id_ == clip_layer_id)
SetNeedsCommit();
}
+void Layer::SetHaveScrollEventHandlers(bool have_scroll_event_handlers) {
+ DCHECK(IsPropertyChangeAllowed());
+ if (have_scroll_event_handlers_ == have_scroll_event_handlers)
+ return;
+ have_scroll_event_handlers_ = have_scroll_event_handlers;
+ SetNeedsCommit();
+}
+
void Layer::SetNonFastScrollableRegion(const Region& region) {
DCHECK(IsPropertyChangeAllowed());
if (non_fast_scrollable_region_ == region)
SetNeedsCommit();
}
-void Layer::SetIs3dSorted(bool sorted) {
+void Layer::Set3dSortingContextId(int id) {
DCHECK(IsPropertyChangeAllowed());
- if (is_3d_sorted_ == sorted)
+ if (id == sorting_context_id_)
return;
- is_3d_sorted_ = sorted;
+ sorting_context_id_ = id;
SetNeedsCommit();
}
return;
is_drawable_ = is_drawable;
- SetNeedsCommit();
+ UpdateDrawsContent(HasDrawableContent());
}
void Layer::SetHideLayerAndSubtree(bool hide) {
bool use_paint_properties = paint_properties_.source_frame_number ==
layer_tree_host_->source_frame_number();
- layer->SetAnchorPoint(anchor_point_);
- layer->SetAnchorPointZ(anchor_point_z_);
+ layer->SetTransformOrigin(transform_origin_);
layer->SetBackgroundColor(background_color_);
layer->SetBounds(use_paint_properties ? paint_properties_.bounds
: bounds_);
layer->SetContentsScale(contents_scale_x(), contents_scale_y());
bool is_tracing;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
- &is_tracing);
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(
+ TRACE_DISABLED_BY_DEFAULT("cc.debug") "," TRACE_DISABLED_BY_DEFAULT(
+ "devtools.timeline.layers"),
+ &is_tracing);
if (is_tracing)
layer->SetDebugInfo(TakeDebugInfo());
layer->SetMasksToBounds(masks_to_bounds_);
layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_);
layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_);
+ layer->SetHaveScrollEventHandlers(have_scroll_event_handlers_);
layer->SetNonFastScrollableRegion(non_fast_scrollable_region_);
layer->SetTouchEventHandlerRegion(touch_event_handler_region_);
layer->SetContentsOpaque(contents_opaque_);
IsContainerForFixedPositionLayers());
layer->SetPositionConstraint(position_constraint_);
layer->SetShouldFlattenTransform(should_flatten_transform_);
- layer->SetIs3dSorted(is_3d_sorted_);
layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
if (!layer->TransformIsAnimatingOnImplOnly() && !TransformIsAnimating())
- layer->SetTransform(transform_);
+ layer->SetTransformAndInvertibility(transform_, transform_is_invertible_);
DCHECK(!(TransformIsAnimating() && layer->TransformIsAnimatingOnImplOnly()));
+ layer->Set3dSortingContextId(sorting_context_id_);
+ layer->SetNumDescendantsThatDrawContent(num_descendants_that_draw_content_);
layer->SetScrollClipLayer(scroll_clip_layer_id_);
layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
}
bool Layer::DrawsContent() const {
+ return draws_content_;
+}
+
+bool Layer::HasDrawableContent() const {
return is_drawable_;
}
+void Layer::UpdateDrawsContent(bool has_drawable_content) {
+ bool draws_content = has_drawable_content;
+ DCHECK(is_drawable_ || !has_drawable_content);
+ if (draws_content == draws_content_)
+ return;
+
+ if (HasDelegatedContent()) {
+ // Layers with delegated content need to be treated as if they have as
+ // many children as the number of layers they own delegated quads for.
+ // Since we don't know this number right now, we choose one that acts like
+ // infinity for our purposes.
+ AddDrawableDescendants(draws_content ? 1000 : -1000);
+ }
+
+ if (parent())
+ parent()->AddDrawableDescendants(draws_content ? 1 : -1);
+
+ draws_content_ = draws_content;
+ SetNeedsCommit();
+}
+
+int Layer::NumDescendantsThatDrawContent() const {
+ return num_descendants_that_draw_content_;
+}
+
void Layer::SavePaintProperties() {
DCHECK(layer_tree_host_);
return false;
}
+bool Layer::IsSuitableForGpuRasterization() const {
+ return true;
+}
+
scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() {
if (client_)
return client_->TakeDebugInfo();
draw_properties_.render_surface.reset();
}
+void Layer::ClearRenderSurfaceLayerList() {
+ if (draw_properties_.render_surface)
+ draw_properties_.render_surface->layer_list().clear();
+}
+
gfx::Vector2dF Layer::ScrollOffsetForAnimation() const {
return TotalScrollOffset();
}
}
void Layer::OnTransformAnimated(const gfx::Transform& transform) {
+ if (transform_ == transform)
+ return;
transform_ = transform;
+ transform_is_invertible_ = transform.IsInvertible();
}
void Layer::OnScrollOffsetAnimated(const gfx::Vector2dF& scroll_offset) {
if (!layer_animation_controller_->animation_registrar())
return false;
+ if (animation->target_property() == Animation::ScrollOffset &&
+ !layer_animation_controller_->animation_registrar()
+ ->supports_scroll_animations())
+ return false;
+
UMA_HISTOGRAM_BOOLEAN("Renderer.AnimationAddedToOrphanLayer",
!layer_tree_host_);
layer_animation_controller_->AddAnimation(animation.Pass());
}
void Layer::PauseAnimation(int animation_id, double time_offset) {
- layer_animation_controller_->PauseAnimation(animation_id, time_offset);
+ layer_animation_controller_->PauseAnimation(
+ animation_id, base::TimeDelta::FromSecondsD(time_offset));
SetNeedsCommit();
}
layer_animation_controller_->RemoveEventObserver(animation_observer);
}
-Region Layer::VisibleContentOpaqueRegion() const {
+SimpleEnclosedRegion Layer::VisibleContentOpaqueRegion() const {
if (contents_opaque())
- return visible_content_rect();
- return Region();
+ return SimpleEnclosedRegion(visible_content_rect());
+ return SimpleEnclosedRegion();
}
ScrollbarLayerInterface* Layer::ToScrollbarLayer() {
void Layer::RemoveFromScrollTree() {
if (scroll_children_.get()) {
- for (std::set<Layer*>::iterator it = scroll_children_->begin();
- it != scroll_children_->end(); ++it)
- (*it)->scroll_parent_ = NULL;
+ std::set<Layer*> copy = *scroll_children_;
+ for (std::set<Layer*>::iterator it = copy.begin(); it != copy.end(); ++it)
+ (*it)->SetScrollParent(NULL);
}
- if (scroll_parent_)
- scroll_parent_->RemoveScrollChild(this);
-
- scroll_parent_ = NULL;
+ DCHECK(!scroll_children_);
+ SetScrollParent(NULL);
}
void Layer::RemoveFromClipTree() {
if (clip_children_.get()) {
- for (std::set<Layer*>::iterator it = clip_children_->begin();
- it != clip_children_->end(); ++it)
- (*it)->clip_parent_ = NULL;
+ std::set<Layer*> copy = *clip_children_;
+ for (std::set<Layer*>::iterator it = copy.begin(); it != copy.end(); ++it)
+ (*it)->SetClipParent(NULL);
}
- if (clip_parent_)
- clip_parent_->RemoveClipChild(this);
+ DCHECK(!clip_children_);
+ SetClipParent(NULL);
+}
- clip_parent_ = NULL;
+void Layer::AddDrawableDescendants(int num) {
+ DCHECK_GE(num_descendants_that_draw_content_, 0);
+ DCHECK_GE(num_descendants_that_draw_content_ + num, 0);
+ if (num == 0)
+ return;
+ num_descendants_that_draw_content_ += num;
+ SetNeedsCommit();
+ if (parent())
+ parent()->AddDrawableDescendants(num);
}
void Layer::RunMicroBenchmark(MicroBenchmark* benchmark) {
benchmark->RunOnLayer(this);
}
+
+bool Layer::HasDelegatedContent() const {
+ return false;
+}
+
} // namespace cc