OLD | NEW |
| (Empty) |
1 // Copyright 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/layer_impl.h" | |
6 | |
7 #include "base/debug/trace_event.h" | |
8 #include "base/stringprintf.h" | |
9 #include "base/values.h" | |
10 #include "cc/animation/animation_registrar.h" | |
11 #include "cc/animation/scrollbar_animation_controller.h" | |
12 #include "cc/animation/scrollbar_animation_controller_linear_fade.h" | |
13 #include "cc/base/math_util.h" | |
14 #include "cc/debug/debug_colors.h" | |
15 #include "cc/debug/layer_tree_debug_state.h" | |
16 #include "cc/quad_sink.h" | |
17 #include "cc/quads/debug_border_draw_quad.h" | |
18 #include "cc/scrollbar_layer_impl.h" | |
19 #include "cc/trees/layer_tree_impl.h" | |
20 #include "cc/trees/layer_tree_settings.h" | |
21 #include "cc/trees/proxy.h" | |
22 #include "ui/gfx/point_conversions.h" | |
23 #include "ui/gfx/quad_f.h" | |
24 #include "ui/gfx/rect_conversions.h" | |
25 | |
26 namespace cc { | |
27 | |
28 LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id) | |
29 : parent_(NULL), | |
30 mask_layer_id_(-1), | |
31 replica_layer_id_(-1), | |
32 layer_id_(id), | |
33 layer_tree_impl_(tree_impl), | |
34 anchor_point_(0.5f, 0.5f), | |
35 anchor_point_z_(0.f), | |
36 scrollable_(false), | |
37 should_scroll_on_main_thread_(false), | |
38 have_wheel_event_handlers_(false), | |
39 background_color_(0), | |
40 stacking_order_changed_(false), | |
41 double_sided_(true), | |
42 layer_property_changed_(false), | |
43 layer_surface_property_changed_(false), | |
44 masks_to_bounds_(false), | |
45 contents_opaque_(false), | |
46 opacity_(1.0), | |
47 preserves_3d_(false), | |
48 use_parent_backface_visibility_(false), | |
49 draw_checkerboard_for_missing_tiles_(false), | |
50 draws_content_(false), | |
51 force_render_surface_(false), | |
52 is_container_for_fixed_position_layers_(false), | |
53 fixed_to_container_layer_(false), | |
54 draw_depth_(0.f), | |
55 #ifndef NDEBUG | |
56 between_will_draw_and_did_draw_(false), | |
57 #endif | |
58 horizontal_scrollbar_layer_(NULL), | |
59 vertical_scrollbar_layer_(NULL) { | |
60 DCHECK(layer_id_ > 0); | |
61 DCHECK(layer_tree_impl_); | |
62 layer_tree_impl_->RegisterLayer(this); | |
63 AnimationRegistrar* registrar = layer_tree_impl_->animationRegistrar(); | |
64 layer_animation_controller_ = | |
65 registrar->GetAnimationControllerForId(layer_id_); | |
66 layer_animation_controller_->AddObserver(this); | |
67 } | |
68 | |
69 LayerImpl::~LayerImpl() { | |
70 #ifndef NDEBUG | |
71 DCHECK(!between_will_draw_and_did_draw_); | |
72 #endif | |
73 layer_tree_impl_->UnregisterLayer(this); | |
74 layer_animation_controller_->RemoveObserver(this); | |
75 } | |
76 | |
77 void LayerImpl::AddChild(scoped_ptr<LayerImpl> child) { | |
78 child->set_parent(this); | |
79 DCHECK_EQ(layer_tree_impl(), child->layer_tree_impl()); | |
80 children_.push_back(child.Pass()); | |
81 layer_tree_impl()->set_needs_update_draw_properties(); | |
82 } | |
83 | |
84 scoped_ptr<LayerImpl> LayerImpl::RemoveChild(LayerImpl* child) { | |
85 for (ScopedPtrVector<LayerImpl>::iterator it = children_.begin(); | |
86 it != children_.end(); | |
87 ++it) { | |
88 if (*it == child) { | |
89 scoped_ptr<LayerImpl> ret = children_.take(it); | |
90 children_.erase(it); | |
91 layer_tree_impl()->set_needs_update_draw_properties(); | |
92 return ret.Pass(); | |
93 } | |
94 } | |
95 return scoped_ptr<LayerImpl>(); | |
96 } | |
97 | |
98 void LayerImpl::ClearChildList() { | |
99 if (children_.empty()) | |
100 return; | |
101 | |
102 children_.clear(); | |
103 layer_tree_impl()->set_needs_update_draw_properties(); | |
104 } | |
105 | |
106 void LayerImpl::CreateRenderSurface() { | |
107 DCHECK(!draw_properties_.render_surface); | |
108 draw_properties_.render_surface = | |
109 make_scoped_ptr(new RenderSurfaceImpl(this)); | |
110 draw_properties_.render_target = this; | |
111 } | |
112 | |
113 scoped_ptr<SharedQuadState> LayerImpl::CreateSharedQuadState() const { | |
114 scoped_ptr<SharedQuadState> state = SharedQuadState::Create(); | |
115 state->SetAll(draw_properties_.target_space_transform, | |
116 draw_properties_.content_bounds, | |
117 draw_properties_.visible_content_rect, | |
118 draw_properties_.clip_rect, | |
119 draw_properties_.is_clipped, | |
120 draw_properties_.opacity); | |
121 return state.Pass(); | |
122 } | |
123 | |
124 void LayerImpl::WillDraw(ResourceProvider* resource_provider) { | |
125 #ifndef NDEBUG | |
126 // willDraw/didDraw must be matched. | |
127 DCHECK(!between_will_draw_and_did_draw_); | |
128 between_will_draw_and_did_draw_ = true; | |
129 #endif | |
130 } | |
131 | |
132 void LayerImpl::DidDraw(ResourceProvider* resource_provider) { | |
133 #ifndef NDEBUG | |
134 DCHECK(between_will_draw_and_did_draw_); | |
135 between_will_draw_and_did_draw_ = false; | |
136 #endif | |
137 } | |
138 | |
139 bool LayerImpl::ShowDebugBorders() const { | |
140 return layer_tree_impl()->debug_state().showDebugBorders; | |
141 } | |
142 | |
143 void LayerImpl::GetDebugBorderProperties(SkColor* color, float* width) const { | |
144 if (draws_content_) { | |
145 *color = DebugColors::ContentLayerBorderColor(); | |
146 *width = DebugColors::ContentLayerBorderWidth(layer_tree_impl()); | |
147 return; | |
148 } | |
149 | |
150 if (masks_to_bounds_) { | |
151 *color = DebugColors::MaskingLayerBorderColor(); | |
152 *width = DebugColors::MaskingLayerBorderWidth(layer_tree_impl()); | |
153 return; | |
154 } | |
155 | |
156 *color = DebugColors::ContainerLayerBorderColor(); | |
157 *width = DebugColors::ContainerLayerBorderWidth(layer_tree_impl()); | |
158 } | |
159 | |
160 void LayerImpl::AppendDebugBorderQuad( | |
161 QuadSink* quad_sink, | |
162 const SharedQuadState* shared_quad_state, | |
163 AppendQuadsData* append_quads_data) const { | |
164 if (!ShowDebugBorders()) | |
165 return; | |
166 | |
167 SkColor color; | |
168 float width; | |
169 GetDebugBorderProperties(&color, &width); | |
170 | |
171 gfx::Rect content_rect(content_bounds()); | |
172 scoped_ptr<DebugBorderDrawQuad> debugBorderQuad = | |
173 DebugBorderDrawQuad::Create(); | |
174 debugBorderQuad->SetNew(shared_quad_state, content_rect, color, width); | |
175 quad_sink->Append(debugBorderQuad.PassAs<DrawQuad>(), append_quads_data); | |
176 } | |
177 | |
178 bool LayerImpl::HasDelegatedContent() const { | |
179 return false; | |
180 } | |
181 | |
182 bool LayerImpl::HasContributingDelegatedRenderPasses() const { | |
183 return false; | |
184 } | |
185 | |
186 RenderPass::Id LayerImpl::FirstContributingRenderPassId() const { | |
187 return RenderPass::Id(0, 0); | |
188 } | |
189 | |
190 RenderPass::Id LayerImpl::NextContributingRenderPassId(RenderPass::Id id) | |
191 const { | |
192 return RenderPass::Id(0, 0); | |
193 } | |
194 | |
195 ResourceProvider::ResourceId LayerImpl::ContentsResourceId() const { | |
196 NOTREACHED(); | |
197 return 0; | |
198 } | |
199 | |
200 void LayerImpl::SetSentScrollDelta(gfx::Vector2d sent_scroll_delta) { | |
201 // Pending tree never has sent scroll deltas | |
202 DCHECK(layer_tree_impl()->IsActiveTree()); | |
203 | |
204 if (sent_scroll_delta_ == sent_scroll_delta) | |
205 return; | |
206 | |
207 sent_scroll_delta_ = sent_scroll_delta; | |
208 } | |
209 | |
210 gfx::Vector2dF LayerImpl::ScrollBy(gfx::Vector2dF scroll) { | |
211 gfx::Vector2dF min_delta = -scroll_offset_; | |
212 gfx::Vector2dF max_delta = max_scroll_offset_ - scroll_offset_; | |
213 // Clamp new_delta so that position + delta stays within scroll bounds. | |
214 gfx::Vector2dF new_delta = (scroll_delta_ + scroll); | |
215 new_delta.ClampToMin(min_delta); | |
216 new_delta.ClampToMax(max_delta); | |
217 gfx::Vector2dF unscrolled = scroll_delta_ + scroll - new_delta; | |
218 | |
219 SetScrollDelta(new_delta); | |
220 return unscrolled; | |
221 } | |
222 | |
223 InputHandlerClient::ScrollStatus LayerImpl::TryScroll( | |
224 gfx::PointF screen_space_point, | |
225 InputHandlerClient::ScrollInputType type) const { | |
226 if (should_scroll_on_main_thread()) { | |
227 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed shouldScrollOnMainThread"); | |
228 return InputHandlerClient::ScrollOnMainThread; | |
229 } | |
230 | |
231 if (!screen_space_transform().IsInvertible()) { | |
232 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored nonInvertibleTransform"); | |
233 return InputHandlerClient::ScrollIgnored; | |
234 } | |
235 | |
236 if (!non_fast_scrollable_region().IsEmpty()) { | |
237 bool clipped = false; | |
238 gfx::Transform inverse_screen_space_transform( | |
239 gfx::Transform::kSkipInitialization); | |
240 if (!screen_space_transform().GetInverse(&inverse_screen_space_transform)) { | |
241 // TODO(shawnsingh): We shouldn't be applying a projection if screen space | |
242 // transform is uninvertible here. Perhaps we should be returning | |
243 // ScrollOnMainThread in this case? | |
244 } | |
245 | |
246 gfx::PointF hit_test_point_in_content_space = | |
247 MathUtil::ProjectPoint(inverse_screen_space_transform, | |
248 screen_space_point, | |
249 &clipped); | |
250 gfx::PointF hit_test_point_in_layer_space = | |
251 gfx::ScalePoint(hit_test_point_in_content_space, | |
252 1.f / contents_scale_x(), | |
253 1.f / contents_scale_y()); | |
254 if (!clipped && | |
255 non_fast_scrollable_region().Contains( | |
256 gfx::ToRoundedPoint(hit_test_point_in_layer_space))) { | |
257 TRACE_EVENT0("cc", | |
258 "LayerImpl::tryScroll: Failed nonFastScrollableRegion"); | |
259 return InputHandlerClient::ScrollOnMainThread; | |
260 } | |
261 } | |
262 | |
263 if (type == InputHandlerClient::Wheel && have_wheel_event_handlers()) { | |
264 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Failed wheelEventHandlers"); | |
265 return InputHandlerClient::ScrollOnMainThread; | |
266 } | |
267 | |
268 if (!scrollable()) { | |
269 TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable"); | |
270 return InputHandlerClient::ScrollIgnored; | |
271 } | |
272 | |
273 if (max_scroll_offset_.x() <= 0 && max_scroll_offset_.y() <= 0) { | |
274 TRACE_EVENT0("cc", | |
275 "LayerImpl::tryScroll: Ignored. Technically scrollable," | |
276 " but has no affordance in either direction."); | |
277 return InputHandlerClient::ScrollIgnored; | |
278 } | |
279 | |
280 return InputHandlerClient::ScrollStarted; | |
281 } | |
282 | |
283 bool LayerImpl::DrawCheckerboardForMissingTiles() const { | |
284 return draw_checkerboard_for_missing_tiles_ && | |
285 !layer_tree_impl()->settings().backgroundColorInsteadOfCheckerboard; | |
286 } | |
287 | |
288 gfx::Rect LayerImpl::LayerRectToContentRect( | |
289 const gfx::RectF& layer_rect) const { | |
290 gfx::RectF content_rect = | |
291 gfx::ScaleRect(layer_rect, contents_scale_x(), contents_scale_y()); | |
292 // Intersect with content rect to avoid the extra pixel because for some | |
293 // values x and y, ceil((x / y) * y) may be x + 1. | |
294 content_rect.Intersect(gfx::Rect(content_bounds())); | |
295 return gfx::ToEnclosingRect(content_rect); | |
296 } | |
297 | |
298 skia::RefPtr<SkPicture> LayerImpl::GetPicture() { | |
299 return skia::RefPtr<SkPicture>(); | |
300 } | |
301 | |
302 bool LayerImpl::CanClipSelf() const { | |
303 return false; | |
304 } | |
305 | |
306 bool LayerImpl::AreVisibleResourcesReady() const { | |
307 return true; | |
308 } | |
309 | |
310 scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) { | |
311 return LayerImpl::Create(tree_impl, layer_id_); | |
312 } | |
313 | |
314 void LayerImpl::PushPropertiesTo(LayerImpl* layer) { | |
315 layer->SetAnchorPoint(anchor_point_); | |
316 layer->SetAnchorPointZ(anchor_point_z_); | |
317 layer->SetBackgroundColor(background_color_); | |
318 layer->SetBounds(bounds_); | |
319 layer->SetContentBounds(content_bounds()); | |
320 layer->SetContentsScale(contents_scale_x(), contents_scale_y()); | |
321 layer->SetDebugName(debug_name_); | |
322 layer->SetDoubleSided(double_sided_); | |
323 layer->SetDrawCheckerboardForMissingTiles( | |
324 draw_checkerboard_for_missing_tiles_); | |
325 layer->SetForceRenderSurface(force_render_surface_); | |
326 layer->SetDrawsContent(DrawsContent()); | |
327 layer->SetFilters(filters()); | |
328 layer->SetFilter(filter()); | |
329 layer->SetBackgroundFilters(background_filters()); | |
330 layer->SetMasksToBounds(masks_to_bounds_); | |
331 layer->SetShouldScrollOnMainThread(should_scroll_on_main_thread_); | |
332 layer->SetHaveWheelEventHandlers(have_wheel_event_handlers_); | |
333 layer->SetNonFastScrollableRegion(non_fast_scrollable_region_); | |
334 layer->SetTouchEventHandlerRegion(touch_event_handler_region_); | |
335 layer->SetContentsOpaque(contents_opaque_); | |
336 layer->SetOpacity(opacity_); | |
337 layer->SetPosition(position_); | |
338 layer->SetIsContainerForFixedPositionLayers( | |
339 is_container_for_fixed_position_layers_); | |
340 layer->SetFixedToContainerLayer(fixed_to_container_layer_); | |
341 layer->SetPreserves3d(preserves_3d()); | |
342 layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_); | |
343 layer->SetSublayerTransform(sublayer_transform_); | |
344 layer->SetTransform(transform_); | |
345 | |
346 layer->SetScrollable(scrollable_); | |
347 layer->SetScrollOffset(scroll_offset_); | |
348 layer->SetMaxScrollOffset(max_scroll_offset_); | |
349 | |
350 // If the main thread commits multiple times before the impl thread actually | |
351 // draws, then damage tracking will become incorrect if we simply clobber the | |
352 // updateRect here. The LayerImpl's updateRect needs to accumulate (i.e. | |
353 // union) any update changes that have occurred on the main thread. | |
354 update_rect_.Union(layer->update_rect()); | |
355 layer->set_update_rect(update_rect_); | |
356 | |
357 layer->SetScrollDelta(layer->scroll_delta() - layer->sent_scroll_delta()); | |
358 layer->SetSentScrollDelta(gfx::Vector2d()); | |
359 | |
360 layer->SetStackingOrderChanged(stacking_order_changed_); | |
361 | |
362 layer_animation_controller_->PushAnimationUpdatesTo( | |
363 layer->layer_animation_controller()); | |
364 | |
365 // Reset any state that should be cleared for the next update. | |
366 stacking_order_changed_ = false; | |
367 update_rect_ = gfx::RectF(); | |
368 } | |
369 | |
370 std::string LayerImpl::IndentString(int indent) { | |
371 std::string str; | |
372 for (int i = 0; i != indent; ++i) | |
373 str.append(" "); | |
374 return str; | |
375 } | |
376 | |
377 void LayerImpl::DumpLayerProperties(std::string* str, int indent) const { | |
378 std::string indent_str = IndentString(indent); | |
379 str->append(indent_str); | |
380 base::StringAppendF(str, "layer ID: %d\n", layer_id_); | |
381 | |
382 str->append(indent_str); | |
383 base::StringAppendF( | |
384 str, "bounds: %d, %d\n", bounds().width(), bounds().height()); | |
385 | |
386 if (draw_properties_.render_target) { | |
387 str->append(indent_str); | |
388 base::StringAppendF( | |
389 str, "renderTarget: %d\n", draw_properties_.render_target->layer_id_); | |
390 } | |
391 | |
392 str->append(indent_str); | |
393 base::StringAppendF(str, "position: %f, %f\n", position_.x(), position_.y()); | |
394 | |
395 str->append(indent_str); | |
396 base::StringAppendF(str, "contentsOpaque: %d\n", contents_opaque_); | |
397 | |
398 str->append(indent_str); | |
399 const gfx::Transform& transform = draw_properties_.target_space_transform; | |
400 base::StringAppendF(str, | |
401 "drawTransform: %f, %f, %f, %f // %f, %f, %f, %f" | |
402 " // %f, %f, %f, %f // %f, %f, %f, %f\n", | |
403 transform.matrix().getDouble(0, 0), | |
404 transform.matrix().getDouble(0, 1), | |
405 transform.matrix().getDouble(0, 2), | |
406 transform.matrix().getDouble(0, 3), | |
407 transform.matrix().getDouble(1, 0), | |
408 transform.matrix().getDouble(1, 1), | |
409 transform.matrix().getDouble(1, 2), | |
410 transform.matrix().getDouble(1, 3), | |
411 transform.matrix().getDouble(2, 0), | |
412 transform.matrix().getDouble(2, 1), | |
413 transform.matrix().getDouble(2, 2), | |
414 transform.matrix().getDouble(2, 3), | |
415 transform.matrix().getDouble(3, 0), | |
416 transform.matrix().getDouble(3, 1), | |
417 transform.matrix().getDouble(3, 2), | |
418 transform.matrix().getDouble(3, 3)); | |
419 | |
420 str->append(indent_str); | |
421 base::StringAppendF( | |
422 str, "draws_content: %s\n", draws_content_ ? "yes" : "no"); | |
423 } | |
424 | |
425 std::string LayerImpl::LayerTreeAsText() const { | |
426 std::string str; | |
427 DumpLayer(&str, 0); | |
428 return str; | |
429 } | |
430 | |
431 void LayerImpl::DumpLayer(std::string* str, int indent) const { | |
432 str->append(IndentString(indent)); | |
433 base::StringAppendF(str, "%s(%s)\n", LayerTypeAsString(), debug_name_.data()); | |
434 DumpLayerProperties(str, indent+2); | |
435 if (replica_layer_) { | |
436 str->append(IndentString(indent+2)); | |
437 str->append("Replica:\n"); | |
438 replica_layer_->DumpLayer(str, indent+3); | |
439 } | |
440 if (mask_layer_) { | |
441 str->append(IndentString(indent+2)); | |
442 str->append("Mask:\n"); | |
443 mask_layer_->DumpLayer(str, indent+3); | |
444 } | |
445 for (size_t i = 0; i < children_.size(); ++i) | |
446 children_[i]->DumpLayer(str, indent+1); | |
447 } | |
448 | |
449 base::DictionaryValue* LayerImpl::LayerTreeAsJson() const { | |
450 base::ListValue* list; | |
451 base::DictionaryValue* result = new base::DictionaryValue; | |
452 result->SetString("LayerType", LayerTypeAsString()); | |
453 | |
454 list = new base::ListValue; | |
455 list->AppendInteger(bounds().width()); | |
456 list->AppendInteger(bounds().height()); | |
457 result->Set("Bounds", list); | |
458 | |
459 list = new base::ListValue; | |
460 list->AppendDouble(position_.x()); | |
461 list->AppendDouble(position_.y()); | |
462 result->Set("Position", list); | |
463 | |
464 const gfx::Transform& gfx_transform = draw_properties_.target_space_transform; | |
465 double transform[16]; | |
466 gfx_transform.matrix().asColMajord(transform); | |
467 list = new base::ListValue; | |
468 for (int i = 0; i < 16; ++i) | |
469 list->AppendDouble(transform[i]); | |
470 result->Set("DrawTransform", list); | |
471 | |
472 result->SetBoolean("DrawsContent", draws_content_); | |
473 result->SetDouble("Opacity", opacity()); | |
474 | |
475 list = new base::ListValue; | |
476 for (size_t i = 0; i < children_.size(); ++i) | |
477 list->Append(children_[i]->LayerTreeAsJson()); | |
478 result->Set("Children", list); | |
479 | |
480 return result; | |
481 } | |
482 | |
483 void LayerImpl::SetStackingOrderChanged(bool stacking_order_changed) { | |
484 if (stacking_order_changed) { | |
485 stacking_order_changed_ = true; | |
486 NoteLayerPropertyChangedForSubtree(); | |
487 } | |
488 } | |
489 | |
490 bool LayerImpl::LayerSurfacePropertyChanged() const { | |
491 if (layer_surface_property_changed_) | |
492 return true; | |
493 | |
494 // If this layer's surface property hasn't changed, we want to see if | |
495 // some layer above us has changed this property. This is done for the | |
496 // case when such parent layer does not draw content, and therefore will | |
497 // not be traversed by the damage tracker. We need to make sure that | |
498 // property change on such layer will be caught by its descendants. | |
499 LayerImpl* current = this->parent_; | |
500 while (current && !current->draw_properties_.render_surface) { | |
501 if (current->layer_surface_property_changed_) | |
502 return true; | |
503 current = current->parent_; | |
504 } | |
505 | |
506 return false; | |
507 } | |
508 | |
509 void LayerImpl::NoteLayerSurfacePropertyChanged() { | |
510 layer_surface_property_changed_ = true; | |
511 layer_tree_impl()->set_needs_update_draw_properties(); | |
512 } | |
513 | |
514 void LayerImpl::NoteLayerPropertyChanged() { | |
515 layer_property_changed_ = true; | |
516 layer_tree_impl()->set_needs_update_draw_properties(); | |
517 } | |
518 | |
519 void LayerImpl::NoteLayerPropertyChangedForSubtree() { | |
520 NoteLayerPropertyChanged(); | |
521 NoteLayerPropertyChangedForDescendants(); | |
522 } | |
523 | |
524 void LayerImpl::NoteLayerPropertyChangedForDescendants() { | |
525 layer_tree_impl()->set_needs_update_draw_properties(); | |
526 for (size_t i = 0; i < children_.size(); ++i) | |
527 children_[i]->NoteLayerPropertyChangedForSubtree(); | |
528 } | |
529 | |
530 const char* LayerImpl::LayerTypeAsString() const { | |
531 return "Layer"; | |
532 } | |
533 | |
534 void LayerImpl::ResetAllChangeTrackingForSubtree() { | |
535 layer_property_changed_ = false; | |
536 layer_surface_property_changed_ = false; | |
537 | |
538 update_rect_ = gfx::RectF(); | |
539 | |
540 if (draw_properties_.render_surface) | |
541 draw_properties_.render_surface->ResetPropertyChangedFlag(); | |
542 | |
543 if (mask_layer_) | |
544 mask_layer_->ResetAllChangeTrackingForSubtree(); | |
545 | |
546 if (replica_layer_) { | |
547 // This also resets the replica mask, if it exists. | |
548 replica_layer_->ResetAllChangeTrackingForSubtree(); | |
549 } | |
550 | |
551 for (size_t i = 0; i < children_.size(); ++i) | |
552 children_[i]->ResetAllChangeTrackingForSubtree(); | |
553 } | |
554 | |
555 bool LayerImpl::LayerIsAlwaysDamaged() const { | |
556 return false; | |
557 } | |
558 | |
559 void LayerImpl::OnOpacityAnimated(float opacity) { | |
560 SetOpacity(opacity); | |
561 } | |
562 | |
563 void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) { | |
564 SetTransform(transform); | |
565 } | |
566 | |
567 bool LayerImpl::IsActive() const { | |
568 return layer_tree_impl_->IsActiveTree(); | |
569 } | |
570 | |
571 void LayerImpl::SetBounds(gfx::Size bounds) { | |
572 if (bounds_ == bounds) | |
573 return; | |
574 | |
575 bounds_ = bounds; | |
576 | |
577 if (masks_to_bounds()) | |
578 NoteLayerPropertyChangedForSubtree(); | |
579 else | |
580 NoteLayerPropertyChanged(); | |
581 } | |
582 | |
583 void LayerImpl::SetMaskLayer(scoped_ptr<LayerImpl> mask_layer) { | |
584 int new_layer_id = mask_layer ? mask_layer->id() : -1; | |
585 | |
586 if (mask_layer) { | |
587 DCHECK_EQ(layer_tree_impl(), mask_layer->layer_tree_impl()); | |
588 DCHECK_NE(new_layer_id, mask_layer_id_); | |
589 } else if (new_layer_id == mask_layer_id_) { | |
590 return; | |
591 } | |
592 | |
593 mask_layer_ = mask_layer.Pass(); | |
594 mask_layer_id_ = new_layer_id; | |
595 if (mask_layer_) | |
596 mask_layer_->set_parent(this); | |
597 NoteLayerPropertyChangedForSubtree(); | |
598 } | |
599 | |
600 scoped_ptr<LayerImpl> LayerImpl::TakeMaskLayer() { | |
601 mask_layer_id_ = -1; | |
602 return mask_layer_.Pass(); | |
603 } | |
604 | |
605 void LayerImpl::SetReplicaLayer(scoped_ptr<LayerImpl> replica_layer) { | |
606 int new_layer_id = replica_layer ? replica_layer->id() : -1; | |
607 | |
608 if (replica_layer) { | |
609 DCHECK_EQ(layer_tree_impl(), replica_layer->layer_tree_impl()); | |
610 DCHECK_NE(new_layer_id, replica_layer_id_); | |
611 } else if (new_layer_id == replica_layer_id_) { | |
612 return; | |
613 } | |
614 | |
615 replica_layer_ = replica_layer.Pass(); | |
616 replica_layer_id_ = new_layer_id; | |
617 if (replica_layer_) | |
618 replica_layer_->set_parent(this); | |
619 NoteLayerPropertyChangedForSubtree(); | |
620 } | |
621 | |
622 scoped_ptr<LayerImpl> LayerImpl::TakeReplicaLayer() { | |
623 replica_layer_id_ = -1; | |
624 return replica_layer_.Pass(); | |
625 } | |
626 | |
627 ScrollbarLayerImpl* LayerImpl::ToScrollbarLayer() { | |
628 return NULL; | |
629 } | |
630 | |
631 void LayerImpl::SetDrawsContent(bool draws_content) { | |
632 if (draws_content_ == draws_content) | |
633 return; | |
634 | |
635 draws_content_ = draws_content; | |
636 NoteLayerPropertyChanged(); | |
637 } | |
638 | |
639 void LayerImpl::SetAnchorPoint(gfx::PointF anchor_point) { | |
640 if (anchor_point_ == anchor_point) | |
641 return; | |
642 | |
643 anchor_point_ = anchor_point; | |
644 NoteLayerPropertyChangedForSubtree(); | |
645 } | |
646 | |
647 void LayerImpl::SetAnchorPointZ(float anchor_point_z) { | |
648 if (anchor_point_z_ == anchor_point_z) | |
649 return; | |
650 | |
651 anchor_point_z_ = anchor_point_z; | |
652 NoteLayerPropertyChangedForSubtree(); | |
653 } | |
654 | |
655 void LayerImpl::SetBackgroundColor(SkColor background_color) { | |
656 if (background_color_ == background_color) | |
657 return; | |
658 | |
659 background_color_ = background_color; | |
660 NoteLayerPropertyChanged(); | |
661 } | |
662 | |
663 void LayerImpl::SetFilters(const WebKit::WebFilterOperations& filters) { | |
664 if (filters_ == filters) | |
665 return; | |
666 | |
667 DCHECK(!filter_); | |
668 filters_ = filters; | |
669 NoteLayerPropertyChangedForSubtree(); | |
670 } | |
671 | |
672 void LayerImpl::SetBackgroundFilters( | |
673 const WebKit::WebFilterOperations& filters) { | |
674 if (background_filters_ == filters) | |
675 return; | |
676 | |
677 background_filters_ = filters; | |
678 NoteLayerPropertyChanged(); | |
679 } | |
680 | |
681 void LayerImpl::SetFilter(const skia::RefPtr<SkImageFilter>& filter) { | |
682 if (filter_.get() == filter.get()) | |
683 return; | |
684 | |
685 DCHECK(filters_.isEmpty()); | |
686 filter_ = filter; | |
687 NoteLayerPropertyChangedForSubtree(); | |
688 } | |
689 | |
690 void LayerImpl::SetMasksToBounds(bool masks_to_bounds) { | |
691 if (masks_to_bounds_ == masks_to_bounds) | |
692 return; | |
693 | |
694 masks_to_bounds_ = masks_to_bounds; | |
695 NoteLayerPropertyChangedForSubtree(); | |
696 } | |
697 | |
698 void LayerImpl::SetContentsOpaque(bool opaque) { | |
699 if (contents_opaque_ == opaque) | |
700 return; | |
701 | |
702 contents_opaque_ = opaque; | |
703 NoteLayerPropertyChangedForSubtree(); | |
704 } | |
705 | |
706 void LayerImpl::SetOpacity(float opacity) { | |
707 if (opacity_ == opacity) | |
708 return; | |
709 | |
710 opacity_ = opacity; | |
711 NoteLayerSurfacePropertyChanged(); | |
712 } | |
713 | |
714 bool LayerImpl::OpacityIsAnimating() const { | |
715 return layer_animation_controller_->IsAnimatingProperty(Animation::Opacity); | |
716 } | |
717 | |
718 bool LayerImpl::OpacityIsAnimatingOnImplOnly() const { | |
719 Animation* opacity_animation = | |
720 layer_animation_controller_->GetAnimation(Animation::Opacity); | |
721 return opacity_animation && opacity_animation->is_impl_only(); | |
722 } | |
723 | |
724 void LayerImpl::SetPosition(gfx::PointF position) { | |
725 if (position_ == position) | |
726 return; | |
727 | |
728 position_ = position; | |
729 NoteLayerPropertyChangedForSubtree(); | |
730 } | |
731 | |
732 void LayerImpl::SetPreserves3d(bool preserves3_d) { | |
733 if (preserves_3d_ == preserves3_d) | |
734 return; | |
735 | |
736 preserves_3d_ = preserves3_d; | |
737 NoteLayerPropertyChangedForSubtree(); | |
738 } | |
739 | |
740 void LayerImpl::SetSublayerTransform(const gfx::Transform& sublayer_transform) { | |
741 if (sublayer_transform_ == sublayer_transform) | |
742 return; | |
743 | |
744 sublayer_transform_ = sublayer_transform; | |
745 // Sublayer transform does not affect the current layer; it affects only its | |
746 // children. | |
747 NoteLayerPropertyChangedForDescendants(); | |
748 } | |
749 | |
750 void LayerImpl::SetTransform(const gfx::Transform& transform) { | |
751 if (transform_ == transform) | |
752 return; | |
753 | |
754 transform_ = transform; | |
755 NoteLayerSurfacePropertyChanged(); | |
756 } | |
757 | |
758 bool LayerImpl::TransformIsAnimating() const { | |
759 return layer_animation_controller_->IsAnimatingProperty(Animation::Transform); | |
760 } | |
761 | |
762 bool LayerImpl::TransformIsAnimatingOnImplOnly() const { | |
763 Animation* transform_animation = | |
764 layer_animation_controller_->GetAnimation(Animation::Transform); | |
765 return transform_animation && transform_animation->is_impl_only(); | |
766 } | |
767 | |
768 void LayerImpl::SetContentBounds(gfx::Size content_bounds) { | |
769 if (this->content_bounds() == content_bounds) | |
770 return; | |
771 | |
772 draw_properties_.content_bounds = content_bounds; | |
773 NoteLayerPropertyChanged(); | |
774 } | |
775 | |
776 void LayerImpl::SetContentsScale(float contents_scale_x, | |
777 float contents_scale_y) { | |
778 if (this->contents_scale_x() == contents_scale_x && | |
779 this->contents_scale_y() == contents_scale_y) | |
780 return; | |
781 | |
782 draw_properties_.contents_scale_x = contents_scale_x; | |
783 draw_properties_.contents_scale_y = contents_scale_y; | |
784 NoteLayerPropertyChanged(); | |
785 } | |
786 | |
787 void LayerImpl::CalculateContentsScale( | |
788 float ideal_contents_scale, | |
789 bool animating_transform_to_screen, | |
790 float* contents_scale_x, | |
791 float* contents_scale_y, | |
792 gfx::Size* content_bounds) { | |
793 // Base LayerImpl has all of its content scales and content bounds pushed | |
794 // from its Layer during commit and just reuses those values as-is. | |
795 *contents_scale_x = this->contents_scale_x(); | |
796 *contents_scale_y = this->contents_scale_y(); | |
797 *content_bounds = this->content_bounds(); | |
798 } | |
799 | |
800 void LayerImpl::UpdateScrollbarPositions() { | |
801 gfx::Vector2dF current_offset = scroll_offset_ + scroll_delta_; | |
802 | |
803 if (horizontal_scrollbar_layer_) { | |
804 horizontal_scrollbar_layer_->SetCurrentPos(current_offset.x()); | |
805 horizontal_scrollbar_layer_->SetTotalSize(bounds_.width()); | |
806 horizontal_scrollbar_layer_->SetMaximum(max_scroll_offset_.x()); | |
807 } | |
808 if (vertical_scrollbar_layer_) { | |
809 vertical_scrollbar_layer_->SetCurrentPos(current_offset.y()); | |
810 vertical_scrollbar_layer_->SetTotalSize(bounds_.height()); | |
811 vertical_scrollbar_layer_->SetMaximum(max_scroll_offset_.y()); | |
812 } | |
813 | |
814 if (current_offset == last_scroll_offset_) | |
815 return; | |
816 last_scroll_offset_ = current_offset; | |
817 | |
818 if (scrollbar_animation_controller_ && | |
819 !scrollbar_animation_controller_->isScrollGestureInProgress()) { | |
820 scrollbar_animation_controller_->didProgrammaticallyUpdateScroll( | |
821 base::TimeTicks::Now()); | |
822 } | |
823 | |
824 // Get the current_offset_.y() value for a sanity-check on scrolling | |
825 // benchmark metrics. Specifically, we want to make sure | |
826 // BasicMouseWheelSmoothScrollGesture has proper scroll curves. | |
827 if (layer_tree_impl()->IsActiveTree()) { | |
828 TRACE_COUNTER_ID1("gpu", "scroll_offset_y", this->id(), current_offset.y()); | |
829 } | |
830 } | |
831 | |
832 void LayerImpl::SetScrollOffset(gfx::Vector2d scroll_offset) { | |
833 if (scroll_offset_ == scroll_offset) | |
834 return; | |
835 | |
836 scroll_offset_ = scroll_offset; | |
837 NoteLayerPropertyChangedForSubtree(); | |
838 UpdateScrollbarPositions(); | |
839 } | |
840 | |
841 void LayerImpl::SetScrollDelta(gfx::Vector2dF scroll_delta) { | |
842 if (scroll_delta_ == scroll_delta) | |
843 return; | |
844 | |
845 if (layer_tree_impl()->IsActiveTree()) { | |
846 LayerImpl* pending_twin = layer_tree_impl()->FindPendingTreeLayerById(id()); | |
847 if (pending_twin) { | |
848 // The pending twin can't mirror the scroll delta of the active | |
849 // layer. Although the delta - sent scroll delta difference is | |
850 // identical for both twins, the sent scroll delta for the pending | |
851 // layer is zero, as anything that has been sent has been baked | |
852 // into the layer's position/scroll offset as a part of commit. | |
853 DCHECK(pending_twin->sent_scroll_delta().IsZero()); | |
854 pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta()); | |
855 } | |
856 } | |
857 | |
858 scroll_delta_ = scroll_delta; | |
859 NoteLayerPropertyChangedForSubtree(); | |
860 | |
861 UpdateScrollbarPositions(); | |
862 } | |
863 | |
864 gfx::Vector2dF LayerImpl::TotalScrollOffset() const { | |
865 return scroll_offset_ + scroll_delta_; | |
866 } | |
867 | |
868 void LayerImpl::SetImplTransform(const gfx::Transform& transform) { | |
869 if (impl_transform_ == transform) | |
870 return; | |
871 | |
872 impl_transform_ = transform; | |
873 NoteLayerPropertyChangedForSubtree(); | |
874 } | |
875 | |
876 void LayerImpl::SetDoubleSided(bool double_sided) { | |
877 if (double_sided_ == double_sided) | |
878 return; | |
879 | |
880 double_sided_ = double_sided; | |
881 NoteLayerPropertyChangedForSubtree(); | |
882 } | |
883 | |
884 Region LayerImpl::VisibleContentOpaqueRegion() const { | |
885 if (contents_opaque()) | |
886 return visible_content_rect(); | |
887 return Region(); | |
888 } | |
889 | |
890 void LayerImpl::DidLoseOutputSurface() {} | |
891 | |
892 void LayerImpl::SetMaxScrollOffset(gfx::Vector2d max_scroll_offset) { | |
893 if (max_scroll_offset_ == max_scroll_offset) | |
894 return; | |
895 max_scroll_offset_ = max_scroll_offset; | |
896 | |
897 layer_tree_impl()->set_needs_update_draw_properties(); | |
898 UpdateScrollbarPositions(); | |
899 } | |
900 | |
901 void LayerImpl::SetScrollbarOpacity(float opacity) { | |
902 if (horizontal_scrollbar_layer_) | |
903 horizontal_scrollbar_layer_->SetOpacity(opacity); | |
904 if (vertical_scrollbar_layer_) | |
905 vertical_scrollbar_layer_->SetOpacity(opacity); | |
906 } | |
907 | |
908 inline scoped_ptr<ScrollbarAnimationController> | |
909 CreateScrollbarAnimationControllerWithFade(LayerImpl* layer) { | |
910 base::TimeDelta fadeout_delay = base::TimeDelta::FromMilliseconds(300); | |
911 base::TimeDelta fadeout_length = base::TimeDelta::FromMilliseconds(300); | |
912 return ScrollbarAnimationControllerLinearFade::create( | |
913 layer, fadeout_delay, fadeout_length) | |
914 .PassAs<ScrollbarAnimationController>(); | |
915 } | |
916 | |
917 void LayerImpl::DidBecomeActive() { | |
918 if (!layer_tree_impl_->settings().useLinearFadeScrollbarAnimator) | |
919 return; | |
920 | |
921 bool need_scrollbar_animation_controller = horizontal_scrollbar_layer_ || | |
922 vertical_scrollbar_layer_; | |
923 if (need_scrollbar_animation_controller) { | |
924 if (!scrollbar_animation_controller_) { | |
925 scrollbar_animation_controller_ = | |
926 CreateScrollbarAnimationControllerWithFade(this); | |
927 } | |
928 } else { | |
929 scrollbar_animation_controller_.reset(); | |
930 } | |
931 | |
932 } | |
933 void LayerImpl::SetHorizontalScrollbarLayer( | |
934 ScrollbarLayerImpl* scrollbar_layer) { | |
935 horizontal_scrollbar_layer_ = scrollbar_layer; | |
936 if (horizontal_scrollbar_layer_) | |
937 horizontal_scrollbar_layer_->set_scroll_layer_id(id()); | |
938 } | |
939 | |
940 void LayerImpl::SetVerticalScrollbarLayer(ScrollbarLayerImpl* scrollbar_layer) { | |
941 vertical_scrollbar_layer_ = scrollbar_layer; | |
942 if (vertical_scrollbar_layer_) | |
943 vertical_scrollbar_layer_->set_scroll_layer_id(id()); | |
944 } | |
945 | |
946 void LayerImpl::AsValueInto(base::DictionaryValue* dict) const { | |
947 dict->SetInteger("id", id()); | |
948 dict->Set("bounds", MathUtil::AsValue(bounds()).release()); | |
949 dict->SetInteger("draws_content", DrawsContent()); | |
950 | |
951 bool clipped; | |
952 gfx::QuadF layer_quad = MathUtil::MapQuad( | |
953 screen_space_transform(), | |
954 gfx::QuadF(gfx::Rect(content_bounds())), | |
955 &clipped); | |
956 dict->Set("layer_quad", MathUtil::AsValue(layer_quad).release()); | |
957 | |
958 } | |
959 | |
960 scoped_ptr<base::Value> LayerImpl::AsValue() const { | |
961 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); | |
962 AsValueInto(state.get()); | |
963 return state.PassAs<base::Value>(); | |
964 } | |
965 | |
966 } // namespace cc | |
OLD | NEW |