Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Side by Side Diff: cc/trees/occlusion_tracker.cc

Issue 202523002: cc: Replace Region with SimpleEnclosedRegion for occlusion tracking (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: simpleregion: . Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698