[go: nahoru, domu]

Reland of: cc: Add occlusion checker as a fixed view of occlusion tracker.

This patch adds an occlusion checker to get the state of
occlusion tracker for permanent checks. That is, occlusion
checker does not have to be queried during a layer walk.

BUG=410932
R=danakj

Committed: https://crrev.com/1af780529157c94a9e0f05bcf478543b85714f6b
Cr-Commit-Position: refs/heads/master@{#294205}

Review URL: https://codereview.chromium.org/547723002

Cr-Commit-Position: refs/heads/master@{#294280}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 300150f..6d70f46 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -452,6 +452,8 @@
     "trees/layer_tree_impl.h",
     "trees/layer_tree_settings.cc",
     "trees/layer_tree_settings.h",
+    "trees/occlusion.cc",
+    "trees/occlusion.h",
     "trees/occlusion_tracker.cc",
     "trees/occlusion_tracker.h",
     "trees/proxy.cc",
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 9d62397..af640a2 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -481,6 +481,8 @@
         'trees/layer_tree_impl.h',
         'trees/layer_tree_settings.cc',
         'trees/layer_tree_settings.h',
+        'trees/occlusion.cc',
+        'trees/occlusion.h',
         'trees/occlusion_tracker.cc',
         'trees/occlusion_tracker.h',
         'trees/proxy.cc',
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index c10710c..65143ab 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -49,6 +49,7 @@
 class LayerTreeHostImpl;
 class LayerTreeImpl;
 class MicroBenchmarkImpl;
+class Occlusion;
 template <typename LayerType>
 class OcclusionTracker;
 class RenderPass;
@@ -204,8 +205,7 @@
   virtual RenderPassId FirstContributingRenderPassId() const;
   virtual RenderPassId NextContributingRenderPassId(RenderPassId id) const;
 
-  virtual void UpdateTiles(
-      const OcclusionTracker<LayerImpl>* occlusion_tracker) {}
+  virtual void UpdateTiles(const Occlusion& occlusion_in_layer_space) {}
   virtual void NotifyTileStateChanged(const Tile* tile) {}
 
   virtual ScrollbarLayerImplBase* ToScrollbarLayer();
diff --git a/cc/layers/picture_image_layer_impl_unittest.cc b/cc/layers/picture_image_layer_impl_unittest.cc
index 48b4d7b..f22b6cd 100644
--- a/cc/layers/picture_image_layer_impl_unittest.cc
+++ b/cc/layers/picture_image_layer_impl_unittest.cc
@@ -84,7 +84,7 @@
         maximum_animation_contents_scale;
     layer->draw_properties().screen_space_transform_is_animating =
         animating_transform_to_screen;
-    layer->UpdateTiles(NULL);
+    layer->UpdateTiles(Occlusion());
   }
 
  protected:
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 05dab30..1205e07 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -420,17 +420,11 @@
 }
 
 void PictureLayerImpl::UpdateTiles(
-    const OcclusionTracker<LayerImpl>* occlusion_tracker) {
+    const Occlusion& occlusion_in_content_space) {
   TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTiles");
 
   DoPostCommitInitializationIfNeeded();
 
-  // TODO(danakj): We should always get an occlusion tracker when we are using
-  // occlusion, so update this check when we don't use a pending tree in the
-  // browser compositor.
-  DCHECK(!occlusion_tracker ||
-         layer_tree_impl()->settings().use_occlusion_for_tile_prioritization);
-
   visible_rect_for_tile_priority_ = visible_content_rect();
   viewport_rect_for_tile_priority_ =
       layer_tree_impl()->ViewportRectForTilePriority();
@@ -465,14 +459,14 @@
 
   should_update_tile_priorities_ = true;
 
-  UpdateTilePriorities(occlusion_tracker);
+  UpdateTilePriorities(occlusion_in_content_space);
 
   if (layer_tree_impl()->IsPendingTree())
     MarkVisibleResourcesAsRequired();
 }
 
 void PictureLayerImpl::UpdateTilePriorities(
-    const OcclusionTracker<LayerImpl>* occlusion_tracker) {
+    const Occlusion& occlusion_in_content_space) {
   TRACE_EVENT0("cc", "PictureLayerImpl::UpdateTilePriorities");
 
   double current_frame_time_in_seconds =
@@ -502,9 +496,7 @@
                                                  visible_layer_rect,
                                                  ideal_contents_scale_,
                                                  current_frame_time_in_seconds,
-                                                 occlusion_tracker,
-                                                 render_target(),
-                                                 draw_transform());
+                                                 occlusion_in_content_space);
   }
 
   // Tile priorities were modified.
@@ -756,7 +748,7 @@
     // when we stop using the pending tree in the browser compositor. If we want
     // to support occlusion tracking here, we need to dirty the draw properties
     // or save occlusion as a draw property.
-    UpdateTilePriorities(NULL);
+    UpdateTilePriorities(Occlusion());
   }
 }
 
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index fd4fe0a8..c7d987f 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -110,7 +110,7 @@
                            const OcclusionTracker<LayerImpl>& occlusion_tracker,
                            AppendQuadsData* append_quads_data) OVERRIDE;
   virtual void UpdateTiles(
-      const OcclusionTracker<LayerImpl>* occlusion_tracker) OVERRIDE;
+      const Occlusion& occlusion_in_content_space) OVERRIDE;
   virtual void NotifyTileStateChanged(const Tile* tile) OVERRIDE;
   virtual void DidBecomeActive() OVERRIDE;
   virtual void DidBeginTracing() OVERRIDE;
@@ -160,8 +160,7 @@
   void RemoveAllTilings();
   void SyncFromActiveLayer(const PictureLayerImpl* other);
   void AddTilingsForRasterScale();
-  void UpdateTilePriorities(
-      const OcclusionTracker<LayerImpl>* occlusion_tracker);
+  void UpdateTilePriorities(const Occlusion& occlusion_in_content_space);
   virtual bool ShouldAdjustRasterScale() const;
   virtual void RecalculateRasterScales();
   void CleanUpTilingsOnActiveLayer(
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 44662d7..6742207 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -160,7 +160,7 @@
         maximum_animation_contents_scale;
     layer->draw_properties().screen_space_transform_is_animating =
         animating_transform_to_screen;
-    layer->UpdateTiles(NULL);
+    layer->UpdateTiles(Occlusion());
   }
   static void VerifyAllTilesExistAndHavePile(
       const PictureLayerTiling* tiling,
@@ -348,7 +348,7 @@
                                         resourceless_software_draw);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
   gfx::Rect viewport_rect_for_tile_priority_in_view_space =
       viewport_rect_for_tile_priority;
@@ -386,7 +386,7 @@
                                         resourceless_software_draw);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
   gfx::Transform screen_to_view(gfx::Transform::kSkipInitialization);
   bool success = transform_for_tile_priority.GetInverse(&screen_to_view);
@@ -447,7 +447,7 @@
                                         resourceless_software_draw);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
   gfx::Rect visible_rect_for_tile_priority =
       active_layer_->visible_rect_for_tile_priority();
@@ -475,7 +475,7 @@
                                         viewport,
                                         transform,
                                         resourceless_software_draw);
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
   visible_rect_for_tile_priority =
       gfx::ScaleToEnclosingRect(visible_rect_for_tile_priority, 2);
@@ -1508,7 +1508,7 @@
   time_ticks += base::TimeDelta::FromMilliseconds(200);
   host_impl_.SetCurrentBeginFrameArgs(
       CreateBeginFrameArgsForTesting(time_ticks));
-  pending_layer_->UpdateTiles(NULL);
+  pending_layer_->UpdateTiles(Occlusion());
 
   pending_layer_->MarkVisibleResourcesAsRequired();
 
@@ -2575,7 +2575,7 @@
 
   pending_layer_->draw_properties().visible_content_rect =
       gfx::Rect(1100, 1100, 500, 500);
-  pending_layer_->UpdateTiles(NULL);
+  pending_layer_->UpdateTiles(Occlusion());
 
   unique_tiles.clear();
   high_res_tile_count = 0u;
@@ -2605,7 +2605,7 @@
 
   pending_layer_->draw_properties().visible_content_rect =
       gfx::Rect(0, 0, 500, 500);
-  pending_layer_->UpdateTiles(NULL);
+  pending_layer_->UpdateTiles(Occlusion());
 
   std::vector<Tile*> high_res_tiles = high_res_tiling->AllTilesForTesting();
   for (std::vector<Tile*>::iterator tile_it = high_res_tiles.begin();
@@ -3169,7 +3169,7 @@
                                         resourceless_software_draw);
   active_layer_->draw_properties().visible_content_rect = viewport;
   active_layer_->draw_properties().screen_space_transform = transform;
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
   gfx::Rect visible_rect_for_tile_priority =
       active_layer_->visible_rect_for_tile_priority();
@@ -3197,7 +3197,7 @@
                                         viewport,
                                         transform,
                                         resourceless_software_draw);
-  active_layer_->UpdateTiles(NULL);
+  active_layer_->UpdateTiles(Occlusion());
 
   visible_rect_for_tile_priority =
       gfx::ScaleToEnclosingRect(visible_rect_for_tile_priority, 2);
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc
index 0d50658..0229879 100644
--- a/cc/resources/picture_layer_tiling.cc
+++ b/cc/resources/picture_layer_tiling.cc
@@ -15,7 +15,6 @@
 #include "cc/base/math_util.h"
 #include "cc/resources/tile.h"
 #include "cc/resources/tile_priority.h"
-#include "cc/trees/occlusion_tracker.h"
 #include "ui/gfx/point_conversions.h"
 #include "ui/gfx/rect_conversions.h"
 #include "ui/gfx/safe_integer_conversions.h"
@@ -540,9 +539,7 @@
     const gfx::Rect& visible_layer_rect,
     float ideal_contents_scale,
     double current_frame_time_in_seconds,
-    const OcclusionTracker<LayerImpl>* occlusion_tracker,
-    const LayerImpl* render_target,
-    const gfx::Transform& draw_transform) {
+    const Occlusion& occlusion_in_layer_space) {
   if (!NeedsUpdateForFrameAtTime(current_frame_time_in_seconds)) {
     // This should never be zero for the purposes of has_ever_been_updated().
     DCHECK_NE(current_frame_time_in_seconds, 0.0);
@@ -605,16 +602,10 @@
     tile->SetPriority(tree, now_priority);
 
     // Set whether tile is occluded or not.
-    bool is_occluded = false;
-    if (occlusion_tracker) {
-      gfx::Rect tile_query_rect = ScaleToEnclosingRect(
-          IntersectRects(tile->content_rect(), visible_rect_in_content_space),
-          1.0f / contents_scale_);
-      // TODO(vmpstr): Remove render_target and draw_transform from the
-      // parameters so they can be hidden from the tiling.
-      is_occluded = occlusion_tracker->Occluded(
-          render_target, tile_query_rect, draw_transform);
-    }
+    gfx::Rect tile_query_rect = ScaleToEnclosingRect(
+        IntersectRects(tile->content_rect(), visible_rect_in_content_space),
+        1.0f / contents_scale_);
+    bool is_occluded = occlusion_in_layer_space.IsOccluded(tile_query_rect);
     tile->set_is_occluded(tree, is_occluded);
   }
 
diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h
index 35bbf94..e3fffee 100644
--- a/cc/resources/picture_layer_tiling.h
+++ b/cc/resources/picture_layer_tiling.h
@@ -17,6 +17,7 @@
 #include "cc/base/tiling_data.h"
 #include "cc/resources/tile.h"
 #include "cc/resources/tile_priority.h"
+#include "cc/trees/occlusion.h"
 #include "ui/gfx/rect.h"
 
 namespace base {
@@ -27,8 +28,6 @@
 
 namespace cc {
 
-template <typename LayerType>
-class OcclusionTracker;
 class PictureLayerTiling;
 class PicturePileImpl;
 
@@ -237,14 +236,11 @@
 
   void Reset();
 
-  void UpdateTilePriorities(
-      WhichTree tree,
-      const gfx::Rect& visible_layer_rect,
-      float ideal_contents_scale,
-      double current_frame_time_in_seconds,
-      const OcclusionTracker<LayerImpl>* occlusion_tracker,
-      const LayerImpl* render_target,
-      const gfx::Transform& draw_transform);
+  void UpdateTilePriorities(WhichTree tree,
+                            const gfx::Rect& visible_layer_rect,
+                            float ideal_contents_scale,
+                            double current_frame_time_in_seconds,
+                            const Occlusion& occlusion_in_layer_space);
 
   // Copies the src_tree priority into the dst_tree priority for all tiles.
   // The src_tree priority is reset to the lowest priority possible.  This
diff --git a/cc/resources/picture_layer_tiling_perftest.cc b/cc/resources/picture_layer_tiling_perftest.cc
index 00338ab..f1b462f 100644
--- a/cc/resources/picture_layer_tiling_perftest.cc
+++ b/cc/resources/picture_layer_tiling_perftest.cc
@@ -74,13 +74,8 @@
 
     timer_.Reset();
     do {
-      picture_layer_tiling_->UpdateTilePriorities(PENDING_TREE,
-                                                  viewport_rect,
-                                                  1.f,
-                                                  timer_.NumLaps() + 1,
-                                                  NULL,
-                                                  NULL,
-                                                  gfx::Transform());
+      picture_layer_tiling_->UpdateTilePriorities(
+          PENDING_TREE, viewport_rect, 1.f, timer_.NumLaps() + 1, Occlusion());
       timer_.NextLap();
     } while (!timer_.HasTimeLimitExpired());
 
@@ -104,13 +99,8 @@
 
     timer_.Reset();
     do {
-      picture_layer_tiling_->UpdateTilePriorities(PENDING_TREE,
-                                                  viewport_rect,
-                                                  1.f,
-                                                  timer_.NumLaps() + 1,
-                                                  NULL,
-                                                  NULL,
-                                                  gfx::Transform());
+      picture_layer_tiling_->UpdateTilePriorities(
+          PENDING_TREE, viewport_rect, 1.f, timer_.NumLaps() + 1, Occlusion());
 
       viewport_rect = gfx::Rect(viewport_rect.x() + xoffsets[offsetIndex],
                                 viewport_rect.y() + yoffsets[offsetIndex],
@@ -139,7 +129,7 @@
         PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
     picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
     picture_layer_tiling_->UpdateTilePriorities(
-        ACTIVE_TREE, viewport, 1.0f, 1.0, NULL, NULL, gfx::Transform());
+        ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
 
     timer_.Reset();
     do {
@@ -164,7 +154,7 @@
         PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
     picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
     picture_layer_tiling_->UpdateTilePriorities(
-        ACTIVE_TREE, viewport, 1.0f, 1.0, NULL, NULL, gfx::Transform());
+        ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
 
     timer_.Reset();
     do {
@@ -194,7 +184,7 @@
         PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
     picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
     picture_layer_tiling_->UpdateTilePriorities(
-        ACTIVE_TREE, viewport, 1.0f, 1.0, NULL, NULL, gfx::Transform());
+        ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
 
     timer_.Reset();
     TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
@@ -226,7 +216,7 @@
         PictureLayerTiling::Create(1, bounds, &picture_layer_tiling_client_);
     picture_layer_tiling_client_.set_tree(ACTIVE_TREE);
     picture_layer_tiling_->UpdateTilePriorities(
-        ACTIVE_TREE, viewport, 1.0f, 1.0, NULL, NULL, gfx::Transform());
+        ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
 
     TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
                                  SMOOTHNESS_TAKES_PRIORITY,
diff --git a/cc/resources/picture_layer_tiling_unittest.cc b/cc/resources/picture_layer_tiling_unittest.cc
index 0795e11..e64191d3 100644
--- a/cc/resources/picture_layer_tiling_unittest.cc
+++ b/cc/resources/picture_layer_tiling_unittest.cc
@@ -44,9 +44,7 @@
                                             visible_layer_rect,
                                             layer_contents_scale,
                                             current_frame_time_in_seconds,
-                                            NULL,
-                                            NULL,
-                                            gfx::Transform());
+                                            Occlusion());
   }
 }
 
@@ -540,8 +538,7 @@
   client.SetTileSize(gfx::Size(100, 100));
   tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client);
 
-  tiling->UpdateTilePriorities(
-      ACTIVE_TREE, viewport, 1.f, 1.0, NULL, NULL, gfx::Transform());
+  tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.f, 1.0, Occlusion());
 
   // Move viewport down 50 pixels in 0.5 seconds.
   gfx::Rect down_skewport =
@@ -607,8 +604,7 @@
   client.set_tree(ACTIVE_TREE);
   tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client);
 
-  tiling->UpdateTilePriorities(
-      ACTIVE_TREE, viewport, 1.f, 1.0, NULL, NULL, gfx::Transform());
+  tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.f, 1.0, Occlusion());
 
   // Move viewport down 50 pixels in 0.5 seconds.
   gfx::Rect down_skewport =
@@ -675,8 +671,7 @@
   gfx::Rect viewport_in_content_space =
       gfx::ToEnclosedRect(gfx::ScaleRect(viewport, 0.25f));
 
-  tiling->UpdateTilePriorities(
-      ACTIVE_TREE, viewport, 1.f, 1.0, NULL, NULL, gfx::Transform());
+  tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.f, 1.0, Occlusion());
 
   gfx::Rect soon_rect = viewport;
   soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
@@ -760,8 +755,7 @@
   EXPECT_EQ(25, skewport.width());
   EXPECT_EQ(35, skewport.height());
 
-  tiling->UpdateTilePriorities(
-      ACTIVE_TREE, viewport, 1.f, 2.0, NULL, NULL, gfx::Transform());
+  tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.f, 2.0, Occlusion());
 
   have_now = false;
   have_eventually = false;
@@ -812,8 +806,7 @@
   EXPECT_FLOAT_EQ(4.f, priority.distance_to_visible);
 
   // Change the underlying layer scale.
-  tiling->UpdateTilePriorities(
-      ACTIVE_TREE, viewport, 2.0f, 3.0, NULL, NULL, gfx::Transform());
+  tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 2.0f, 3.0, Occlusion());
 
   priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
   EXPECT_FLOAT_EQ(136.f, priority.distance_to_visible);
@@ -826,8 +819,7 @@
 
   // Test additional scales.
   tiling = TestablePictureLayerTiling::Create(0.2f, layer_bounds, &client);
-  tiling->UpdateTilePriorities(
-      ACTIVE_TREE, viewport, 1.0f, 4.0, NULL, NULL, gfx::Transform());
+  tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.0f, 4.0, Occlusion());
 
   priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
   EXPECT_FLOAT_EQ(110.f, priority.distance_to_visible);
@@ -838,8 +830,7 @@
   priority = tiling->TileAt(3, 4)->priority(ACTIVE_TREE);
   EXPECT_FLOAT_EQ(60.f, priority.distance_to_visible);
 
-  tiling->UpdateTilePriorities(
-      ACTIVE_TREE, viewport, 0.5f, 5.0, NULL, NULL, gfx::Transform());
+  tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 0.5f, 5.0, Occlusion());
 
   priority = tiling->TileAt(5, 1)->priority(ACTIVE_TREE);
   EXPECT_FLOAT_EQ(55.f, priority.distance_to_visible);
@@ -1087,8 +1078,7 @@
   client.set_tree(ACTIVE_TREE);
 
   tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client);
-  tiling->UpdateTilePriorities(
-      ACTIVE_TREE, viewport, 1.0f, 1.0, NULL, NULL, gfx::Transform());
+  tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
 
   PictureLayerTiling::TilingRasterTileIterator empty_iterator;
   EXPECT_FALSE(empty_iterator);
@@ -1196,10 +1186,9 @@
   client.set_tree(ACTIVE_TREE);
 
   tiling = TestablePictureLayerTiling::Create(1.f, layer_bounds, &client);
+  tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
   tiling->UpdateTilePriorities(
-      ACTIVE_TREE, viewport, 1.0f, 1.0, NULL, NULL, gfx::Transform());
-  tiling->UpdateTilePriorities(
-      ACTIVE_TREE, moved_viewport, 1.0f, 2.0, NULL, NULL, gfx::Transform());
+      ACTIVE_TREE, moved_viewport, 1.0f, 2.0, Occlusion());
 
   gfx::Rect soon_rect = moved_viewport;
   soon_rect.Inset(-312.f, -312.f, -312.f, -312.f);
@@ -1272,8 +1261,7 @@
   client.set_tree(ACTIVE_TREE);
 
   tiling = TestablePictureLayerTiling::Create(1.0f, layer_bounds, &client);
-  tiling->UpdateTilePriorities(
-      ACTIVE_TREE, viewport, 1.0f, 1.0, NULL, NULL, gfx::Transform());
+  tiling->UpdateTilePriorities(ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
 
   PictureLayerTiling::TilingRasterTileIterator empty_iterator;
   EXPECT_FALSE(empty_iterator);
@@ -1351,19 +1339,15 @@
       gfx::Rect(layer_bounds),  // visible content rect
       1.f,                      // current contents scale
       1.0,                      // current frame time
-      NULL,                     // occlusion tracker
-      NULL,                     // render target
-      gfx::Transform());        // draw transform
+      Occlusion());
   VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));
 
   // Make the viewport rect empty. All tiles are killed and become zombies.
   tiling_->UpdateTilePriorities(ACTIVE_TREE,
-                                gfx::Rect(),        // visible content rect
-                                1.f,                // current contents scale
-                                2.0,                // current frame time
-                                NULL,               // occlusion tracker
-                                NULL,               // render target
-                                gfx::Transform());  // draw transform
+                                gfx::Rect(),  // visible content rect
+                                1.f,          // current contents scale
+                                2.0,          // current frame time
+                                Occlusion());
   VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, false));
 }
 
@@ -1381,19 +1365,15 @@
       gfx::Rect(layer_bounds),  // visible content rect
       1.f,                      // current contents scale
       1.0,                      // current frame time
-      NULL,                     // occlusion tracker
-      NULL,                     // render target
-      gfx::Transform());        // draw transform
+      Occlusion());
   VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));
 
   // If the visible content rect is empty, it should still have live tiles.
   tiling_->UpdateTilePriorities(ACTIVE_TREE,
-                                giant_rect,         // visible content rect
-                                1.f,                // current contents scale
-                                2.0,                // current frame time
-                                NULL,               // occlusion tracker
-                                NULL,               // render target
-                                gfx::Transform());  // draw transform
+                                giant_rect,  // visible content rect
+                                1.f,         // current contents scale
+                                2.0,         // current frame time
+                                Occlusion());
   VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));
 }
 
@@ -1410,12 +1390,10 @@
 
   client_.set_tree(ACTIVE_TREE);
   tiling_->UpdateTilePriorities(ACTIVE_TREE,
-                                viewport_rect,      // visible content rect
-                                1.f,                // current contents scale
-                                1.0,                // current frame time
-                                NULL,               // occlusion tracker
-                                NULL,               // render target
-                                gfx::Transform());  // draw transform
+                                viewport_rect,  // visible content rect
+                                1.f,            // current contents scale
+                                1.0,            // current frame time
+                                Occlusion());
   VerifyTiles(1.f, gfx::Rect(layer_bounds), base::Bind(&TileExists, true));
 }
 
@@ -1442,12 +1420,10 @@
   client_.set_tree(ACTIVE_TREE);
   set_max_tiles_for_interest_area(1);
   tiling_->UpdateTilePriorities(ACTIVE_TREE,
-                                visible_rect,       // visible content rect
-                                1.f,                // current contents scale
-                                1.0,                // current frame time
-                                NULL,               // occlusion tracker
-                                NULL,               // render target
-                                gfx::Transform());  // draw transform
+                                visible_rect,  // visible content rect
+                                1.f,           // current contents scale
+                                1.0,           // current frame time
+                                Occlusion());
   VerifyTiles(1.f,
               gfx::Rect(layer_bounds),
               base::Bind(&TilesIntersectingRectExist, visible_rect, true));
@@ -1533,9 +1509,7 @@
                                viewport_in_layer_space,
                                current_layer_contents_scale,
                                current_frame_time_in_seconds,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+                               Occlusion());
 
   ASSERT_TRUE(tiling->TileAt(0, 0));
   ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1590,9 +1564,7 @@
                                viewport_in_layer_space,
                                current_layer_contents_scale,
                                current_frame_time_in_seconds,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+                               Occlusion());
 
   ASSERT_TRUE(tiling->TileAt(0, 0));
   ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1657,9 +1629,7 @@
                                viewport_in_layer_space,
                                current_layer_contents_scale,
                                current_frame_time_in_seconds,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+                               Occlusion());
 
   ASSERT_TRUE(tiling->TileAt(0, 0));
   ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1718,9 +1688,7 @@
                                viewport_in_layer_space,
                                current_layer_contents_scale,
                                current_frame_time_in_seconds,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+                               Occlusion());
 
   ASSERT_TRUE(tiling->TileAt(0, 0));
   ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1803,9 +1771,7 @@
                                viewport_in_layer_space,
                                current_layer_contents_scale,
                                current_frame_time_in_seconds,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+                               Occlusion());
 
   ASSERT_TRUE(tiling->TileAt(0, 0));
   ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1898,9 +1864,7 @@
                                viewport_in_layer_space,
                                current_layer_contents_scale,
                                current_frame_time_in_seconds,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+                               Occlusion());
 
   ASSERT_TRUE(tiling->TileAt(0, 0));
   ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -1964,18 +1928,14 @@
                                viewport_in_layer_space,
                                last_layer_contents_scale,
                                last_frame_time_in_seconds,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+                               Occlusion());
 
   // current frame
   tiling->UpdateTilePriorities(ACTIVE_TREE,
                                viewport_in_layer_space,
                                current_layer_contents_scale,
                                current_frame_time_in_seconds,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+                               Occlusion());
 
   ASSERT_TRUE(tiling->TileAt(0, 0));
   ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -2046,18 +2006,14 @@
                                viewport_in_layer_space,
                                last_layer_contents_scale,
                                last_frame_time_in_seconds,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+                               Occlusion());
 
   // current frame
   tiling->UpdateTilePriorities(ACTIVE_TREE,
                                viewport_in_layer_space,
                                current_layer_contents_scale,
                                current_frame_time_in_seconds,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+                               Occlusion());
 
   ASSERT_TRUE(tiling->TileAt(0, 0));
   ASSERT_TRUE(tiling->TileAt(0, 1));
@@ -2086,13 +2042,8 @@
   tiling = TestablePictureLayerTiling::Create(1.0f,  // contents_scale
                                               gfx::Size(100, 100),
                                               &client);
-  tiling->UpdateTilePriorities(ACTIVE_TREE,
-                               gfx::Rect(0, 0, 100, 100),
-                               1.0f,
-                               1.0f,
-                               NULL,               // occlusion tracker
-                               NULL,               // render target
-                               gfx::Transform());  // draw transform
+  tiling->UpdateTilePriorities(
+      ACTIVE_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion());
 
   std::vector<scoped_refptr<Tile> > tiles = tiling->AllRefTilesForTesting();
   ASSERT_GT(tiles.size(), 0u);
@@ -2132,13 +2083,8 @@
                                                      gfx::Size(10000, 10000),
                                                      &active_client);
   // Create all tiles on this tiling.
-  active_tiling->UpdateTilePriorities(ACTIVE_TREE,
-                                      gfx::Rect(0, 0, 100, 100),
-                                      1.0f,
-                                      1.0f,
-                                      NULL,               // occlusion tracker
-                                      NULL,               // render target
-                                      gfx::Transform());  // draw transform
+  active_tiling->UpdateTilePriorities(
+      ACTIVE_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion());
 
   FakePictureLayerTilingClient recycle_client;
   recycle_client.SetTileSize(gfx::Size(100, 100));
@@ -2152,13 +2098,8 @@
                                                       &recycle_client);
 
   // Create all tiles on the second tiling. All tiles should be shared.
-  recycle_tiling->UpdateTilePriorities(PENDING_TREE,
-                                       gfx::Rect(0, 0, 100, 100),
-                                       1.0f,
-                                       1.0f,
-                                       NULL,               // occlusion tracker
-                                       NULL,               // render target
-                                       gfx::Transform());  // draw transform
+  recycle_tiling->UpdateTilePriorities(
+      PENDING_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion());
 
   // Set the second tiling as recycled.
   active_client.set_twin_tiling(NULL);
@@ -2171,25 +2112,15 @@
   EXPECT_EQ(active_tiling->TileAt(0, 0), recycle_tiling->TileAt(0, 0));
 
   // Move the viewport far away from the (0, 0) tile.
-  active_tiling->UpdateTilePriorities(ACTIVE_TREE,
-                                      gfx::Rect(9000, 9000, 100, 100),
-                                      1.0f,
-                                      2.0,
-                                      NULL,               // occlusion tracker
-                                      NULL,               // render target
-                                      gfx::Transform());  // draw transform
+  active_tiling->UpdateTilePriorities(
+      ACTIVE_TREE, gfx::Rect(9000, 9000, 100, 100), 1.0f, 2.0, Occlusion());
   // Ensure the tile was deleted on both tilings.
   EXPECT_FALSE(active_tiling->TileAt(0, 0));
   EXPECT_FALSE(recycle_tiling->TileAt(0, 0));
 
   // Move the viewport back to (0, 0) tile.
-  active_tiling->UpdateTilePriorities(ACTIVE_TREE,
-                                      gfx::Rect(0, 0, 100, 100),
-                                      1.0f,
-                                      3.0,
-                                      NULL,               // occlusion tracker
-                                      NULL,               // render target
-                                      gfx::Transform());  // draw transform
+  active_tiling->UpdateTilePriorities(
+      ACTIVE_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 3.0, Occlusion());
 
   // Ensure that we now have a tile here, but the recycle tiling does not.
   EXPECT_TRUE(active_tiling->TileAt(0, 0));
@@ -2206,13 +2137,8 @@
                                                      gfx::Size(100, 100),
                                                      &active_client);
   // Create all tiles on this tiling.
-  active_tiling->UpdateTilePriorities(ACTIVE_TREE,
-                                      gfx::Rect(0, 0, 100, 100),
-                                      1.0f,
-                                      1.0f,
-                                      NULL,               // occlusion tracker
-                                      NULL,               // render target
-                                      gfx::Transform());  // draw transform
+  active_tiling->UpdateTilePriorities(
+      ACTIVE_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion());
 
   FakePictureLayerTilingClient recycle_client;
   recycle_client.SetTileSize(gfx::Size(100, 100));
@@ -2226,13 +2152,8 @@
                                                       &recycle_client);
 
   // Create all tiles on the recycle tiling. All tiles should be shared.
-  recycle_tiling->UpdateTilePriorities(PENDING_TREE,
-                                       gfx::Rect(0, 0, 100, 100),
-                                       1.0f,
-                                       1.0f,
-                                       NULL,               // occlusion tracker
-                                       NULL,               // render target
-                                       gfx::Transform());  // draw transform
+  recycle_tiling->UpdateTilePriorities(
+      PENDING_TREE, gfx::Rect(0, 0, 100, 100), 1.0f, 1.0f, Occlusion());
 
   // Set the second tiling as recycled.
   active_client.set_twin_tiling(NULL);
diff --git a/cc/resources/tile_manager_perftest.cc b/cc/resources/tile_manager_perftest.cc
index 3aa04a27..65ec4d8 100644
--- a/cc/resources/tile_manager_perftest.cc
+++ b/cc/resources/tile_manager_perftest.cc
@@ -187,7 +187,7 @@
 
     std::vector<LayerImpl*> layers = CreateLayers(layer_count, 10);
     for (unsigned i = 0; i < layers.size(); ++i)
-      layers[i]->UpdateTiles(NULL);
+      layers[i]->UpdateTiles(Occlusion());
 
     timer_.Reset();
     do {
@@ -214,7 +214,7 @@
 
     std::vector<LayerImpl*> layers = CreateLayers(layer_count, 100);
     for (unsigned i = 0; i < layers.size(); ++i)
-      layers[i]->UpdateTiles(NULL);
+      layers[i]->UpdateTiles(Occlusion());
 
     int priority_count = 0;
     timer_.Reset();
@@ -251,7 +251,7 @@
     for (unsigned i = 0; i < layers.size(); ++i) {
       FakePictureLayerImpl* layer =
           static_cast<FakePictureLayerImpl*>(layers[i]);
-      layer->UpdateTiles(NULL);
+      layer->UpdateTiles(Occlusion());
       for (size_t j = 0; j < layer->GetTilings()->num_tilings(); ++j) {
         tile_manager()->InitializeTilesWithResourcesForTesting(
             layer->GetTilings()->tiling_at(j)->AllTilesForTesting());
@@ -286,7 +286,7 @@
     for (unsigned i = 0; i < layers.size(); ++i) {
       FakePictureLayerImpl* layer =
           static_cast<FakePictureLayerImpl*>(layers[i]);
-      layer->UpdateTiles(NULL);
+      layer->UpdateTiles(Occlusion());
       for (size_t j = 0; j < layer->GetTilings()->num_tilings(); ++j) {
         tile_manager()->InitializeTilesWithResourcesForTesting(
             layer->GetTilings()->tiling_at(j)->AllTilesForTesting());
@@ -396,7 +396,7 @@
       BeginFrameArgs args = CreateBeginFrameArgsForTesting();
       host_impl_.UpdateCurrentBeginFrameArgs(args);
       for (unsigned i = 0; i < layers.size(); ++i)
-        layers[i]->UpdateTiles(NULL);
+        layers[i]->UpdateTiles(Occlusion());
 
       GlobalStateThatImpactsTilePriority global_state(GlobalStateForTest());
       tile_manager()->ManageTiles(global_state);
diff --git a/cc/resources/tile_manager_unittest.cc b/cc/resources/tile_manager_unittest.cc
index f229fcd..fdba0501 100644
--- a/cc/resources/tile_manager_unittest.cc
+++ b/cc/resources/tile_manager_unittest.cc
@@ -646,37 +646,13 @@
   // Renew all of the tile priorities.
   gfx::Rect viewport(50, 50, 100, 100);
   pending_layer_->HighResTiling()->UpdateTilePriorities(
-      PENDING_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      pending_layer_->render_target(),
-      pending_layer_->draw_transform());
+      PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
   pending_layer_->LowResTiling()->UpdateTilePriorities(
-      PENDING_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      pending_layer_->render_target(),
-      pending_layer_->draw_transform());
+      PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
   active_layer_->HighResTiling()->UpdateTilePriorities(
-      ACTIVE_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      active_layer_->render_target(),
-      active_layer_->draw_transform());
+      ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
   active_layer_->LowResTiling()->UpdateTilePriorities(
-      ACTIVE_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      active_layer_->render_target(),
-      active_layer_->draw_transform());
+      ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
 
   // Populate all tiles directly from the tilings.
   all_tiles.clear();
@@ -845,37 +821,13 @@
   // Renew all of the tile priorities.
   gfx::Rect viewport(50, 50, 100, 100);
   pending_layer_->HighResTiling()->UpdateTilePriorities(
-      PENDING_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      pending_layer_->render_target(),
-      pending_layer_->draw_transform());
+      PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
   pending_layer_->LowResTiling()->UpdateTilePriorities(
-      PENDING_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      pending_layer_->render_target(),
-      pending_layer_->draw_transform());
+      PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
   active_layer_->HighResTiling()->UpdateTilePriorities(
-      ACTIVE_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      active_layer_->render_target(),
-      active_layer_->draw_transform());
+      ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
   active_layer_->LowResTiling()->UpdateTilePriorities(
-      ACTIVE_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      active_layer_->render_target(),
-      active_layer_->draw_transform());
+      ACTIVE_TREE, viewport, 1.0f, 1.0, Occlusion());
 
   // Populate all tiles directly from the tilings.
   all_tiles.clear();
@@ -1020,37 +972,13 @@
   // Renew all of the tile priorities.
   gfx::Rect viewport(layer_bounds);
   pending_layer_->HighResTiling()->UpdateTilePriorities(
-      PENDING_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      pending_layer_->render_target(),
-      pending_layer_->draw_transform());
+      PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
   pending_layer_->LowResTiling()->UpdateTilePriorities(
-      PENDING_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      pending_layer_->render_target(),
-      pending_layer_->draw_transform());
+      PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
   pending_child_layer->HighResTiling()->UpdateTilePriorities(
-      PENDING_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      pending_child_layer->render_target(),
-      pending_child_layer->draw_transform());
+      PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
   pending_child_layer->LowResTiling()->UpdateTilePriorities(
-      PENDING_TREE,
-      viewport,
-      1.0f,
-      1.0,
-      NULL,
-      pending_child_layer->render_target(),
-      pending_child_layer->draw_transform());
+      PENDING_TREE, viewport, 1.0f, 1.0, Occlusion());
 
   // Populate all tiles directly from the tilings.
   all_tiles.clear();
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 328234f..e368bb8 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -520,8 +520,13 @@
         occlusion_tracker->EnterLayer(it);
 
       LayerImpl* layer = *it;
+      const Occlusion& occlusion_in_content_space =
+          occlusion_tracker ? occlusion_tracker->GetCurrentOcclusionForLayer(
+                                  layer->draw_transform())
+                            : Occlusion();
+
       if (it.represents_itself())
-        layer->UpdateTiles(occlusion_tracker.get());
+        layer->UpdateTiles(occlusion_in_content_space);
 
       if (!it.represents_contributing_render_surface()) {
         if (occlusion_tracker)
@@ -530,10 +535,10 @@
       }
 
       if (layer->mask_layer())
-        layer->mask_layer()->UpdateTiles(occlusion_tracker.get());
+        layer->mask_layer()->UpdateTiles(occlusion_in_content_space);
       if (layer->replica_layer() && layer->replica_layer()->mask_layer())
         layer->replica_layer()->mask_layer()->UpdateTiles(
-            occlusion_tracker.get());
+            occlusion_in_content_space);
 
       if (occlusion_tracker)
         occlusion_tracker->LeaveLayer(it);
diff --git a/cc/trees/occlusion.cc b/cc/trees/occlusion.cc
new file mode 100644
index 0000000..c91c0ca
--- /dev/null
+++ b/cc/trees/occlusion.cc
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/trees/occlusion.h"
+
+#include "cc/base/math_util.h"
+#include "ui/gfx/rect.h"
+
+namespace cc {
+
+Occlusion::Occlusion() {
+}
+
+Occlusion::Occlusion(const gfx::Transform& draw_transform,
+                     const SimpleEnclosedRegion& occlusion_from_outside_target,
+                     const SimpleEnclosedRegion& occlusion_from_inside_target)
+    : draw_transform_(draw_transform),
+      occlusion_from_outside_target_(occlusion_from_outside_target),
+      occlusion_from_inside_target_(occlusion_from_inside_target) {
+}
+
+bool Occlusion::IsOccluded(const gfx::Rect& content_rect) const {
+  if (content_rect.IsEmpty())
+    return true;
+
+  if (occlusion_from_inside_target_.IsEmpty() &&
+      occlusion_from_outside_target_.IsEmpty()) {
+    return false;
+  }
+
+  // Take the ToEnclosingRect at each step, as we want to contain any unoccluded
+  // partial pixels in the resulting Rect.
+  gfx::Rect unoccluded_rect_in_target_surface =
+      MathUtil::MapEnclosingClippedRect(draw_transform_, content_rect);
+  DCHECK_LE(occlusion_from_inside_target_.GetRegionComplexity(), 1u);
+  DCHECK_LE(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(
+      occlusion_from_inside_target_.bounds());
+  unoccluded_rect_in_target_surface.Subtract(
+      occlusion_from_outside_target_.bounds());
+
+  return unoccluded_rect_in_target_surface.IsEmpty();
+}
+
+}  // namespace cc
diff --git a/cc/trees/occlusion.h b/cc/trees/occlusion.h
new file mode 100644
index 0000000..982d7e81
--- /dev/null
+++ b/cc/trees/occlusion.h
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_TREES_OCCLUSION_H_
+#define CC_TREES_OCCLUSION_H_
+
+#include "base/basictypes.h"
+#include "cc/base/cc_export.h"
+#include "cc/base/simple_enclosed_region.h"
+#include "ui/gfx/transform.h"
+
+namespace gfx {
+class Rect;
+}  // namespace gfx
+
+namespace cc {
+
+class CC_EXPORT Occlusion {
+ public:
+  Occlusion();
+  Occlusion(const gfx::Transform& draw_transform,
+            const SimpleEnclosedRegion& occlusion_from_outside_target,
+            const SimpleEnclosedRegion& occlusion_from_inside_target);
+
+  bool IsOccluded(const gfx::Rect& content_rect) const;
+
+ private:
+  gfx::Transform draw_transform_;
+  SimpleEnclosedRegion occlusion_from_outside_target_;
+  SimpleEnclosedRegion occlusion_from_inside_target_;
+};
+
+}  // namespace cc
+
+#endif  // CC_TREES_OCCLUSION_H_
diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc
index f233e07..8fdd6e25 100644
--- a/cc/trees/occlusion_tracker.cc
+++ b/cc/trees/occlusion_tracker.cc
@@ -28,6 +28,16 @@
 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>
 void OcclusionTracker<LayerType>::EnterLayer(
     const LayerIteratorPosition<LayerType>& layer_iterator) {
   LayerType* render_target = layer_iterator.target_render_surface_layer;
diff --git a/cc/trees/occlusion_tracker.h b/cc/trees/occlusion_tracker.h
index 8d07f434..9b4b74e2 100644
--- a/cc/trees/occlusion_tracker.h
+++ b/cc/trees/occlusion_tracker.h
@@ -11,6 +11,7 @@
 #include "cc/base/cc_export.h"
 #include "cc/base/simple_enclosed_region.h"
 #include "cc/layers/layer_iterator.h"
+#include "cc/trees/occlusion.h"
 #include "ui/gfx/rect.h"
 
 namespace cc {
@@ -35,6 +36,11 @@
   explicit OcclusionTracker(const gfx::Rect& screen_space_clip_rect);
   ~OcclusionTracker();
 
+  // Return an occlusion that retains the current state of the tracker
+  // and can be used outside of a layer walk to check occlusion.
+  Occlusion GetCurrentOcclusionForLayer(
+      const gfx::Transform& draw_transform) const;
+
   // Called at the beginning of each step in the LayerIterator's front-to-back
   // traversal.
   void EnterLayer(const LayerIteratorPosition<LayerType>& layer_iterator);
diff --git a/cc/trees/occlusion_tracker_unittest.cc b/cc/trees/occlusion_tracker_unittest.cc
index aaf655f2..56059cb 100644
--- a/cc/trees/occlusion_tracker_unittest.cc
+++ b/cc/trees/occlusion_tracker_unittest.cc
@@ -85,6 +85,11 @@
   bool OccludedLayer(const LayerType* layer,
                      const gfx::Rect& content_rect) const {
     DCHECK(layer->visible_content_rect().Contains(content_rect));
+    EXPECT_EQ(
+        this->Occluded(
+            layer->render_target(), content_rect, layer->draw_transform()),
+        this->GetCurrentOcclusionForLayer(layer->draw_transform())
+            .IsOccluded(content_rect));
     return this->Occluded(
         layer->render_target(), content_rect, layer->draw_transform());
   }