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.
5 #include "cc/trees/layer_tree_host_common.h"
9 #include "base/debug/trace_event.h"
10 #include "cc/base/math_util.h"
11 #include "cc/layers/heads_up_display_layer_impl.h"
12 #include "cc/layers/layer.h"
13 #include "cc/layers/layer_impl.h"
14 #include "cc/layers/layer_iterator.h"
15 #include "cc/layers/render_surface.h"
16 #include "cc/layers/render_surface_impl.h"
17 #include "cc/trees/layer_sorter.h"
18 #include "cc/trees/layer_tree_impl.h"
19 #include "ui/gfx/point_conversions.h"
20 #include "ui/gfx/rect_conversions.h"
21 #include "ui/gfx/transform.h"
25 ScrollAndScaleSet::ScrollAndScaleSet() {}
27 ScrollAndScaleSet::~ScrollAndScaleSet() {}
29 static void SortLayers(LayerList::iterator forst
,
30 LayerList::iterator end
,
35 static void SortLayers(LayerImplList::iterator first
,
36 LayerImplList::iterator end
,
37 LayerSorter
* layer_sorter
) {
39 TRACE_EVENT0("cc", "LayerTreeHostCommon::SortLayers");
40 layer_sorter
->Sort(first
, end
);
43 inline gfx::Rect
CalculateVisibleRectWithCachedLayerRect(
44 gfx::Rect target_surface_rect
,
45 gfx::Rect layer_bound_rect
,
46 gfx::Rect layer_rect_in_target_space
,
47 const gfx::Transform
& transform
) {
48 // Is this layer fully contained within the target surface?
49 if (target_surface_rect
.Contains(layer_rect_in_target_space
))
50 return layer_bound_rect
;
52 // If the layer doesn't fill up the entire surface, then find the part of
53 // the surface rect where the layer could be visible. This avoids trying to
54 // project surface rect points that are behind the projection point.
55 gfx::Rect minimal_surface_rect
= target_surface_rect
;
56 minimal_surface_rect
.Intersect(layer_rect_in_target_space
);
58 // Project the corners of the target surface rect into the layer space.
59 // This bounding rectangle may be larger than it needs to be (being
60 // axis-aligned), but is a reasonable filter on the space to consider.
61 // Non-invertible transforms will create an empty rect here.
63 gfx::Transform
surface_to_layer(gfx::Transform::kSkipInitialization
);
64 if (!transform
.GetInverse(&surface_to_layer
)) {
65 // TODO(shawnsingh): Some uninvertible transforms may be visible, but
66 // their behaviour is undefined thoughout the compositor. Make their
67 // behaviour well-defined and allow the visible content rect to be non-
72 gfx::Rect layer_rect
= gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
73 surface_to_layer
, gfx::RectF(minimal_surface_rect
)));
74 layer_rect
.Intersect(layer_bound_rect
);
78 gfx::Rect
LayerTreeHostCommon::CalculateVisibleRect(
79 gfx::Rect target_surface_rect
,
80 gfx::Rect layer_bound_rect
,
81 const gfx::Transform
& transform
) {
82 gfx::Rect layer_in_surface_space
=
83 MathUtil::MapClippedRect(transform
, layer_bound_rect
);
84 return CalculateVisibleRectWithCachedLayerRect(
85 target_surface_rect
, layer_bound_rect
, layer_in_surface_space
, transform
);
88 template <typename LayerType
> static inline bool IsRootLayer(LayerType
* layer
) {
89 return !layer
->parent();
92 template <typename LayerType
>
93 static inline bool LayerIsInExisting3DRenderingContext(LayerType
* layer
) {
94 // According to current W3C spec on CSS transforms, a layer is part of an
95 // established 3d rendering context if its parent has transform-style of
97 return layer
->parent() && layer
->parent()->preserves_3d();
100 template <typename LayerType
>
101 static bool IsRootLayerOfNewRenderingContext(LayerType
* layer
) {
102 // According to current W3C spec on CSS transforms (Section 6.1), a layer is
103 // the beginning of 3d rendering context if its parent does not have
104 // transform-style: preserve-3d, but this layer itself does.
106 return !layer
->parent()->preserves_3d() && layer
->preserves_3d();
108 return layer
->preserves_3d();
111 template <typename LayerType
>
112 static bool IsLayerBackFaceVisible(LayerType
* layer
) {
113 // The current W3C spec on CSS transforms says that backface visibility should
114 // be determined differently depending on whether the layer is in a "3d
115 // rendering context" or not. For Chromium code, we can determine whether we
116 // are in a 3d rendering context by checking if the parent preserves 3d.
118 if (LayerIsInExisting3DRenderingContext(layer
))
119 return layer
->draw_transform().IsBackFaceVisible();
121 // In this case, either the layer establishes a new 3d rendering context, or
122 // is not in a 3d rendering context at all.
123 return layer
->transform().IsBackFaceVisible();
126 template <typename LayerType
>
127 static bool IsSurfaceBackFaceVisible(LayerType
* layer
,
128 const gfx::Transform
& draw_transform
) {
129 if (LayerIsInExisting3DRenderingContext(layer
))
130 return draw_transform
.IsBackFaceVisible();
132 if (IsRootLayerOfNewRenderingContext(layer
))
133 return layer
->transform().IsBackFaceVisible();
135 // If the render_surface is not part of a new or existing rendering context,
136 // then the layers that contribute to this surface will decide back-face
137 // visibility for themselves.
141 template <typename LayerType
>
142 static inline bool LayerClipsSubtree(LayerType
* layer
) {
143 return layer
->masks_to_bounds() || layer
->mask_layer();
146 template <typename LayerType
>
147 static gfx::Rect
CalculateVisibleContentRect(
149 gfx::Rect ancestor_clip_rect_in_descendant_surface_space
,
150 gfx::Rect layer_rect_in_target_space
) {
151 DCHECK(layer
->render_target());
153 // Nothing is visible if the layer bounds are empty.
154 if (!layer
->DrawsContent() || layer
->content_bounds().IsEmpty() ||
155 layer
->drawable_content_rect().IsEmpty())
158 // Compute visible bounds in target surface space.
159 gfx::Rect visible_rect_in_target_surface_space
=
160 layer
->drawable_content_rect();
162 if (!layer
->render_target()->render_surface()->clip_rect().IsEmpty()) {
163 // In this case the target surface does clip layers that contribute to
164 // it. So, we have to convert the current surface's clip rect from its
165 // ancestor surface space to the current (descendant) surface
166 // space. This conversion is done outside this function so that it can
167 // be cached instead of computing it redundantly for every layer.
168 visible_rect_in_target_surface_space
.Intersect(
169 ancestor_clip_rect_in_descendant_surface_space
);
172 if (visible_rect_in_target_surface_space
.IsEmpty())
175 return CalculateVisibleRectWithCachedLayerRect(
176 visible_rect_in_target_surface_space
,
177 gfx::Rect(layer
->content_bounds()),
178 layer_rect_in_target_space
,
179 layer
->draw_transform());
182 static inline bool TransformToParentIsKnown(LayerImpl
* layer
) { return true; }
184 static inline bool TransformToParentIsKnown(Layer
* layer
) {
185 return !layer
->TransformIsAnimating();
188 static inline bool TransformToScreenIsKnown(LayerImpl
* layer
) { return true; }
190 static inline bool TransformToScreenIsKnown(Layer
* layer
) {
191 return !layer
->screen_space_transform_is_animating();
194 template <typename LayerType
>
195 static bool LayerShouldBeSkipped(LayerType
* layer
) {
196 // Layers can be skipped if any of these conditions are met.
197 // - does not draw content.
199 // - has empty bounds
200 // - the layer is not double-sided, but its back face is visible.
202 // Some additional conditions need to be computed at a later point after the
203 // recursion is finished.
204 // - the intersection of render_surface content and layer clip_rect is empty
205 // - the visible_content_rect is empty
207 // Note, if the layer should not have been drawn due to being fully
208 // transparent, we would have skipped the entire subtree and never made it
209 // into this function, so it is safe to omit this check here.
211 if (!layer
->DrawsContent() || layer
->bounds().IsEmpty())
214 LayerType
* backface_test_layer
= layer
;
215 if (layer
->use_parent_backface_visibility()) {
216 DCHECK(layer
->parent());
217 DCHECK(!layer
->parent()->use_parent_backface_visibility());
218 backface_test_layer
= layer
->parent();
221 // The layer should not be drawn if (1) it is not double-sided and (2) the
222 // back of the layer is known to be facing the screen.
223 if (!backface_test_layer
->double_sided() &&
224 TransformToScreenIsKnown(backface_test_layer
) &&
225 IsLayerBackFaceVisible(backface_test_layer
))
231 static inline bool SubtreeShouldBeSkipped(LayerImpl
* layer
) {
232 // If layer is on the pending tree and opacity is being animated then
233 // this subtree can't be skipped as we need to create, prioritize and
234 // include tiles for this layer when deciding if tree can be activated.
235 if (layer
->layer_tree_impl()->IsPendingTree() && layer
->OpacityIsAnimating())
238 // The opacity of a layer always applies to its children (either implicitly
239 // via a render surface or explicitly if the parent preserves 3D), so the
240 // entire subtree can be skipped if this layer is fully transparent.
241 return !layer
->opacity();
244 static inline bool SubtreeShouldBeSkipped(Layer
* layer
) {
245 // If the opacity is being animated then the opacity on the main thread is
246 // unreliable (since the impl thread may be using a different opacity), so it
247 // should not be trusted.
248 // In particular, it should not cause the subtree to be skipped.
249 // Similarly, for layers that might animate opacity using an impl-only
250 // animation, their subtree should also not be skipped.
251 return !layer
->opacity() && !layer
->OpacityIsAnimating() &&
252 !layer
->OpacityCanAnimateOnImplThread();
255 // Called on each layer that could be drawn after all information from
256 // CalcDrawProperties has been updated on that layer. May have some false
257 // positives (e.g. layers get this called on them but don't actually get drawn).
258 static inline void UpdateTilePrioritiesForLayer(LayerImpl
* layer
) {
259 layer
->UpdateTilePriorities();
261 // Mask layers don't get this call, so explicitly update them so they can
262 // kick off tile rasterization.
263 if (layer
->mask_layer())
264 layer
->mask_layer()->UpdateTilePriorities();
265 if (layer
->replica_layer() && layer
->replica_layer()->mask_layer())
266 layer
->replica_layer()->mask_layer()->UpdateTilePriorities();
269 static inline void UpdateTilePrioritiesForLayer(Layer
* layer
) {}
271 static inline void SavePaintPropertiesLayer(LayerImpl
* layer
) {}
273 static inline void SavePaintPropertiesLayer(Layer
* layer
) {
274 layer
->SavePaintProperties();
276 if (layer
->mask_layer())
277 layer
->mask_layer()->SavePaintProperties();
278 if (layer
->replica_layer() && layer
->replica_layer()->mask_layer())
279 layer
->replica_layer()->mask_layer()->SavePaintProperties();
282 template <typename LayerType
>
283 static bool SubtreeShouldRenderToSeparateSurface(
285 bool axis_aligned_with_respect_to_parent
) {
287 // A layer and its descendants should render onto a new RenderSurfaceImpl if
288 // any of these rules hold:
291 // The root layer should always have a render_surface.
292 if (IsRootLayer(layer
))
296 if (layer
->force_render_surface())
299 // If the layer uses a mask.
300 if (layer
->mask_layer())
303 // If the layer has a reflection.
304 if (layer
->replica_layer())
307 // If the layer uses a CSS filter.
308 if (!layer
->filters().isEmpty() || !layer
->background_filters().isEmpty() ||
312 int num_descendants_that_draw_content
=
313 layer
->draw_properties().num_descendants_that_draw_content
;
315 // If the layer flattens its subtree (i.e. the layer doesn't preserve-3d), but
316 // it is treated as a 3D object by its parent (i.e. parent does preserve-3d).
317 if (LayerIsInExisting3DRenderingContext(layer
) && !layer
->preserves_3d() &&
318 num_descendants_that_draw_content
> 0) {
319 TRACE_EVENT_INSTANT0(
321 "LayerTreeHostCommon::SubtreeShouldRenderToSeparateSurface flattening",
322 TRACE_EVENT_SCOPE_THREAD
);
326 // If the layer clips its descendants but it is not axis-aligned with respect
328 bool layer_clips_external_content
=
329 LayerClipsSubtree(layer
) || layer
->HasDelegatedContent();
330 if (layer_clips_external_content
&& !axis_aligned_with_respect_to_parent
&&
331 !layer
->draw_properties().descendants_can_clip_selves
) {
332 TRACE_EVENT_INSTANT0(
334 "LayerTreeHostCommon::SubtreeShouldRenderToSeparateSurface clipping",
335 TRACE_EVENT_SCOPE_THREAD
);
339 // If the layer has some translucency and does not have a preserves-3d
340 // transform style. This condition only needs a render surface if two or more
341 // layers in the subtree overlap. But checking layer overlaps is unnecessarily
342 // costly so instead we conservatively create a surface whenever at least two
343 // layers draw content for this subtree.
344 bool at_least_two_layers_in_subtree_draw_content
=
345 num_descendants_that_draw_content
> 0 &&
346 (layer
->DrawsContent() || num_descendants_that_draw_content
> 1);
348 if (layer
->opacity() != 1.f
&& !layer
->preserves_3d() &&
349 at_least_two_layers_in_subtree_draw_content
) {
350 TRACE_EVENT_INSTANT0(
352 "LayerTreeHostCommon::SubtreeShouldRenderToSeparateSurface opacity",
353 TRACE_EVENT_SCOPE_THREAD
);
360 static LayerImpl
* NextTargetSurface(LayerImpl
* layer
) {
361 return layer
->parent() ? layer
->parent()->render_target() : 0;
364 // This function returns a translation matrix that can be applied on a vector
365 // that's in the layer's target surface coordinate, while the position offset is
366 // specified in some ancestor layer's coordinate.
367 gfx::Transform
ComputeSizeDeltaCompensation(
369 LayerImpl
* container
,
370 const gfx::Vector2dF
& position_offset
) {
371 gfx::Transform result_transform
;
373 // To apply a translate in the container's layer space,
374 // the following steps need to be done:
375 // Step 1a. transform from target surface space to the container's target
377 // Step 1b. transform from container's target surface space to the
378 // container's layer space
379 // Step 2. apply the compensation
380 // Step 3. transform back to target surface space
382 gfx::Transform target_surface_space_to_container_layer_space
;
384 LayerImpl
* container_target_surface
=
385 container
? container
->render_target() : 0;
386 for (LayerImpl
* current_target_surface
= NextTargetSurface(layer
);
387 current_target_surface
&&
388 current_target_surface
!= container_target_surface
;
389 current_target_surface
= NextTargetSurface(current_target_surface
)) {
390 // Note: Concat is used here to convert the result coordinate space from
391 // current render surface to the next render surface.
392 target_surface_space_to_container_layer_space
.ConcatTransform(
393 current_target_surface
->render_surface()->draw_transform());
397 gfx::Transform container_layer_space_to_container_target_surface_space
=
398 container
->draw_transform();
399 container_layer_space_to_container_target_surface_space
.Scale(
400 container
->contents_scale_x(), container
->contents_scale_y());
402 gfx::Transform container_target_surface_space_to_container_layer_space
;
403 if (container_layer_space_to_container_target_surface_space
.GetInverse(
404 &container_target_surface_space_to_container_layer_space
)) {
405 // Note: Again, Concat is used to conver the result coordinate space from
406 // the container render surface to the container layer.
407 target_surface_space_to_container_layer_space
.ConcatTransform(
408 container_target_surface_space_to_container_layer_space
);
413 gfx::Transform container_layer_space_to_target_surface_space
;
414 if (target_surface_space_to_container_layer_space
.GetInverse(
415 &container_layer_space_to_target_surface_space
))
416 result_transform
.PreconcatTransform(
417 container_layer_space_to_target_surface_space
);
419 // FIXME: A non-invertible matrix could still make meaningful projection.
420 // For example ScaleZ(0) is non-invertible but the layer is still visible.
421 return gfx::Transform();
425 result_transform
.Translate(position_offset
.x(), position_offset
.y());
428 result_transform
.PreconcatTransform(
429 target_surface_space_to_container_layer_space
);
431 return result_transform
;
434 void ApplyPositionAdjustment(
437 const gfx::Transform
& scroll_compensation
,
438 gfx::Transform
* combined_transform
) { }
439 void ApplyPositionAdjustment(
441 LayerImpl
* container
,
442 const gfx::Transform
& scroll_compensation
,
443 gfx::Transform
* combined_transform
)
445 if (!layer
->position_constraint().is_fixed_position())
448 // Special case: this layer is a composited fixed-position layer; we need to
449 // explicitly compensate for all ancestors' nonzero scroll_deltas to keep
450 // this layer fixed correctly.
451 // Note carefully: this is Concat, not Preconcat
452 // (current_scroll_compensation * combined_transform).
453 combined_transform
->ConcatTransform(scroll_compensation
);
455 // For right-edge or bottom-edge anchored fixed position layers,
456 // the layer should relocate itself if the container changes its size.
457 bool fixed_to_right_edge
=
458 layer
->position_constraint().is_fixed_to_right_edge();
459 bool fixed_to_bottom_edge
=
460 layer
->position_constraint().is_fixed_to_bottom_edge();
461 gfx::Vector2dF position_offset
=
462 container
? container
->fixed_container_size_delta() : gfx::Vector2dF();
463 position_offset
.set_x(fixed_to_right_edge
? position_offset
.x() : 0);
464 position_offset
.set_y(fixed_to_bottom_edge
? position_offset
.y() : 0);
465 if (position_offset
.IsZero())
468 // Note: Again, this is Concat. The compensation matrix will be applied on
469 // the vector in target surface space.
470 combined_transform
->ConcatTransform(
471 ComputeSizeDeltaCompensation(layer
, container
, position_offset
));
474 gfx::Transform
ComputeScrollCompensationForThisLayer(
475 LayerImpl
* scrolling_layer
,
476 const gfx::Transform
& parent_matrix
) {
477 // For every layer that has non-zero scroll_delta, we have to compute a
478 // transform that can undo the scroll_delta translation. In particular, we
479 // want this matrix to premultiply a fixed-position layer's parent_matrix, so
480 // we design this transform in three steps as follows. The steps described
481 // here apply from right-to-left, so Step 1 would be the right-most matrix:
483 // Step 1. transform from target surface space to the exact space where
484 // scroll_delta is actually applied.
485 // -- this is inverse of the matrix in step 3
486 // Step 2. undo the scroll_delta
487 // -- this is just a translation by scroll_delta.
488 // Step 3. transform back to target surface space.
489 // -- this transform is the "partial_layer_origin_transform" =
490 // (parent_matrix * scale(layer->pageScaleDelta()));
492 // These steps create a matrix that both start and end in target surface
493 // space. So this matrix can pre-multiply any fixed-position layer's
494 // draw_transform to undo the scroll_deltas -- as long as that fixed position
495 // layer is fixed onto the same render_target as this scrolling_layer.
498 gfx::Transform partial_layer_origin_transform
= parent_matrix
;
499 partial_layer_origin_transform
.PreconcatTransform(
500 scrolling_layer
->impl_transform());
502 gfx::Transform scroll_compensation_for_this_layer
=
503 partial_layer_origin_transform
; // Step 3
504 scroll_compensation_for_this_layer
.Translate(
505 scrolling_layer
->scroll_delta().x(),
506 scrolling_layer
->scroll_delta().y()); // Step 2
508 gfx::Transform
inverse_partial_layer_origin_transform(
509 gfx::Transform::kSkipInitialization
);
510 if (!partial_layer_origin_transform
.GetInverse(
511 &inverse_partial_layer_origin_transform
)) {
512 // TODO(shawnsingh): Either we need to handle uninvertible transforms
513 // here, or DCHECK that the transform is invertible.
515 scroll_compensation_for_this_layer
.PreconcatTransform(
516 inverse_partial_layer_origin_transform
); // Step 1
517 return scroll_compensation_for_this_layer
;
520 gfx::Transform
ComputeScrollCompensationMatrixForChildren(
521 Layer
* current_layer
,
522 const gfx::Transform
& current_parent_matrix
,
523 const gfx::Transform
& current_scroll_compensation
) {
524 // The main thread (i.e. Layer) does not need to worry about scroll
525 // compensation. So we can just return an identity matrix here.
526 return gfx::Transform();
529 gfx::Transform
ComputeScrollCompensationMatrixForChildren(
531 const gfx::Transform
& parent_matrix
,
532 const gfx::Transform
& current_scroll_compensation_matrix
) {
533 // "Total scroll compensation" is the transform needed to cancel out all
534 // scroll_delta translations that occurred since the nearest container layer,
535 // even if there are render_surfaces in-between.
537 // There are some edge cases to be aware of, that are not explicit in the
539 // - A layer that is both a fixed-position and container should not be its
540 // own container, instead, that means it is fixed to an ancestor, and is a
541 // container for any fixed-position descendants.
542 // - A layer that is a fixed-position container and has a render_surface
543 // should behave the same as a container without a render_surface, the
544 // render_surface is irrelevant in that case.
545 // - A layer that does not have an explicit container is simply fixed to the
546 // viewport. (i.e. the root render_surface.)
547 // - If the fixed-position layer has its own render_surface, then the
548 // render_surface is the one who gets fixed.
550 // This function needs to be called AFTER layers create their own
554 // Avoid the overheads (including stack allocation and matrix
555 // initialization/copy) if we know that the scroll compensation doesn't need
556 // to be reset or adjusted.
557 if (!layer
->IsContainerForFixedPositionLayers() &&
558 layer
->scroll_delta().IsZero() && !layer
->render_surface())
559 return current_scroll_compensation_matrix
;
561 // Start as identity matrix.
562 gfx::Transform next_scroll_compensation_matrix
;
564 // If this layer is not a container, then it inherits the existing scroll
566 if (!layer
->IsContainerForFixedPositionLayers())
567 next_scroll_compensation_matrix
= current_scroll_compensation_matrix
;
569 // If the current layer has a non-zero scroll_delta, then we should compute
570 // its local scroll compensation and accumulate it to the
571 // next_scroll_compensation_matrix.
572 if (!layer
->scroll_delta().IsZero()) {
573 gfx::Transform scroll_compensation_for_this_layer
=
574 ComputeScrollCompensationForThisLayer(layer
, parent_matrix
);
575 next_scroll_compensation_matrix
.PreconcatTransform(
576 scroll_compensation_for_this_layer
);
579 // If the layer created its own render_surface, we have to adjust
580 // next_scroll_compensation_matrix. The adjustment allows us to continue
581 // using the scroll compensation on the next surface.
582 // Step 1 (right-most in the math): transform from the new surface to the
583 // original ancestor surface
584 // Step 2: apply the scroll compensation
585 // Step 3: transform back to the new surface.
586 if (layer
->render_surface() &&
587 !next_scroll_compensation_matrix
.IsIdentity()) {
588 gfx::Transform
inverse_surface_draw_transform(
589 gfx::Transform::kSkipInitialization
);
590 if (!layer
->render_surface()->draw_transform().GetInverse(
591 &inverse_surface_draw_transform
)) {
592 // TODO(shawnsingh): Either we need to handle uninvertible transforms
593 // here, or DCHECK that the transform is invertible.
595 next_scroll_compensation_matrix
=
596 inverse_surface_draw_transform
* next_scroll_compensation_matrix
*
597 layer
->render_surface()->draw_transform();
600 return next_scroll_compensation_matrix
;
603 template <typename LayerType
>
604 static inline void CalculateContentsScale(LayerType
* layer
,
605 float contents_scale
,
606 bool animating_transform_to_screen
) {
607 layer
->CalculateContentsScale(contents_scale
,
608 animating_transform_to_screen
,
609 &layer
->draw_properties().contents_scale_x
,
610 &layer
->draw_properties().contents_scale_y
,
611 &layer
->draw_properties().content_bounds
);
613 LayerType
* mask_layer
= layer
->mask_layer();
615 mask_layer
->CalculateContentsScale(
617 animating_transform_to_screen
,
618 &mask_layer
->draw_properties().contents_scale_x
,
619 &mask_layer
->draw_properties().contents_scale_y
,
620 &mask_layer
->draw_properties().content_bounds
);
623 LayerType
* replica_mask_layer
=
624 layer
->replica_layer() ? layer
->replica_layer()->mask_layer() : NULL
;
625 if (replica_mask_layer
) {
626 replica_mask_layer
->CalculateContentsScale(
628 animating_transform_to_screen
,
629 &replica_mask_layer
->draw_properties().contents_scale_x
,
630 &replica_mask_layer
->draw_properties().contents_scale_y
,
631 &replica_mask_layer
->draw_properties().content_bounds
);
635 static inline void UpdateLayerContentsScale(
637 const gfx::Transform
& combined_transform
,
638 float device_scale_factor
,
639 float page_scale_factor
,
640 bool animating_transform_to_screen
) {
641 gfx::Vector2dF transform_scale
= MathUtil::ComputeTransform2dScaleComponents(
642 combined_transform
, device_scale_factor
* page_scale_factor
);
643 float contents_scale
= std::max(transform_scale
.x(), transform_scale
.y());
644 CalculateContentsScale(layer
, contents_scale
, animating_transform_to_screen
);
647 static inline void UpdateLayerContentsScale(
649 const gfx::Transform
& combined_transform
,
650 float device_scale_factor
,
651 float page_scale_factor
,
652 bool animating_transform_to_screen
) {
653 float raster_scale
= layer
->raster_scale();
655 if (layer
->automatically_compute_raster_scale()) {
656 gfx::Vector2dF transform_scale
=
657 MathUtil::ComputeTransform2dScaleComponents(combined_transform
, 0.f
);
658 float combined_scale
= std::max(transform_scale
.x(), transform_scale
.y());
659 float ideal_raster_scale
= combined_scale
/ device_scale_factor
;
660 if (!layer
->bounds_contain_page_scale())
661 ideal_raster_scale
/= page_scale_factor
;
663 bool need_to_set_raster_scale
= !raster_scale
;
665 // If we've previously saved a raster_scale but the ideal changes, things
666 // are unpredictable and we should just use 1.
667 if (raster_scale
&& raster_scale
!= 1.f
&&
668 ideal_raster_scale
!= raster_scale
) {
669 ideal_raster_scale
= 1.f
;
670 need_to_set_raster_scale
= true;
673 if (need_to_set_raster_scale
) {
674 bool use_and_save_ideal_scale
=
675 ideal_raster_scale
>= 1.f
&& !animating_transform_to_screen
;
676 if (use_and_save_ideal_scale
) {
677 raster_scale
= ideal_raster_scale
;
678 layer
->SetRasterScale(raster_scale
);
686 float contents_scale
= raster_scale
* device_scale_factor
;
687 if (!layer
->bounds_contain_page_scale())
688 contents_scale
*= page_scale_factor
;
690 CalculateContentsScale(layer
, contents_scale
, animating_transform_to_screen
);
693 template <typename LayerType
, typename LayerList
>
694 static inline void RemoveSurfaceForEarlyExit(
695 LayerType
* layer_to_remove
,
696 LayerList
* render_surface_layer_list
) {
697 DCHECK(layer_to_remove
->render_surface());
698 // Technically, we know that the layer we want to remove should be
699 // at the back of the render_surface_layer_list. However, we have had
700 // bugs before that added unnecessary layers here
701 // (https://bugs.webkit.org/show_bug.cgi?id=74147), but that causes
702 // things to crash. So here we proactively remove any additional
703 // layers from the end of the list.
704 while (render_surface_layer_list
->back() != layer_to_remove
) {
705 render_surface_layer_list
->back()->ClearRenderSurface();
706 render_surface_layer_list
->pop_back();
708 DCHECK_EQ(render_surface_layer_list
->back(), layer_to_remove
);
709 render_surface_layer_list
->pop_back();
710 layer_to_remove
->ClearRenderSurface();
713 // Recursively walks the layer tree to compute any information that is needed
714 // before doing the main recursion.
715 template <typename LayerType
>
716 static void PreCalculateMetaInformation(LayerType
* layer
) {
717 if (layer
->HasDelegatedContent()) {
718 // Layers with delegated content need to be treated as if they have as many
719 // children as the number of layers they own delegated quads for. Since we
720 // don't know this number right now, we choose one that acts like infinity
722 layer
->draw_properties().num_descendants_that_draw_content
= 1000;
723 layer
->draw_properties().descendants_can_clip_selves
= false;
727 int num_descendants_that_draw_content
= 0;
728 bool descendants_can_clip_selves
= true;
729 bool sublayer_transform_prevents_clip
=
730 !layer
->sublayer_transform().IsPositiveScaleOrTranslation();
732 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
733 LayerType
* child_layer
= layer
->children()[i
];
734 PreCalculateMetaInformation
<LayerType
>(child_layer
);
736 num_descendants_that_draw_content
+= child_layer
->DrawsContent() ? 1 : 0;
737 num_descendants_that_draw_content
+=
738 child_layer
->draw_properties().num_descendants_that_draw_content
;
740 if ((child_layer
->DrawsContent() && !child_layer
->CanClipSelf()) ||
741 !child_layer
->draw_properties().descendants_can_clip_selves
||
742 sublayer_transform_prevents_clip
||
743 !child_layer
->transform().IsPositiveScaleOrTranslation())
744 descendants_can_clip_selves
= false;
747 layer
->draw_properties().num_descendants_that_draw_content
=
748 num_descendants_that_draw_content
;
749 layer
->draw_properties().descendants_can_clip_selves
=
750 descendants_can_clip_selves
;
753 static void RoundTranslationComponents(gfx::Transform
* transform
) {
755 setDouble(0, 3, MathUtil::Round(transform
->matrix().getDouble(0, 3)));
757 setDouble(1, 3, MathUtil::Round(transform
->matrix().getDouble(1, 3)));
760 // Recursively walks the layer tree starting at the given node and computes all
761 // the necessary transformations, clip rects, render surfaces, etc.
762 template <typename LayerType
, typename LayerList
, typename RenderSurfaceType
>
763 static void CalculateDrawPropertiesInternal(
765 const gfx::Transform
& parent_matrix
,
766 const gfx::Transform
& full_hierarchy_matrix
,
767 const gfx::Transform
& current_scroll_compensation_matrix
,
768 LayerType
* current_fixed_container
,
769 gfx::Rect clip_rect_from_ancestor
,
770 gfx::Rect clip_rect_from_ancestor_in_descendant_space
,
771 bool ancestor_clips_subtree
,
772 RenderSurfaceType
* nearest_ancestor_that_moves_pixels
,
773 LayerList
* render_surface_layer_list
,
774 LayerList
* layer_list
,
775 LayerSorter
* layer_sorter
,
776 int max_texture_size
,
777 float device_scale_factor
,
778 float page_scale_factor
,
779 bool subtree_can_use_lcd_text
,
780 gfx::Rect
* drawable_content_rect_of_subtree
,
781 bool update_tile_priorities
) {
782 // This function computes the new matrix transformations recursively for this
783 // layer and all its descendants. It also computes the appropriate render
785 // Some important points to remember:
787 // 0. Here, transforms are notated in Matrix x Vector order, and in words we
788 // describe what the transform does from left to right.
790 // 1. In our terminology, the "layer origin" refers to the top-left corner of
791 // a layer, and the positive Y-axis points downwards. This interpretation is
792 // valid because the orthographic projection applied at draw time flips the Y
793 // axis appropriately.
795 // 2. The anchor point, when given as a PointF object, is specified in "unit
796 // layer space", where the bounds of the layer map to [0, 1]. However, as a
797 // Transform object, the transform to the anchor point is specified in "layer
798 // space", where the bounds of the layer map to [bounds.width(),
801 // 3. Definition of various transforms used:
802 // M[parent] is the parent matrix, with respect to the nearest render
803 // surface, passed down recursively.
805 // M[root] is the full hierarchy, with respect to the root, passed down
808 // Tr[origin] is the translation matrix from the parent's origin to
809 // this layer's origin.
811 // Tr[origin2anchor] is the translation from the layer's origin to its
814 // Tr[origin2center] is the translation from the layer's origin to its
817 // M[layer] is the layer's matrix (applied at the anchor point)
819 // M[sublayer] is the layer's sublayer transform (also applied at the
820 // layer's anchor point)
822 // S[layer2content] is the ratio of a layer's content_bounds() to its
825 // Some composite transforms can help in understanding the sequence of
827 // composite_layer_transform = Tr[origin2anchor] * M[layer] *
828 // Tr[origin2anchor].inverse()
830 // composite_sublayer_transform = Tr[origin2anchor] * M[sublayer] *
831 // Tr[origin2anchor].inverse()
833 // 4. When a layer (or render surface) is drawn, it is drawn into a "target
834 // render surface". Therefore the draw transform does not necessarily
835 // transform from screen space to local layer space. Instead, the draw
836 // transform is the transform between the "target render surface space" and
837 // local layer space. Note that render surfaces, except for the root, also
838 // draw themselves into a different target render surface, and so their draw
839 // transform and origin transforms are also described with respect to the
842 // Using these definitions, then:
844 // The draw transform for the layer is:
845 // M[draw] = M[parent] * Tr[origin] * composite_layer_transform *
846 // S[layer2content] = M[parent] * Tr[layer->position() + anchor] *
847 // M[layer] * Tr[anchor2origin] * S[layer2content]
849 // Interpreting the math left-to-right, this transforms from the
850 // layer's render surface to the origin of the layer in content space.
852 // The screen space transform is:
853 // M[screenspace] = M[root] * Tr[origin] * composite_layer_transform *
855 // = M[root] * Tr[layer->position() + anchor] * M[layer]
856 // * Tr[anchor2origin] * S[layer2content]
858 // Interpreting the math left-to-right, this transforms from the root
859 // render surface's content space to the origin of the layer in content
862 // The transform hierarchy that is passed on to children (i.e. the child's
863 // parent_matrix) is:
864 // M[parent]_for_child = M[parent] * Tr[origin] *
865 // composite_layer_transform * composite_sublayer_transform
866 // = M[parent] * Tr[layer->position() + anchor] *
867 // M[layer] * Tr[anchor2origin] *
868 // composite_sublayer_transform
870 // and a similar matrix for the full hierarchy with respect to the
873 // Finally, note that the final matrix used by the shader for the layer is P *
874 // M[draw] * S . This final product is computed in drawTexturedQuad(), where:
875 // P is the projection matrix
876 // S is the scale adjustment (to scale up a canonical quad to the
879 // When a render surface has a replica layer, that layer's transform is used
880 // to draw a second copy of the surface. gfx::Transforms named here are
881 // relative to the surface, unless they specify they are relative to the
884 // We will denote a scale by device scale S[deviceScale]
886 // The render surface draw transform to its target surface origin is:
887 // M[surfaceDraw] = M[owningLayer->Draw]
889 // The render surface origin transform to its the root (screen space) origin
891 // M[surface2root] = M[owningLayer->screenspace] *
892 // S[deviceScale].inverse()
894 // The replica draw transform to its target surface origin is:
895 // M[replicaDraw] = S[deviceScale] * M[surfaceDraw] *
896 // Tr[replica->position() + replica->anchor()] * Tr[replica] *
897 // Tr[origin2anchor].inverse() * S[contents_scale].inverse()
899 // The replica draw transform to the root (screen space) origin is:
900 // M[replica2root] = M[surface2root] * Tr[replica->position()] *
901 // Tr[replica] * Tr[origin2anchor].inverse()
904 // If we early-exit anywhere in this function, the drawable_content_rect of
905 // this subtree should be considered empty.
906 *drawable_content_rect_of_subtree
= gfx::Rect();
908 // The root layer cannot skip CalcDrawProperties.
909 if (!IsRootLayer(layer
) && SubtreeShouldBeSkipped(layer
))
912 // As this function proceeds, these are the properties for the current
913 // layer that actually get computed. To avoid unnecessary copies
914 // (particularly for matrices), we do computations directly on these values
916 DrawProperties
<LayerType
, RenderSurfaceType
>& layer_draw_properties
=
917 layer
->draw_properties();
919 gfx::Rect clip_rect_for_subtree
;
920 bool subtree_should_be_clipped
= false;
922 // This value is cached on the stack so that we don't have to inverse-project
923 // the surface's clip rect redundantly for every layer. This value is the
924 // same as the surface's clip rect, except that instead of being described
925 // in the target surface space (i.e. the ancestor surface space), it is
926 // described in the current surface space.
927 gfx::Rect clip_rect_for_subtree_in_descendant_space
;
929 float accumulated_draw_opacity
= layer
->opacity();
930 bool animating_opacity_to_target
= layer
->OpacityIsAnimating();
931 bool animating_opacity_to_screen
= animating_opacity_to_target
;
932 if (layer
->parent()) {
933 accumulated_draw_opacity
*= layer
->parent()->draw_opacity();
934 animating_opacity_to_target
|= layer
->parent()->draw_opacity_is_animating();
935 animating_opacity_to_screen
|=
936 layer
->parent()->screen_space_opacity_is_animating();
939 bool animating_transform_to_target
= layer
->TransformIsAnimating();
940 bool animating_transform_to_screen
= animating_transform_to_target
;
941 if (layer
->parent()) {
942 animating_transform_to_target
|=
943 layer
->parent()->draw_transform_is_animating();
944 animating_transform_to_screen
|=
945 layer
->parent()->screen_space_transform_is_animating();
948 gfx::Size bounds
= layer
->bounds();
949 gfx::PointF anchor_point
= layer
->anchor_point();
950 gfx::PointF position
= layer
->position() - layer
->scroll_delta();
952 gfx::Transform combined_transform
= parent_matrix
;
953 if (!layer
->transform().IsIdentity()) {
954 // LT = Tr[origin] * Tr[origin2anchor]
955 combined_transform
.Translate3d(
956 position
.x() + anchor_point
.x() * bounds
.width(),
957 position
.y() + anchor_point
.y() * bounds
.height(),
958 layer
->anchor_point_z());
959 // LT = Tr[origin] * Tr[origin2anchor] * M[layer]
960 combined_transform
.PreconcatTransform(layer
->transform());
961 // LT = Tr[origin] * Tr[origin2anchor] * M[layer] * Tr[anchor2origin]
962 combined_transform
.Translate3d(-anchor_point
.x() * bounds
.width(),
963 -anchor_point
.y() * bounds
.height(),
964 -layer
->anchor_point_z());
966 combined_transform
.Translate(position
.x(), position
.y());
969 // The layer's contents_scale is determined from the combined_transform, which
970 // then informs the layer's draw_transform.
971 UpdateLayerContentsScale(layer
,
975 animating_transform_to_screen
);
977 // If there is a transformation from the impl thread then it should be at
978 // the start of the combined_transform, but we don't want it to affect the
979 // computation of contents_scale above.
980 // Note carefully: this is Concat, not Preconcat (impl_transform *
981 // combined_transform).
982 combined_transform
.ConcatTransform(layer
->impl_transform());
984 if (!animating_transform_to_target
&& layer
->scrollable() &&
985 combined_transform
.IsScaleOrTranslation()) {
986 // Align the scrollable layer's position to screen space pixels to avoid
987 // blurriness. To avoid side-effects, do this only if the transform is
989 RoundTranslationComponents(&combined_transform
);
992 // Apply adjustment from position constraints.
993 ApplyPositionAdjustment(layer
, current_fixed_container
,
994 current_scroll_compensation_matrix
, &combined_transform
);
996 // The draw_transform that gets computed below is effectively the layer's
997 // draw_transform, unless the layer itself creates a render_surface. In that
998 // case, the render_surface re-parents the transforms.
999 layer_draw_properties
.target_space_transform
= combined_transform
;
1000 // M[draw] = M[parent] * LT * S[layer2content]
1001 layer_draw_properties
.target_space_transform
.Scale
1002 (1.f
/ layer
->contents_scale_x(), 1.f
/ layer
->contents_scale_y());
1004 // The layer's screen_space_transform represents the transform between root
1005 // layer's "screen space" and local content space.
1006 layer_draw_properties
.screen_space_transform
= full_hierarchy_matrix
;
1007 if (!layer
->preserves_3d())
1008 layer_draw_properties
.screen_space_transform
.FlattenTo2d();
1009 layer_draw_properties
.screen_space_transform
.PreconcatTransform
1010 (layer_draw_properties
.target_space_transform
);
1012 // Adjusting text AA method during animation may cause repaints, which in-turn
1014 bool adjust_text_aa
=
1015 !animating_opacity_to_screen
&& !animating_transform_to_screen
;
1016 // To avoid color fringing, LCD text should only be used on opaque layers with
1017 // just integral translation.
1018 bool layer_can_use_lcd_text
=
1019 subtree_can_use_lcd_text
&& (accumulated_draw_opacity
== 1.f
) &&
1020 layer_draw_properties
.target_space_transform
.
1021 IsIdentityOrIntegerTranslation();
1023 gfx::RectF
content_rect(layer
->content_bounds());
1025 // full_hierarchy_matrix is the matrix that transforms objects between screen
1026 // space (except projection matrix) and the most recent RenderSurfaceImpl's
1027 // space. next_hierarchy_matrix will only change if this layer uses a new
1028 // RenderSurfaceImpl, otherwise remains the same.
1029 gfx::Transform next_hierarchy_matrix
= full_hierarchy_matrix
;
1030 gfx::Transform sublayer_matrix
;
1032 gfx::Vector2dF render_surface_sublayer_scale
=
1033 MathUtil::ComputeTransform2dScaleComponents(
1034 combined_transform
, device_scale_factor
* page_scale_factor
);
1036 if (SubtreeShouldRenderToSeparateSurface(
1037 layer
, combined_transform
.IsScaleOrTranslation())) {
1038 // Check back-face visibility before continuing with this surface and its
1040 if (!layer
->double_sided() && TransformToParentIsKnown(layer
) &&
1041 IsSurfaceBackFaceVisible(layer
, combined_transform
))
1044 if (!layer
->render_surface())
1045 layer
->CreateRenderSurface();
1047 RenderSurfaceType
* render_surface
= layer
->render_surface();
1048 render_surface
->ClearLayerLists();
1050 // The owning layer's draw transform has a scale from content to layer
1051 // space which we do not want; so here we use the combined_transform
1052 // instead of the draw_transform. However, we do need to add a different
1053 // scale factor that accounts for the surface's pixel dimensions.
1054 combined_transform
.Scale(1.0 / render_surface_sublayer_scale
.x(),
1055 1.0 / render_surface_sublayer_scale
.y());
1056 render_surface
->SetDrawTransform(combined_transform
);
1058 // The owning layer's transform was re-parented by the surface, so the
1059 // layer's new draw_transform only needs to scale the layer to surface
1061 layer_draw_properties
.target_space_transform
.MakeIdentity();
1062 layer_draw_properties
.target_space_transform
.
1063 Scale(render_surface_sublayer_scale
.x() / layer
->contents_scale_x(),
1064 render_surface_sublayer_scale
.y() / layer
->contents_scale_y());
1066 // Inside the surface's subtree, we scale everything to the owning layer's
1067 // scale. The sublayer matrix transforms layer rects into target surface
1069 DCHECK(sublayer_matrix
.IsIdentity());
1070 sublayer_matrix
.Scale(render_surface_sublayer_scale
.x(),
1071 render_surface_sublayer_scale
.y());
1073 // The opacity value is moved from the layer to its surface, so that the
1074 // entire subtree properly inherits opacity.
1075 render_surface
->SetDrawOpacity(accumulated_draw_opacity
);
1076 render_surface
->SetDrawOpacityIsAnimating(animating_opacity_to_target
);
1077 animating_opacity_to_target
= false;
1078 layer_draw_properties
.opacity
= 1.f
;
1079 layer_draw_properties
.opacity_is_animating
= animating_opacity_to_target
;
1080 layer_draw_properties
.screen_space_opacity_is_animating
=
1081 animating_opacity_to_screen
;
1083 render_surface
->SetTargetSurfaceTransformsAreAnimating(
1084 animating_transform_to_target
);
1085 render_surface
->SetScreenSpaceTransformsAreAnimating(
1086 animating_transform_to_screen
);
1087 animating_transform_to_target
= false;
1088 layer_draw_properties
.target_space_transform_is_animating
=
1089 animating_transform_to_target
;
1090 layer_draw_properties
.screen_space_transform_is_animating
=
1091 animating_transform_to_screen
;
1093 // Update the aggregate hierarchy matrix to include the transform of the
1094 // newly created RenderSurfaceImpl.
1095 next_hierarchy_matrix
.PreconcatTransform(render_surface
->draw_transform());
1097 // The new render_surface here will correctly clip the entire subtree. So,
1098 // we do not need to continue propagating the clipping state further down
1099 // the tree. This way, we can avoid transforming clip rects from ancestor
1100 // target surface space to current target surface space that could cause
1101 // more w < 0 headaches.
1102 subtree_should_be_clipped
= false;
1104 if (layer
->mask_layer()) {
1105 DrawProperties
<LayerType
, RenderSurfaceType
>& mask_layer_draw_properties
=
1106 layer
->mask_layer()->draw_properties();
1107 mask_layer_draw_properties
.render_target
= layer
;
1108 mask_layer_draw_properties
.visible_content_rect
=
1109 gfx::Rect(layer
->content_bounds());
1112 if (layer
->replica_layer() && layer
->replica_layer()->mask_layer()) {
1113 DrawProperties
<LayerType
, RenderSurfaceType
>&
1114 replica_mask_draw_properties
=
1115 layer
->replica_layer()->mask_layer()->draw_properties();
1116 replica_mask_draw_properties
.render_target
= layer
;
1117 replica_mask_draw_properties
.visible_content_rect
=
1118 gfx::Rect(layer
->content_bounds());
1121 // TODO(senorblanco): make this smarter for the SkImageFilter case (check
1122 // for pixel-moving filters)
1123 if (layer
->filters().hasFilterThatMovesPixels() || layer
->filter())
1124 nearest_ancestor_that_moves_pixels
= render_surface
;
1126 // The render surface clip rect is expressed in the space where this surface
1127 // draws, i.e. the same space as clip_rect_from_ancestor.
1128 render_surface
->SetIsClipped(ancestor_clips_subtree
);
1129 if (ancestor_clips_subtree
) {
1130 render_surface
->SetClipRect(clip_rect_from_ancestor
);
1132 gfx::Transform
inverse_surface_draw_transform(
1133 gfx::Transform::kSkipInitialization
);
1134 if (!render_surface
->draw_transform().GetInverse(
1135 &inverse_surface_draw_transform
)) {
1136 // TODO(shawnsingh): Either we need to handle uninvertible transforms
1137 // here, or DCHECK that the transform is invertible.
1139 clip_rect_for_subtree_in_descendant_space
=
1140 gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
1141 inverse_surface_draw_transform
, render_surface
->clip_rect()));
1143 render_surface
->SetClipRect(gfx::Rect());
1144 clip_rect_for_subtree_in_descendant_space
=
1145 clip_rect_from_ancestor_in_descendant_space
;
1148 render_surface
->SetNearestAncestorThatMovesPixels(
1149 nearest_ancestor_that_moves_pixels
);
1151 // If the new render surface is drawn translucent or with a non-integral
1152 // translation then the subtree that gets drawn on this render surface
1153 // cannot use LCD text.
1154 subtree_can_use_lcd_text
= layer_can_use_lcd_text
;
1156 render_surface_layer_list
->push_back(layer
);
1158 DCHECK(layer
->parent());
1160 // Note: layer_draw_properties.target_space_transform is computed above,
1161 // before this if-else statement.
1162 layer_draw_properties
.target_space_transform_is_animating
=
1163 animating_transform_to_target
;
1164 layer_draw_properties
.screen_space_transform_is_animating
=
1165 animating_transform_to_screen
;
1166 layer_draw_properties
.opacity
= accumulated_draw_opacity
;
1167 layer_draw_properties
.opacity_is_animating
= animating_opacity_to_target
;
1168 layer_draw_properties
.screen_space_opacity_is_animating
=
1169 animating_opacity_to_screen
;
1170 sublayer_matrix
= combined_transform
;
1172 layer
->ClearRenderSurface();
1174 // Layers without render_surfaces directly inherit the ancestor's clip
1176 subtree_should_be_clipped
= ancestor_clips_subtree
;
1177 if (ancestor_clips_subtree
)
1178 clip_rect_for_subtree
= clip_rect_from_ancestor
;
1180 // The surface's cached clip rect value propagates regardless of what
1181 // clipping goes on between layers here.
1182 clip_rect_for_subtree_in_descendant_space
=
1183 clip_rect_from_ancestor_in_descendant_space
;
1185 // Layers that are not their own render_target will render into the target
1186 // of their nearest ancestor.
1187 layer_draw_properties
.render_target
= layer
->parent()->render_target();
1191 layer_draw_properties
.can_use_lcd_text
= layer_can_use_lcd_text
;
1193 gfx::Rect rect_in_target_space
= ToEnclosingRect(
1194 MathUtil::MapClippedRect(layer
->draw_transform(), content_rect
));
1196 if (LayerClipsSubtree(layer
)) {
1197 subtree_should_be_clipped
= true;
1198 if (ancestor_clips_subtree
&& !layer
->render_surface()) {
1199 clip_rect_for_subtree
= clip_rect_from_ancestor
;
1200 clip_rect_for_subtree
.Intersect(rect_in_target_space
);
1202 clip_rect_for_subtree
= rect_in_target_space
;
1206 // Flatten to 2D if the layer doesn't preserve 3D.
1207 if (!layer
->preserves_3d())
1208 sublayer_matrix
.FlattenTo2d();
1210 // Apply the sublayer transform at the anchor point of the layer.
1211 if (!layer
->sublayer_transform().IsIdentity()) {
1212 sublayer_matrix
.Translate(layer
->anchor_point().x() * bounds
.width(),
1213 layer
->anchor_point().y() * bounds
.height());
1214 sublayer_matrix
.PreconcatTransform(layer
->sublayer_transform());
1215 sublayer_matrix
.Translate(-layer
->anchor_point().x() * bounds
.width(),
1216 -layer
->anchor_point().y() * bounds
.height());
1219 LayerList
& descendants
=
1220 (layer
->render_surface() ? layer
->render_surface()->layer_list()
1223 // Any layers that are appended after this point are in the layer's subtree
1224 // and should be included in the sorting process.
1225 size_t sorting_start_index
= descendants
.size();
1227 if (!LayerShouldBeSkipped(layer
))
1228 descendants
.push_back(layer
);
1230 gfx::Transform next_scroll_compensation_matrix
=
1231 ComputeScrollCompensationMatrixForChildren(
1232 layer
, parent_matrix
, current_scroll_compensation_matrix
);
1233 LayerType
* next_fixed_container
=
1234 layer
->IsContainerForFixedPositionLayers() ?
1235 layer
: current_fixed_container
;
1237 gfx::Rect accumulated_drawable_content_rect_of_children
;
1238 for (size_t i
= 0; i
< layer
->children().size(); ++i
) {
1240 LayerTreeHostCommon::get_child_as_raw_ptr(layer
->children(), i
);
1241 gfx::Rect drawable_content_rect_of_child_subtree
;
1242 CalculateDrawPropertiesInternal
<LayerType
, LayerList
, RenderSurfaceType
>(
1245 next_hierarchy_matrix
,
1246 next_scroll_compensation_matrix
,
1247 next_fixed_container
,
1248 clip_rect_for_subtree
,
1249 clip_rect_for_subtree_in_descendant_space
,
1250 subtree_should_be_clipped
,
1251 nearest_ancestor_that_moves_pixels
,
1252 render_surface_layer_list
,
1256 device_scale_factor
,
1258 subtree_can_use_lcd_text
,
1259 &drawable_content_rect_of_child_subtree
,
1260 update_tile_priorities
);
1261 if (!drawable_content_rect_of_child_subtree
.IsEmpty()) {
1262 accumulated_drawable_content_rect_of_children
.Union(
1263 drawable_content_rect_of_child_subtree
);
1264 if (child
->render_surface())
1265 descendants
.push_back(child
);
1269 if (layer
->render_surface() && !IsRootLayer(layer
) &&
1270 layer
->render_surface()->layer_list().empty()) {
1271 RemoveSurfaceForEarlyExit(layer
, render_surface_layer_list
);
1275 // Compute the total drawable_content_rect for this subtree (the rect is in
1276 // target surface space).
1277 gfx::Rect local_drawable_content_rect_of_subtree
=
1278 accumulated_drawable_content_rect_of_children
;
1279 if (layer
->DrawsContent())
1280 local_drawable_content_rect_of_subtree
.Union(rect_in_target_space
);
1281 if (subtree_should_be_clipped
)
1282 local_drawable_content_rect_of_subtree
.Intersect(clip_rect_for_subtree
);
1284 // Compute the layer's drawable content rect (the rect is in target surface
1286 layer_draw_properties
.drawable_content_rect
= rect_in_target_space
;
1287 if (subtree_should_be_clipped
) {
1288 layer_draw_properties
.drawable_content_rect
.
1289 Intersect(clip_rect_for_subtree
);
1292 // Tell the layer the rect that is clipped by. In theory we could use a
1293 // tighter clip rect here (drawable_content_rect), but that actually does not
1294 // reduce how much would be drawn, and instead it would create unnecessary
1295 // changes to scissor state affecting GPU performance.
1296 layer_draw_properties
.is_clipped
= subtree_should_be_clipped
;
1297 if (subtree_should_be_clipped
) {
1298 layer_draw_properties
.clip_rect
= clip_rect_for_subtree
;
1300 // Initialize the clip rect to a safe value that will not clip the
1301 // layer, just in case clipping is still accidentally used.
1302 layer_draw_properties
.clip_rect
= rect_in_target_space
;
1305 // Compute the layer's visible content rect (the rect is in content space)
1306 layer_draw_properties
.visible_content_rect
= CalculateVisibleContentRect(
1307 layer
, clip_rect_for_subtree_in_descendant_space
, rect_in_target_space
);
1309 // Compute the remaining properties for the render surface, if the layer has
1311 if (IsRootLayer(layer
)) {
1312 // The root layer's surface's content_rect is always the entire viewport.
1313 DCHECK(layer
->render_surface());
1314 layer
->render_surface()->SetContentRect(clip_rect_from_ancestor
);
1315 } else if (layer
->render_surface() && !IsRootLayer(layer
)) {
1316 RenderSurfaceType
* render_surface
= layer
->render_surface();
1317 gfx::Rect clipped_content_rect
= local_drawable_content_rect_of_subtree
;
1319 // Don't clip if the layer is reflected as the reflection shouldn't be
1320 // clipped. If the layer is animating, then the surface's transform to
1321 // its target is not known on the main thread, and we should not use it
1323 if (!layer
->replica_layer() && TransformToParentIsKnown(layer
)) {
1324 // Note, it is correct to use ancestor_clips_subtree here, because we are
1325 // looking at this layer's render_surface, not the layer itself.
1326 if (ancestor_clips_subtree
&& !clipped_content_rect
.IsEmpty()) {
1327 gfx::Rect surface_clip_rect
= LayerTreeHostCommon::CalculateVisibleRect(
1328 render_surface
->clip_rect(),
1329 clipped_content_rect
,
1330 render_surface
->draw_transform());
1331 clipped_content_rect
.Intersect(surface_clip_rect
);
1335 // The RenderSurfaceImpl backing texture cannot exceed the maximum supported
1337 clipped_content_rect
.set_width(
1338 std::min(clipped_content_rect
.width(), max_texture_size
));
1339 clipped_content_rect
.set_height(
1340 std::min(clipped_content_rect
.height(), max_texture_size
));
1342 if (clipped_content_rect
.IsEmpty()) {
1343 render_surface
->ClearLayerLists();
1344 RemoveSurfaceForEarlyExit(layer
, render_surface_layer_list
);
1348 render_surface
->SetContentRect(clipped_content_rect
);
1350 // The owning layer's screen_space_transform has a scale from content to
1351 // layer space which we need to undo and replace with a scale from the
1352 // surface's subtree into layer space.
1353 gfx::Transform screen_space_transform
= layer
->screen_space_transform();
1354 screen_space_transform
.Scale(
1355 layer
->contents_scale_x() / render_surface_sublayer_scale
.x(),
1356 layer
->contents_scale_y() / render_surface_sublayer_scale
.y());
1357 render_surface
->SetScreenSpaceTransform(screen_space_transform
);
1359 if (layer
->replica_layer()) {
1360 gfx::Transform surface_origin_to_replica_origin_transform
;
1361 surface_origin_to_replica_origin_transform
.Scale(
1362 render_surface_sublayer_scale
.x(), render_surface_sublayer_scale
.y());
1363 surface_origin_to_replica_origin_transform
.Translate(
1364 layer
->replica_layer()->position().x() +
1365 layer
->replica_layer()->anchor_point().x() * bounds
.width(),
1366 layer
->replica_layer()->position().y() +
1367 layer
->replica_layer()->anchor_point().y() * bounds
.height());
1368 surface_origin_to_replica_origin_transform
.PreconcatTransform(
1369 layer
->replica_layer()->transform());
1370 surface_origin_to_replica_origin_transform
.Translate(
1371 -layer
->replica_layer()->anchor_point().x() * bounds
.width(),
1372 -layer
->replica_layer()->anchor_point().y() * bounds
.height());
1373 surface_origin_to_replica_origin_transform
.Scale(
1374 1.0 / render_surface_sublayer_scale
.x(),
1375 1.0 / render_surface_sublayer_scale
.y());
1377 // Compute the replica's "originTransform" that maps from the replica's
1378 // origin space to the target surface origin space.
1379 gfx::Transform replica_origin_transform
=
1380 layer
->render_surface()->draw_transform() *
1381 surface_origin_to_replica_origin_transform
;
1382 render_surface
->SetReplicaDrawTransform(replica_origin_transform
);
1384 // Compute the replica's "screen_space_transform" that maps from the
1385 // replica's origin space to the screen's origin space.
1386 gfx::Transform replica_screen_space_transform
=
1387 layer
->render_surface()->screen_space_transform() *
1388 surface_origin_to_replica_origin_transform
;
1389 render_surface
->SetReplicaScreenSpaceTransform(
1390 replica_screen_space_transform
);
1394 if (update_tile_priorities
)
1395 UpdateTilePrioritiesForLayer(layer
);
1397 // If neither this layer nor any of its children were added, early out.
1398 if (sorting_start_index
== descendants
.size())
1401 // If preserves-3d then sort all the descendants in 3D so that they can be
1402 // drawn from back to front. If the preserves-3d property is also set on the
1403 // parent then skip the sorting as the parent will sort all the descendants
1405 if (layer_sorter
&& descendants
.size() && layer
->preserves_3d() &&
1406 (!layer
->parent() || !layer
->parent()->preserves_3d())) {
1407 SortLayers(descendants
.begin() + sorting_start_index
,
1412 if (layer
->render_surface()) {
1413 *drawable_content_rect_of_subtree
=
1414 gfx::ToEnclosingRect(layer
->render_surface()->DrawableContentRect());
1416 *drawable_content_rect_of_subtree
= local_drawable_content_rect_of_subtree
;
1419 if (layer
->HasContributingDelegatedRenderPasses()) {
1420 layer
->render_target()->render_surface()->
1421 AddContributingDelegatedRenderPassLayer(layer
);
1424 SavePaintPropertiesLayer(layer
);
1427 void LayerTreeHostCommon::CalculateDrawProperties(
1429 gfx::Size device_viewport_size
,
1430 float device_scale_factor
,
1431 float page_scale_factor
,
1432 int max_texture_size
,
1433 bool can_use_lcd_text
,
1434 LayerList
* render_surface_layer_list
) {
1435 gfx::Rect total_drawable_content_rect
;
1436 gfx::Transform identity_matrix
;
1437 gfx::Transform device_scale_transform
;
1438 device_scale_transform
.Scale(device_scale_factor
, device_scale_factor
);
1439 LayerList dummy_layer_list
;
1441 // The root layer's render_surface should receive the device viewport as the
1442 // initial clip rect.
1443 bool subtree_should_be_clipped
= true;
1444 gfx::Rect
device_viewport_rect(device_viewport_size
);
1445 bool update_tile_priorities
= false;
1447 // This function should have received a root layer.
1448 DCHECK(IsRootLayer(root_layer
));
1450 PreCalculateMetaInformation
<Layer
>(root_layer
);
1451 CalculateDrawPropertiesInternal
<Layer
,
1453 RenderSurface
>(root_layer
,
1454 device_scale_transform
,
1458 device_viewport_rect
,
1459 device_viewport_rect
,
1460 subtree_should_be_clipped
,
1462 render_surface_layer_list
,
1466 device_scale_factor
,
1469 &total_drawable_content_rect
,
1470 update_tile_priorities
);
1472 // The dummy layer list should not have been used.
1473 DCHECK_EQ(0u, dummy_layer_list
.size());
1474 // A root layer render_surface should always exist after
1475 // CalculateDrawProperties.
1476 DCHECK(root_layer
->render_surface());
1479 void LayerTreeHostCommon::CalculateDrawProperties(
1480 LayerImpl
* root_layer
,
1481 gfx::Size device_viewport_size
,
1482 float device_scale_factor
,
1483 float page_scale_factor
,
1484 int max_texture_size
,
1485 bool can_use_lcd_text
,
1486 LayerImplList
* render_surface_layer_list
,
1487 bool update_tile_priorities
) {
1488 gfx::Rect total_drawable_content_rect
;
1489 gfx::Transform identity_matrix
;
1490 gfx::Transform device_scale_transform
;
1491 device_scale_transform
.Scale(device_scale_factor
, device_scale_factor
);
1492 LayerImplList dummy_layer_list
;
1493 LayerSorter layer_sorter
;
1495 // The root layer's render_surface should receive the device viewport as the
1496 // initial clip rect.
1497 bool subtree_should_be_clipped
= true;
1498 gfx::Rect
device_viewport_rect(device_viewport_size
);
1500 // This function should have received a root layer.
1501 DCHECK(IsRootLayer(root_layer
));
1503 PreCalculateMetaInformation
<LayerImpl
>(root_layer
);
1504 CalculateDrawPropertiesInternal
<LayerImpl
,
1508 device_scale_transform
,
1512 device_viewport_rect
,
1513 device_viewport_rect
,
1514 subtree_should_be_clipped
,
1516 render_surface_layer_list
,
1520 device_scale_factor
,
1523 &total_drawable_content_rect
,
1524 update_tile_priorities
);
1526 // The dummy layer list should not have been used.
1527 DCHECK_EQ(0u, dummy_layer_list
.size());
1528 // A root layer render_surface should always exist after
1529 // CalculateDrawProperties.
1530 DCHECK(root_layer
->render_surface());
1533 static bool PointHitsRect(
1534 gfx::PointF screen_space_point
,
1535 const gfx::Transform
& local_space_to_screen_space_transform
,
1536 gfx::RectF local_space_rect
) {
1537 // If the transform is not invertible, then assume that this point doesn't hit
1539 gfx::Transform
inverse_local_space_to_screen_space(
1540 gfx::Transform::kSkipInitialization
);
1541 if (!local_space_to_screen_space_transform
.GetInverse(
1542 &inverse_local_space_to_screen_space
))
1545 // Transform the hit test point from screen space to the local space of the
1547 bool clipped
= false;
1548 gfx::PointF hit_test_point_in_local_space
= MathUtil::ProjectPoint(
1549 inverse_local_space_to_screen_space
, screen_space_point
, &clipped
);
1551 // If ProjectPoint could not project to a valid value, then we assume that
1552 // this point doesn't hit this rect.
1556 return local_space_rect
.Contains(hit_test_point_in_local_space
);
1559 static bool PointHitsRegion(gfx::PointF screen_space_point
,
1560 const gfx::Transform
& screen_space_transform
,
1561 const Region
& layer_space_region
,
1562 float layer_content_scale_x
,
1563 float layer_content_scale_y
) {
1564 // If the transform is not invertible, then assume that this point doesn't hit
1566 gfx::Transform
inverse_screen_space_transform(
1567 gfx::Transform::kSkipInitialization
);
1568 if (!screen_space_transform
.GetInverse(&inverse_screen_space_transform
))
1571 // Transform the hit test point from screen space to the local space of the
1573 bool clipped
= false;
1574 gfx::PointF hit_test_point_in_content_space
= MathUtil::ProjectPoint(
1575 inverse_screen_space_transform
, screen_space_point
, &clipped
);
1576 gfx::PointF hit_test_point_in_layer_space
=
1577 gfx::ScalePoint(hit_test_point_in_content_space
,
1578 1.f
/ layer_content_scale_x
,
1579 1.f
/ layer_content_scale_y
);
1581 // If ProjectPoint could not project to a valid value, then we assume that
1582 // this point doesn't hit this region.
1586 return layer_space_region
.Contains(
1587 gfx::ToRoundedPoint(hit_test_point_in_layer_space
));
1590 static bool PointIsClippedBySurfaceOrClipRect(gfx::PointF screen_space_point
,
1592 LayerImpl
* current_layer
= layer
;
1594 // Walk up the layer tree and hit-test any render_surfaces and any layer
1595 // clip rects that are active.
1596 while (current_layer
) {
1597 if (current_layer
->render_surface() &&
1600 current_layer
->render_surface()->screen_space_transform(),
1601 current_layer
->render_surface()->content_rect()))
1604 // Note that drawable content rects are actually in target surface space, so
1605 // the transform we have to provide is the target surface's
1606 // screen_space_transform.
1607 LayerImpl
* render_target
= current_layer
->render_target();
1608 if (LayerClipsSubtree(current_layer
) &&
1611 render_target
->render_surface()->screen_space_transform(),
1612 current_layer
->drawable_content_rect()))
1615 current_layer
= current_layer
->parent();
1618 // If we have finished walking all ancestors without having already exited,
1619 // then the point is not clipped by any ancestors.
1623 LayerImpl
* LayerTreeHostCommon::FindLayerThatIsHitByPoint(
1624 gfx::PointF screen_space_point
,
1625 const LayerImplList
& render_surface_layer_list
) {
1626 LayerImpl
* found_layer
= NULL
;
1628 typedef LayerIterator
<LayerImpl
,
1631 LayerIteratorActions::FrontToBack
> LayerIteratorType
;
1632 LayerIteratorType end
= LayerIteratorType::End(&render_surface_layer_list
);
1634 for (LayerIteratorType
1635 it
= LayerIteratorType::Begin(&render_surface_layer_list
);
1638 // We don't want to consider render_surfaces for hit testing.
1639 if (!it
.represents_itself())
1642 LayerImpl
* current_layer
= (*it
);
1644 gfx::RectF
content_rect(current_layer
->content_bounds());
1645 if (!PointHitsRect(screen_space_point
,
1646 current_layer
->screen_space_transform(),
1650 // At this point, we think the point does hit the layer, but we need to walk
1651 // up the parents to ensure that the layer was not clipped in such a way
1652 // that the hit point actually should not hit the layer.
1653 if (PointIsClippedBySurfaceOrClipRect(screen_space_point
, current_layer
))
1656 // Skip the HUD layer.
1657 if (current_layer
== current_layer
->layer_tree_impl()->hud_layer())
1660 found_layer
= current_layer
;
1664 // This can potentially return NULL, which means the screen_space_point did
1665 // not successfully hit test any layers, not even the root layer.
1669 LayerImpl
* LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion(
1670 gfx::PointF screen_space_point
,
1671 const LayerImplList
& render_surface_layer_list
) {
1672 LayerImpl
* found_layer
= NULL
;
1674 typedef LayerIterator
<LayerImpl
,
1677 LayerIteratorActions::FrontToBack
> LayerIteratorType
;
1678 LayerIteratorType end
= LayerIteratorType::End(&render_surface_layer_list
);
1680 for (LayerIteratorType
1681 it
= LayerIteratorType::Begin(&render_surface_layer_list
);
1684 // We don't want to consider render_surfaces for hit testing.
1685 if (!it
.represents_itself())
1688 LayerImpl
* current_layer
= (*it
);
1690 if (!LayerHasTouchEventHandlersAt(screen_space_point
, current_layer
))
1693 found_layer
= current_layer
;
1697 // This can potentially return NULL, which means the screen_space_point did
1698 // not successfully hit test any layers, not even the root layer.
1702 bool LayerTreeHostCommon::LayerHasTouchEventHandlersAt(
1703 gfx::PointF screen_space_point
,
1704 LayerImpl
* layer_impl
) {
1705 if (layer_impl
->touch_event_handler_region().IsEmpty())
1708 if (!PointHitsRegion(screen_space_point
,
1709 layer_impl
->screen_space_transform(),
1710 layer_impl
->touch_event_handler_region(),
1711 layer_impl
->contents_scale_x(),
1712 layer_impl
->contents_scale_y()))
1715 // At this point, we think the point does hit the touch event handler region
1716 // on the layer, but we need to walk up the parents to ensure that the layer
1717 // was not clipped in such a way that the hit point actually should not hit
1719 if (PointIsClippedBySurfaceOrClipRect(screen_space_point
, layer_impl
))