Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: cc/layers/layer_impl.cc

Issue 895853003: Update from https://crrev.com/314320 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/layers/layer_impl.h ('k') | cc/layers/layer_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/layers/layer_impl.h" 5 #include "cc/layers/layer_impl.h"
6 6
7 #include "base/debug/trace_event.h"
8 #include "base/debug/trace_event_argument.h"
9 #include "base/json/json_reader.h" 7 #include "base/json/json_reader.h"
10 #include "base/strings/stringprintf.h" 8 #include "base/strings/stringprintf.h"
9 #include "base/trace_event/trace_event.h"
10 #include "base/trace_event/trace_event_argument.h"
11 #include "cc/animation/animation_registrar.h" 11 #include "cc/animation/animation_registrar.h"
12 #include "cc/animation/scrollbar_animation_controller.h" 12 #include "cc/animation/scrollbar_animation_controller.h"
13 #include "cc/base/math_util.h" 13 #include "cc/base/math_util.h"
14 #include "cc/base/simple_enclosed_region.h" 14 #include "cc/base/simple_enclosed_region.h"
15 #include "cc/debug/debug_colors.h" 15 #include "cc/debug/debug_colors.h"
16 #include "cc/debug/layer_tree_debug_state.h" 16 #include "cc/debug/layer_tree_debug_state.h"
17 #include "cc/debug/micro_benchmark_impl.h" 17 #include "cc/debug/micro_benchmark_impl.h"
18 #include "cc/debug/traced_value.h" 18 #include "cc/debug/traced_value.h"
19 #include "cc/input/layer_scroll_offset_delegate.h" 19 #include "cc/input/layer_scroll_offset_delegate.h"
20 #include "cc/layers/layer_utils.h" 20 #include "cc/layers/layer_utils.h"
21 #include "cc/layers/painted_scrollbar_layer_impl.h" 21 #include "cc/layers/painted_scrollbar_layer_impl.h"
22 #include "cc/output/copy_output_request.h" 22 #include "cc/output/copy_output_request.h"
23 #include "cc/quads/debug_border_draw_quad.h" 23 #include "cc/quads/debug_border_draw_quad.h"
24 #include "cc/quads/render_pass.h" 24 #include "cc/quads/render_pass.h"
25 #include "cc/trees/layer_tree_host_common.h" 25 #include "cc/trees/layer_tree_host_common.h"
26 #include "cc/trees/layer_tree_impl.h" 26 #include "cc/trees/layer_tree_impl.h"
27 #include "cc/trees/layer_tree_settings.h" 27 #include "cc/trees/layer_tree_settings.h"
28 #include "cc/trees/proxy.h" 28 #include "cc/trees/proxy.h"
29 #include "ui/gfx/geometry/box_f.h" 29 #include "ui/gfx/geometry/box_f.h"
30 #include "ui/gfx/geometry/point_conversions.h" 30 #include "ui/gfx/geometry/point_conversions.h"
31 #include "ui/gfx/geometry/quad_f.h" 31 #include "ui/gfx/geometry/quad_f.h"
32 #include "ui/gfx/geometry/rect_conversions.h" 32 #include "ui/gfx/geometry/rect_conversions.h"
33 #include "ui/gfx/geometry/size_conversions.h" 33 #include "ui/gfx/geometry/size_conversions.h"
34 #include "ui/gfx/geometry/vector2d_conversions.h" 34 #include "ui/gfx/geometry/vector2d_conversions.h"
35 35
36 namespace cc { 36 namespace cc {
37 LayerImpl::LayerImpl(LayerTreeImpl* tree_impl, int id) 37 LayerImpl::LayerImpl(LayerTreeImpl* layer_impl, int id)
38 : LayerImpl(layer_impl, id, new LayerImpl::SyncedScrollOffset) {
39 }
40
41 LayerImpl::LayerImpl(LayerTreeImpl* tree_impl,
42 int id,
43 scoped_refptr<SyncedScrollOffset> scroll_offset)
38 : parent_(nullptr), 44 : parent_(nullptr),
39 scroll_parent_(nullptr), 45 scroll_parent_(nullptr),
40 clip_parent_(nullptr), 46 clip_parent_(nullptr),
41 mask_layer_id_(-1), 47 mask_layer_id_(-1),
42 replica_layer_id_(-1), 48 replica_layer_id_(-1),
43 layer_id_(id), 49 layer_id_(id),
44 layer_tree_impl_(tree_impl), 50 layer_tree_impl_(tree_impl),
51 scroll_offset_(scroll_offset),
45 scroll_offset_delegate_(nullptr), 52 scroll_offset_delegate_(nullptr),
46 scroll_clip_layer_(nullptr), 53 scroll_clip_layer_(nullptr),
47 should_scroll_on_main_thread_(false), 54 should_scroll_on_main_thread_(false),
48 have_wheel_event_handlers_(false), 55 have_wheel_event_handlers_(false),
49 have_scroll_event_handlers_(false), 56 have_scroll_event_handlers_(false),
50 user_scrollable_horizontal_(true), 57 user_scrollable_horizontal_(true),
51 user_scrollable_vertical_(true), 58 user_scrollable_vertical_(true),
52 stacking_order_changed_(false), 59 stacking_order_changed_(false),
53 double_sided_(true), 60 double_sided_(true),
54 should_flatten_transform_(true), 61 should_flatten_transform_(true),
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 continue; 237 continue;
231 238
232 gfx::Rect request_in_layer_space = request->area(); 239 gfx::Rect request_in_layer_space = request->area();
233 gfx::Rect request_in_content_space = 240 gfx::Rect request_in_content_space =
234 LayerRectToContentRect(request_in_layer_space); 241 LayerRectToContentRect(request_in_layer_space);
235 request->set_area(MathUtil::MapEnclosingClippedRect( 242 request->set_area(MathUtil::MapEnclosingClippedRect(
236 draw_properties_.target_space_transform, request_in_content_space)); 243 draw_properties_.target_space_transform, request_in_content_space));
237 } 244 }
238 245
239 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this); 246 layer_tree_impl()->RemoveLayerWithCopyOutputRequest(this);
247 layer_tree_impl()->set_needs_update_draw_properties();
240 } 248 }
241 249
242 void LayerImpl::ClearRenderSurfaceLayerList() { 250 void LayerImpl::ClearRenderSurfaceLayerList() {
243 if (render_surface_) 251 if (render_surface_)
244 render_surface_->ClearLayerLists(); 252 render_surface_->ClearLayerLists();
245 } 253 }
246 254
247 void LayerImpl::PopulateSharedQuadState(SharedQuadState* state) const { 255 void LayerImpl::PopulateSharedQuadState(SharedQuadState* state) const {
248 state->SetAll( 256 state->SetAll(
249 draw_properties_.target_space_transform, draw_properties_.content_bounds, 257 draw_properties_.target_space_transform, draw_properties_.content_bounds,
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 bool resourceless_software_draw) { 348 bool resourceless_software_draw) {
341 return false; 349 return false;
342 } 350 }
343 351
344 void LayerImpl::GetContentsResourceId(ResourceProvider::ResourceId* resource_id, 352 void LayerImpl::GetContentsResourceId(ResourceProvider::ResourceId* resource_id,
345 gfx::Size* resource_size) const { 353 gfx::Size* resource_size) const {
346 NOTREACHED(); 354 NOTREACHED();
347 *resource_id = 0; 355 *resource_id = 0;
348 } 356 }
349 357
350 void LayerImpl::SetSentScrollDelta(const gfx::Vector2dF& sent_scroll_delta) { 358 gfx::Vector2dF LayerImpl::ScrollBy(const gfx::Vector2dF& scroll) {
351 // Pending tree never has sent scroll deltas 359 RefreshFromScrollDelegate();
352 DCHECK(layer_tree_impl()->IsActiveTree());
353 360
354 if (sent_scroll_delta_ == sent_scroll_delta) 361 gfx::ScrollOffset adjusted_scroll(scroll);
355 return;
356
357 sent_scroll_delta_ = sent_scroll_delta;
358 }
359
360 gfx::Vector2dF LayerImpl::ScrollBy(const gfx::Vector2dF& scroll) {
361 gfx::Vector2dF adjusted_scroll = scroll;
362 if (layer_tree_impl()->settings().use_pinch_virtual_viewport) { 362 if (layer_tree_impl()->settings().use_pinch_virtual_viewport) {
363 if (!user_scrollable_horizontal_) 363 if (!user_scrollable_horizontal_)
364 adjusted_scroll.set_x(0); 364 adjusted_scroll.set_x(0);
365 if (!user_scrollable_vertical_) 365 if (!user_scrollable_vertical_)
366 adjusted_scroll.set_y(0); 366 adjusted_scroll.set_y(0);
367 } 367 }
368 DCHECK(scrollable()); 368 DCHECK(scrollable());
369 gfx::Vector2dF min_delta = -ScrollOffsetToVector2dF(scroll_offset_); 369 gfx::ScrollOffset old_offset = CurrentScrollOffset();
370 gfx::Vector2dF max_delta = MaxScrollOffset().DeltaFrom(scroll_offset_); 370 gfx::ScrollOffset new_offset =
371 // Clamp new_delta so that position + delta stays within scroll bounds. 371 ClampScrollOffsetToLimits(old_offset + adjusted_scroll);
372 gfx::Vector2dF new_delta = (ScrollDelta() + adjusted_scroll); 372 SetCurrentScrollOffset(new_offset);
373 new_delta.SetToMax(min_delta);
374 new_delta.SetToMin(max_delta);
375 gfx::Vector2dF unscrolled =
376 ScrollDelta() + scroll - new_delta;
377 SetScrollDelta(new_delta);
378 373
379 return unscrolled; 374 gfx::ScrollOffset unscrolled =
375 old_offset + gfx::ScrollOffset(scroll) - new_offset;
376 return gfx::Vector2dF(unscrolled.x(), unscrolled.y());
380 } 377 }
381 378
382 void LayerImpl::SetScrollClipLayer(int scroll_clip_layer_id) { 379 void LayerImpl::SetScrollClipLayer(int scroll_clip_layer_id) {
383 scroll_clip_layer_ = layer_tree_impl()->LayerById(scroll_clip_layer_id); 380 scroll_clip_layer_ = layer_tree_impl()->LayerById(scroll_clip_layer_id);
384 } 381 }
385 382
386 bool LayerImpl::user_scrollable(ScrollbarOrientation orientation) const { 383 bool LayerImpl::user_scrollable(ScrollbarOrientation orientation) const {
387 return (orientation == HORIZONTAL) ? user_scrollable_horizontal_ 384 return (orientation == HORIZONTAL) ? user_scrollable_horizontal_
388 : user_scrollable_vertical_; 385 : user_scrollable_vertical_;
389 } 386 }
390 387
391 void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() { 388 void LayerImpl::ApplySentScrollDeltasFromAbortedCommit() {
392 if (sent_scroll_delta_.IsZero())
393 return;
394
395 // Pending tree never has sent scroll deltas
396 DCHECK(layer_tree_impl()->IsActiveTree()); 389 DCHECK(layer_tree_impl()->IsActiveTree());
397 390 scroll_offset_->AbortCommit();
398 // The combination of pending tree and aborted commits with impl scrolls
399 // shouldn't happen; we don't know how to update its deltas correctly.
400 DCHECK(!layer_tree_impl()->FindPendingTreeLayerById(id()));
401
402 // Apply sent scroll deltas to scroll position / scroll delta as if the
403 // main thread had applied them and then committed those values.
404 SetScrollOffsetAndDelta(
405 scroll_offset_ + gfx::ScrollOffset(sent_scroll_delta_),
406 ScrollDelta() - sent_scroll_delta_);
407 SetSentScrollDelta(gfx::Vector2dF());
408 }
409
410 void LayerImpl::ApplyScrollDeltasSinceBeginMainFrame() {
411 // Only the pending tree can have missing scrolls.
412 DCHECK(layer_tree_impl()->IsPendingTree());
413 if (!scrollable())
414 return;
415
416 // Pending tree should never have sent scroll deltas.
417 DCHECK(sent_scroll_delta().IsZero());
418
419 LayerImpl* active_twin = layer_tree_impl()->FindActiveTreeLayerById(id());
420 if (active_twin) {
421 // Scrolls that happens after begin frame (where the sent scroll delta
422 // comes from) and commit need to be applied to the pending tree
423 // so that it is up to date with the total scroll.
424 SetScrollDelta(active_twin->ScrollDelta() -
425 active_twin->sent_scroll_delta());
426 }
427 } 391 }
428 392
429 InputHandler::ScrollStatus LayerImpl::TryScroll( 393 InputHandler::ScrollStatus LayerImpl::TryScroll(
430 const gfx::PointF& screen_space_point, 394 const gfx::PointF& screen_space_point,
431 InputHandler::ScrollInputType type) const { 395 InputHandler::ScrollInputType type) const {
432 if (should_scroll_on_main_thread()) { 396 if (should_scroll_on_main_thread()) {
433 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread"); 397 TRACE_EVENT0("cc", "LayerImpl::TryScroll: Failed ShouldScrollOnMainThread");
434 return InputHandler::ScrollOnMainThread; 398 return InputHandler::ScrollOnMainThread;
435 } 399 }
436 400
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 // values x and y, ceil((x / y) * y) may be x + 1. 459 // values x and y, ceil((x / y) * y) may be x + 1.
496 content_rect.Intersect(gfx::Rect(content_bounds())); 460 content_rect.Intersect(gfx::Rect(content_bounds()));
497 return gfx::ToEnclosingRect(content_rect); 461 return gfx::ToEnclosingRect(content_rect);
498 } 462 }
499 463
500 skia::RefPtr<SkPicture> LayerImpl::GetPicture() { 464 skia::RefPtr<SkPicture> LayerImpl::GetPicture() {
501 return skia::RefPtr<SkPicture>(); 465 return skia::RefPtr<SkPicture>();
502 } 466 }
503 467
504 scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) { 468 scoped_ptr<LayerImpl> LayerImpl::CreateLayerImpl(LayerTreeImpl* tree_impl) {
505 return LayerImpl::Create(tree_impl, layer_id_); 469 return LayerImpl::Create(tree_impl, layer_id_, scroll_offset_);
506 } 470 }
507 471
508 void LayerImpl::PushPropertiesTo(LayerImpl* layer) { 472 void LayerImpl::PushPropertiesTo(LayerImpl* layer) {
509 layer->SetTransformOrigin(transform_origin_); 473 layer->SetTransformOrigin(transform_origin_);
510 layer->SetBackgroundColor(background_color_); 474 layer->SetBackgroundColor(background_color_);
511 layer->SetBounds(bounds_); 475 layer->SetBounds(bounds_);
512 layer->SetContentBounds(content_bounds()); 476 layer->SetContentBounds(content_bounds());
513 layer->SetContentsScale(contents_scale_x(), contents_scale_y()); 477 layer->SetContentsScale(contents_scale_x(), contents_scale_y());
514 layer->SetDoubleSided(double_sided_); 478 layer->SetDoubleSided(double_sided_);
515 layer->SetDrawCheckerboardForMissingTiles( 479 layer->SetDrawCheckerboardForMissingTiles(
(...skipping 19 matching lines...) Expand all
535 layer->SetPositionConstraint(position_constraint_); 499 layer->SetPositionConstraint(position_constraint_);
536 layer->SetShouldFlattenTransform(should_flatten_transform_); 500 layer->SetShouldFlattenTransform(should_flatten_transform_);
537 layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_); 501 layer->SetUseParentBackfaceVisibility(use_parent_backface_visibility_);
538 layer->SetTransformAndInvertibility(transform_, transform_is_invertible_); 502 layer->SetTransformAndInvertibility(transform_, transform_is_invertible_);
539 503
540 layer->SetScrollClipLayer(scroll_clip_layer_ ? scroll_clip_layer_->id() 504 layer->SetScrollClipLayer(scroll_clip_layer_ ? scroll_clip_layer_->id()
541 : Layer::INVALID_ID); 505 : Layer::INVALID_ID);
542 layer->set_user_scrollable_horizontal(user_scrollable_horizontal_); 506 layer->set_user_scrollable_horizontal(user_scrollable_horizontal_);
543 layer->set_user_scrollable_vertical(user_scrollable_vertical_); 507 layer->set_user_scrollable_vertical(user_scrollable_vertical_);
544 508
545 // Save the difference but clear the sent delta so that we don't subtract 509 layer->SetScrollCompensationAdjustment(scroll_compensation_adjustment_);
546 // it again in SetScrollOffsetAndDelta's pending twin mirroring logic.
547 gfx::Vector2dF remaining_delta =
548 layer_animation_controller_->scroll_offset_animation_was_interrupted()
549 ? gfx::Vector2dF()
550 : layer->ScrollDelta() - layer->sent_scroll_delta();
551 510
552 layer->SetSentScrollDelta(gfx::Vector2dF()); 511 layer->PushScrollOffset(nullptr);
553 layer->SetScrollOffsetAndDelta(scroll_offset_, remaining_delta);
554 512
555 layer->Set3dSortingContextId(sorting_context_id_); 513 layer->Set3dSortingContextId(sorting_context_id_);
556 layer->SetNumDescendantsThatDrawContent(num_descendants_that_draw_content_); 514 layer->SetNumDescendantsThatDrawContent(num_descendants_that_draw_content_);
557 515
558 LayerImpl* scroll_parent = nullptr; 516 LayerImpl* scroll_parent = nullptr;
559 if (scroll_parent_) { 517 if (scroll_parent_) {
560 scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id()); 518 scroll_parent = layer->layer_tree_impl()->LayerById(scroll_parent_->id());
561 DCHECK(scroll_parent); 519 DCHECK(scroll_parent);
562 } 520 }
563 521
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 } 713 }
756 714
757 for (size_t i = 0; i < children_.size(); ++i) 715 for (size_t i = 0; i < children_.size(); ++i)
758 children_[i]->ResetAllChangeTrackingForSubtree(); 716 children_[i]->ResetAllChangeTrackingForSubtree();
759 717
760 needs_push_properties_ = false; 718 needs_push_properties_ = false;
761 num_dependents_need_push_properties_ = 0; 719 num_dependents_need_push_properties_ = 0;
762 } 720 }
763 721
764 gfx::ScrollOffset LayerImpl::ScrollOffsetForAnimation() const { 722 gfx::ScrollOffset LayerImpl::ScrollOffsetForAnimation() const {
765 return TotalScrollOffset(); 723 return CurrentScrollOffset();
766 } 724 }
767 725
768 void LayerImpl::OnFilterAnimated(const FilterOperations& filters) { 726 void LayerImpl::OnFilterAnimated(const FilterOperations& filters) {
769 SetFilters(filters); 727 SetFilters(filters);
770 } 728 }
771 729
772 void LayerImpl::OnOpacityAnimated(float opacity) { 730 void LayerImpl::OnOpacityAnimated(float opacity) {
773 SetOpacity(opacity); 731 SetOpacity(opacity);
774 } 732 }
775 733
776 void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) { 734 void LayerImpl::OnTransformAnimated(const gfx::Transform& transform) {
777 SetTransform(transform); 735 SetTransform(transform);
778 } 736 }
779 737
780 void LayerImpl::OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) { 738 void LayerImpl::OnScrollOffsetAnimated(const gfx::ScrollOffset& scroll_offset) {
781 // Only layers in the active tree should need to do anything here, since 739 // Only layers in the active tree should need to do anything here, since
782 // layers in the pending tree will find out about these changes as a 740 // layers in the pending tree will find out about these changes as a
783 // result of the call to SetScrollDelta. 741 // result of the shared SyncedProperty.
784 if (!IsActive()) 742 if (!IsActive())
785 return; 743 return;
786 744
787 SetScrollDelta(scroll_offset.DeltaFrom(scroll_offset_)); 745 SetCurrentScrollOffset(scroll_offset);
788 746
789 layer_tree_impl_->DidAnimateScrollOffset(); 747 layer_tree_impl_->DidAnimateScrollOffset();
790 } 748 }
791 749
792 void LayerImpl::OnAnimationWaitingForDeletion() {} 750 void LayerImpl::OnAnimationWaitingForDeletion() {}
793 751
794 bool LayerImpl::IsActive() const { 752 bool LayerImpl::IsActive() const {
795 return layer_tree_impl_->IsActiveTree(); 753 return layer_tree_impl_->IsActiveTree();
796 } 754 }
797 755
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 1051
1094 draw_properties_.contents_scale_x = contents_scale_x; 1052 draw_properties_.contents_scale_x = contents_scale_x;
1095 draw_properties_.contents_scale_y = contents_scale_y; 1053 draw_properties_.contents_scale_y = contents_scale_y;
1096 NoteLayerPropertyChanged(); 1054 NoteLayerPropertyChanged();
1097 } 1055 }
1098 1056
1099 void LayerImpl::SetScrollOffsetDelegate( 1057 void LayerImpl::SetScrollOffsetDelegate(
1100 ScrollOffsetDelegate* scroll_offset_delegate) { 1058 ScrollOffsetDelegate* scroll_offset_delegate) {
1101 // Having both a scroll parent and a scroll offset delegate is unsupported. 1059 // Having both a scroll parent and a scroll offset delegate is unsupported.
1102 DCHECK(!scroll_parent_); 1060 DCHECK(!scroll_parent_);
1103 if (!scroll_offset_delegate && scroll_offset_delegate_) { 1061 RefreshFromScrollDelegate();
1104 scroll_delta_ = scroll_offset_delegate_->GetTotalScrollOffset().DeltaFrom(
1105 scroll_offset_);
1106 }
1107 gfx::ScrollOffset total_offset = TotalScrollOffset();
1108 scroll_offset_delegate_ = scroll_offset_delegate; 1062 scroll_offset_delegate_ = scroll_offset_delegate;
1109 if (scroll_offset_delegate_) 1063 if (scroll_offset_delegate_)
1110 scroll_offset_delegate_->SetTotalScrollOffset(total_offset); 1064 scroll_offset_delegate_->SetCurrentScrollOffset(CurrentScrollOffset());
1111 } 1065 }
1112 1066
1113 bool LayerImpl::IsExternalFlingActive() const { 1067 bool LayerImpl::IsExternalFlingActive() const {
1114 return scroll_offset_delegate_ && 1068 return scroll_offset_delegate_ &&
1115 scroll_offset_delegate_->IsExternalFlingActive(); 1069 scroll_offset_delegate_->IsExternalFlingActive();
1116 } 1070 }
1117 1071
1118 void LayerImpl::DidScroll() { 1072 void LayerImpl::SetCurrentScrollOffset(const gfx::ScrollOffset& scroll_offset) {
1073 DCHECK(IsActive());
1074 if (scroll_offset_->SetCurrent(scroll_offset))
1075 DidUpdateScrollOffset();
1076 }
1077
1078 void LayerImpl::PushScrollOffsetFromMainThread(
1079 const gfx::ScrollOffset& scroll_offset) {
1080 PushScrollOffset(&scroll_offset);
1081 }
1082
1083 gfx::ScrollOffset LayerImpl::PullDeltaForMainThread() {
1084 RefreshFromScrollDelegate();
1085
1086 // TODO(aelias, miletus): Remove all this temporary flooring machinery when
1087 // Blink fully supports fractional scrolls.
1088 gfx::ScrollOffset current_offset = CurrentScrollOffset();
1089 gfx::Vector2dF current_delta = ScrollDelta();
1090 gfx::Vector2dF floored_delta(floor(current_delta.x()),
1091 floor(current_delta.y()));
1092 gfx::Vector2dF diff_delta = floored_delta - current_delta;
1093 gfx::ScrollOffset tmp_offset = ScrollOffsetWithDelta(current_offset,
1094 diff_delta);
1095 scroll_offset_->SetCurrent(tmp_offset);
1096 gfx::ScrollOffset delta = scroll_offset_->PullDeltaForMainThread();
1097 scroll_offset_->SetCurrent(current_offset);
1098 return delta;
1099 }
1100
1101 void LayerImpl::RefreshFromScrollDelegate() {
1102 if (scroll_offset_delegate_) {
1103 SetCurrentScrollOffset(
1104 gfx::ScrollOffset(scroll_offset_delegate_->GetCurrentScrollOffset()));
1105 }
1106 }
1107
1108 gfx::ScrollOffset LayerImpl::CurrentScrollOffset() const {
1109 return scroll_offset_->Current(IsActive());
1110 }
1111
1112 gfx::Vector2dF LayerImpl::ScrollDelta() const {
1113 if (IsActive())
1114 return gfx::Vector2dF(scroll_offset_->Delta().x(),
1115 scroll_offset_->Delta().y());
1116 else
1117 return gfx::Vector2dF(scroll_offset_->PendingDelta().get().x(),
1118 scroll_offset_->PendingDelta().get().y());
1119 }
1120
1121 void LayerImpl::SetScrollDelta(const gfx::Vector2dF& delta) {
1122 DCHECK(IsActive());
1123 SetCurrentScrollOffset(scroll_offset_->ActiveBase() +
1124 gfx::ScrollOffset(delta));
1125 }
1126
1127 gfx::ScrollOffset LayerImpl::BaseScrollOffset() const {
1128 if (IsActive())
1129 return scroll_offset_->ActiveBase();
1130 else
1131 return scroll_offset_->PendingBase();
1132 }
1133
1134 void LayerImpl::PushScrollOffset(const gfx::ScrollOffset* scroll_offset) {
1135 DCHECK(scroll_offset || IsActive());
1136 bool changed = false;
1137 if (scroll_offset) {
1138 DCHECK(!IsActive() || !layer_tree_impl_->FindPendingTreeLayerById(id()));
1139 changed |= scroll_offset_->PushFromMainThread(*scroll_offset);
1140 }
1141 if (IsActive()) {
1142 changed |= scroll_offset_->PushPendingToActive();
1143 if (layer_animation_controller_->scroll_offset_animation_was_interrupted())
1144 SetScrollDelta(gfx::Vector2dF());
1145 }
1146
1147 if (changed)
1148 DidUpdateScrollOffset();
1149 }
1150
1151 void LayerImpl::DidUpdateScrollOffset() {
1152 if (scroll_offset_delegate_) {
1153 scroll_offset_delegate_->SetCurrentScrollOffset(CurrentScrollOffset());
1154 scroll_offset_delegate_->Update();
1155 RefreshFromScrollDelegate();
1156 }
1157
1119 NoteLayerPropertyChangedForSubtree(); 1158 NoteLayerPropertyChangedForSubtree();
1120 ScrollbarParametersDidChange(false); 1159 ScrollbarParametersDidChange(false);
1121 } 1160 }
1122 1161
1123 void LayerImpl::SetScrollOffset(const gfx::ScrollOffset& scroll_offset) {
1124 SetScrollOffsetAndDelta(scroll_offset, ScrollDelta());
1125 }
1126
1127 void LayerImpl::SetScrollOffsetAndDelta(const gfx::ScrollOffset& scroll_offset,
1128 const gfx::Vector2dF& scroll_delta) {
1129 bool changed = false;
1130
1131 last_scroll_offset_ = scroll_offset;
1132
1133 if (scroll_offset_ != scroll_offset) {
1134 changed = true;
1135 scroll_offset_ = scroll_offset;
1136
1137 if (scroll_offset_delegate_)
1138 scroll_offset_delegate_->SetTotalScrollOffset(TotalScrollOffset());
1139 }
1140
1141 if (ScrollDelta() != scroll_delta) {
1142 changed = true;
1143 if (layer_tree_impl()->IsActiveTree()) {
1144 LayerImpl* pending_twin =
1145 layer_tree_impl()->FindPendingTreeLayerById(id());
1146 if (pending_twin) {
1147 // The pending twin can't mirror the scroll delta of the active
1148 // layer. Although the delta - sent scroll delta difference is
1149 // identical for both twins, the sent scroll delta for the pending
1150 // layer is zero, as anything that has been sent has been baked
1151 // into the layer's position/scroll offset as a part of commit.
1152 DCHECK(pending_twin->sent_scroll_delta().IsZero());
1153 pending_twin->SetScrollDelta(scroll_delta - sent_scroll_delta());
1154 }
1155 }
1156
1157 if (scroll_offset_delegate_) {
1158 scroll_offset_delegate_->SetTotalScrollOffset(
1159 ScrollOffsetWithDelta(scroll_offset_, scroll_delta));
1160 } else {
1161 scroll_delta_ = scroll_delta;
1162 }
1163 }
1164
1165 if (changed) {
1166 if (scroll_offset_delegate_)
1167 scroll_offset_delegate_->Update();
1168 DidScroll();
1169 }
1170 }
1171
1172 gfx::Vector2dF LayerImpl::ScrollDelta() const {
1173 if (scroll_offset_delegate_) {
1174 return scroll_offset_delegate_->GetTotalScrollOffset().DeltaFrom(
1175 scroll_offset_);
1176 }
1177 return scroll_delta_;
1178 }
1179
1180 void LayerImpl::SetScrollDelta(const gfx::Vector2dF& scroll_delta) {
1181 SetScrollOffsetAndDelta(scroll_offset_, scroll_delta);
1182 }
1183
1184 gfx::ScrollOffset LayerImpl::TotalScrollOffset() const {
1185 return ScrollOffsetWithDelta(scroll_offset_, ScrollDelta());
1186 }
1187
1188 void LayerImpl::SetDoubleSided(bool double_sided) { 1162 void LayerImpl::SetDoubleSided(bool double_sided) {
1189 if (double_sided_ == double_sided) 1163 if (double_sided_ == double_sided)
1190 return; 1164 return;
1191 1165
1192 double_sided_ = double_sided; 1166 double_sided_ = double_sided;
1193 NoteLayerPropertyChangedForSubtree(); 1167 NoteLayerPropertyChangedForSubtree();
1194 } 1168 }
1195 1169
1196 SimpleEnclosedRegion LayerImpl::VisibleContentOpaqueRegion() const { 1170 SimpleEnclosedRegion LayerImpl::VisibleContentOpaqueRegion() const {
1197 if (contents_opaque()) 1171 if (contents_opaque())
1198 return SimpleEnclosedRegion(visible_content_rect()); 1172 return SimpleEnclosedRegion(visible_content_rect());
1199 return SimpleEnclosedRegion(); 1173 return SimpleEnclosedRegion();
1200 } 1174 }
1201 1175
1202 void LayerImpl::DidBeginTracing() {} 1176 void LayerImpl::DidBeginTracing() {}
1203 1177
1204 void LayerImpl::ReleaseResources() {} 1178 void LayerImpl::ReleaseResources() {}
1205 1179
1206 gfx::ScrollOffset LayerImpl::MaxScrollOffset() const { 1180 gfx::ScrollOffset LayerImpl::MaxScrollOffset() const {
1207 if (!scroll_clip_layer_ || bounds().IsEmpty()) 1181 if (!scroll_clip_layer_ || bounds().IsEmpty())
1208 return gfx::ScrollOffset(); 1182 return gfx::ScrollOffset();
1209 1183
1210 LayerImpl const* page_scale_layer = layer_tree_impl()->page_scale_layer(); 1184 LayerImpl const* page_scale_layer = layer_tree_impl()->page_scale_layer();
1211 DCHECK(this != page_scale_layer); 1185 DCHECK(this != page_scale_layer);
1212 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() || 1186 DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
1213 IsContainerForFixedPositionLayers()); 1187 IsContainerForFixedPositionLayers());
1214 1188
1215 gfx::SizeF scaled_scroll_bounds(BoundsForScrolling());
1216
1217 float scale_factor = 1.f; 1189 float scale_factor = 1.f;
1218 for (LayerImpl const* current_layer = this; 1190 for (LayerImpl const* current_layer = this;
1219 current_layer != scroll_clip_layer_; 1191 current_layer != scroll_clip_layer_->parent();
1220 current_layer = current_layer->parent()) { 1192 current_layer = current_layer->parent()) {
1221 DCHECK(current_layer); 1193 if (current_layer == page_scale_layer)
1222 float current_layer_scale = 1.f; 1194 scale_factor = layer_tree_impl()->current_page_scale_factor();
1195 }
1223 1196
1224 const gfx::Transform& layer_transform = current_layer->transform(); 1197 gfx::SizeF scaled_scroll_bounds =
1225 if (current_layer == page_scale_layer) { 1198 gfx::ToFlooredSize(gfx::ScaleSize(BoundsForScrolling(), scale_factor));
1226 DCHECK(layer_transform.IsIdentity());
1227 current_layer_scale = layer_tree_impl()->current_page_scale_factor();
1228 } else {
1229 // TODO(wjmaclean) Should we allow for translation too?
1230 DCHECK(layer_transform.IsScale2d());
1231 gfx::Vector2dF layer_scale = layer_transform.Scale2d();
1232 // TODO(wjmaclean) Allow for non-isotropic scales.
1233 DCHECK(layer_scale.x() == layer_scale.y());
1234 current_layer_scale = layer_scale.x();
1235 }
1236
1237 scale_factor *= current_layer_scale;
1238 }
1239 // TODO(wjmaclean) Once we move to a model where the two-viewport model is
1240 // turned on in all builds, remove the next two lines. For now however, the
1241 // page scale layer may coincide with the clip layer, and so this is
1242 // necessary.
1243 if (page_scale_layer == scroll_clip_layer_)
1244 scale_factor *= layer_tree_impl()->current_page_scale_factor();
1245
1246 scaled_scroll_bounds.SetSize(scale_factor * scaled_scroll_bounds.width(),
1247 scale_factor * scaled_scroll_bounds.height());
1248 scaled_scroll_bounds = gfx::ToFlooredSize(scaled_scroll_bounds); 1199 scaled_scroll_bounds = gfx::ToFlooredSize(scaled_scroll_bounds);
1249 1200
1250 gfx::ScrollOffset max_offset( 1201 gfx::ScrollOffset max_offset(
1251 scaled_scroll_bounds.width() - scroll_clip_layer_->bounds().width(), 1202 scaled_scroll_bounds.width() - scroll_clip_layer_->bounds().width(),
1252 scaled_scroll_bounds.height() - scroll_clip_layer_->bounds().height()); 1203 scaled_scroll_bounds.height() - scroll_clip_layer_->bounds().height());
1253 // We need the final scroll offset to be in CSS coords. 1204 // We need the final scroll offset to be in CSS coords.
1254 max_offset.Scale(1 / scale_factor); 1205 max_offset.Scale(1 / scale_factor);
1255 max_offset.SetToMax(gfx::ScrollOffset()); 1206 max_offset.SetToMax(gfx::ScrollOffset());
1256 return max_offset; 1207 return max_offset;
1257 } 1208 }
1258 1209
1210 gfx::ScrollOffset LayerImpl::ClampScrollOffsetToLimits(
1211 gfx::ScrollOffset offset) const {
1212 offset.SetToMin(MaxScrollOffset());
1213 offset.SetToMax(gfx::ScrollOffset());
1214 return offset;
1215 }
1216
1259 gfx::Vector2dF LayerImpl::ClampScrollToMaxScrollOffset() { 1217 gfx::Vector2dF LayerImpl::ClampScrollToMaxScrollOffset() {
1260 gfx::ScrollOffset max_offset = MaxScrollOffset(); 1218 gfx::ScrollOffset old_offset = CurrentScrollOffset();
1261 gfx::ScrollOffset old_offset = TotalScrollOffset(); 1219 gfx::ScrollOffset clamped_offset = ClampScrollOffsetToLimits(old_offset);
1262 gfx::ScrollOffset clamped_offset = old_offset;
1263
1264 clamped_offset.SetToMin(max_offset);
1265 clamped_offset.SetToMax(gfx::ScrollOffset());
1266 gfx::Vector2dF delta = clamped_offset.DeltaFrom(old_offset); 1220 gfx::Vector2dF delta = clamped_offset.DeltaFrom(old_offset);
1267 if (!delta.IsZero()) 1221 if (!delta.IsZero())
1268 ScrollBy(delta); 1222 ScrollBy(delta);
1269
1270 return delta; 1223 return delta;
1271 } 1224 }
1272 1225
1273 void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase* scrollbar_layer, 1226 void LayerImpl::SetScrollbarPosition(ScrollbarLayerImplBase* scrollbar_layer,
1274 LayerImpl* scrollbar_clip_layer, 1227 LayerImpl* scrollbar_clip_layer,
1275 bool on_resize) const { 1228 bool on_resize) const {
1276 DCHECK(scrollbar_layer); 1229 DCHECK(scrollbar_layer);
1277 LayerImpl* page_scale_layer = layer_tree_impl()->page_scale_layer(); 1230 LayerImpl* page_scale_layer = layer_tree_impl()->page_scale_layer();
1278 1231
1279 DCHECK(this != page_scale_layer); 1232 DCHECK(this != page_scale_layer);
1280 DCHECK(scrollbar_clip_layer); 1233 DCHECK(scrollbar_clip_layer);
1281 gfx::RectF clip_rect(gfx::PointF(), 1234 gfx::RectF clip_rect(gfx::PointF(),
1282 scrollbar_clip_layer->BoundsForScrolling()); 1235 scrollbar_clip_layer->BoundsForScrolling());
1283 1236
1284 // See comment in MaxScrollOffset() regarding the use of the content layer 1237 // See comment in MaxScrollOffset() regarding the use of the content layer
1285 // bounds here. 1238 // bounds here.
1286 gfx::RectF scroll_rect(gfx::PointF(), BoundsForScrolling()); 1239 gfx::RectF scroll_rect(gfx::PointF(), BoundsForScrolling());
1287 1240
1288 if (scroll_rect.size().IsEmpty()) 1241 if (scroll_rect.size().IsEmpty())
1289 return; 1242 return;
1290 1243
1291 // TODO(wjmaclean) This computation is nearly identical to the one in
1292 // MaxScrollOffset. Find some way to combine these.
1293 gfx::ScrollOffset current_offset; 1244 gfx::ScrollOffset current_offset;
1294 for (LayerImpl const* current_layer = this; 1245 for (LayerImpl const* current_layer = this;
1295 current_layer != scrollbar_clip_layer; 1246 current_layer != scrollbar_clip_layer->parent();
1296 current_layer = current_layer->parent()) { 1247 current_layer = current_layer->parent()) {
1297 DCHECK(current_layer); 1248 current_offset += current_layer->CurrentScrollOffset();
1298 const gfx::Transform& layer_transform = current_layer->transform();
1299 if (current_layer == page_scale_layer) { 1249 if (current_layer == page_scale_layer) {
1300 DCHECK(layer_transform.IsIdentity());
1301 float scale_factor = layer_tree_impl()->current_page_scale_factor(); 1250 float scale_factor = layer_tree_impl()->current_page_scale_factor();
1302 current_offset.Scale(scale_factor); 1251 current_offset.Scale(scale_factor);
1303 scroll_rect.Scale(scale_factor); 1252 scroll_rect.Scale(scale_factor);
1304 } else {
1305 DCHECK(layer_transform.IsScale2d());
1306 gfx::Vector2dF layer_scale = layer_transform.Scale2d();
1307 DCHECK(layer_scale.x() == layer_scale.y());
1308 gfx::ScrollOffset new_offset = ScrollOffsetWithDelta(
1309 current_layer->scroll_offset(), current_layer->ScrollDelta());
1310 new_offset.Scale(layer_scale.x(), layer_scale.y());
1311 current_offset += new_offset;
1312 } 1253 }
1313 } 1254 }
1314 // TODO(wjmaclean) Once we move to a model where the two-viewport model is
1315 // turned on in all builds, remove the next two lines. For now however, the
1316 // page scale layer may coincide with the clip layer, and so this is
1317 // necessary.
1318 if (page_scale_layer == scrollbar_clip_layer) {
1319 scroll_rect.Scale(layer_tree_impl()->current_page_scale_factor());
1320 current_offset.Scale(layer_tree_impl()->current_page_scale_factor());
1321 }
1322 1255
1323 bool scrollbar_needs_animation = false; 1256 bool scrollbar_needs_animation = false;
1324 scrollbar_needs_animation |= scrollbar_layer->SetVerticalAdjust( 1257 scrollbar_needs_animation |= scrollbar_layer->SetVerticalAdjust(
1325 scrollbar_clip_layer->bounds_delta().y()); 1258 scrollbar_clip_layer->bounds_delta().y());
1326 if (scrollbar_layer->orientation() == HORIZONTAL) { 1259 if (scrollbar_layer->orientation() == HORIZONTAL) {
1327 float visible_ratio = clip_rect.width() / scroll_rect.width(); 1260 float visible_ratio = clip_rect.width() / scroll_rect.width();
1328 scrollbar_needs_animation |= 1261 scrollbar_needs_animation |=
1329 scrollbar_layer->SetCurrentPos(current_offset.x()); 1262 scrollbar_layer->SetCurrentPos(current_offset.x());
1330 scrollbar_needs_animation |= 1263 scrollbar_needs_animation |=
1331 scrollbar_layer->SetMaximum(scroll_rect.width() - clip_rect.width()); 1264 scrollbar_layer->SetMaximum(scroll_rect.width() - clip_rect.width());
1332 scrollbar_needs_animation |= 1265 scrollbar_needs_animation |=
1333 scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio); 1266 scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio);
1334 } else { 1267 } else {
1335 float visible_ratio = clip_rect.height() / scroll_rect.height(); 1268 float visible_ratio = clip_rect.height() / scroll_rect.height();
1336 scrollbar_needs_animation |= 1269 scrollbar_needs_animation |=
1337 scrollbar_layer->SetCurrentPos(current_offset.y()); 1270 scrollbar_layer->SetCurrentPos(current_offset.y());
1338 scrollbar_needs_animation |= 1271 scrollbar_needs_animation |=
1339 scrollbar_layer->SetMaximum(scroll_rect.height() - clip_rect.height()); 1272 scrollbar_layer->SetMaximum(scroll_rect.height() - clip_rect.height());
1340 scrollbar_needs_animation |= 1273 scrollbar_needs_animation |=
1341 scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio); 1274 scrollbar_layer->SetVisibleToTotalLengthRatio(visible_ratio);
1342 } 1275 }
1343 if (scrollbar_needs_animation) { 1276 if (scrollbar_needs_animation) {
1344 layer_tree_impl()->set_needs_update_draw_properties(); 1277 layer_tree_impl()->set_needs_update_draw_properties();
1345 // TODO(wjmaclean) The scrollbar animator for the pinch-zoom scrollbars 1278 // TODO(wjmaclean) The scrollbar animator for the pinch-zoom scrollbars
1346 // should activate for every scroll on the main frame, not just the 1279 // should activate for every scroll on the main frame, not just the
1347 // scrolls that move the pinch virtual viewport (i.e. trigger from 1280 // scrolls that move the pinch virtual viewport (i.e. trigger from
1348 // either inner or outer viewport). 1281 // either inner or outer viewport).
1349 if (scrollbar_animation_controller_) { 1282 if (scrollbar_animation_controller_) {
1350 // When both non-overlay and overlay scrollbars are both present, don't 1283 // Non-overlay scrollbars shouldn't trigger animations.
1351 // animate the overlay scrollbars when page scale factor is at the min. 1284 if (scrollbar_layer->is_overlay_scrollbar())
1352 // Non-overlay scrollbars also shouldn't trigger animations.
1353 bool is_animatable_scrollbar =
1354 scrollbar_layer->is_overlay_scrollbar() &&
1355 ((layer_tree_impl()->current_page_scale_factor() >
1356 layer_tree_impl()->min_page_scale_factor()) ||
1357 !layer_tree_impl()->settings().use_pinch_zoom_scrollbars);
1358 if (is_animatable_scrollbar)
1359 scrollbar_animation_controller_->DidScrollUpdate(on_resize); 1285 scrollbar_animation_controller_->DidScrollUpdate(on_resize);
1360 } 1286 }
1361 } 1287 }
1362 } 1288 }
1363 1289
1364 void LayerImpl::DidBecomeActive() { 1290 void LayerImpl::DidBecomeActive() {
1365 if (layer_tree_impl_->settings().scrollbar_animator == 1291 if (layer_tree_impl_->settings().scrollbar_animator ==
1366 LayerTreeSettings::NoAnimator) { 1292 LayerTreeSettings::NoAnimator) {
1367 return; 1293 return;
1368 } 1294 }
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1470 state->SetInteger("layer_id", id()); 1396 state->SetInteger("layer_id", id());
1471 MathUtil::AddToTracedValue("bounds", bounds_, state); 1397 MathUtil::AddToTracedValue("bounds", bounds_, state);
1472 1398
1473 state->SetDouble("opacity", opacity()); 1399 state->SetDouble("opacity", opacity());
1474 1400
1475 MathUtil::AddToTracedValue("position", position_, state); 1401 MathUtil::AddToTracedValue("position", position_, state);
1476 1402
1477 state->SetInteger("draws_content", DrawsContent()); 1403 state->SetInteger("draws_content", DrawsContent());
1478 state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes()); 1404 state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
1479 1405
1480 MathUtil::AddToTracedValue("scroll_offset", scroll_offset_, state); 1406 MathUtil::AddToTracedValue(
1407 "scroll_offset", scroll_offset_ ? scroll_offset_->Current(IsActive())
1408 : gfx::ScrollOffset(),
1409 state);
1410
1481 MathUtil::AddToTracedValue("transform_origin", transform_origin_, state); 1411 MathUtil::AddToTracedValue("transform_origin", transform_origin_, state);
1482 1412
1483 bool clipped; 1413 bool clipped;
1484 gfx::QuadF layer_quad = MathUtil::MapQuad( 1414 gfx::QuadF layer_quad = MathUtil::MapQuad(
1485 screen_space_transform(), 1415 screen_space_transform(),
1486 gfx::QuadF(gfx::Rect(content_bounds())), 1416 gfx::QuadF(gfx::Rect(content_bounds())),
1487 &clipped); 1417 &clipped);
1488 MathUtil::AddToTracedValue("layer_quad", layer_quad, state); 1418 MathUtil::AddToTracedValue("layer_quad", layer_quad, state);
1489 if (!touch_event_handler_region_.IsEmpty()) { 1419 if (!touch_event_handler_region_.IsEmpty()) {
1490 state->BeginArray("touch_event_handler_region"); 1420 state->BeginArray("touch_event_handler_region");
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1608 SetNeedsPushProperties(); 1538 SetNeedsPushProperties();
1609 layer_tree_impl()->set_needs_update_draw_properties(); 1539 layer_tree_impl()->set_needs_update_draw_properties();
1610 if (should_have_render_surface) { 1540 if (should_have_render_surface) {
1611 render_surface_ = make_scoped_ptr(new RenderSurfaceImpl(this)); 1541 render_surface_ = make_scoped_ptr(new RenderSurfaceImpl(this));
1612 return; 1542 return;
1613 } 1543 }
1614 render_surface_.reset(); 1544 render_surface_.reset();
1615 } 1545 }
1616 1546
1617 } // namespace cc 1547 } // namespace cc
OLDNEW
« no previous file with comments | « cc/layers/layer_impl.h ('k') | cc/layers/layer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698