Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/trees/draw_property_utils.h" | 5 #include "cc/trees/draw_property_utils.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "cc/base/math_util.h" | 9 #include "cc/base/math_util.h" |
| 10 #include "cc/layers/layer.h" | 10 #include "cc/layers/layer.h" |
| 11 #include "cc/layers/layer_impl.h" | 11 #include "cc/layers/layer_impl.h" |
| 12 #include "cc/trees/layer_tree_impl.h" | |
| 12 #include "cc/trees/property_tree.h" | 13 #include "cc/trees/property_tree.h" |
| 13 #include "cc/trees/property_tree_builder.h" | 14 #include "cc/trees/property_tree_builder.h" |
| 14 #include "ui/gfx/geometry/rect_conversions.h" | 15 #include "ui/gfx/geometry/rect_conversions.h" |
| 15 | 16 |
| 16 namespace cc { | 17 namespace cc { |
| 17 | 18 |
| 18 namespace { | 19 namespace { |
| 19 | 20 |
| 20 template <typename LayerType> | 21 template <typename LayerType> |
| 21 void CalculateVisibleRects( | 22 void CalculateVisibleRects( |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 } | 151 } |
| 151 | 152 |
| 152 template <typename LayerType> | 153 template <typename LayerType> |
| 153 static bool TransformToScreenIsKnown(LayerType* layer, | 154 static bool TransformToScreenIsKnown(LayerType* layer, |
| 154 const TransformTree& tree) { | 155 const TransformTree& tree) { |
| 155 const TransformNode* node = tree.Node(layer->transform_tree_index()); | 156 const TransformNode* node = tree.Node(layer->transform_tree_index()); |
| 156 return !node->data.to_screen_is_animated; | 157 return !node->data.to_screen_is_animated; |
| 157 } | 158 } |
| 158 | 159 |
| 159 template <typename LayerType> | 160 template <typename LayerType> |
| 160 static bool IsLayerBackFaceExposed(LayerType* layer, | |
| 161 const TransformTree& tree) { | |
| 162 if (!TransformToScreenIsKnown(layer, tree)) | |
| 163 return false; | |
| 164 if (LayerIsInExisting3DRenderingContext(layer)) | |
| 165 return DrawTransformFromPropertyTrees(layer, tree).IsBackFaceVisible(); | |
| 166 return layer->transform().IsBackFaceVisible(); | |
| 167 } | |
| 168 | |
| 169 template <typename LayerType> | |
| 170 static bool IsSurfaceBackFaceExposed(LayerType* layer, | |
| 171 const TransformTree& tree) { | |
| 172 if (!TransformToScreenIsKnown(layer, tree)) | |
| 173 return false; | |
| 174 if (LayerIsInExisting3DRenderingContext(layer)) | |
| 175 return DrawTransformFromPropertyTrees(layer, tree).IsBackFaceVisible(); | |
| 176 | |
| 177 if (IsRootLayerOfNewRenderingContext(layer)) | |
| 178 return layer->transform().IsBackFaceVisible(); | |
| 179 | |
| 180 // If the render_surface is not part of a new or existing rendering context, | |
| 181 // then the layers that contribute to this surface will decide back-face | |
| 182 // visibility for themselves. | |
| 183 return false; | |
| 184 } | |
| 185 | |
| 186 template <typename LayerType> | |
| 187 static bool HasSingularTransform(LayerType* layer, const TransformTree& tree) { | 161 static bool HasSingularTransform(LayerType* layer, const TransformTree& tree) { |
| 188 const TransformNode* node = tree.Node(layer->transform_tree_index()); | 162 const TransformNode* node = tree.Node(layer->transform_tree_index()); |
| 189 return !node->data.is_invertible || !node->data.ancestors_are_invertible; | 163 return !node->data.is_invertible || !node->data.ancestors_are_invertible; |
| 190 } | 164 } |
| 191 | 165 |
| 192 template <typename LayerType> | 166 template <typename LayerType> |
| 193 static bool IsBackFaceInvisible(LayerType* layer, const TransformTree& tree) { | 167 static bool IsLayerBackFaceVisible(LayerType* layer, |
| 194 LayerType* backface_test_layer = layer; | 168 const TransformTree& tree) { |
| 195 if (layer->use_parent_backface_visibility()) { | 169 // The current W3C spec on CSS transforms says that backface visibility should |
| 196 DCHECK(layer->parent()); | 170 // be determined differently depending on whether the layer is in a "3d |
| 197 DCHECK(!layer->parent()->use_parent_backface_visibility()); | 171 // rendering context" or not. For Chromium code, we can determine whether we |
| 198 backface_test_layer = layer->parent(); | 172 // are in a 3d rendering context by checking if the parent preserves 3d. |
| 199 } | 173 |
| 200 return !backface_test_layer->double_sided() && | 174 if (LayerIsInExisting3DRenderingContext(layer)) |
| 201 IsLayerBackFaceExposed(backface_test_layer, tree); | 175 return DrawTransformFromPropertyTrees(layer, tree).IsBackFaceVisible(); |
| 176 | |
| 177 // In this case, either the layer establishes a new 3d rendering context, or | |
| 178 // is not in a 3d rendering context at all. | |
| 179 return layer->transform().IsBackFaceVisible(); | |
| 202 } | 180 } |
| 203 | 181 |
| 204 template <typename LayerType> | 182 template <typename LayerType> |
| 205 static bool IsAnimatingTransformToScreen(LayerType* layer, | 183 static bool IsAnimatingTransformToScreen(LayerType* layer, |
| 206 const TransformTree& tree) { | 184 const TransformTree& tree) { |
| 207 const TransformNode* node = tree.Node(layer->transform_tree_index()); | 185 const TransformNode* node = tree.Node(layer->transform_tree_index()); |
| 208 return node->data.to_screen_is_animated; | 186 return node->data.to_screen_is_animated; |
| 209 } | 187 } |
| 210 | 188 |
| 211 template <typename LayerType> | 189 static inline bool TransformToScreenIsKnown(Layer* layer, |
| 212 static bool IsInvisibleDueToTransform(LayerType* layer, | 190 const TransformTree& tree) { |
| 213 const TransformTree& tree) { | 191 return !IsAnimatingTransformToScreen(layer, tree); |
| 214 if (IsAnimatingTransformToScreen(layer, tree)) | |
| 215 return false; | |
| 216 return HasSingularTransform(layer, tree) || IsBackFaceInvisible(layer, tree); | |
| 217 } | 192 } |
| 218 | 193 |
| 219 bool LayerIsInvisible(const Layer* layer) { | 194 static inline bool TransformToScreenIsKnown(LayerImpl* layer, |
| 195 const TransformTree& tree) { | |
| 196 return true; | |
| 197 } | |
| 198 | |
| 199 template <typename LayerType> | |
| 200 static bool HasInvertibleOrAnimatedTransform(LayerType* layer) { | |
| 201 return layer->transform_is_invertible() || layer->TransformIsAnimating(); | |
| 202 } | |
| 203 | |
| 204 static inline bool SubtreeShouldBeSkipped(LayerImpl* layer, | |
| 205 bool layer_is_drawn) { | |
| 206 // If the layer transform is not invertible, it should not be drawn. | |
| 207 // TODO(ajuma): Correctly process subtrees with singular transform for the | |
| 208 // case where we may animate to a non-singular transform and wish to | |
| 209 // pre-raster. | |
| 210 if (!HasInvertibleOrAnimatedTransform(layer)) | |
| 211 return true; | |
| 212 | |
| 213 // When we need to do a readback/copy of a layer's output, we can not skip | |
| 214 // it or any of its ancestors. | |
| 215 if (layer->draw_properties().layer_or_descendant_has_copy_request) | |
| 216 return false; | |
| 217 | |
| 218 // We cannot skip the the subtree if a descendant has a wheel or touch handler | |
| 219 // or the hit testing code will break (it requires fresh transforms, etc). | |
| 220 if (layer->draw_properties().layer_or_descendant_has_input_handler) | |
| 221 return false; | |
| 222 | |
| 223 // If the layer is not drawn, then skip it and its subtree. | |
| 224 if (!layer_is_drawn) | |
| 225 return true; | |
| 226 | |
| 227 // If layer is on the pending tree and opacity is being animated then | |
| 228 // this subtree can't be skipped as we need to create, prioritize and | |
| 229 // include tiles for this layer when deciding if tree can be activated. | |
| 230 if (layer->layer_tree_impl()->IsPendingTree() && layer->OpacityIsAnimating()) | |
| 231 return false; | |
| 232 | |
| 233 // The opacity of a layer always applies to its children (either implicitly | |
| 234 // via a render surface or explicitly if the parent preserves 3D), so the | |
| 235 // entire subtree can be skipped if this layer is fully transparent. | |
| 236 return !layer->opacity(); | |
| 237 } | |
| 238 | |
| 239 static inline bool SubtreeShouldBeSkipped(Layer* layer, bool layer_is_drawn) { | |
| 240 // If the layer transform is not invertible, it should not be drawn. | |
| 241 if (!layer->transform_is_invertible() && !layer->TransformIsAnimating()) | |
| 242 return true; | |
| 243 | |
| 244 // When we need to do a readback/copy of a layer's output, we can not skip | |
| 245 // it or any of its ancestors. | |
| 246 if (layer->draw_properties().layer_or_descendant_has_copy_request) | |
| 247 return false; | |
| 248 | |
| 249 // We cannot skip the the subtree if a descendant has a wheel or touch handler | |
| 250 // or the hit testing code will break (it requires fresh transforms, etc). | |
| 251 if (layer->draw_properties().layer_or_descendant_has_input_handler) | |
| 252 return false; | |
| 253 | |
| 254 // If the layer is not drawn, then skip it and its subtree. | |
| 255 if (!layer_is_drawn) | |
| 256 return true; | |
| 257 | |
| 258 // If the opacity is being animated then the opacity on the main thread is | |
| 259 // unreliable (since the impl thread may be using a different opacity), so it | |
| 260 // should not be trusted. | |
| 261 // In particular, it should not cause the subtree to be skipped. | |
| 262 // Similarly, for layers that might animate opacity using an impl-only | |
| 263 // animation, their subtree should also not be skipped. | |
| 220 return !layer->opacity() && !layer->OpacityIsAnimating() && | 264 return !layer->opacity() && !layer->OpacityIsAnimating() && |
| 221 !layer->OpacityCanAnimateOnImplThread(); | 265 !layer->OpacityCanAnimateOnImplThread(); |
| 222 } | 266 } |
| 223 | 267 |
| 224 bool LayerIsInvisible(const LayerImpl* layer) { | 268 template <typename LayerType> |
| 225 return !layer->opacity() && !layer->OpacityIsAnimating(); | 269 static bool LayerShouldBeSkipped(LayerType* layer, |
| 270 bool layer_is_drawn, | |
| 271 const TransformTree& tree) { | |
| 272 // Layers can be skipped if any of these conditions are met. | |
| 273 // - is not drawn due to it or one of its ancestors being hidden (or having | |
| 274 // no copy requests). | |
| 275 // - does not draw content. | |
| 276 // - is transparent. | |
| 277 // - has empty bounds | |
| 278 // - the layer is not double-sided, but its back face is visible. | |
| 279 // | |
| 280 // Some additional conditions need to be computed at a later point after the | |
| 281 // recursion is finished. | |
| 282 // - the intersection of render_surface content and layer clip_rect is empty | |
| 283 // - the visible_content_rect is empty | |
| 284 // | |
| 285 // Note, if the layer should not have been drawn due to being fully | |
| 286 // transparent, we would have skipped the entire subtree and never made it | |
| 287 // into this function, so it is safe to omit this check here. | |
| 288 if (!layer_is_drawn) | |
| 289 return true; | |
| 290 | |
| 291 if (!layer->DrawsContent() || layer->bounds().IsEmpty()) | |
| 292 return true; | |
| 293 | |
| 294 LayerType* backface_test_layer = layer; | |
| 295 if (layer->use_parent_backface_visibility()) { | |
| 296 DCHECK(layer->parent()); | |
| 297 DCHECK(!layer->parent()->use_parent_backface_visibility()); | |
| 298 backface_test_layer = layer->parent(); | |
| 299 } | |
| 300 | |
| 301 // The layer should not be drawn if (1) it is not double-sided and (2) the | |
| 302 // back of the layer is known to be facing the screen. | |
| 303 if (!backface_test_layer->double_sided() && | |
| 304 TransformToScreenIsKnown(backface_test_layer, tree) && | |
| 305 IsLayerBackFaceVisible(backface_test_layer, tree)) | |
| 306 return true; | |
| 307 | |
| 308 return false; | |
| 226 } | 309 } |
| 227 | 310 |
| 228 template <typename LayerType> | 311 template <typename LayerType> |
| 229 void FindLayersThatNeedVisibleRects(LayerType* layer, | 312 void FindLayersThatNeedVisibleRects(LayerType* layer, |
| 230 const TransformTree& tree, | 313 const TransformTree& tree, |
| 231 bool subtree_is_visible_from_ancestor, | 314 bool subtree_is_visible_from_ancestor, |
| 232 std::vector<LayerType*>* layers_to_update) { | 315 std::vector<LayerType*>* layers_to_update) { |
| 233 const bool layer_is_invisible = LayerIsInvisible(layer); | |
| 234 const bool layer_is_backfacing = | |
| 235 (layer->has_render_surface() && !layer->double_sided() && | |
| 236 IsSurfaceBackFaceExposed(layer, tree)); | |
| 237 | |
| 238 const bool subtree_is_invisble = layer_is_invisible || layer_is_backfacing; | |
| 239 if (subtree_is_invisble) | |
| 240 return; | |
| 241 | |
| 242 bool layer_is_drawn = | 316 bool layer_is_drawn = |
| 243 layer->HasCopyRequest() || | 317 layer->HasCopyRequest() || |
| 244 (subtree_is_visible_from_ancestor && !layer->hide_layer_and_subtree()); | 318 (subtree_is_visible_from_ancestor && !layer->hide_layer_and_subtree()); |
| 245 | 319 |
| 246 if (layer_is_drawn && layer->DrawsContent()) { | 320 if (!!layer->parent() && SubtreeShouldBeSkipped(layer, layer_is_drawn)) |
|
ajuma
2015/04/27 19:54:22
Does removing the !! here trigger a compiler warni
Ian Vollick
2015/04/27 20:13:05
Nope. Removed.
| |
| 247 const bool visible = !IsInvisibleDueToTransform(layer, tree); | 321 return; |
| 248 if (visible) | 322 |
| 249 layers_to_update->push_back(layer); | 323 if (!LayerShouldBeSkipped(layer, layer_is_drawn, tree)) |
| 250 } | 324 layers_to_update->push_back(layer); |
| 251 | 325 |
| 252 for (size_t i = 0; i < layer->children().size(); ++i) { | 326 for (size_t i = 0; i < layer->children().size(); ++i) { |
| 253 FindLayersThatNeedVisibleRects(layer->child_at(i), tree, layer_is_drawn, | 327 FindLayersThatNeedVisibleRects(layer->child_at(i), tree, layer_is_drawn, |
| 254 layers_to_update); | 328 layers_to_update); |
| 255 } | 329 } |
| 256 } | 330 } |
| 257 | 331 |
| 258 } // namespace | 332 } // namespace |
| 259 | 333 |
| 260 void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) { | 334 void ComputeClips(ClipTree* clip_tree, const TransformTree& transform_tree) { |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 516 const OpacityTree& tree) { | 590 const OpacityTree& tree) { |
| 517 return DrawOpacityFromPropertyTreesInternal(layer, tree); | 591 return DrawOpacityFromPropertyTreesInternal(layer, tree); |
| 518 } | 592 } |
| 519 | 593 |
| 520 float DrawOpacityFromPropertyTrees(const LayerImpl* layer, | 594 float DrawOpacityFromPropertyTrees(const LayerImpl* layer, |
| 521 const OpacityTree& tree) { | 595 const OpacityTree& tree) { |
| 522 return DrawOpacityFromPropertyTreesInternal(layer, tree); | 596 return DrawOpacityFromPropertyTreesInternal(layer, tree); |
| 523 } | 597 } |
| 524 | 598 |
| 525 } // namespace cc | 599 } // namespace cc |
| OLD | NEW |