Index: cc/trees/layer_tree_host_common.cc |
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc |
index e1258b05af0863d3b648fb1b37a3acadfa25722a..7a552d8a5014ccfaf8caeaa674cfb2dfa4bddb70 100644 |
--- a/cc/trees/layer_tree_host_common.cc |
+++ b/cc/trees/layer_tree_host_common.cc |
@@ -342,6 +342,120 @@ static bool SubtreeShouldRenderToSeparateSurface( |
return false; |
} |
+static LayerImpl* NextTargetSurface(LayerImpl* layer) { |
+ return layer->parent() ? layer->parent()->render_target() : 0; |
+} |
+ |
+// This function returns a translation matrix that can be applied on a vector |
+// that's in the layer's target surface coordinate, while the position offset is |
+// specified in some ancestor layer's coordinate. |
+gfx::Transform ComputeSizeDeltaCompensation( |
+ LayerImpl* layer, |
+ LayerImpl* container, |
+ const gfx::Vector2dF& position_offset) { |
+ gfx::Transform result_transform; |
+ |
+ // To apply a translate in the container's layer space, |
+ // the following steps need to be done: |
+ // Step 1a. transform from target surface space to the container's target |
+ // surface space |
+ // Step 1b. transform from container's target surface space to the |
+ // container's layer space |
+ // Step 2. apply the compensation |
+ // Step 3. transform back to target surface space |
+ |
+ gfx::Transform target_surface_space_to_container_layer_space; |
+ // Calculate step 1a |
+ LayerImpl* container_target_surface = |
+ container ? container->render_target() : 0; |
+ for (LayerImpl* current_target_surface = NextTargetSurface(layer); |
+ current_target_surface && |
+ current_target_surface != container_target_surface; |
+ current_target_surface = NextTargetSurface(current_target_surface)) { |
+ // Note: Concat is used here to convert the result coordinate space from |
+ // current render surface to the next render surface. |
+ target_surface_space_to_container_layer_space.ConcatTransform( |
+ current_target_surface->render_surface()->draw_transform()); |
+ } |
+ // Calculate step 1b |
+ if (container) { |
+ gfx::Transform container_layer_space_to_container_target_surface_space = |
+ container->draw_transform(); |
+ container_layer_space_to_container_target_surface_space.Scale( |
+ container->contents_scale_x(), container->contents_scale_y()); |
+ |
+ gfx::Transform container_target_surface_space_to_container_layer_space; |
+ if (container_layer_space_to_container_target_surface_space.GetInverse( |
+ &container_target_surface_space_to_container_layer_space)) { |
+ // Note: Again, Concat is used to conver the result coordinate space from |
+ // the container render surface to the container layer. |
+ target_surface_space_to_container_layer_space.ConcatTransform( |
+ container_target_surface_space_to_container_layer_space); |
+ } |
+ } |
+ |
+ // Apply step 3 |
+ gfx::Transform container_layer_space_to_target_surface_space; |
+ if (target_surface_space_to_container_layer_space.GetInverse( |
+ &container_layer_space_to_target_surface_space)) |
+ result_transform.PreconcatTransform( |
+ container_layer_space_to_target_surface_space); |
+ else { |
+ // FIXME: A non-invertible matrix could still make meaningful projection. |
+ // For example ScaleZ(0) is non-invertible but the layer is still visible. |
+ return gfx::Transform(); |
+ } |
+ |
+ // Apply step 2 |
+ result_transform.Translate(position_offset.x(), position_offset.y()); |
+ |
+ // Apply step 1 |
+ result_transform.PreconcatTransform( |
+ target_surface_space_to_container_layer_space); |
+ |
+ return result_transform; |
+} |
+ |
+void ApplyPositionAdjustment( |
+ Layer* layer, |
+ Layer* container, |
+ const gfx::Transform& scroll_compensation, |
+ gfx::Transform* combined_transform) { } |
+void ApplyPositionAdjustment( |
+ LayerImpl* layer, |
+ LayerImpl* container, |
+ const gfx::Transform& scroll_compensation, |
+ gfx::Transform* combined_transform) |
+{ |
+ if (!layer->position_constraint().is_fixed_position()) |
+ return; |
+ |
+ // Special case: this layer is a composited fixed-position layer; we need to |
+ // explicitly compensate for all ancestors' nonzero scroll_deltas to keep |
+ // this layer fixed correctly. |
+ // Note carefully: this is Concat, not Preconcat |
+ // (current_scroll_compensation * combined_transform). |
+ combined_transform->ConcatTransform(scroll_compensation); |
+ |
+ // For right-edge or bottom-edge anchored fixed position layers, |
+ // the layer should relocate itself if the container changes its size. |
+ bool fixed_to_right_edge = |
+ layer->position_constraint().is_fixed_to_right_edge(); |
+ bool fixed_to_bottom_edge = |
+ layer->position_constraint().is_fixed_to_bottom_edge(); |
+ gfx::Vector2dF position_offset = |
+ container ? container->fixed_container_size_delta() : gfx::Vector2dF(); |
+ position_offset.set_x(fixed_to_right_edge ? position_offset.x() : 0); |
+ position_offset.set_y(fixed_to_bottom_edge ? position_offset.y() : 0); |
+ if (position_offset.IsZero()) |
+ return; |
+ |
+ // Note: Again, this is Concat. The compensation matrix will be applied on |
+ // the vector in target surface space. |
+ combined_transform->ConcatTransform( |
+ ComputeSizeDeltaCompensation(layer, container, position_offset)); |
+} |
+ |
gfx::Transform ComputeScrollCompensationForThisLayer( |
LayerImpl* scrolling_layer, |
const gfx::Transform& parent_matrix) { |
@@ -425,7 +539,7 @@ gfx::Transform ComputeScrollCompensationMatrixForChildren( |
// Avoid the overheads (including stack allocation and matrix |
// initialization/copy) if we know that the scroll compensation doesn't need |
// to be reset or adjusted. |
- if (!layer->is_container_for_fixed_position_layers() && |
+ if (!layer->IsContainerForFixedPositionLayers() && |
layer->scroll_delta().IsZero() && !layer->render_surface()) |
return current_scroll_compensation_matrix; |
@@ -434,7 +548,7 @@ gfx::Transform ComputeScrollCompensationMatrixForChildren( |
// If this layer is not a container, then it inherits the existing scroll |
// compensations. |
- if (!layer->is_container_for_fixed_position_layers()) |
+ if (!layer->IsContainerForFixedPositionLayers()) |
next_scroll_compensation_matrix = current_scroll_compensation_matrix; |
// If the current layer has a non-zero scroll_delta, then we should compute |
@@ -636,6 +750,7 @@ static void CalculateDrawPropertiesInternal( |
const gfx::Transform& parent_matrix, |
const gfx::Transform& full_hierarchy_matrix, |
const gfx::Transform& current_scroll_compensation_matrix, |
+ LayerType* current_fixed_container, |
gfx::Rect clip_rect_from_ancestor, |
gfx::Rect clip_rect_from_ancestor_in_descendant_space, |
bool ancestor_clips_subtree, |
@@ -859,14 +974,9 @@ static void CalculateDrawPropertiesInternal( |
RoundTranslationComponents(&combined_transform); |
} |
- if (layer->fixed_to_container_layer()) { |
- // Special case: this layer is a composited fixed-position layer; we need to |
- // explicitly compensate for all ancestors' nonzero scroll_deltas to keep |
- // this layer fixed correctly. |
- // Note carefully: this is Concat, not Preconcat |
- // (current_scroll_compensation * combined_transform). |
- combined_transform.ConcatTransform(current_scroll_compensation_matrix); |
- } |
+ // Apply adjustment from position constraints. |
+ ApplyPositionAdjustment(layer, current_fixed_container, |
+ current_scroll_compensation_matrix, &combined_transform); |
// The draw_transform that gets computed below is effectively the layer's |
// draw_transform, unless the layer itself creates a render_surface. In that |
@@ -1105,6 +1215,9 @@ static void CalculateDrawPropertiesInternal( |
gfx::Transform next_scroll_compensation_matrix = |
ComputeScrollCompensationMatrixForChildren( |
layer, parent_matrix, current_scroll_compensation_matrix); |
+ LayerType* next_fixed_container = |
+ layer->IsContainerForFixedPositionLayers() ? |
+ layer : current_fixed_container; |
gfx::Rect accumulated_drawable_content_rect_of_children; |
for (size_t i = 0; i < layer->children().size(); ++i) { |
@@ -1116,6 +1229,7 @@ static void CalculateDrawPropertiesInternal( |
sublayer_matrix, |
next_hierarchy_matrix, |
next_scroll_compensation_matrix, |
+ next_fixed_container, |
clip_rect_for_subtree, |
clip_rect_for_subtree_in_descendant_space, |
subtree_should_be_clipped, |
@@ -1323,6 +1437,7 @@ void LayerTreeHostCommon::CalculateDrawProperties( |
device_scale_transform, |
identity_matrix, |
identity_matrix, |
+ NULL, |
device_viewport_rect, |
device_viewport_rect, |
subtree_should_be_clipped, |
@@ -1376,6 +1491,7 @@ void LayerTreeHostCommon::CalculateDrawProperties( |
device_scale_transform, |
identity_matrix, |
identity_matrix, |
+ NULL, |
device_viewport_rect, |
device_viewport_rect, |
subtree_should_be_clipped, |