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

Side by Side Diff: cc/trees/draw_property_utils.cc

Issue 1056793009: Reconcile property tree and CDP layer skipping logic (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | cc/trees/layer_tree_host_common_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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))
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
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
OLDNEW
« no previous file with comments | « no previous file | cc/trees/layer_tree_host_common_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698