Index: cc/trees/occlusion_tracker.cc |
diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc |
index fb3b5acfe94c90fc145aa1f44279270e1f7a453f..a25b444fc6b1dd4580557f1d323865582ce8283b 100644 |
--- a/cc/trees/occlusion_tracker.cc |
+++ b/cc/trees/occlusion_tracker.cc |
@@ -7,6 +7,7 @@ |
#include <algorithm> |
#include "cc/base/math_util.h" |
+#include "cc/base/region.h" |
#include "cc/layers/layer.h" |
#include "cc/layers/layer_impl.h" |
#include "cc/layers/render_surface.h" |
@@ -65,13 +66,13 @@ static gfx::Rect ScreenSpaceClipRectInTargetSurface( |
} |
template <typename RenderSurfaceType> |
-static Region TransformSurfaceOpaqueRegion( |
- const Region& region, |
+static SimpleEnclosedRegion TransformSurfaceOpaqueRegion( |
+ const SimpleEnclosedRegion& region, |
bool have_clip_rect, |
const gfx::Rect& clip_rect_in_new_target, |
const gfx::Transform& transform) { |
if (region.IsEmpty()) |
- return Region(); |
+ return region; |
// Verify that rects within the |surface| will remain rects in its target |
// surface after applying |transform|. If this is true, then apply |transform| |
@@ -79,23 +80,19 @@ static Region TransformSurfaceOpaqueRegion( |
// TODO(danakj): Find a rect interior to each transformed quad. |
if (!transform.Preserves2dAxisAlignment()) |
- return Region(); |
+ return SimpleEnclosedRegion(); |
- // TODO(danakj): If the Region is too complex, degrade gracefully here by |
- // skipping rects in it. |
- Region transformed_region; |
- for (Region::Iterator rects(region); rects.has_rect(); rects.next()) { |
+ gfx::Rect transformed_rect; |
+ for (size_t i = 0; i < region.GetRegionComplexity(); ++i) { |
bool clipped; |
gfx::QuadF transformed_quad = |
- MathUtil::MapQuad(transform, gfx::QuadF(rects.rect()), &clipped); |
- gfx::Rect transformed_rect = |
- gfx::ToEnclosedRect(transformed_quad.BoundingBox()); |
+ MathUtil::MapQuad(transform, gfx::QuadF(region.GetRect(i)), &clipped); |
+ transformed_rect = gfx::ToEnclosedRect(transformed_quad.BoundingBox()); |
DCHECK(!clipped); // We only map if the transform preserves axis alignment. |
if (have_clip_rect) |
transformed_rect.Intersect(clip_rect_in_new_target); |
- transformed_region.Union(transformed_rect); |
} |
- return transformed_region; |
+ return SimpleEnclosedRegion(transformed_rect); |
} |
static inline bool LayerOpacityKnown(const Layer* layer) { |
@@ -240,11 +237,12 @@ void OcclusionTracker<LayerType>::FinishedRenderTarget( |
} |
template <typename LayerType> |
-static void ReduceOcclusionBelowSurface(LayerType* contributing_layer, |
- const gfx::Rect& surface_rect, |
- const gfx::Transform& surface_transform, |
- LayerType* render_target, |
- Region* occlusion_from_inside_target) { |
+static void ReduceOcclusionBelowSurface( |
+ LayerType* contributing_layer, |
+ const gfx::Rect& surface_rect, |
+ const gfx::Transform& surface_transform, |
+ LayerType* render_target, |
+ SimpleEnclosedRegion* occlusion_from_inside_target) { |
if (surface_rect.IsEmpty()) |
return; |
@@ -265,13 +263,13 @@ static void ReduceOcclusionBelowSurface(LayerType* contributing_layer, |
// to expand outside the clip. |
affected_area_in_target.Inset( |
-outset_left, -outset_top, -outset_right, -outset_bottom); |
- Region affected_occlusion = IntersectRegions(*occlusion_from_inside_target, |
- affected_area_in_target); |
- Region::Iterator affected_occlusion_rects(affected_occlusion); |
+ SimpleEnclosedRegion affected_occlusion = IntersectSimpleEnclosedRegions( |
+ *occlusion_from_inside_target, |
+ SimpleEnclosedRegion(affected_area_in_target)); |
occlusion_from_inside_target->Subtract(affected_area_in_target); |
- for (; affected_occlusion_rects.has_rect(); affected_occlusion_rects.next()) { |
- gfx::Rect occlusion_rect = affected_occlusion_rects.rect(); |
+ for (size_t i = 0; i < affected_occlusion.GetRegionComplexity(); ++i) { |
+ gfx::Rect occlusion_rect = affected_occlusion.GetRect(i); |
// Shrink the rect by expanding the non-opaque pixels outside the rect. |
@@ -309,7 +307,7 @@ void OcclusionTracker<LayerType>::LeaveToRenderTarget( |
const typename LayerType::RenderSurfaceType* old_surface = |
old_target->render_surface(); |
- Region old_occlusion_from_inside_target_in_new_target = |
+ SimpleEnclosedRegion old_occlusion_from_inside_target_in_new_target = |
TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( |
stack_[last_index].occlusion_from_inside_target, |
old_surface->is_clipped(), |
@@ -324,7 +322,7 @@ void OcclusionTracker<LayerType>::LeaveToRenderTarget( |
old_surface->replica_draw_transform())); |
} |
- Region old_occlusion_from_outside_target_in_new_target = |
+ SimpleEnclosedRegion old_occlusion_from_outside_target_in_new_target = |
TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>( |
stack_[last_index].occlusion_from_outside_target, |
false, |
@@ -400,8 +398,6 @@ void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( |
const LayerType* layer) { |
DCHECK(!stack_.empty()); |
DCHECK_EQ(layer->render_target(), stack_.back().target); |
- if (stack_.empty()) |
- return; |
if (!LayerOpacityKnown(layer) || layer->draw_opacity() < 1) |
return; |
@@ -415,7 +411,7 @@ void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( |
if (!LayerTransformsToTargetKnown(layer)) |
return; |
- Region opaque_contents = layer->VisibleContentOpaqueRegion(); |
+ SimpleEnclosedRegion opaque_contents = layer->VisibleContentOpaqueRegion(); |
if (opaque_contents.IsEmpty()) |
return; |
@@ -434,14 +430,12 @@ void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( |
layer->render_target()->render_surface()->content_rect()); |
} |
- for (Region::Iterator opaque_content_rects(opaque_contents); |
- opaque_content_rects.has_rect(); |
- opaque_content_rects.next()) { |
+ for (size_t i = 0; i < opaque_contents.GetRegionComplexity(); ++i) { |
bool clipped; |
- gfx::QuadF transformed_quad = MathUtil::MapQuad( |
- layer->draw_transform(), |
- gfx::QuadF(opaque_content_rects.rect()), |
- &clipped); |
+ gfx::QuadF transformed_quad = |
+ MathUtil::MapQuad(layer->draw_transform(), |
+ gfx::QuadF(opaque_contents.GetRect(i)), |
+ &clipped); |
gfx::Rect transformed_rect = |
gfx::ToEnclosedRect(transformed_quad.BoundingBox()); |
DCHECK(!clipped); // We only map if the transform preserves axis alignment. |
@@ -468,8 +462,9 @@ void OcclusionTracker<LayerType>::MarkOccludedBehindLayer( |
if (!non_occluding_screen_space_rects_) |
return; |
- Region non_opaque_contents = |
- SubtractRegions(gfx::Rect(layer->content_bounds()), opaque_contents); |
+ Region non_opaque_contents(gfx::Rect(layer->content_bounds())); |
+ non_opaque_contents.Subtract(opaque_contents); |
+ |
for (Region::Iterator non_opaque_content_rects(non_opaque_contents); |
non_opaque_content_rects.has_rect(); |
non_opaque_content_rects.next()) { |
@@ -514,8 +509,9 @@ bool OcclusionTracker<LayerType>::Occluded( |
DCHECK(render_target->render_surface()); |
DCHECK_EQ(render_target, stack_.back().target); |
- if (stack_.back().occlusion_from_inside_target.IsEmpty() && |
- stack_.back().occlusion_from_outside_target.IsEmpty()) { |
+ const StackObject& back = stack_.back(); |
+ if (back.occlusion_from_inside_target.IsEmpty() && |
+ back.occlusion_from_outside_target.IsEmpty()) { |
return false; |
} |
@@ -525,17 +521,16 @@ bool OcclusionTracker<LayerType>::Occluded( |
// Take the ToEnclosingRect at each step, as we want to contain any unoccluded |
// partial pixels in the resulting Rect. |
- Region unoccluded_region_in_target_surface = |
+ gfx::Rect unoccluded_rect_in_target_surface = |
MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); |
- unoccluded_region_in_target_surface.Subtract( |
- stack_.back().occlusion_from_inside_target); |
- gfx::RectF unoccluded_rect_in_target_surface_without_outside_occlusion = |
- unoccluded_region_in_target_surface.bounds(); |
- unoccluded_region_in_target_surface.Subtract( |
- stack_.back().occlusion_from_outside_target); |
- |
- gfx::RectF unoccluded_rect_in_target_surface = |
- unoccluded_region_in_target_surface.bounds(); |
+ DCHECK_LE(back.occlusion_from_inside_target.GetRegionComplexity(), 1u); |
+ DCHECK_LE(back.occlusion_from_outside_target.GetRegionComplexity(), 1u); |
+ // These subtract operations are more lossy than if we did both operations at |
+ // once. |
+ unoccluded_rect_in_target_surface.Subtract( |
+ stack_.back().occlusion_from_inside_target.bounds()); |
+ unoccluded_rect_in_target_surface.Subtract( |
+ stack_.back().occlusion_from_outside_target.bounds()); |
return unoccluded_rect_in_target_surface.IsEmpty(); |
} |
@@ -544,13 +539,13 @@ template <typename LayerType> |
gfx::Rect OcclusionTracker<LayerType>::UnoccludedContentRect( |
const gfx::Rect& content_rect, |
const gfx::Transform& draw_transform) const { |
- if (stack_.empty()) |
- return content_rect; |
+ DCHECK(!stack_.empty()); |
if (content_rect.IsEmpty()) |
return content_rect; |
- if (stack_.back().occlusion_from_inside_target.IsEmpty() && |
- stack_.back().occlusion_from_outside_target.IsEmpty()) { |
+ const StackObject& back = stack_.back(); |
+ if (back.occlusion_from_inside_target.IsEmpty() && |
+ back.occlusion_from_outside_target.IsEmpty()) { |
return content_rect; |
} |
@@ -560,18 +555,20 @@ gfx::Rect OcclusionTracker<LayerType>::UnoccludedContentRect( |
// Take the ToEnclosingRect at each step, as we want to contain any unoccluded |
// partial pixels in the resulting Rect. |
- Region unoccluded_region_in_target_surface = |
+ gfx::Rect unoccluded_rect_in_target_surface = |
MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); |
- unoccluded_region_in_target_surface.Subtract( |
- stack_.back().occlusion_from_inside_target); |
- unoccluded_region_in_target_surface.Subtract( |
- stack_.back().occlusion_from_outside_target); |
- |
- if (unoccluded_region_in_target_surface.IsEmpty()) |
+ DCHECK_LE(back.occlusion_from_inside_target.GetRegionComplexity(), 1u); |
+ DCHECK_LE(back.occlusion_from_outside_target.GetRegionComplexity(), 1u); |
+ // These subtract operations are more lossy than if we did both operations at |
+ // once. |
+ unoccluded_rect_in_target_surface.Subtract( |
+ back.occlusion_from_inside_target.bounds()); |
+ unoccluded_rect_in_target_surface.Subtract( |
+ back.occlusion_from_outside_target.bounds()); |
+ |
+ if (unoccluded_rect_in_target_surface.IsEmpty()) |
return gfx::Rect(); |
- gfx::Rect unoccluded_rect_in_target_surface = |
- unoccluded_region_in_target_surface.bounds(); |
gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( |
inverse_draw_transform, unoccluded_rect_in_target_surface); |
unoccluded_rect.Intersect(content_rect); |
@@ -594,7 +591,6 @@ gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect( |
return content_rect; |
const StackObject& second_last = stack_[stack_.size() - 2]; |
- |
if (second_last.occlusion_from_inside_target.IsEmpty() && |
second_last.occlusion_from_outside_target.IsEmpty()) |
return content_rect; |
@@ -605,18 +601,21 @@ gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect( |
// Take the ToEnclosingRect at each step, as we want to contain any unoccluded |
// partial pixels in the resulting Rect. |
- Region unoccluded_region_in_target_surface = |
+ gfx::Rect unoccluded_rect_in_target_surface = |
MathUtil::MapEnclosingClippedRect(draw_transform, content_rect); |
- unoccluded_region_in_target_surface.Subtract( |
- second_last.occlusion_from_inside_target); |
- unoccluded_region_in_target_surface.Subtract( |
- second_last.occlusion_from_outside_target); |
- |
- if (unoccluded_region_in_target_surface.IsEmpty()) |
+ DCHECK_LE(second_last.occlusion_from_inside_target.GetRegionComplexity(), 1u); |
+ DCHECK_LE(second_last.occlusion_from_outside_target.GetRegionComplexity(), |
+ 1u); |
+ // These subtract operations are more lossy than if we did both operations at |
+ // once. |
+ unoccluded_rect_in_target_surface.Subtract( |
+ second_last.occlusion_from_inside_target.bounds()); |
+ unoccluded_rect_in_target_surface.Subtract( |
+ second_last.occlusion_from_outside_target.bounds()); |
+ |
+ if (unoccluded_rect_in_target_surface.IsEmpty()) |
return gfx::Rect(); |
- gfx::Rect unoccluded_rect_in_target_surface = |
- unoccluded_region_in_target_surface.bounds(); |
gfx::Rect unoccluded_rect = MathUtil::ProjectEnclosingClippedRect( |
inverse_draw_transform, unoccluded_rect_in_target_surface); |
unoccluded_rect.Intersect(content_rect); |
@@ -624,6 +623,17 @@ gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect( |
return unoccluded_rect; |
} |
+template <typename LayerType> |
+Region OcclusionTracker<LayerType>::ComputeVisibleRegionInScreen() const { |
+ DCHECK(!stack_.back().target->parent()); |
+ const SimpleEnclosedRegion& occluded = |
+ stack_.back().occlusion_from_inside_target; |
+ Region visible_region(screen_space_clip_rect_); |
+ for (size_t i = 0; i < occluded.GetRegionComplexity(); ++i) |
+ visible_region.Subtract(occluded.GetRect(i)); |
+ return visible_region; |
+} |
+ |
// Instantiate (and export) templates here for the linker. |
template class OcclusionTracker<Layer>; |
template class OcclusionTracker<LayerImpl>; |