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

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 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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698