| 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 <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "cc/base/math_util.h" | 9 #include "cc/base/math_util.h" |
| 10 #include "cc/base/region.h" |
| 10 #include "cc/layers/layer.h" | 11 #include "cc/layers/layer.h" |
| 11 #include "cc/layers/layer_impl.h" | 12 #include "cc/layers/layer_impl.h" |
| 12 #include "cc/layers/render_surface.h" | 13 #include "cc/layers/render_surface.h" |
| 13 #include "cc/layers/render_surface_impl.h" | 14 #include "cc/layers/render_surface_impl.h" |
| 14 #include "ui/gfx/quad_f.h" | 15 #include "ui/gfx/quad_f.h" |
| 15 #include "ui/gfx/rect_conversions.h" | 16 #include "ui/gfx/rect_conversions.h" |
| 16 | 17 |
| 17 namespace cc { | 18 namespace cc { |
| 18 | 19 |
| 19 template <typename LayerType> | 20 template <typename LayerType> |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 gfx::Transform::kSkipInitialization); | 59 gfx::Transform::kSkipInitialization); |
| 59 if (!target_surface->screen_space_transform().GetInverse( | 60 if (!target_surface->screen_space_transform().GetInverse( |
| 60 &inverse_screen_space_transform)) | 61 &inverse_screen_space_transform)) |
| 61 return target_surface->content_rect(); | 62 return target_surface->content_rect(); |
| 62 | 63 |
| 63 return MathUtil::ProjectEnclosingClippedRect(inverse_screen_space_transform, | 64 return MathUtil::ProjectEnclosingClippedRect(inverse_screen_space_transform, |
| 64 screen_space_clip_rect); | 65 screen_space_clip_rect); |
| 65 } | 66 } |
| 66 | 67 |
| 67 template <typename RenderSurfaceType> | 68 template <typename RenderSurfaceType> |
| 68 static Region TransformSurfaceOpaqueRegion( | 69 static SimpleEnclosedRegion TransformSurfaceOpaqueRegion( |
| 69 const Region& region, | 70 const SimpleEnclosedRegion& region, |
| 70 bool have_clip_rect, | 71 bool have_clip_rect, |
| 71 const gfx::Rect& clip_rect_in_new_target, | 72 const gfx::Rect& clip_rect_in_new_target, |
| 72 const gfx::Transform& transform) { | 73 const gfx::Transform& transform) { |
| 73 if (region.IsEmpty()) | 74 if (region.IsEmpty()) |
| 74 return Region(); | 75 return region; |
| 75 | 76 |
| 76 // Verify that rects within the |surface| will remain rects in its target | 77 // Verify that rects within the |surface| will remain rects in its target |
| 77 // surface after applying |transform|. If this is true, then apply |transform| | 78 // surface after applying |transform|. If this is true, then apply |transform| |
| 78 // to each rect within |region| in order to transform the entire Region. | 79 // to each rect within |region| in order to transform the entire Region. |
| 79 | 80 |
| 80 // TODO(danakj): Find a rect interior to each transformed quad. | 81 // TODO(danakj): Find a rect interior to each transformed quad. |
| 81 if (!transform.Preserves2dAxisAlignment()) | 82 if (!transform.Preserves2dAxisAlignment()) |
| 82 return Region(); | 83 return SimpleEnclosedRegion(); |
| 83 | 84 |
| 84 // TODO(danakj): If the Region is too complex, degrade gracefully here by | 85 gfx::Rect transformed_rect; |
| 85 // skipping rects in it. | 86 for (size_t i = 0; i < region.GetRegionComplexity(); ++i) { |
| 86 Region transformed_region; | |
| 87 for (Region::Iterator rects(region); rects.has_rect(); rects.next()) { | |
| 88 bool clipped; | 87 bool clipped; |
| 89 gfx::QuadF transformed_quad = | 88 gfx::QuadF transformed_quad = |
| 90 MathUtil::MapQuad(transform, gfx::QuadF(rects.rect()), &clipped); | 89 MathUtil::MapQuad(transform, gfx::QuadF(region.GetRect(i)), &clipped); |
| 91 gfx::Rect transformed_rect = | 90 transformed_rect = gfx::ToEnclosedRect(transformed_quad.BoundingBox()); |
| 92 gfx::ToEnclosedRect(transformed_quad.BoundingBox()); | |
| 93 DCHECK(!clipped); // We only map if the transform preserves axis alignment. | 91 DCHECK(!clipped); // We only map if the transform preserves axis alignment. |
| 94 if (have_clip_rect) | 92 if (have_clip_rect) |
| 95 transformed_rect.Intersect(clip_rect_in_new_target); | 93 transformed_rect.Intersect(clip_rect_in_new_target); |
| 96 transformed_region.Union(transformed_rect); | |
| 97 } | 94 } |
| 98 return transformed_region; | 95 return SimpleEnclosedRegion(transformed_rect); |
| 99 } | 96 } |
| 100 | 97 |
| 101 static inline bool LayerOpacityKnown(const Layer* layer) { | 98 static inline bool LayerOpacityKnown(const Layer* layer) { |
| 102 return !layer->draw_opacity_is_animating(); | 99 return !layer->draw_opacity_is_animating(); |
| 103 } | 100 } |
| 104 static inline bool LayerOpacityKnown(const LayerImpl* layer) { | 101 static inline bool LayerOpacityKnown(const LayerImpl* layer) { |
| 105 return true; | 102 return true; |
| 106 } | 103 } |
| 107 static inline bool LayerTransformsToTargetKnown(const Layer* layer) { | 104 static inline bool LayerTransformsToTargetKnown(const Layer* layer) { |
| 108 return !layer->draw_transform_is_animating(); | 105 return !layer->draw_transform_is_animating(); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 finished_target->filters().HasFilterThatAffectsOpacity()) { | 230 finished_target->filters().HasFilterThatAffectsOpacity()) { |
| 234 stack_.back().occlusion_from_outside_target.Clear(); | 231 stack_.back().occlusion_from_outside_target.Clear(); |
| 235 stack_.back().occlusion_from_inside_target.Clear(); | 232 stack_.back().occlusion_from_inside_target.Clear(); |
| 236 } else if (!SurfaceTransformsToTargetKnown(surface)) { | 233 } else if (!SurfaceTransformsToTargetKnown(surface)) { |
| 237 stack_.back().occlusion_from_inside_target.Clear(); | 234 stack_.back().occlusion_from_inside_target.Clear(); |
| 238 stack_.back().occlusion_from_outside_target.Clear(); | 235 stack_.back().occlusion_from_outside_target.Clear(); |
| 239 } | 236 } |
| 240 } | 237 } |
| 241 | 238 |
| 242 template <typename LayerType> | 239 template <typename LayerType> |
| 243 static void ReduceOcclusionBelowSurface(LayerType* contributing_layer, | 240 static void ReduceOcclusionBelowSurface( |
| 244 const gfx::Rect& surface_rect, | 241 LayerType* contributing_layer, |
| 245 const gfx::Transform& surface_transform, | 242 const gfx::Rect& surface_rect, |
| 246 LayerType* render_target, | 243 const gfx::Transform& surface_transform, |
| 247 Region* occlusion_from_inside_target) { | 244 LayerType* render_target, |
| 245 SimpleEnclosedRegion* occlusion_from_inside_target) { |
| 248 if (surface_rect.IsEmpty()) | 246 if (surface_rect.IsEmpty()) |
| 249 return; | 247 return; |
| 250 | 248 |
| 251 gfx::Rect affected_area_in_target = | 249 gfx::Rect affected_area_in_target = |
| 252 MathUtil::MapEnclosingClippedRect(surface_transform, surface_rect); | 250 MathUtil::MapEnclosingClippedRect(surface_transform, surface_rect); |
| 253 if (contributing_layer->render_surface()->is_clipped()) { | 251 if (contributing_layer->render_surface()->is_clipped()) { |
| 254 affected_area_in_target.Intersect( | 252 affected_area_in_target.Intersect( |
| 255 contributing_layer->render_surface()->clip_rect()); | 253 contributing_layer->render_surface()->clip_rect()); |
| 256 } | 254 } |
| 257 if (affected_area_in_target.IsEmpty()) | 255 if (affected_area_in_target.IsEmpty()) |
| 258 return; | 256 return; |
| 259 | 257 |
| 260 int outset_top, outset_right, outset_bottom, outset_left; | 258 int outset_top, outset_right, outset_bottom, outset_left; |
| 261 contributing_layer->background_filters().GetOutsets( | 259 contributing_layer->background_filters().GetOutsets( |
| 262 &outset_top, &outset_right, &outset_bottom, &outset_left); | 260 &outset_top, &outset_right, &outset_bottom, &outset_left); |
| 263 | 261 |
| 264 // The filter can move pixels from outside of the clip, so allow affected_area | 262 // The filter can move pixels from outside of the clip, so allow affected_area |
| 265 // to expand outside the clip. | 263 // to expand outside the clip. |
| 266 affected_area_in_target.Inset( | 264 affected_area_in_target.Inset( |
| 267 -outset_left, -outset_top, -outset_right, -outset_bottom); | 265 -outset_left, -outset_top, -outset_right, -outset_bottom); |
| 268 Region affected_occlusion = IntersectRegions(*occlusion_from_inside_target, | 266 SimpleEnclosedRegion affected_occlusion = IntersectSimpleEnclosedRegions( |
| 269 affected_area_in_target); | 267 *occlusion_from_inside_target, |
| 270 Region::Iterator affected_occlusion_rects(affected_occlusion); | 268 SimpleEnclosedRegion(affected_area_in_target)); |
| 271 | 269 |
| 272 occlusion_from_inside_target->Subtract(affected_area_in_target); | 270 occlusion_from_inside_target->Subtract(affected_area_in_target); |
| 273 for (; affected_occlusion_rects.has_rect(); affected_occlusion_rects.next()) { | 271 for (size_t i = 0; i < affected_occlusion.GetRegionComplexity(); ++i) { |
| 274 gfx::Rect occlusion_rect = affected_occlusion_rects.rect(); | 272 gfx::Rect occlusion_rect = affected_occlusion.GetRect(i); |
| 275 | 273 |
| 276 // Shrink the rect by expanding the non-opaque pixels outside the rect. | 274 // Shrink the rect by expanding the non-opaque pixels outside the rect. |
| 277 | 275 |
| 278 // The left outset of the filters moves pixels on the right side of | 276 // The left outset of the filters moves pixels on the right side of |
| 279 // the occlusion_rect into it, shrinking its right edge. | 277 // the occlusion_rect into it, shrinking its right edge. |
| 280 int shrink_left = | 278 int shrink_left = |
| 281 occlusion_rect.x() == affected_area_in_target.x() ? 0 : outset_right; | 279 occlusion_rect.x() == affected_area_in_target.x() ? 0 : outset_right; |
| 282 int shrink_top = | 280 int shrink_top = |
| 283 occlusion_rect.y() == affected_area_in_target.y() ? 0 : outset_bottom; | 281 occlusion_rect.y() == affected_area_in_target.y() ? 0 : outset_bottom; |
| 284 int shrink_right = | 282 int shrink_right = |
| (...skipping 17 matching lines...) Expand all Loading... |
| 302 stack_.size() > 1 && stack_[last_index - 1].target == new_target; | 300 stack_.size() > 1 && stack_[last_index - 1].target == new_target; |
| 303 | 301 |
| 304 // We merge the screen occlusion from the current RenderSurfaceImpl subtree | 302 // We merge the screen occlusion from the current RenderSurfaceImpl subtree |
| 305 // out to its parent target RenderSurfaceImpl. The target occlusion can be | 303 // out to its parent target RenderSurfaceImpl. The target occlusion can be |
| 306 // merged out as well but needs to be transformed to the new target. | 304 // merged out as well but needs to be transformed to the new target. |
| 307 | 305 |
| 308 const LayerType* old_target = stack_[last_index].target; | 306 const LayerType* old_target = stack_[last_index].target; |
| 309 const typename LayerType::RenderSurfaceType* old_surface = | 307 const typename LayerType::RenderSurfaceType* old_surface = |
| 310 old_target->render_surface(); | 308 old_target->render_surface(); |
| 311 | 309 |
| 312 Region old_occlusion_from_inside_target_in_new_target = | 310 SimpleEnclosedRegion old_occlusion_from_inside_target_in_new_target = |
| 313 TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( | 311 TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( |
| 314 stack_[last_index].occlusion_from_inside_target, | 312 stack_[last_index].occlusion_from_inside_target, |
| 315 old_surface->is_clipped(), | 313 old_surface->is_clipped(), |
| 316 old_surface->clip_rect(), | 314 old_surface->clip_rect(), |
| 317 old_surface->draw_transform()); | 315 old_surface->draw_transform()); |
| 318 if (old_target->has_replica() && !old_target->replica_has_mask()) { | 316 if (old_target->has_replica() && !old_target->replica_has_mask()) { |
| 319 old_occlusion_from_inside_target_in_new_target.Union( | 317 old_occlusion_from_inside_target_in_new_target.Union( |
| 320 TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( | 318 TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( |
| 321 stack_[last_index].occlusion_from_inside_target, | 319 stack_[last_index].occlusion_from_inside_target, |
| 322 old_surface->is_clipped(), | 320 old_surface->is_clipped(), |
| 323 old_surface->clip_rect(), | 321 old_surface->clip_rect(), |
| 324 old_surface->replica_draw_transform())); | 322 old_surface->replica_draw_transform())); |
| 325 } | 323 } |
| 326 | 324 |
| 327 Region old_occlusion_from_outside_target_in_new_target = | 325 SimpleEnclosedRegion old_occlusion_from_outside_target_in_new_target = |
| 328 TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( | 326 TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( |
| 329 stack_[last_index].occlusion_from_outside_target, | 327 stack_[last_index].occlusion_from_outside_target, |
| 330 false, | 328 false, |
| 331 gfx::Rect(), | 329 gfx::Rect(), |
| 332 old_surface->draw_transform()); | 330 old_surface->draw_transform()); |
| 333 | 331 |
| 334 gfx::Rect unoccluded_surface_rect; | 332 gfx::Rect unoccluded_surface_rect; |
| 335 gfx::Rect unoccluded_replica_rect; | 333 gfx::Rect unoccluded_replica_rect; |
| 336 if (old_target->background_filters().HasFilterThatMovesPixels()) { | 334 if (old_target->background_filters().HasFilterThatMovesPixels()) { |
| 337 unoccluded_surface_rect = UnoccludedContributingSurfaceContentRect( | 335 unoccluded_surface_rect = UnoccludedContributingSurfaceContentRect( |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 old_surface->replica_draw_transform(), | 391 old_surface->replica_draw_transform(), |
| 394 new_target, | 392 new_target, |
| 395 &stack_.back().occlusion_from_outside_target); | 393 &stack_.back().occlusion_from_outside_target); |
| 396 } | 394 } |
| 397 | 395 |
| 398 template <typename LayerType> | 396 template <typename LayerType> |
| 399 void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( | 397 void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( |
| 400 const LayerType* layer) { | 398 const LayerType* layer) { |
| 401 DCHECK(!stack_.empty()); | 399 DCHECK(!stack_.empty()); |
| 402 DCHECK_EQ(layer->render_target(), stack_.back().target); | 400 DCHECK_EQ(layer->render_target(), stack_.back().target); |
| 403 if (stack_.empty()) | |
| 404 return; | |
| 405 | 401 |
| 406 if (!LayerOpacityKnown(layer) || layer->draw_opacity() < 1) | 402 if (!LayerOpacityKnown(layer) || layer->draw_opacity() < 1) |
| 407 return; | 403 return; |
| 408 | 404 |
| 409 if (!layer->uses_default_blend_mode()) | 405 if (!layer->uses_default_blend_mode()) |
| 410 return; | 406 return; |
| 411 | 407 |
| 412 if (LayerIsInUnsorted3dRenderingContext(layer)) | 408 if (LayerIsInUnsorted3dRenderingContext(layer)) |
| 413 return; | 409 return; |
| 414 | 410 |
| 415 if (!LayerTransformsToTargetKnown(layer)) | 411 if (!LayerTransformsToTargetKnown(layer)) |
| 416 return; | 412 return; |
| 417 | 413 |
| 418 Region opaque_contents = layer->VisibleContentOpaqueRegion(); | 414 SimpleEnclosedRegion opaque_contents = layer->VisibleContentOpaqueRegion(); |
| 419 if (opaque_contents.IsEmpty()) | 415 if (opaque_contents.IsEmpty()) |
| 420 return; | 416 return; |
| 421 | 417 |
| 422 DCHECK(layer->visible_content_rect().Contains(opaque_contents.bounds())); | 418 DCHECK(layer->visible_content_rect().Contains(opaque_contents.bounds())); |
| 423 | 419 |
| 424 // TODO(danakj): Find a rect interior to each transformed quad. | 420 // TODO(danakj): Find a rect interior to each transformed quad. |
| 425 if (!layer->draw_transform().Preserves2dAxisAlignment()) | 421 if (!layer->draw_transform().Preserves2dAxisAlignment()) |
| 426 return; | 422 return; |
| 427 | 423 |
| 428 gfx::Rect clip_rect_in_target = ScreenSpaceClipRectInTargetSurface( | 424 gfx::Rect clip_rect_in_target = ScreenSpaceClipRectInTargetSurface( |
| 429 layer->render_target()->render_surface(), screen_space_clip_rect_); | 425 layer->render_target()->render_surface(), screen_space_clip_rect_); |
| 430 if (layer->is_clipped()) { | 426 if (layer->is_clipped()) { |
| 431 clip_rect_in_target.Intersect(layer->clip_rect()); | 427 clip_rect_in_target.Intersect(layer->clip_rect()); |
| 432 } else { | 428 } else { |
| 433 clip_rect_in_target.Intersect( | 429 clip_rect_in_target.Intersect( |
| 434 layer->render_target()->render_surface()->content_rect()); | 430 layer->render_target()->render_surface()->content_rect()); |
| 435 } | 431 } |
| 436 | 432 |
| 437 for (Region::Iterator opaque_content_rects(opaque_contents); | 433 for (size_t i = 0; i < opaque_contents.GetRegionComplexity(); ++i) { |
| 438 opaque_content_rects.has_rect(); | |
| 439 opaque_content_rects.next()) { | |
| 440 bool clipped; | 434 bool clipped; |
| 441 gfx::QuadF transformed_quad = MathUtil::MapQuad( | 435 gfx::QuadF transformed_quad = |
| 442 layer->draw_transform(), | 436 MathUtil::MapQuad(layer->draw_transform(), |
| 443 gfx::QuadF(opaque_content_rects.rect()), | 437 gfx::QuadF(opaque_contents.GetRect(i)), |
| 444 &clipped); | 438 &clipped); |
| 445 gfx::Rect transformed_rect = | 439 gfx::Rect transformed_rect = |
| 446 gfx::ToEnclosedRect(transformed_quad.BoundingBox()); | 440 gfx::ToEnclosedRect(transformed_quad.BoundingBox()); |
| 447 DCHECK(!clipped); // We only map if the transform preserves axis alignment. | 441 DCHECK(!clipped); // We only map if the transform preserves axis alignment. |
| 448 transformed_rect.Intersect(clip_rect_in_target); | 442 transformed_rect.Intersect(clip_rect_in_target); |
| 449 if (transformed_rect.width() < minimum_tracking_size_.width() && | 443 if (transformed_rect.width() < minimum_tracking_size_.width() && |
| 450 transformed_rect.height() < minimum_tracking_size_.height()) | 444 transformed_rect.height() < minimum_tracking_size_.height()) |
| 451 continue; | 445 continue; |
| 452 stack_.back().occlusion_from_inside_target.Union(transformed_rect); | 446 stack_.back().occlusion_from_inside_target.Union(transformed_rect); |
| 453 | 447 |
| 454 if (!occluding_screen_space_rects_) | 448 if (!occluding_screen_space_rects_) |
| 455 continue; | 449 continue; |
| 456 | 450 |
| 457 // Save the occluding area in screen space for debug visualization. | 451 // Save the occluding area in screen space for debug visualization. |
| 458 gfx::QuadF screen_space_quad = MathUtil::MapQuad( | 452 gfx::QuadF screen_space_quad = MathUtil::MapQuad( |
| 459 layer->render_target()->render_surface()->screen_space_transform(), | 453 layer->render_target()->render_surface()->screen_space_transform(), |
| 460 gfx::QuadF(transformed_rect), &clipped); | 454 gfx::QuadF(transformed_rect), &clipped); |
| 461 // TODO(danakj): Store the quad in the debug info instead of the bounding | 455 // TODO(danakj): Store the quad in the debug info instead of the bounding |
| 462 // box. | 456 // box. |
| 463 gfx::Rect screen_space_rect = | 457 gfx::Rect screen_space_rect = |
| 464 gfx::ToEnclosedRect(screen_space_quad.BoundingBox()); | 458 gfx::ToEnclosedRect(screen_space_quad.BoundingBox()); |
| 465 occluding_screen_space_rects_->push_back(screen_space_rect); | 459 occluding_screen_space_rects_->push_back(screen_space_rect); |
| 466 } | 460 } |
| 467 | 461 |
| 468 if (!non_occluding_screen_space_rects_) | 462 if (!non_occluding_screen_space_rects_) |
| 469 return; | 463 return; |
| 470 | 464 |
| 471 Region non_opaque_contents = | 465 Region non_opaque_contents(gfx::Rect(layer->content_bounds())); |
| 472 SubtractRegions(gfx::Rect(layer->content_bounds()), opaque_contents); | 466 non_opaque_contents.Subtract(opaque_contents); |
| 467 |
| 473 for (Region::Iterator non_opaque_content_rects(non_opaque_contents); | 468 for (Region::Iterator non_opaque_content_rects(non_opaque_contents); |
| 474 non_opaque_content_rects.has_rect(); | 469 non_opaque_content_rects.has_rect(); |
| 475 non_opaque_content_rects.next()) { | 470 non_opaque_content_rects.next()) { |
| 476 // We've already checked for clipping in the MapQuad call above, these calls | 471 // We've already checked for clipping in the MapQuad call above, these calls |
| 477 // should not clip anything further. | 472 // should not clip anything further. |
| 478 gfx::Rect transformed_rect = gfx::ToEnclosedRect( | 473 gfx::Rect transformed_rect = gfx::ToEnclosedRect( |
| 479 MathUtil::MapClippedRect(layer->draw_transform(), | 474 MathUtil::MapClippedRect(layer->draw_transform(), |
| 480 gfx::RectF(non_opaque_content_rects.rect()))); | 475 gfx::RectF(non_opaque_content_rects.rect()))); |
| 481 transformed_rect.Intersect(clip_rect_in_target); | 476 transformed_rect.Intersect(clip_rect_in_target); |
| 482 if (transformed_rect.IsEmpty()) | 477 if (transformed_rect.IsEmpty()) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 507 return true; | 502 return true; |
| 508 | 503 |
| 509 // For tests with no render target. | 504 // For tests with no render target. |
| 510 if (!render_target) | 505 if (!render_target) |
| 511 return false; | 506 return false; |
| 512 | 507 |
| 513 DCHECK_EQ(render_target->render_target(), render_target); | 508 DCHECK_EQ(render_target->render_target(), render_target); |
| 514 DCHECK(render_target->render_surface()); | 509 DCHECK(render_target->render_surface()); |
| 515 DCHECK_EQ(render_target, stack_.back().target); | 510 DCHECK_EQ(render_target, stack_.back().target); |
| 516 | 511 |
| 517 if (stack_.back().occlusion_from_inside_target.IsEmpty() && | 512 const StackObject& back = stack_.back(); |
| 518 stack_.back().occlusion_from_outside_target.IsEmpty()) { | 513 if (back.occlusion_from_inside_target.IsEmpty() && |
| 514 back.occlusion_from_outside_target.IsEmpty()) { |
| 519 return false; | 515 return false; |
| 520 } | 516 } |
| 521 | 517 |
| 522 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); | 518 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); |
| 523 if (!draw_transform.GetInverse(&inverse_draw_transform)) | 519 if (!draw_transform.GetInverse(&inverse_draw_transform)) |
| 524 return false; | 520 return false; |
| 525 | 521 |
| 526 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded | 522 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded |
| 527 // partial pixels in the resulting Rect. | 523 // partial pixels in the resulting Rect. |
| 528 Region unoccluded_region_in_target_surface = | 524 gfx::Rect unoccluded_rect_in_target_surface = |
| 529 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); | 525 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); |
| 530 unoccluded_region_in_target_surface.Subtract( | 526 DCHECK_LE(back.occlusion_from_inside_target.GetRegionComplexity(), 1u); |
| 531 stack_.back().occlusion_from_inside_target); | 527 DCHECK_LE(back.occlusion_from_outside_target.GetRegionComplexity(), 1u); |
| 532 gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion = | 528 // These subtract operations are more lossy than if we did both operations at |
| 533 unoccluded_region_in_target_surface.bounds(); | 529 // once. |
| 534 unoccluded_region_in_target_surface.Subtract( | 530 unoccluded_rect_in_target_surface.Subtract( |
| 535 stack_.back().occlusion_from_outside_target); | 531 stack_.back().occlusion_from_inside_target.bounds()); |
| 536 | 532 unoccluded_rect_in_target_surface.Subtract( |
| 537 gfx::RectF unoccluded_rect_in_target_surface = | 533 stack_.back().occlusion_from_outside_target.bounds()); |
| 538 unoccluded_region_in_target_surface.bounds(); | |
| 539 | 534 |
| 540 return unoccluded_rect_in_target_surface.IsEmpty(); | 535 return unoccluded_rect_in_target_surface.IsEmpty(); |
| 541 } | 536 } |
| 542 | 537 |
| 543 template <typename LayerType> | 538 template <typename LayerType> |
| 544 gfx::Rect OcclusionTracker<LayerType>::UnoccludedContentRect( | 539 gfx::Rect OcclusionTracker<LayerType>::UnoccludedContentRect( |
| 545 const gfx::Rect& content_rect, | 540 const gfx::Rect& content_rect, |
| 546 const gfx::Transform& draw_transform) const { | 541 const gfx::Transform& draw_transform) const { |
| 547 if (stack_.empty()) | 542 DCHECK(!stack_.empty()); |
| 548 return content_rect; | |
| 549 if (content_rect.IsEmpty()) | 543 if (content_rect.IsEmpty()) |
| 550 return content_rect; | 544 return content_rect; |
| 551 | 545 |
| 552 if (stack_.back().occlusion_from_inside_target.IsEmpty() && | 546 const StackObject& back = stack_.back(); |
| 553 stack_.back().occlusion_from_outside_target.IsEmpty()) { | 547 if (back.occlusion_from_inside_target.IsEmpty() && |
| 548 back.occlusion_from_outside_target.IsEmpty()) { |
| 554 return content_rect; | 549 return content_rect; |
| 555 } | 550 } |
| 556 | 551 |
| 557 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); | 552 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); |
| 558 if (!draw_transform.GetInverse(&inverse_draw_transform)) | 553 if (!draw_transform.GetInverse(&inverse_draw_transform)) |
| 559 return content_rect; | 554 return content_rect; |
| 560 | 555 |
| 561 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded | 556 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded |
| 562 // partial pixels in the resulting Rect. | 557 // partial pixels in the resulting Rect. |
| 563 Region unoccluded_region_in_target_surface = | 558 gfx::Rect unoccluded_rect_in_target_surface = |
| 564 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); | 559 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); |
| 565 unoccluded_region_in_target_surface.Subtract( | 560 DCHECK_LE(back.occlusion_from_inside_target.GetRegionComplexity(), 1u); |
| 566 stack_.back().occlusion_from_inside_target); | 561 DCHECK_LE(back.occlusion_from_outside_target.GetRegionComplexity(), 1u); |
| 567 unoccluded_region_in_target_surface.Subtract( | 562 // These subtract operations are more lossy than if we did both operations at |
| 568 stack_.back().occlusion_from_outside_target); | 563 // once. |
| 564 unoccluded_rect_in_target_surface.Subtract( |
| 565 back.occlusion_from_inside_target.bounds()); |
| 566 unoccluded_rect_in_target_surface.Subtract( |
| 567 back.occlusion_from_outside_target.bounds()); |
| 569 | 568 |
| 570 if (unoccluded_region_in_target_surface.IsEmpty()) | 569 if (unoccluded_rect_in_target_surface.IsEmpty()) |
| 571 return gfx::Rect(); | 570 return gfx::Rect(); |
| 572 | 571 |
| 573 gfx::Rect unoccluded_rect_in_target_surface = | |
| 574 unoccluded_region_in_target_surface.bounds(); | |
| 575 gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( | 572 gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( |
| 576 inverse_draw_transform, unoccluded_rect_in_target_surface); | 573 inverse_draw_transform, unoccluded_rect_in_target_surface); |
| 577 unoccluded_rect.Intersect(content_rect); | 574 unoccluded_rect.Intersect(content_rect); |
| 578 | 575 |
| 579 return unoccluded_rect; | 576 return unoccluded_rect; |
| 580 } | 577 } |
| 581 | 578 |
| 582 template <typename LayerType> | 579 template <typename LayerType> |
| 583 gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect( | 580 gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect( |
| 584 const gfx::Rect& content_rect, | 581 const gfx::Rect& content_rect, |
| 585 const gfx::Transform& draw_transform) const { | 582 const gfx::Transform& draw_transform) const { |
| 586 if (content_rect.IsEmpty()) | 583 if (content_rect.IsEmpty()) |
| 587 return content_rect; | 584 return content_rect; |
| 588 | 585 |
| 589 // A contributing surface doesn't get occluded by things inside its own | 586 // A contributing surface doesn't get occluded by things inside its own |
| 590 // surface, so only things outside the surface can occlude it. That occlusion | 587 // surface, so only things outside the surface can occlude it. That occlusion |
| 591 // is found just below the top of the stack (if it exists). | 588 // is found just below the top of the stack (if it exists). |
| 592 bool has_occlusion = stack_.size() > 1; | 589 bool has_occlusion = stack_.size() > 1; |
| 593 if (!has_occlusion) | 590 if (!has_occlusion) |
| 594 return content_rect; | 591 return content_rect; |
| 595 | 592 |
| 596 const StackObject& second_last = stack_[stack_.size() - 2]; | 593 const StackObject& second_last = stack_[stack_.size() - 2]; |
| 597 | |
| 598 if (second_last.occlusion_from_inside_target.IsEmpty() && | 594 if (second_last.occlusion_from_inside_target.IsEmpty() && |
| 599 second_last.occlusion_from_outside_target.IsEmpty()) | 595 second_last.occlusion_from_outside_target.IsEmpty()) |
| 600 return content_rect; | 596 return content_rect; |
| 601 | 597 |
| 602 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); | 598 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); |
| 603 if (!draw_transform.GetInverse(&inverse_draw_transform)) | 599 if (!draw_transform.GetInverse(&inverse_draw_transform)) |
| 604 return content_rect; | 600 return content_rect; |
| 605 | 601 |
| 606 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded | 602 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded |
| 607 // partial pixels in the resulting Rect. | 603 // partial pixels in the resulting Rect. |
| 608 Region unoccluded_region_in_target_surface = | 604 gfx::Rect unoccluded_rect_in_target_surface = |
| 609 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); | 605 MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); |
| 610 unoccluded_region_in_target_surface.Subtract( | 606 DCHECK_LE(second_last.occlusion_from_inside_target.GetRegionComplexity(), 1u); |
| 611 second_last.occlusion_from_inside_target); | 607 DCHECK_LE(second_last.occlusion_from_outside_target.GetRegionComplexity(), |
| 612 unoccluded_region_in_target_surface.Subtract( | 608 1u); |
| 613 second_last.occlusion_from_outside_target); | 609 // These subtract operations are more lossy than if we did both operations at |
| 610 // once. |
| 611 unoccluded_rect_in_target_surface.Subtract( |
| 612 second_last.occlusion_from_inside_target.bounds()); |
| 613 unoccluded_rect_in_target_surface.Subtract( |
| 614 second_last.occlusion_from_outside_target.bounds()); |
| 614 | 615 |
| 615 if (unoccluded_region_in_target_surface.IsEmpty()) | 616 if (unoccluded_rect_in_target_surface.IsEmpty()) |
| 616 return gfx::Rect(); | 617 return gfx::Rect(); |
| 617 | 618 |
| 618 gfx::Rect unoccluded_rect_in_target_surface = | |
| 619 unoccluded_region_in_target_surface.bounds(); | |
| 620 gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( | 619 gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( |
| 621 inverse_draw_transform, unoccluded_rect_in_target_surface); | 620 inverse_draw_transform, unoccluded_rect_in_target_surface); |
| 622 unoccluded_rect.Intersect(content_rect); | 621 unoccluded_rect.Intersect(content_rect); |
| 623 | 622 |
| 624 return unoccluded_rect; | 623 return unoccluded_rect; |
| 625 } | 624 } |
| 626 | 625 |
| 626 template <typename LayerType> |
| 627 Region OcclusionTracker<LayerType>::ComputeVisibleRegionInScreen() const { |
| 628 DCHECK(!stack_.back().target->parent()); |
| 629 const SimpleEnclosedRegion& occluded = |
| 630 stack_.back().occlusion_from_inside_target; |
| 631 Region visible_region(screen_space_clip_rect_); |
| 632 for (size_t i = 0; i < occluded.GetRegionComplexity(); ++i) |
| 633 visible_region.Subtract(occluded.GetRect(i)); |
| 634 return visible_region; |
| 635 } |
| 636 |
| 627 // Instantiate (and export) templates here for the linker. | 637 // Instantiate (and export) templates here for the linker. |
| 628 template class OcclusionTracker<Layer>; | 638 template class OcclusionTracker<Layer>; |
| 629 template class OcclusionTracker<LayerImpl>; | 639 template class OcclusionTracker<LayerImpl>; |
| 630 | 640 |
| 631 } // namespace cc | 641 } // namespace cc |
| OLD | NEW |