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 |