| 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; |
| 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 |