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

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

Issue 23708021: Do not clip inside OcclusionTracker. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added DCHECK Created 7 years, 3 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/debug/overdraw_metrics.h" 10 #include "cc/debug/overdraw_metrics.h"
11 #include "cc/layers/layer.h" 11 #include "cc/layers/layer.h"
12 #include "cc/layers/layer_impl.h" 12 #include "cc/layers/layer_impl.h"
13 #include "cc/layers/render_surface.h" 13 #include "cc/layers/render_surface.h"
14 #include "cc/layers/render_surface_impl.h" 14 #include "cc/layers/render_surface_impl.h"
15 #include "ui/gfx/quad_f.h" 15 #include "ui/gfx/quad_f.h"
16 #include "ui/gfx/rect_conversions.h" 16 #include "ui/gfx/rect_conversions.h"
17 17
18 namespace cc { 18 namespace cc {
19 19
20 template <typename LayerType, typename RenderSurfaceType> 20 template <typename LayerType, typename RenderSurfaceType>
21 OcclusionTrackerBase<LayerType, RenderSurfaceType>::OcclusionTrackerBase( 21 OcclusionTrackerBase<LayerType, RenderSurfaceType>::OcclusionTrackerBase(
22 gfx::Rect screen_space_clip_rect, bool record_metrics_for_frame) 22 bool record_metrics_for_frame)
23 : screen_space_clip_rect_(screen_space_clip_rect), 23 : overdraw_metrics_(OverdrawMetrics::Create(record_metrics_for_frame)),
24 overdraw_metrics_(OverdrawMetrics::Create(record_metrics_for_frame)),
25 prevent_occlusion_(false), 24 prevent_occlusion_(false),
26 occluding_screen_space_rects_(NULL), 25 occluding_screen_space_rects_(NULL),
27 non_occluding_screen_space_rects_(NULL) {} 26 non_occluding_screen_space_rects_(NULL) {}
28 27
29 template <typename LayerType, typename RenderSurfaceType> 28 template <typename LayerType, typename RenderSurfaceType>
30 OcclusionTrackerBase<LayerType, RenderSurfaceType>::~OcclusionTrackerBase() {} 29 OcclusionTrackerBase<LayerType, RenderSurfaceType>::~OcclusionTrackerBase() {}
31 30
32 template <typename LayerType, typename RenderSurfaceType> 31 template <typename LayerType, typename RenderSurfaceType>
33 void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterLayer( 32 void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterLayer(
34 const LayerIteratorPosition<LayerType>& layer_iterator, 33 const LayerIteratorPosition<LayerType>& layer_iterator,
(...skipping 17 matching lines...) Expand all
52 MarkOccludedBehindLayer(layer_iterator.current_layer); 51 MarkOccludedBehindLayer(layer_iterator.current_layer);
53 // TODO(danakj): This should be done when entering the contributing surface, 52 // TODO(danakj): This should be done when entering the contributing surface,
54 // but in a way that the surface's own occlusion won't occlude itself. 53 // but in a way that the surface's own occlusion won't occlude itself.
55 else if (layer_iterator.represents_contributing_render_surface) 54 else if (layer_iterator.represents_contributing_render_surface)
56 LeaveToRenderTarget(render_target); 55 LeaveToRenderTarget(render_target);
57 56
58 prevent_occlusion_ = false; 57 prevent_occlusion_ = false;
59 } 58 }
60 59
61 template <typename RenderSurfaceType> 60 template <typename RenderSurfaceType>
62 static gfx::Rect ScreenSpaceClipRectInTargetSurface(
63 const RenderSurfaceType* target_surface, gfx::Rect screen_space_clip_rect) {
64 gfx::Transform inverse_screen_space_transform(
65 gfx::Transform::kSkipInitialization);
66 if (!target_surface->screen_space_transform().GetInverse(
67 &inverse_screen_space_transform))
68 return target_surface->content_rect();
69
70 return gfx::ToEnclosingRect(MathUtil::ProjectClippedRect(
71 inverse_screen_space_transform, screen_space_clip_rect));
72 }
73
74 template <typename RenderSurfaceType>
75 static Region TransformSurfaceOpaqueRegion(const Region& region, 61 static Region TransformSurfaceOpaqueRegion(const Region& region,
76 bool have_clip_rect,
77 gfx::Rect clip_rect_in_new_target,
78 const gfx::Transform& transform) { 62 const gfx::Transform& transform) {
79 if (region.IsEmpty()) 63 if (region.IsEmpty())
80 return Region(); 64 return Region();
81 65
82 // Verify that rects within the |surface| will remain rects in its target 66 // Verify that rects within the |surface| will remain rects in its target
83 // surface after applying |transform|. If this is true, then apply |transform| 67 // surface after applying |transform|. If this is true, then apply |transform|
84 // to each rect within |region| in order to transform the entire Region. 68 // to each rect within |region| in order to transform the entire Region.
85 69
86 // TODO(danakj): Find a rect interior to each transformed quad. 70 // TODO(danakj): Find a rect interior to each transformed quad.
87 if (!transform.Preserves2dAxisAlignment()) 71 if (!transform.Preserves2dAxisAlignment())
88 return Region(); 72 return Region();
89 73
90 // TODO(danakj): If the Region is too complex, degrade gracefully here by 74 // TODO(danakj): If the Region is too complex, degrade gracefully here by
91 // skipping rects in it. 75 // skipping rects in it.
92 Region transformed_region; 76 Region transformed_region;
93 for (Region::Iterator rects(region); rects.has_rect(); rects.next()) { 77 for (Region::Iterator rects(region); rects.has_rect(); rects.next()) {
94 bool clipped; 78 bool clipped;
95 gfx::QuadF transformed_quad = 79 gfx::QuadF transformed_quad =
96 MathUtil::MapQuad(transform, gfx::QuadF(rects.rect()), &clipped); 80 MathUtil::MapQuad(transform, gfx::QuadF(rects.rect()), &clipped);
97 gfx::Rect transformed_rect = 81 gfx::Rect transformed_rect =
98 gfx::ToEnclosedRect(transformed_quad.BoundingBox()); 82 gfx::ToEnclosedRect(transformed_quad.BoundingBox());
99 DCHECK(!clipped); // We only map if the transform preserves axis alignment. 83 DCHECK(!clipped); // We only map if the transform preserves axis alignment.
100 if (have_clip_rect)
danakj 2013/09/16 17:29:08 I don't really understand this change. It's just a
101 transformed_rect.Intersect(clip_rect_in_new_target);
102 transformed_region.Union(transformed_rect); 84 transformed_region.Union(transformed_rect);
103 } 85 }
104 return transformed_region; 86 return transformed_region;
105 } 87 }
106 88
107 static inline bool LayerOpacityKnown(const Layer* layer) { 89 static inline bool LayerOpacityKnown(const Layer* layer) {
108 return !layer->draw_opacity_is_animating(); 90 return !layer->draw_opacity_is_animating();
109 } 91 }
110 static inline bool LayerOpacityKnown(const LayerImpl* layer) { 92 static inline bool LayerOpacityKnown(const LayerImpl* layer) {
111 return true; 93 return true;
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 if (!copy_outside_occlusion_forward) 182 if (!copy_outside_occlusion_forward)
201 return; 183 return;
202 184
203 int last_index = stack_.size() - 1; 185 int last_index = stack_.size() - 1;
204 gfx::Transform old_target_to_new_target_transform( 186 gfx::Transform old_target_to_new_target_transform(
205 inverse_new_target_screen_space_transform, 187 inverse_new_target_screen_space_transform,
206 old_target->render_surface()->screen_space_transform()); 188 old_target->render_surface()->screen_space_transform());
207 stack_[last_index].occlusion_from_outside_target = 189 stack_[last_index].occlusion_from_outside_target =
208 TransformSurfaceOpaqueRegion<RenderSurfaceType>( 190 TransformSurfaceOpaqueRegion<RenderSurfaceType>(
209 stack_[last_index - 1].occlusion_from_outside_target, 191 stack_[last_index - 1].occlusion_from_outside_target,
210 false,
211 gfx::Rect(),
212 old_target_to_new_target_transform); 192 old_target_to_new_target_transform);
213 stack_[last_index].occlusion_from_outside_target.Union( 193 stack_[last_index].occlusion_from_outside_target.Union(
214 TransformSurfaceOpaqueRegion<RenderSurfaceType>( 194 TransformSurfaceOpaqueRegion<RenderSurfaceType>(
215 stack_[last_index - 1].occlusion_from_inside_target, 195 stack_[last_index - 1].occlusion_from_inside_target,
216 false,
217 gfx::Rect(),
218 old_target_to_new_target_transform)); 196 old_target_to_new_target_transform));
219 } 197 }
220 198
221 template <typename LayerType, typename RenderSurfaceType> 199 template <typename LayerType, typename RenderSurfaceType>
222 void OcclusionTrackerBase<LayerType, RenderSurfaceType>::FinishedRenderTarget( 200 void OcclusionTrackerBase<LayerType, RenderSurfaceType>::FinishedRenderTarget(
223 const LayerType* finished_target) { 201 const LayerType* finished_target) {
224 // Make sure we know about the target surface. 202 // Make sure we know about the target surface.
225 EnterRenderTarget(finished_target); 203 EnterRenderTarget(finished_target);
226 204
227 RenderSurfaceType* surface = finished_target->render_surface(); 205 RenderSurfaceType* surface = finished_target->render_surface();
(...skipping 25 matching lines...) Expand all
253 static void ReduceOcclusionBelowSurface(LayerType* contributing_layer, 231 static void ReduceOcclusionBelowSurface(LayerType* contributing_layer,
254 gfx::Rect surface_rect, 232 gfx::Rect surface_rect,
255 const gfx::Transform& surface_transform, 233 const gfx::Transform& surface_transform,
256 LayerType* render_target, 234 LayerType* render_target,
257 Region* occlusion_from_inside_target) { 235 Region* occlusion_from_inside_target) {
258 if (surface_rect.IsEmpty()) 236 if (surface_rect.IsEmpty())
259 return; 237 return;
260 238
261 gfx::Rect affected_area_in_target = gfx::ToEnclosingRect( 239 gfx::Rect affected_area_in_target = gfx::ToEnclosingRect(
262 MathUtil::MapClippedRect(surface_transform, gfx::RectF(surface_rect))); 240 MathUtil::MapClippedRect(surface_transform, gfx::RectF(surface_rect)));
263 if (contributing_layer->render_surface()->is_clipped()) {
264 affected_area_in_target.Intersect(
danakj 2013/09/16 17:29:08 Again, just an intersection. I think there's two w
alokp 2013/09/17 00:31:41 I have decided to break this into two patches - on
265 contributing_layer->render_surface()->clip_rect());
266 }
267 if (affected_area_in_target.IsEmpty())
268 return;
269 241
270 int outset_top, outset_right, outset_bottom, outset_left; 242 int outset_top, outset_right, outset_bottom, outset_left;
271 contributing_layer->background_filters().GetOutsets( 243 contributing_layer->background_filters().GetOutsets(
272 &outset_top, &outset_right, &outset_bottom, &outset_left); 244 &outset_top, &outset_right, &outset_bottom, &outset_left);
273 245
274 // The filter can move pixels from outside of the clip, so allow affected_area 246 // The filter can move pixels from outside of the clip, so allow affected_area
275 // to expand outside the clip. 247 // to expand outside the clip.
276 affected_area_in_target.Inset( 248 affected_area_in_target.Inset(
277 -outset_left, -outset_top, -outset_right, -outset_bottom); 249 -outset_left, -outset_top, -outset_right, -outset_bottom);
278 250
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 // We merge the screen occlusion from the current RenderSurfaceImpl subtree 292 // We merge the screen occlusion from the current RenderSurfaceImpl subtree
321 // out to its parent target RenderSurfaceImpl. The target occlusion can be 293 // out to its parent target RenderSurfaceImpl. The target occlusion can be
322 // merged out as well but needs to be transformed to the new target. 294 // merged out as well but needs to be transformed to the new target.
323 295
324 const LayerType* old_target = stack_[last_index].target; 296 const LayerType* old_target = stack_[last_index].target;
325 const RenderSurfaceType* old_surface = old_target->render_surface(); 297 const RenderSurfaceType* old_surface = old_target->render_surface();
326 298
327 Region old_occlusion_from_inside_target_in_new_target = 299 Region old_occlusion_from_inside_target_in_new_target =
328 TransformSurfaceOpaqueRegion<RenderSurfaceType>( 300 TransformSurfaceOpaqueRegion<RenderSurfaceType>(
329 stack_[last_index].occlusion_from_inside_target, 301 stack_[last_index].occlusion_from_inside_target,
330 old_surface->is_clipped(),
331 old_surface->clip_rect(),
332 old_surface->draw_transform()); 302 old_surface->draw_transform());
333 if (old_target->has_replica() && !old_target->replica_has_mask()) { 303 if (old_target->has_replica() && !old_target->replica_has_mask()) {
334 old_occlusion_from_inside_target_in_new_target.Union( 304 old_occlusion_from_inside_target_in_new_target.Union(
335 TransformSurfaceOpaqueRegion<RenderSurfaceType>( 305 TransformSurfaceOpaqueRegion<RenderSurfaceType>(
336 stack_[last_index].occlusion_from_inside_target, 306 stack_[last_index].occlusion_from_inside_target,
337 old_surface->is_clipped(),
338 old_surface->clip_rect(),
339 old_surface->replica_draw_transform())); 307 old_surface->replica_draw_transform()));
340 } 308 }
309 // Verify that the occluded region is contained inside the
310 // target surface clip-rect.
311 DCHECK(!old_surface->is_clipped() ||
312 old_surface->clip_rect().Contains(
313 old_occlusion_from_inside_target_in_new_target.bounds()));
341 314
342 Region old_occlusion_from_outside_target_in_new_target = 315 Region old_occlusion_from_outside_target_in_new_target =
343 TransformSurfaceOpaqueRegion<RenderSurfaceType>( 316 TransformSurfaceOpaqueRegion<RenderSurfaceType>(
344 stack_[last_index].occlusion_from_outside_target, 317 stack_[last_index].occlusion_from_outside_target,
345 false,
346 gfx::Rect(),
347 old_surface->draw_transform()); 318 old_surface->draw_transform());
348 319
349 gfx::Rect unoccluded_surface_rect; 320 gfx::Rect unoccluded_surface_rect;
350 gfx::Rect unoccluded_replica_rect; 321 gfx::Rect unoccluded_replica_rect;
351 if (old_target->background_filters().HasFilterThatMovesPixels()) { 322 if (old_target->background_filters().HasFilterThatMovesPixels()) {
352 unoccluded_surface_rect = UnoccludedContributingSurfaceContentRect( 323 unoccluded_surface_rect = UnoccludedContributingSurfaceContentRect(
353 old_target, false, old_surface->content_rect(), NULL); 324 old_target, false, old_surface->content_rect(), NULL);
354 if (old_target->has_replica()) { 325 if (old_target->has_replica()) {
355 unoccluded_replica_rect = UnoccludedContributingSurfaceContentRect( 326 unoccluded_replica_rect = UnoccludedContributingSurfaceContentRect(
356 old_target, true, old_surface->content_rect(), NULL); 327 old_target, true, old_surface->content_rect(), NULL);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 396
426 if (!LayerTransformsToTargetKnown(layer)) 397 if (!LayerTransformsToTargetKnown(layer))
427 return; 398 return;
428 399
429 Region opaque_contents = layer->VisibleContentOpaqueRegion(); 400 Region opaque_contents = layer->VisibleContentOpaqueRegion();
430 if (opaque_contents.IsEmpty()) 401 if (opaque_contents.IsEmpty())
431 return; 402 return;
432 403
433 DCHECK(layer->visible_content_rect().Contains(opaque_contents.bounds())); 404 DCHECK(layer->visible_content_rect().Contains(opaque_contents.bounds()));
434 405
435 // TODO(danakj): Find a rect interior to each transformed quad. 406 // TODO(danakj): Find a rect interior to each transformed quad.
danakj 2013/09/16 17:29:08 Remove this TODO and mention we don't support non-
436 if (!layer->draw_transform().Preserves2dAxisAlignment()) 407 if (!layer->draw_transform().Preserves2dAxisAlignment())
437 return; 408 return;
438 409
439 gfx::Rect clip_rect_in_target = ScreenSpaceClipRectInTargetSurface(
440 layer->render_target()->render_surface(), screen_space_clip_rect_);
441 if (layer->is_clipped()) {
442 clip_rect_in_target.Intersect(layer->clip_rect());
443 } else {
444 clip_rect_in_target.Intersect(
445 layer->render_target()->render_surface()->content_rect());
446 }
447
448 for (Region::Iterator opaque_content_rects(opaque_contents); 410 for (Region::Iterator opaque_content_rects(opaque_contents);
449 opaque_content_rects.has_rect(); 411 opaque_content_rects.has_rect();
450 opaque_content_rects.next()) { 412 opaque_content_rects.next()) {
451 bool clipped; 413 bool clipped;
452 gfx::QuadF transformed_quad = MathUtil::MapQuad( 414 gfx::QuadF transformed_quad = MathUtil::MapQuad(
453 layer->draw_transform(), 415 layer->draw_transform(),
454 gfx::QuadF(opaque_content_rects.rect()), 416 gfx::QuadF(opaque_content_rects.rect()),
455 &clipped); 417 &clipped);
456 gfx::Rect transformed_rect = 418 gfx::Rect transformed_rect =
457 gfx::ToEnclosedRect(transformed_quad.BoundingBox()); 419 gfx::ToEnclosedRect(transformed_quad.BoundingBox());
458 DCHECK(!clipped); // We only map if the transform preserves axis alignment. 420 DCHECK(!clipped); // We only map if the transform preserves axis alignment.
459 transformed_rect.Intersect(clip_rect_in_target); 421 #ifndef NDEBUG
danakj 2013/09/16 17:29:08 if (DCHECK_IS_ON()) {
422 // Verify that the occluded region is contained inside the target surface
423 // clip-rect or bounds. We do not do any clipping here in occlusion tracker.
424 // We assume that visible-content-rect has already been clipped during
425 // CalculateDrawProperties.
426 gfx::Rect clip_rect_in_target = layer->is_clipped() ?
427 layer->clip_rect() :
428 layer->render_target()->render_surface()->content_rect();
429 DCHECK(clip_rect_in_target.Contains(transformed_rect));
danakj 2013/09/16 17:29:08 Note that this DCHECK is verifying the clip rect i
430 #endif // NDEBUG
460 if (transformed_rect.width() < minimum_tracking_size_.width() && 431 if (transformed_rect.width() < minimum_tracking_size_.width() &&
461 transformed_rect.height() < minimum_tracking_size_.height()) 432 transformed_rect.height() < minimum_tracking_size_.height())
462 continue; 433 continue;
463 stack_.back().occlusion_from_inside_target.Union(transformed_rect); 434 stack_.back().occlusion_from_inside_target.Union(transformed_rect);
464 435
465 if (!occluding_screen_space_rects_) 436 if (!occluding_screen_space_rects_)
466 continue; 437 continue;
467 438
468 // Save the occluding area in screen space for debug visualization. 439 // Save the occluding area in screen space for debug visualization.
469 gfx::QuadF screen_space_quad = MathUtil::MapQuad( 440 gfx::QuadF screen_space_quad = MathUtil::MapQuad(
470 layer->render_target()->render_surface()->screen_space_transform(), 441 layer->render_target()->render_surface()->screen_space_transform(),
471 gfx::QuadF(transformed_rect), &clipped); 442 gfx::QuadF(transformed_rect), &clipped);
472 // TODO(danakj): Store the quad in the debug info instead of the bounding 443 // TODO(danakj): Store the quad in the debug info instead of the bounding
473 // box. 444 // box.
474 gfx::Rect screen_space_rect = 445 gfx::Rect screen_space_rect =
475 gfx::ToEnclosedRect(screen_space_quad.BoundingBox()); 446 gfx::ToEnclosedRect(screen_space_quad.BoundingBox());
476 occluding_screen_space_rects_->push_back(screen_space_rect); 447 occluding_screen_space_rects_->push_back(screen_space_rect);
477 } 448 }
478 449
450
danakj 2013/09/16 17:29:08 extra whitespace
alokp 2013/09/17 00:31:41 Done.
479 if (!non_occluding_screen_space_rects_) 451 if (!non_occluding_screen_space_rects_)
480 return; 452 return;
481 453
482 Region non_opaque_contents = 454 Region non_opaque_contents =
483 SubtractRegions(gfx::Rect(layer->content_bounds()), opaque_contents); 455 SubtractRegions(gfx::Rect(layer->content_bounds()), opaque_contents);
484 for (Region::Iterator non_opaque_content_rects(non_opaque_contents); 456 for (Region::Iterator non_opaque_content_rects(non_opaque_contents);
485 non_opaque_content_rects.has_rect(); 457 non_opaque_content_rects.has_rect();
486 non_opaque_content_rects.next()) { 458 non_opaque_content_rects.next()) {
487 // We've already checked for clipping in the MapQuad call above, these calls 459 // We've already checked for clipping in the MapQuad call above, these calls
488 // should not clip anything further. 460 // should not clip anything further.
489 gfx::Rect transformed_rect = gfx::ToEnclosedRect( 461 gfx::Rect transformed_rect = gfx::ToEnclosedRect(
490 MathUtil::MapClippedRect(layer->draw_transform(), 462 MathUtil::MapClippedRect(layer->draw_transform(),
491 gfx::RectF(non_opaque_content_rects.rect()))); 463 gfx::RectF(non_opaque_content_rects.rect())));
492 transformed_rect.Intersect(clip_rect_in_target);
493 if (transformed_rect.IsEmpty()) 464 if (transformed_rect.IsEmpty())
494 continue; 465 continue;
495 466
496 bool clipped; 467 bool clipped;
497 gfx::QuadF screen_space_quad = MathUtil::MapQuad( 468 gfx::QuadF screen_space_quad = MathUtil::MapQuad(
498 layer->render_target()->render_surface()->screen_space_transform(), 469 layer->render_target()->render_surface()->screen_space_transform(),
499 gfx::QuadF(transformed_rect), 470 gfx::QuadF(transformed_rect),
500 &clipped); 471 &clipped);
501 // TODO(danakj): Store the quad in the debug info instead of the bounding 472 // TODO(danakj): Store the quad in the debug info instead of the bounding
502 // box. 473 // box.
503 gfx::Rect screen_space_rect = 474 gfx::Rect screen_space_rect =
504 gfx::ToEnclosedRect(screen_space_quad.BoundingBox()); 475 gfx::ToEnclosedRect(screen_space_quad.BoundingBox());
505 non_occluding_screen_space_rects_->push_back(screen_space_rect); 476 non_occluding_screen_space_rects_->push_back(screen_space_rect);
506 } 477 }
507 } 478 }
508 479
509 template <typename LayerType, typename RenderSurfaceType> 480 template <typename LayerType, typename RenderSurfaceType>
510 bool OcclusionTrackerBase<LayerType, RenderSurfaceType>::Occluded( 481 bool OcclusionTrackerBase<LayerType, RenderSurfaceType>::Occluded(
511 const LayerType* render_target, 482 const LayerType* render_target,
512 gfx::Rect content_rect, 483 gfx::Rect content_rect,
513 const gfx::Transform& draw_transform, 484 const gfx::Transform& draw_transform,
514 bool impl_draw_transform_is_unknown, 485 bool impl_draw_transform_is_unknown,
515 bool is_clipped,
516 gfx::Rect clip_rect_in_target,
517 bool* has_occlusion_from_outside_target_surface) const { 486 bool* has_occlusion_from_outside_target_surface) const {
518 if (has_occlusion_from_outside_target_surface) 487 if (has_occlusion_from_outside_target_surface)
519 *has_occlusion_from_outside_target_surface = false; 488 *has_occlusion_from_outside_target_surface = false;
520 if (prevent_occlusion_) 489 if (prevent_occlusion_)
521 return false; 490 return false;
522 491
523 DCHECK(!stack_.empty()); 492 DCHECK(!stack_.empty());
524 if (stack_.empty()) 493 if (stack_.empty())
525 return false; 494 return false;
526 if (content_rect.IsEmpty()) 495 if (content_rect.IsEmpty())
527 return true; 496 return true;
528 if (impl_draw_transform_is_unknown) 497 if (impl_draw_transform_is_unknown)
529 return false; 498 return false;
530 499
531 // For tests with no render target. 500 // For tests with no render target.
532 if (!render_target) 501 if (!render_target)
533 return false; 502 return false;
534 503
535 DCHECK_EQ(render_target->render_target(), render_target); 504 DCHECK_EQ(render_target->render_target(), render_target);
536 DCHECK(render_target->render_surface()); 505 DCHECK(render_target->render_surface());
537 DCHECK_EQ(render_target, stack_.back().target); 506 DCHECK_EQ(render_target, stack_.back().target);
538 507
508 if (stack_.back().occlusion_from_inside_target.IsEmpty() &&
509 stack_.back().occlusion_from_outside_target.IsEmpty()) {
510 return false;
511 }
512
539 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); 513 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
540 if (!draw_transform.GetInverse(&inverse_draw_transform)) 514 if (!draw_transform.GetInverse(&inverse_draw_transform))
541 return false; 515 return false;
542 516
543 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded 517 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded
544 // partial pixels in the resulting Rect. 518 // partial pixels in the resulting Rect.
545 Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect( 519 Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect(
546 MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect))); 520 MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect)));
547 // Layers can't clip across surfaces, so count this as internal occlusion.
548 if (is_clipped)
549 unoccluded_region_in_target_surface.Intersect(clip_rect_in_target);
danakj 2013/09/16 17:29:08 I think I buy that this can go away (and not move
550 unoccluded_region_in_target_surface.Subtract( 521 unoccluded_region_in_target_surface.Subtract(
551 stack_.back().occlusion_from_inside_target); 522 stack_.back().occlusion_from_inside_target);
552 gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion = 523 gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion =
553 unoccluded_region_in_target_surface.bounds(); 524 unoccluded_region_in_target_surface.bounds();
554 unoccluded_region_in_target_surface.Subtract( 525 unoccluded_region_in_target_surface.Subtract(
555 stack_.back().occlusion_from_outside_target); 526 stack_.back().occlusion_from_outside_target);
556 527
557 // Treat other clipping as occlusion from outside the surface.
danakj 2013/09/16 17:29:08 I'm not sure why you say that the has_occlusion_fr
alokp 2013/09/17 00:31:41 You are right. I do not see how I can preserve thi
558 // TODO(danakj): Clip to visibleContentRect?
559 unoccluded_region_in_target_surface.Intersect(
560 render_target->render_surface()->content_rect());
561 unoccluded_region_in_target_surface.Intersect(
562 ScreenSpaceClipRectInTargetSurface(render_target->render_surface(),
563 screen_space_clip_rect_));
564
565 gfx::RectF unoccluded_rect_in_target_surface = 528 gfx::RectF unoccluded_rect_in_target_surface =
566 unoccluded_region_in_target_surface.bounds(); 529 unoccluded_region_in_target_surface.bounds();
567 530
568 if (has_occlusion_from_outside_target_surface) { 531 if (has_occlusion_from_outside_target_surface) {
569 // Check if the unoccluded rect shrank when applying outside occlusion. 532 // Check if the unoccluded rect shrank when applying outside occlusion.
570 *has_occlusion_from_outside_target_surface = !gfx::SubtractRects( 533 *has_occlusion_from_outside_target_surface = !gfx::SubtractRects(
571 unoccluded_rect_in_target_surface_without_outside_occlusion, 534 unoccluded_rect_in_target_surface_without_outside_occlusion,
572 unoccluded_rect_in_target_surface).IsEmpty(); 535 unoccluded_rect_in_target_surface).IsEmpty();
573 } 536 }
574 537
575 return unoccluded_rect_in_target_surface.IsEmpty(); 538 return unoccluded_rect_in_target_surface.IsEmpty();
576 } 539 }
577 540
578 template <typename LayerType, typename RenderSurfaceType> 541 template <typename LayerType, typename RenderSurfaceType>
579 gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>:: 542 gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
580 UnoccludedContentRect( 543 UnoccludedContentRect(
581 const LayerType* render_target, 544 const LayerType* render_target,
582 gfx::Rect content_rect, 545 gfx::Rect content_rect,
583 const gfx::Transform& draw_transform, 546 const gfx::Transform& draw_transform,
584 bool impl_draw_transform_is_unknown, 547 bool impl_draw_transform_is_unknown,
585 bool is_clipped,
586 gfx::Rect clip_rect_in_target,
587 bool* has_occlusion_from_outside_target_surface) const { 548 bool* has_occlusion_from_outside_target_surface) const {
588 if (has_occlusion_from_outside_target_surface) 549 if (has_occlusion_from_outside_target_surface)
589 *has_occlusion_from_outside_target_surface = false; 550 *has_occlusion_from_outside_target_surface = false;
590 if (prevent_occlusion_) 551 if (prevent_occlusion_)
591 return content_rect; 552 return content_rect;
592 553
593 DCHECK(!stack_.empty()); 554 DCHECK(!stack_.empty());
594 if (stack_.empty()) 555 if (stack_.empty())
595 return content_rect; 556 return content_rect;
596 if (content_rect.IsEmpty()) 557 if (content_rect.IsEmpty())
597 return content_rect; 558 return content_rect;
598 if (impl_draw_transform_is_unknown) 559 if (impl_draw_transform_is_unknown)
599 return content_rect; 560 return content_rect;
600 561
601 // For tests with no render target. 562 // For tests with no render target.
602 if (!render_target) 563 if (!render_target)
603 return content_rect; 564 return content_rect;
604 565
605 DCHECK_EQ(render_target->render_target(), render_target); 566 DCHECK_EQ(render_target->render_target(), render_target);
606 DCHECK(render_target->render_surface()); 567 DCHECK(render_target->render_surface());
607 DCHECK_EQ(render_target, stack_.back().target); 568 DCHECK_EQ(render_target, stack_.back().target);
608 569
570 if (stack_.back().occlusion_from_inside_target.IsEmpty() &&
571 stack_.back().occlusion_from_outside_target.IsEmpty()) {
572 return content_rect;
573 }
574
609 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); 575 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
610 if (!draw_transform.GetInverse(&inverse_draw_transform)) 576 if (!draw_transform.GetInverse(&inverse_draw_transform))
611 return content_rect; 577 return content_rect;
612 578
613 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded 579 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded
614 // partial pixels in the resulting Rect. 580 // partial pixels in the resulting Rect.
615 Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect( 581 Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect(
616 MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect))); 582 MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect)));
617 // Layers can't clip across surfaces, so count this as internal occlusion.
618 if (is_clipped)
619 unoccluded_region_in_target_surface.Intersect(clip_rect_in_target);
620 unoccluded_region_in_target_surface.Subtract( 583 unoccluded_region_in_target_surface.Subtract(
621 stack_.back().occlusion_from_inside_target); 584 stack_.back().occlusion_from_inside_target);
622 gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion = 585 gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion =
623 unoccluded_region_in_target_surface.bounds(); 586 unoccluded_region_in_target_surface.bounds();
624 unoccluded_region_in_target_surface.Subtract( 587 unoccluded_region_in_target_surface.Subtract(
625 stack_.back().occlusion_from_outside_target); 588 stack_.back().occlusion_from_outside_target);
626 589
627 // Treat other clipping as occlusion from outside the surface.
628 // TODO(danakj): Clip to visibleContentRect?
629 unoccluded_region_in_target_surface.Intersect(
630 render_target->render_surface()->content_rect());
631 unoccluded_region_in_target_surface.Intersect(
632 ScreenSpaceClipRectInTargetSurface(render_target->render_surface(),
633 screen_space_clip_rect_));
634
635 gfx::RectF unoccluded_rect_in_target_surface = 590 gfx::RectF unoccluded_rect_in_target_surface =
636 unoccluded_region_in_target_surface.bounds(); 591 unoccluded_region_in_target_surface.bounds();
637 gfx::Rect unoccluded_rect = gfx::ToEnclosingRect( 592 gfx::Rect unoccluded_rect = gfx::ToEnclosingRect(
638 MathUtil::ProjectClippedRect(inverse_draw_transform, 593 MathUtil::ProjectClippedRect(inverse_draw_transform,
639 unoccluded_rect_in_target_surface)); 594 unoccluded_rect_in_target_surface));
640 unoccluded_rect.Intersect(content_rect); 595 unoccluded_rect.Intersect(content_rect);
641 596
642 if (has_occlusion_from_outside_target_surface) { 597 if (has_occlusion_from_outside_target_surface) {
643 // Check if the unoccluded rect shrank when applying outside occlusion. 598 // Check if the unoccluded rect shrank when applying outside occlusion.
644 *has_occlusion_from_outside_target_surface = !gfx::SubtractRects( 599 *has_occlusion_from_outside_target_surface = !gfx::SubtractRects(
(...skipping 23 matching lines...) Expand all
668 DCHECK_EQ(layer, stack_.back().target); 623 DCHECK_EQ(layer, stack_.back().target);
669 624
670 if (has_occlusion_from_outside_target_surface) 625 if (has_occlusion_from_outside_target_surface)
671 *has_occlusion_from_outside_target_surface = false; 626 *has_occlusion_from_outside_target_surface = false;
672 if (prevent_occlusion_) 627 if (prevent_occlusion_)
673 return content_rect; 628 return content_rect;
674 629
675 if (content_rect.IsEmpty()) 630 if (content_rect.IsEmpty())
676 return content_rect; 631 return content_rect;
677 632
633 // A contributing surface doesn't get occluded by things inside its own
634 // surface, so only things outside the surface can occlude it. That occlusion
635 // is found just below the top of the stack (if it exists).
636 if (stack_.size() == 1)
637 return content_rect;
638 const StackObject& second_last = stack_[stack_.size() - 2];
639 if (second_last.occlusion_from_inside_target.IsEmpty() &&
640 second_last.occlusion_from_outside_target.IsEmpty()) {
641 return content_rect;
642 }
643
678 const RenderSurfaceType* surface = layer->render_surface(); 644 const RenderSurfaceType* surface = layer->render_surface();
679 const LayerType* contributing_surface_render_target =
680 layer->parent()->render_target();
681
682 if (!SurfaceTransformsToTargetKnown(surface)) 645 if (!SurfaceTransformsToTargetKnown(surface))
683 return content_rect; 646 return content_rect;
684 647
685 gfx::Transform draw_transform = 648 gfx::Transform draw_transform =
686 for_replica ? surface->replica_draw_transform() 649 for_replica ? surface->replica_draw_transform()
687 : surface->draw_transform(); 650 : surface->draw_transform();
688 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization); 651 gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
689 if (!draw_transform.GetInverse(&inverse_draw_transform)) 652 if (!draw_transform.GetInverse(&inverse_draw_transform))
690 return content_rect; 653 return content_rect;
691 654
692 // A contributing surface doesn't get occluded by things inside its own
693 // surface, so only things outside the surface can occlude it. That occlusion
694 // is found just below the top of the stack (if it exists).
695 bool has_occlusion = stack_.size() > 1;
696
697 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded 655 // Take the ToEnclosingRect at each step, as we want to contain any unoccluded
698 // partial pixels in the resulting Rect. 656 // partial pixels in the resulting Rect.
699 Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect( 657 Region unoccluded_region_in_target_surface = gfx::ToEnclosingRect(
700 MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect))); 658 MathUtil::MapClippedRect(draw_transform, gfx::RectF(content_rect)));
701 // Layers can't clip across surfaces, so count this as internal occlusion. 659 unoccluded_region_in_target_surface.Subtract(
702 if (surface->is_clipped()) 660 second_last.occlusion_from_inside_target);
703 unoccluded_region_in_target_surface.Intersect(surface->clip_rect());
704 if (has_occlusion) {
705 const StackObject& second_last = stack_[stack_.size() - 2];
706 unoccluded_region_in_target_surface.Subtract(
707 second_last.occlusion_from_inside_target);
708 }
709 gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion = 661 gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion =
710 unoccluded_region_in_target_surface.bounds(); 662 unoccluded_region_in_target_surface.bounds();
711 if (has_occlusion) { 663 unoccluded_region_in_target_surface.Subtract(
712 const StackObject& second_last = stack_[stack_.size() - 2]; 664 second_last.occlusion_from_outside_target);
713 unoccluded_region_in_target_surface.Subtract(
714 second_last.occlusion_from_outside_target);
715 }
716
717 // Treat other clipping as occlusion from outside the target surface.
718 unoccluded_region_in_target_surface.Intersect(
719 contributing_surface_render_target->render_surface()->content_rect());
720 unoccluded_region_in_target_surface.Intersect(
721 ScreenSpaceClipRectInTargetSurface(
722 contributing_surface_render_target->render_surface(),
723 screen_space_clip_rect_));
724 665
725 gfx::RectF unoccluded_rect_in_target_surface = 666 gfx::RectF unoccluded_rect_in_target_surface =
726 unoccluded_region_in_target_surface.bounds(); 667 unoccluded_region_in_target_surface.bounds();
727 gfx::Rect unoccluded_rect = gfx::ToEnclosingRect( 668 gfx::Rect unoccluded_rect = gfx::ToEnclosingRect(
728 MathUtil::ProjectClippedRect(inverse_draw_transform, 669 MathUtil::ProjectClippedRect(inverse_draw_transform,
729 unoccluded_rect_in_target_surface)); 670 unoccluded_rect_in_target_surface));
730 unoccluded_rect.Intersect(content_rect); 671 unoccluded_rect.Intersect(content_rect);
731 672
732 if (has_occlusion_from_outside_target_surface) { 673 if (has_occlusion_from_outside_target_surface) {
733 // Check if the unoccluded rect shrank when applying outside occlusion. 674 // Check if the unoccluded rect shrank when applying outside occlusion.
734 *has_occlusion_from_outside_target_surface = !gfx::SubtractRects( 675 *has_occlusion_from_outside_target_surface = !gfx::SubtractRects(
735 unoccluded_rect_in_target_surface_without_outside_occlusion, 676 unoccluded_rect_in_target_surface_without_outside_occlusion,
736 unoccluded_rect_in_target_surface).IsEmpty(); 677 unoccluded_rect_in_target_surface).IsEmpty();
737 } 678 }
738 679
739 return unoccluded_rect; 680 return unoccluded_rect;
740 } 681 }
741 682
742 // Instantiate (and export) templates here for the linker. 683 // Instantiate (and export) templates here for the linker.
743 template class OcclusionTrackerBase<Layer, RenderSurface>; 684 template class OcclusionTrackerBase<Layer, RenderSurface>;
744 template class OcclusionTrackerBase<LayerImpl, RenderSurfaceImpl>; 685 template class OcclusionTrackerBase<LayerImpl, RenderSurfaceImpl>;
745 686
746 } // namespace cc 687 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698