OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/trees/occlusion_tracker.h" | 5 #include "cc/trees/occlusion_tracker.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "cc/base/math_util.h" | 9 #include "cc/base/math_util.h" |
10 #include "cc/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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |