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 |