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