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

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

Issue 2751783002: cc: Replace LayerIterator with iterator that walks layer list and effect tree (Closed)
Patch Set: Rebase Created 3 years, 8 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 | « cc/trees/occlusion_tracker.h ('k') | cc/trees/occlusion_tracker_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 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 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/occlusion_tracker.h" 5 #include "cc/trees/occlusion_tracker.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 } 49 }
50 50
51 const RenderSurfaceImpl* 51 const RenderSurfaceImpl*
52 OcclusionTracker::OcclusionSurfaceForContributingSurface() const { 52 OcclusionTracker::OcclusionSurfaceForContributingSurface() const {
53 // A contributing surface doesn't get occluded by things inside its own 53 // A contributing surface doesn't get occluded by things inside its own
54 // surface, so only things outside the surface can occlude it. That occlusion 54 // surface, so only things outside the surface can occlude it. That occlusion
55 // is found just below the top of the stack (if it exists). 55 // is found just below the top of the stack (if it exists).
56 return (stack_.size() < 2) ? nullptr : stack_[stack_.size() - 2].target; 56 return (stack_.size() < 2) ? nullptr : stack_[stack_.size() - 2].target;
57 } 57 }
58 58
59 void OcclusionTracker::EnterLayer(const LayerIteratorPosition& layer_iterator) { 59 void OcclusionTracker::EnterLayer(
60 LayerImpl* render_target = layer_iterator.target_render_surface_layer; 60 const EffectTreeLayerListIterator::Position& iterator) {
61 RenderSurfaceImpl* render_target = iterator.target_render_surface;
61 62
62 if (layer_iterator.represents_itself) 63 if (iterator.state == EffectTreeLayerListIterator::State::LAYER)
63 EnterRenderTarget(render_target); 64 EnterRenderTarget(render_target);
64 else if (layer_iterator.represents_target_render_surface) 65 else if (iterator.state == EffectTreeLayerListIterator::State::TARGET_SURFACE)
65 FinishedRenderTarget(render_target); 66 FinishedRenderTarget(render_target);
66 } 67 }
67 68
68 void OcclusionTracker::LeaveLayer(const LayerIteratorPosition& layer_iterator) { 69 void OcclusionTracker::LeaveLayer(
69 LayerImpl* render_target = layer_iterator.target_render_surface_layer; 70 const EffectTreeLayerListIterator::Position& iterator) {
71 RenderSurfaceImpl* render_target = iterator.target_render_surface;
70 72
71 if (layer_iterator.represents_itself) 73 if (iterator.state == EffectTreeLayerListIterator::State::LAYER)
72 MarkOccludedBehindLayer(layer_iterator.current_layer); 74 MarkOccludedBehindLayer(iterator.current_layer);
73 // TODO(danakj): This should be done when entering the contributing surface, 75 // TODO(danakj): This should be done when entering the contributing surface,
74 // but in a way that the surface's own occlusion won't occlude itself. 76 // but in a way that the surface's own occlusion won't occlude itself.
75 else if (layer_iterator.represents_contributing_render_surface) 77 else if (iterator.state ==
78 EffectTreeLayerListIterator::State::CONTRIBUTING_SURFACE)
76 LeaveToRenderTarget(render_target); 79 LeaveToRenderTarget(render_target);
77 } 80 }
78 81
79 static gfx::Rect ScreenSpaceClipRectInTargetSurface( 82 static gfx::Rect ScreenSpaceClipRectInTargetSurface(
80 const RenderSurfaceImpl* target_surface, 83 const RenderSurfaceImpl* target_surface,
81 const gfx::Rect& screen_space_clip_rect) { 84 const gfx::Rect& screen_space_clip_rect) {
82 gfx::Transform inverse_screen_space_transform( 85 gfx::Transform inverse_screen_space_transform(
83 gfx::Transform::kSkipInitialization); 86 gfx::Transform::kSkipInitialization);
84 if (!target_surface->screen_space_transform().GetInverse( 87 if (!target_surface->screen_space_transform().GetInverse(
85 &inverse_screen_space_transform)) 88 &inverse_screen_space_transform))
(...skipping 24 matching lines...) Expand all
110 gfx::Rect transformed_rect = 113 gfx::Rect transformed_rect =
111 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform, 114 MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform,
112 region.GetRect(i)); 115 region.GetRect(i));
113 if (have_clip_rect) 116 if (have_clip_rect)
114 transformed_rect.Intersect(clip_rect_in_new_target); 117 transformed_rect.Intersect(clip_rect_in_new_target);
115 transformed_region.Union(transformed_rect); 118 transformed_region.Union(transformed_rect);
116 } 119 }
117 return transformed_region; 120 return transformed_region;
118 } 121 }
119 122
120 void OcclusionTracker::EnterRenderTarget(const LayerImpl* new_target) { 123 void OcclusionTracker::EnterRenderTarget(
121 DCHECK(new_target->GetRenderSurface()); 124 const RenderSurfaceImpl* new_target_surface) {
122 RenderSurfaceImpl* new_target_surface = new_target->GetRenderSurface(); 125 DCHECK(new_target_surface);
123 if (!stack_.empty() && stack_.back().target == new_target_surface) 126 if (!stack_.empty() && stack_.back().target == new_target_surface)
124 return; 127 return;
125 128
126 const RenderSurfaceImpl* old_target_surface = NULL; 129 const RenderSurfaceImpl* old_target_surface = NULL;
127 const RenderSurfaceImpl* old_occlusion_immune_ancestor = NULL; 130 const RenderSurfaceImpl* old_occlusion_immune_ancestor = NULL;
128 if (!stack_.empty()) { 131 if (!stack_.empty()) {
129 old_target_surface = stack_.back().target; 132 old_target_surface = stack_.back().target;
130 old_occlusion_immune_ancestor = 133 old_occlusion_immune_ancestor =
131 old_target_surface->nearest_occlusion_immune_ancestor(); 134 old_target_surface->nearest_occlusion_immune_ancestor();
132 } 135 }
(...skipping 13 matching lines...) Expand all
146 new_occlusion_immune_ancestor != old_occlusion_immune_ancestor; 149 new_occlusion_immune_ancestor != old_occlusion_immune_ancestor;
147 150
148 gfx::Transform inverse_new_target_screen_space_transform( 151 gfx::Transform inverse_new_target_screen_space_transform(
149 // Note carefully, not used if screen space transform is uninvertible. 152 // Note carefully, not used if screen space transform is uninvertible.
150 gfx::Transform::kSkipInitialization); 153 gfx::Transform::kSkipInitialization);
151 bool have_transform_from_screen_to_new_target = 154 bool have_transform_from_screen_to_new_target =
152 new_target_surface->screen_space_transform().GetInverse( 155 new_target_surface->screen_space_transform().GetInverse(
153 &inverse_new_target_screen_space_transform); 156 &inverse_new_target_screen_space_transform);
154 157
155 bool entering_root_target = 158 bool entering_root_target =
156 new_target->layer_tree_impl()->IsRootLayer(new_target); 159 new_target_surface->render_target() == new_target_surface;
157 160
158 bool copy_outside_occlusion_forward = 161 bool copy_outside_occlusion_forward =
159 stack_.size() > 1 && 162 stack_.size() > 1 &&
160 !entering_unoccluded_subtree && 163 !entering_unoccluded_subtree &&
161 have_transform_from_screen_to_new_target && 164 have_transform_from_screen_to_new_target &&
162 !entering_root_target; 165 !entering_root_target;
163 if (!copy_outside_occlusion_forward) 166 if (!copy_outside_occlusion_forward)
164 return; 167 return;
165 168
166 size_t last_index = stack_.size() - 1; 169 size_t last_index = stack_.size() - 1;
167 gfx::Transform old_target_to_new_target_transform( 170 gfx::Transform old_target_to_new_target_transform(
168 inverse_new_target_screen_space_transform, 171 inverse_new_target_screen_space_transform,
169 old_target_surface->screen_space_transform()); 172 old_target_surface->screen_space_transform());
170 stack_[last_index].occlusion_from_outside_target = 173 stack_[last_index].occlusion_from_outside_target =
171 TransformSurfaceOpaqueRegion( 174 TransformSurfaceOpaqueRegion(
172 stack_[last_index - 1].occlusion_from_outside_target, false, 175 stack_[last_index - 1].occlusion_from_outside_target, false,
173 gfx::Rect(), old_target_to_new_target_transform); 176 gfx::Rect(), old_target_to_new_target_transform);
174 stack_[last_index].occlusion_from_outside_target.Union( 177 stack_[last_index].occlusion_from_outside_target.Union(
175 TransformSurfaceOpaqueRegion( 178 TransformSurfaceOpaqueRegion(
176 stack_[last_index - 1].occlusion_from_inside_target, false, 179 stack_[last_index - 1].occlusion_from_inside_target, false,
177 gfx::Rect(), old_target_to_new_target_transform)); 180 gfx::Rect(), old_target_to_new_target_transform));
178 } 181 }
179 182
180 void OcclusionTracker::FinishedRenderTarget(const LayerImpl* finished_target) { 183 void OcclusionTracker::FinishedRenderTarget(
184 const RenderSurfaceImpl* finished_target_surface) {
181 // Make sure we know about the target surface. 185 // Make sure we know about the target surface.
182 EnterRenderTarget(finished_target); 186 EnterRenderTarget(finished_target_surface);
183 187
184 RenderSurfaceImpl* surface = finished_target->GetRenderSurface(); 188 bool is_hidden =
189 finished_target_surface->OwningEffectNode()->screen_space_opacity == 0.f;
185 190
186 // Readbacks always happen on render targets so we only need to check 191 // Readbacks always happen on render targets so we only need to check
187 // for readbacks here. 192 // for readbacks here.
188 bool target_is_only_for_copy_request = 193 bool target_is_only_for_copy_request =
189 surface->HasCopyRequest() && finished_target->IsHidden(); 194 finished_target_surface->HasCopyRequest() && is_hidden;
190 195
191 // If the occlusion within the surface can not be applied to things outside of 196 // If the occlusion within the surface can not be applied to things outside of
192 // the surface's subtree, then clear the occlusion here so it won't be used. 197 // the surface's subtree, then clear the occlusion here so it won't be used.
193 if (surface->MaskLayer() || surface->draw_opacity() < 1 || 198 if (finished_target_surface->HasMask() ||
194 !surface->UsesDefaultBlendMode() || target_is_only_for_copy_request || 199 finished_target_surface->draw_opacity() < 1 ||
195 surface->Filters().HasFilterThatAffectsOpacity()) { 200 !finished_target_surface->UsesDefaultBlendMode() ||
201 target_is_only_for_copy_request ||
202 finished_target_surface->Filters().HasFilterThatAffectsOpacity()) {
196 stack_.back().occlusion_from_outside_target.Clear(); 203 stack_.back().occlusion_from_outside_target.Clear();
197 stack_.back().occlusion_from_inside_target.Clear(); 204 stack_.back().occlusion_from_inside_target.Clear();
198 } 205 }
199 } 206 }
200 207
201 static void ReduceOcclusionBelowSurface( 208 static void ReduceOcclusionBelowSurface(
202 const RenderSurfaceImpl* contributing_surface, 209 const RenderSurfaceImpl* contributing_surface,
203 const gfx::Rect& surface_rect, 210 const gfx::Rect& surface_rect,
204 const gfx::Transform& surface_transform, 211 const gfx::Transform& surface_transform,
205 SimpleEnclosedRegion* occlusion_from_inside_target) { 212 SimpleEnclosedRegion* occlusion_from_inside_target) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 int shrink_bottom = 252 int shrink_bottom =
246 occlusion_rect.bottom() == affected_area_in_target.bottom() ? 253 occlusion_rect.bottom() == affected_area_in_target.bottom() ?
247 0 : outset_top; 254 0 : outset_top;
248 255
249 occlusion_rect.Inset(shrink_left, shrink_top, shrink_right, shrink_bottom); 256 occlusion_rect.Inset(shrink_left, shrink_top, shrink_right, shrink_bottom);
250 257
251 occlusion_from_inside_target->Union(occlusion_rect); 258 occlusion_from_inside_target->Union(occlusion_rect);
252 } 259 }
253 } 260 }
254 261
255 void OcclusionTracker::LeaveToRenderTarget(const LayerImpl* new_target) { 262 void OcclusionTracker::LeaveToRenderTarget(
263 const RenderSurfaceImpl* new_target_surface) {
256 DCHECK(!stack_.empty()); 264 DCHECK(!stack_.empty());
257 size_t last_index = stack_.size() - 1; 265 size_t last_index = stack_.size() - 1;
258 DCHECK(new_target->GetRenderSurface()); 266 DCHECK(new_target_surface);
259 RenderSurfaceImpl* new_surface = new_target->GetRenderSurface();
260 bool surface_will_be_at_top_after_pop = 267 bool surface_will_be_at_top_after_pop =
261 stack_.size() > 1 && stack_[last_index - 1].target == new_surface; 268 stack_.size() > 1 && stack_[last_index - 1].target == new_target_surface;
262 269
263 // We merge the screen occlusion from the current RenderSurfaceImpl subtree 270 // We merge the screen occlusion from the current RenderSurfaceImpl subtree
264 // out to its parent target RenderSurfaceImpl. The target occlusion can be 271 // out to its parent target RenderSurfaceImpl. The target occlusion can be
265 // merged out as well but needs to be transformed to the new target. 272 // merged out as well but needs to be transformed to the new target.
266 273
267 const RenderSurfaceImpl* old_surface = stack_[last_index].target; 274 const RenderSurfaceImpl* old_surface = stack_[last_index].target;
268 275
269 SimpleEnclosedRegion old_occlusion_from_inside_target_in_new_target = 276 SimpleEnclosedRegion old_occlusion_from_inside_target_in_new_target =
270 TransformSurfaceOpaqueRegion( 277 TransformSurfaceOpaqueRegion(
271 stack_[last_index].occlusion_from_inside_target, 278 stack_[last_index].occlusion_from_inside_target,
272 old_surface->is_clipped(), old_surface->clip_rect(), 279 old_surface->is_clipped(), old_surface->clip_rect(),
273 old_surface->draw_transform()); 280 old_surface->draw_transform());
274 281
275 SimpleEnclosedRegion old_occlusion_from_outside_target_in_new_target = 282 SimpleEnclosedRegion old_occlusion_from_outside_target_in_new_target =
276 TransformSurfaceOpaqueRegion( 283 TransformSurfaceOpaqueRegion(
277 stack_[last_index].occlusion_from_outside_target, false, gfx::Rect(), 284 stack_[last_index].occlusion_from_outside_target, false, gfx::Rect(),
278 old_surface->draw_transform()); 285 old_surface->draw_transform());
279 286
280 gfx::Rect unoccluded_surface_rect; 287 gfx::Rect unoccluded_surface_rect;
281 if (old_surface->BackgroundFilters().HasFilterThatMovesPixels()) { 288 if (old_surface->BackgroundFilters().HasFilterThatMovesPixels()) {
282 Occlusion surface_occlusion = GetCurrentOcclusionForContributingSurface( 289 Occlusion surface_occlusion = GetCurrentOcclusionForContributingSurface(
283 old_surface->draw_transform()); 290 old_surface->draw_transform());
284 unoccluded_surface_rect = 291 unoccluded_surface_rect =
285 surface_occlusion.GetUnoccludedContentRect(old_surface->content_rect()); 292 surface_occlusion.GetUnoccludedContentRect(old_surface->content_rect());
286 } 293 }
287 294
295 bool is_root = new_target_surface->render_target() == new_target_surface;
288 if (surface_will_be_at_top_after_pop) { 296 if (surface_will_be_at_top_after_pop) {
289 // Merge the top of the stack down. 297 // Merge the top of the stack down.
290 stack_[last_index - 1].occlusion_from_inside_target.Union( 298 stack_[last_index - 1].occlusion_from_inside_target.Union(
291 old_occlusion_from_inside_target_in_new_target); 299 old_occlusion_from_inside_target_in_new_target);
292 // TODO(danakj): Strictly this should subtract the inside target occlusion 300 // TODO(danakj): Strictly this should subtract the inside target occlusion
293 // before union. 301 // before union.
294 if (!new_target->layer_tree_impl()->IsRootLayer(new_target)) { 302 if (!is_root) {
295 stack_[last_index - 1].occlusion_from_outside_target.Union( 303 stack_[last_index - 1].occlusion_from_outside_target.Union(
296 old_occlusion_from_outside_target_in_new_target); 304 old_occlusion_from_outside_target_in_new_target);
297 } 305 }
298 stack_.pop_back(); 306 stack_.pop_back();
299 } else { 307 } else {
300 // Replace the top of the stack with the new pushed surface. 308 // Replace the top of the stack with the new pushed surface.
301 stack_.back().target = new_surface; 309 stack_.back().target = new_target_surface;
302 stack_.back().occlusion_from_inside_target = 310 stack_.back().occlusion_from_inside_target =
303 old_occlusion_from_inside_target_in_new_target; 311 old_occlusion_from_inside_target_in_new_target;
304 if (!new_target->layer_tree_impl()->IsRootLayer(new_target)) { 312 if (!is_root) {
305 stack_.back().occlusion_from_outside_target = 313 stack_.back().occlusion_from_outside_target =
306 old_occlusion_from_outside_target_in_new_target; 314 old_occlusion_from_outside_target_in_new_target;
307 } else { 315 } else {
308 stack_.back().occlusion_from_outside_target.Clear(); 316 stack_.back().occlusion_from_outside_target.Clear();
309 } 317 }
310 } 318 }
311 319
312 if (!old_surface->BackgroundFilters().HasFilterThatMovesPixels()) 320 if (!old_surface->BackgroundFilters().HasFilterThatMovesPixels())
313 return; 321 return;
314 322
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 DCHECK(layer_tree->RootRenderSurface() == stack_.back().target); 378 DCHECK(layer_tree->RootRenderSurface() == stack_.back().target);
371 const SimpleEnclosedRegion& occluded = 379 const SimpleEnclosedRegion& occluded =
372 stack_.back().occlusion_from_inside_target; 380 stack_.back().occlusion_from_inside_target;
373 Region visible_region(screen_space_clip_rect_); 381 Region visible_region(screen_space_clip_rect_);
374 for (size_t i = 0; i < occluded.GetRegionComplexity(); ++i) 382 for (size_t i = 0; i < occluded.GetRegionComplexity(); ++i)
375 visible_region.Subtract(occluded.GetRect(i)); 383 visible_region.Subtract(occluded.GetRect(i));
376 return visible_region; 384 return visible_region;
377 } 385 }
378 386
379 } // namespace cc 387 } // namespace cc
OLDNEW
« no previous file with comments | « cc/trees/occlusion_tracker.h ('k') | cc/trees/occlusion_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698