OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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; |
jaydasika
2017/03/22 20:49:42
Can LayerImpl::IsHidden be deleted as its not bein
ajuma
2017/03/24 17:25:07
Good catch, there was still one unit test using it
| |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |