Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / cc / trees / occlusion_tracker.cc
index 11982a8..bce1fd5 100644 (file)
@@ -7,29 +7,38 @@
 #include <algorithm>
 
 #include "cc/base/math_util.h"
-#include "cc/debug/overdraw_metrics.h"
+#include "cc/base/region.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/layer_impl.h"
 #include "cc/layers/render_surface.h"
 #include "cc/layers/render_surface_impl.h"
-#include "ui/gfx/quad_f.h"
-#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/geometry/quad_f.h"
+#include "ui/gfx/geometry/rect_conversions.h"
 
 namespace cc {
 
-template <typename LayerType, typename RenderSurfaceType>
-OcclusionTrackerBase<LayerType, RenderSurfaceType>::OcclusionTrackerBase(
-    const gfx::Rect& screen_space_clip_rect, bool record_metrics_for_frame)
+template <typename LayerType>
+OcclusionTracker<LayerType>::OcclusionTracker(
+    const gfx::Rect& screen_space_clip_rect)
     : screen_space_clip_rect_(screen_space_clip_rect),
-      overdraw_metrics_(OverdrawMetrics::Create(record_metrics_for_frame)),
       occluding_screen_space_rects_(NULL),
       non_occluding_screen_space_rects_(NULL) {}
 
-template <typename LayerType, typename RenderSurfaceType>
-OcclusionTrackerBase<LayerType, RenderSurfaceType>::~OcclusionTrackerBase() {}
+template <typename LayerType>
+OcclusionTracker<LayerType>::~OcclusionTracker() {}
+
+template <typename LayerType>
+Occlusion OcclusionTracker<LayerType>::GetCurrentOcclusionForLayer(
+    const gfx::Transform& draw_transform) const {
+  DCHECK(!stack_.empty());
+  const StackObject& back = stack_.back();
+  return Occlusion(draw_transform,
+                   back.occlusion_from_outside_target,
+                   back.occlusion_from_inside_target);
+}
 
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterLayer(
+template <typename LayerType>
+void OcclusionTracker<LayerType>::EnterLayer(
     const LayerIteratorPosition<LayerType>& layer_iterator) {
   LayerType* render_target = layer_iterator.target_render_surface_layer;
 
@@ -39,8 +48,8 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterLayer(
     FinishedRenderTarget(render_target);
 }
 
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::LeaveLayer(
+template <typename LayerType>
+void OcclusionTracker<LayerType>::LeaveLayer(
     const LayerIteratorPosition<LayerType>& layer_iterator) {
   LayerType* render_target = layer_iterator.target_render_surface_layer;
 
@@ -67,13 +76,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|
@@ -81,18 +90,13 @@ 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()) {
-    bool clipped;
-    gfx::QuadF transformed_quad =
-        MathUtil::MapQuad(transform, gfx::QuadF(rects.rect()), &clipped);
+  SimpleEnclosedRegion transformed_region;
+  for (size_t i = 0; i < region.GetRegionComplexity(); ++i) {
     gfx::Rect transformed_rect =
-        gfx::ToEnclosedRect(transformed_quad.BoundingBox());
-    DCHECK(!clipped);  // We only map if the transform preserves axis alignment.
+        MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(transform,
+                                                            region.GetRect(i));
     if (have_clip_rect)
       transformed_rect.Intersect(clip_rect_in_new_target);
     transformed_region.Union(transformed_rect);
@@ -133,7 +137,7 @@ static inline bool SurfaceTransformsToScreenKnown(const RenderSurfaceImpl* rs) {
 }
 
 static inline bool LayerIsInUnsorted3dRenderingContext(const Layer* layer) {
-  return layer->is_3d_sorted();
+  return layer->Is3dSorted();
 }
 static inline bool LayerIsInUnsorted3dRenderingContext(const LayerImpl* layer) {
   return false;
@@ -145,20 +149,21 @@ static inline bool LayerIsHidden(const LayerType* layer) {
          (layer->parent() && LayerIsHidden(layer->parent()));
 }
 
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterRenderTarget(
+template <typename LayerType>
+void OcclusionTracker<LayerType>::EnterRenderTarget(
     const LayerType* new_target) {
   if (!stack_.empty() && stack_.back().target == new_target)
     return;
 
   const LayerType* old_target = NULL;
-  const RenderSurfaceType* old_occlusion_immune_ancestor = NULL;
+  const typename LayerType::RenderSurfaceType* old_occlusion_immune_ancestor =
+      NULL;
   if (!stack_.empty()) {
     old_target = stack_.back().target;
     old_occlusion_immune_ancestor =
         old_target->render_surface()->nearest_occlusion_immune_ancestor();
   }
-  const RenderSurfaceType* new_occlusion_immune_ancestor =
+  const typename LayerType::RenderSurfaceType* new_occlusion_immune_ancestor =
       new_target->render_surface()->nearest_occlusion_immune_ancestor();
 
   stack_.push_back(StackObject(new_target));
@@ -198,26 +203,27 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::EnterRenderTarget(
       inverse_new_target_screen_space_transform,
       old_target->render_surface()->screen_space_transform());
   stack_[last_index].occlusion_from_outside_target =
-      TransformSurfaceOpaqueRegion<RenderSurfaceType>(
+      TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>(
           stack_[last_index - 1].occlusion_from_outside_target,
           false,
           gfx::Rect(),
           old_target_to_new_target_transform);
   stack_[last_index].occlusion_from_outside_target.Union(
-      TransformSurfaceOpaqueRegion<RenderSurfaceType>(
+      TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>(
           stack_[last_index - 1].occlusion_from_inside_target,
           false,
           gfx::Rect(),
           old_target_to_new_target_transform));
 }
 
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::FinishedRenderTarget(
+template <typename LayerType>
+void OcclusionTracker<LayerType>::FinishedRenderTarget(
     const LayerType* finished_target) {
   // Make sure we know about the target surface.
   EnterRenderTarget(finished_target);
 
-  RenderSurfaceType* surface = finished_target->render_surface();
+  typename LayerType::RenderSurfaceType* surface =
+      finished_target->render_surface();
 
   // Readbacks always happen on render targets so we only need to check
   // for readbacks here.
@@ -240,11 +246,12 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::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 +272,12 @@ 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 = *occlusion_from_inside_target;
+  affected_occlusion.Intersect(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.
 
@@ -294,8 +300,8 @@ static void ReduceOcclusionBelowSurface(LayerType* contributing_layer,
   }
 }
 
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::LeaveToRenderTarget(
+template <typename LayerType>
+void OcclusionTracker<LayerType>::LeaveToRenderTarget(
     const LayerType* new_target) {
   int last_index = stack_.size() - 1;
   bool surface_will_be_at_top_after_pop =
@@ -306,25 +312,26 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::LeaveToRenderTarget(
   // merged out as well but needs to be transformed to the new target.
 
   const LayerType* old_target = stack_[last_index].target;
-  const RenderSurfaceType* old_surface = old_target->render_surface();
+  const typename LayerType::RenderSurfaceType* old_surface =
+      old_target->render_surface();
 
-  Region old_occlusion_from_inside_target_in_new_target =
-      TransformSurfaceOpaqueRegion<RenderSurfaceType>(
+  SimpleEnclosedRegion old_occlusion_from_inside_target_in_new_target =
+      TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>(
           stack_[last_index].occlusion_from_inside_target,
           old_surface->is_clipped(),
           old_surface->clip_rect(),
           old_surface->draw_transform());
   if (old_target->has_replica() && !old_target->replica_has_mask()) {
     old_occlusion_from_inside_target_in_new_target.Union(
-        TransformSurfaceOpaqueRegion<RenderSurfaceType>(
+        TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>(
             stack_[last_index].occlusion_from_inside_target,
             old_surface->is_clipped(),
             old_surface->clip_rect(),
             old_surface->replica_draw_transform()));
   }
 
-  Region old_occlusion_from_outside_target_in_new_target =
-      TransformSurfaceOpaqueRegion<RenderSurfaceType>(
+  SimpleEnclosedRegion old_occlusion_from_outside_target_in_new_target =
+      TransformSurfaceOpaqueRegion<typename LayerType::RenderSurfaceType>(
           stack_[last_index].occlusion_from_outside_target,
           false,
           gfx::Rect(),
@@ -334,10 +341,11 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::LeaveToRenderTarget(
   gfx::Rect unoccluded_replica_rect;
   if (old_target->background_filters().HasFilterThatMovesPixels()) {
     unoccluded_surface_rect = UnoccludedContributingSurfaceContentRect(
-        old_target, false, old_surface->content_rect());
+        old_surface->content_rect(), old_surface->draw_transform());
     if (old_target->has_replica()) {
       unoccluded_replica_rect = UnoccludedContributingSurfaceContentRect(
-          old_target, true, old_surface->content_rect());
+          old_surface->content_rect(),
+          old_surface->replica_draw_transform());
     }
   }
 
@@ -393,16 +401,11 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::LeaveToRenderTarget(
                               &stack_.back().occlusion_from_outside_target);
 }
 
-template <typename LayerType, typename RenderSurfaceType>
-void OcclusionTrackerBase<LayerType, RenderSurfaceType>::
-    MarkOccludedBehindLayer(const LayerType* layer) {
+template <typename LayerType>
+void OcclusionTracker<LayerType>::MarkOccludedBehindLayer(
+    const LayerType* layer) {
   DCHECK(!stack_.empty());
   DCHECK_EQ(layer->render_target(), stack_.back().target);
-  if (stack_.empty())
-    return;
-
-  if (!layer->DrawsContent())
-    return;
 
   if (!LayerOpacityKnown(layer) || layer->draw_opacity() < 1)
     return;
@@ -416,7 +419,7 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::
   if (!LayerTransformsToTargetKnown(layer))
     return;
 
-  Region opaque_contents = layer->VisibleContentOpaqueRegion();
+  SimpleEnclosedRegion opaque_contents = layer->VisibleContentOpaqueRegion();
   if (opaque_contents.IsEmpty())
     return;
 
@@ -435,17 +438,10 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::
         layer->render_target()->render_surface()->content_rect());
   }
 
-  for (Region::Iterator opaque_content_rects(opaque_contents);
-       opaque_content_rects.has_rect();
-       opaque_content_rects.next()) {
-    bool clipped;
-    gfx::QuadF transformed_quad = MathUtil::MapQuad(
-        layer->draw_transform(),
-        gfx::QuadF(opaque_content_rects.rect()),
-        &clipped);
+  for (size_t i = 0; i < opaque_contents.GetRegionComplexity(); ++i) {
     gfx::Rect transformed_rect =
-        gfx::ToEnclosedRect(transformed_quad.BoundingBox());
-    DCHECK(!clipped);  // We only map if the transform preserves axis alignment.
+        MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
+            layer->draw_transform(), opaque_contents.GetRect(i));
     transformed_rect.Intersect(clip_rect_in_target);
     if (transformed_rect.width() < minimum_tracking_size_.width() &&
         transformed_rect.height() < minimum_tracking_size_.height())
@@ -456,6 +452,7 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::
       continue;
 
     // Save the occluding area in screen space for debug visualization.
+    bool clipped;
     gfx::QuadF screen_space_quad = MathUtil::MapQuad(
         layer->render_target()->render_surface()->screen_space_transform(),
         gfx::QuadF(transformed_rect), &clipped);
@@ -469,16 +466,15 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::
   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()) {
-    // We've already checked for clipping in the MapQuad call above, these calls
-    // should not clip anything further.
-    gfx::Rect transformed_rect = gfx::ToEnclosedRect(
-        MathUtil::MapClippedRect(layer->draw_transform(),
-                                 gfx::RectF(non_opaque_content_rects.rect())));
+    gfx::Rect transformed_rect =
+        MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
+            layer->draw_transform(), non_opaque_content_rects.rect());
     transformed_rect.Intersect(clip_rect_in_target);
     if (transformed_rect.IsEmpty())
       continue;
@@ -496,97 +492,46 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::
   }
 }
 
-template <typename LayerType, typename RenderSurfaceType>
-bool OcclusionTrackerBase<LayerType, RenderSurfaceType>::Occluded(
-    const LayerType* render_target,
+template <typename LayerType>
+gfx::Rect OcclusionTracker<LayerType>::UnoccludedContributingSurfaceContentRect(
     const gfx::Rect& content_rect,
-    const gfx::Transform& draw_transform,
-    bool impl_draw_transform_is_unknown) const {
-  DCHECK(!stack_.empty());
-  if (stack_.empty())
-    return false;
-  if (content_rect.IsEmpty())
-    return true;
-  if (impl_draw_transform_is_unknown)
-    return false;
-
-  // For tests with no render target.
-  if (!render_target)
-    return false;
-
-  DCHECK_EQ(render_target->render_target(), render_target);
-  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()) {
-    return false;
-  }
-
-  gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
-  if (!draw_transform.GetInverse(&inverse_draw_transform))
-    return false;
-
-  // 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 =
-      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();
-
-  return unoccluded_rect_in_target_surface.IsEmpty();
-}
-
-template <typename LayerType, typename RenderSurfaceType>
-gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
-    UnoccludedContentRect(
-        const LayerType* render_target,
-        const gfx::Rect& content_rect,
-        const gfx::Transform& draw_transform,
-        bool impl_draw_transform_is_unknown) const {
-  DCHECK(!stack_.empty());
-  if (stack_.empty())
-    return content_rect;
+    const gfx::Transform& draw_transform) const {
   if (content_rect.IsEmpty())
     return content_rect;
-  if (impl_draw_transform_is_unknown)
-    return content_rect;
 
-  // For tests with no render target.
-  if (!render_target)
+  // A contributing surface doesn't get occluded by things inside its own
+  // surface, so only things outside the surface can occlude it. That occlusion
+  // is found just below the top of the stack (if it exists).
+  bool has_occlusion = stack_.size() > 1;
+  if (!has_occlusion)
     return content_rect;
 
-  DCHECK_EQ(render_target->render_target(), render_target);
-  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& second_last = stack_[stack_.size() - 2];
+  if (second_last.occlusion_from_inside_target.IsEmpty() &&
+      second_last.occlusion_from_outside_target.IsEmpty())
     return content_rect;
-  }
 
   gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
-  if (!draw_transform.GetInverse(&inverse_draw_transform))
-    return content_rect;
+  bool ok = draw_transform.GetInverse(&inverse_draw_transform);
+  DCHECK(ok);
 
   // 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);
+  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);
@@ -594,79 +539,19 @@ gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
   return unoccluded_rect;
 }
 
-template <typename LayerType, typename RenderSurfaceType>
-gfx::Rect OcclusionTrackerBase<LayerType, RenderSurfaceType>::
-    UnoccludedContributingSurfaceContentRect(
-        const LayerType* layer,
-        bool for_replica,
-        const gfx::Rect& content_rect) const {
-  DCHECK(!stack_.empty());
-  // The layer is a contributing render_target so it should have a surface.
-  DCHECK(layer->render_surface());
-  // The layer is a contributing render_target so its target should be itself.
-  DCHECK_EQ(layer->render_target(), layer);
-  // The layer should not be the root, else what is is contributing to?
-  DCHECK(layer->parent());
-  // This should be called while the layer is still considered the current
-  // target in the occlusion tracker.
-  DCHECK_EQ(layer, stack_.back().target);
-
-  if (content_rect.IsEmpty())
-    return content_rect;
-
-  const RenderSurfaceType* surface = layer->render_surface();
-  const LayerType* contributing_surface_render_target =
-      layer->parent()->render_target();
-
-  if (!SurfaceTransformsToTargetKnown(surface))
-    return content_rect;
-
-  gfx::Transform draw_transform =
-      for_replica ? surface->replica_draw_transform()
-                  : surface->draw_transform();
-  gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
-  if (!draw_transform.GetInverse(&inverse_draw_transform))
-    return content_rect;
-
-  // A contributing surface doesn't get occluded by things inside its own
-  // surface, so only things outside the surface can occlude it. That occlusion
-  // is found just below the top of the stack (if it exists).
-  bool has_occlusion = stack_.size() > 1;
-
-  // 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 =
-      MathUtil::MapEnclosingClippedRect(draw_transform, content_rect);
-  // Layers can't clip across surfaces, so count this as internal occlusion.
-  if (surface->is_clipped())
-    unoccluded_region_in_target_surface.Intersect(surface->clip_rect());
-  if (has_occlusion) {
-    const StackObject& second_last = stack_[stack_.size() - 2];
-    unoccluded_region_in_target_surface.Subtract(
-        second_last.occlusion_from_inside_target);
-    unoccluded_region_in_target_surface.Subtract(
-        second_last.occlusion_from_outside_target);
-  }
-
-  // Treat other clipping as occlusion from outside the target surface.
-  unoccluded_region_in_target_surface.Intersect(
-      contributing_surface_render_target->render_surface()->content_rect());
-  unoccluded_region_in_target_surface.Intersect(
-      ScreenSpaceClipRectInTargetSurface(
-          contributing_surface_render_target->render_surface(),
-          screen_space_clip_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);
-
-  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 OcclusionTrackerBase<Layer, RenderSurface>;
-template class OcclusionTrackerBase<LayerImpl, RenderSurfaceImpl>;
+template class OcclusionTracker<Layer>;
+template class OcclusionTracker<LayerImpl>;
 
 }  // namespace cc