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 |