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