Home | History | Annotate | Download | only in trees
      1 // Copyright 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CC_TREES_OCCLUSION_TRACKER_H_
      6 #define CC_TREES_OCCLUSION_TRACKER_H_
      7 
      8 #include <vector>
      9 
     10 #include "base/basictypes.h"
     11 #include "cc/base/cc_export.h"
     12 #include "cc/base/region.h"
     13 #include "cc/layers/layer_iterator.h"
     14 #include "ui/gfx/rect.h"
     15 
     16 namespace cc {
     17 class OverdrawMetrics;
     18 class LayerImpl;
     19 class RenderSurfaceImpl;
     20 class Layer;
     21 class RenderSurface;
     22 
     23 // This class is used to track occlusion of layers while traversing them in a
     24 // front-to-back order. As each layer is visited, one of the methods in this
     25 // class is called to notify it about the current target surface. Then,
     26 // occlusion in the content space of the current layer may be queried, via
     27 // methods such as Occluded() and UnoccludedContentRect(). If the current layer
     28 // owns a RenderSurfaceImpl, then occlusion on that RenderSurfaceImpl may also
     29 // be queried via surfaceOccluded() and surfaceUnoccludedContentRect(). Finally,
     30 // once finished with the layer, occlusion behind the layer should be marked by
     31 // calling MarkOccludedBehindLayer().
     32 template <typename LayerType, typename RenderSurfaceType>
     33 class CC_EXPORT OcclusionTrackerBase {
     34  public:
     35   OcclusionTrackerBase(gfx::Rect screen_space_clip_rect,
     36                        bool record_metrics_for_frame);
     37   ~OcclusionTrackerBase();
     38 
     39   // Called at the beginning of each step in the LayerIterator's front-to-back
     40   // traversal.
     41   void EnterLayer(const LayerIteratorPosition<LayerType>& layer_iterator);
     42   // Called at the end of each step in the LayerIterator's front-to-back
     43   // traversal.
     44   void LeaveLayer(const LayerIteratorPosition<LayerType>& layer_iterator);
     45 
     46   // Returns true if the given rect in content space for a layer is fully
     47   // occluded in either screen space or the layer's target surface.
     48   // |render_target| is the contributing layer's render target, and
     49   // |draw_transform| and |impl_draw_transform_is_unknown| are relative to that.
     50   bool Occluded(const LayerType* render_target,
     51                 gfx::Rect content_rect,
     52                 const gfx::Transform& draw_transform,
     53                 bool impl_draw_transform_is_unknown) const;
     54 
     55   // Gives an unoccluded sub-rect of |content_rect| in the content space of a
     56   // layer. Used when considering occlusion for a layer that paints/draws
     57   // something. |render_target| is the contributing layer's render target, and
     58   // |draw_transform| and |impl_draw_transform_is_unknown| are relative to that.
     59   gfx::Rect UnoccludedContentRect(
     60       const LayerType* render_target,
     61       gfx::Rect content_rect,
     62       const gfx::Transform& draw_transform,
     63       bool impl_draw_transform_is_unknown) const;
     64 
     65   // Gives an unoccluded sub-rect of |content_rect| in the content space of the
     66   // render_target owned by the layer. Used when considering occlusion for a
     67   // contributing surface that is rendering into another target.
     68   gfx::Rect UnoccludedContributingSurfaceContentRect(
     69       const LayerType* layer,
     70       bool for_replica,
     71       gfx::Rect content_rect) const;
     72 
     73   // Report operations for recording overdraw metrics.
     74   OverdrawMetrics* overdraw_metrics() const {
     75     return overdraw_metrics_.get();
     76   }
     77 
     78   // Gives the region of the screen that is not occluded by something opaque.
     79   Region ComputeVisibleRegionInScreen() const {
     80     DCHECK(!stack_.back().target->parent());
     81     return SubtractRegions(screen_space_clip_rect_,
     82                            stack_.back().occlusion_from_inside_target);
     83   }
     84 
     85   void set_minimum_tracking_size(gfx::Size size) {
     86     minimum_tracking_size_ = size;
     87   }
     88 
     89   // The following is used for visualization purposes.
     90   void set_occluding_screen_space_rects_container(
     91       std::vector<gfx::Rect>* rects) {
     92     occluding_screen_space_rects_ = rects;
     93   }
     94   void set_non_occluding_screen_space_rects_container(
     95       std::vector<gfx::Rect>* rects) {
     96     non_occluding_screen_space_rects_ = rects;
     97   }
     98 
     99  protected:
    100   struct StackObject {
    101     StackObject() : target(0) {}
    102     explicit StackObject(const LayerType* target) : target(target) {}
    103     const LayerType* target;
    104     Region occlusion_from_outside_target;
    105     Region occlusion_from_inside_target;
    106   };
    107 
    108   // The stack holds occluded regions for subtrees in the
    109   // RenderSurfaceImpl-Layer tree, so that when we leave a subtree we may apply
    110   // a mask to it, but not to the parts outside the subtree.
    111   // - The first time we see a new subtree under a target, we add that target to
    112   // the top of the stack. This can happen as a layer representing itself, or as
    113   // a target surface.
    114   // - When we visit a target surface, we apply its mask to its subtree, which
    115   // is at the top of the stack.
    116   // - When we visit a layer representing itself, we add its occlusion to the
    117   // current subtree, which is at the top of the stack.
    118   // - When we visit a layer representing a contributing surface, the current
    119   // target will never be the top of the stack since we just came from the
    120   // contributing surface.
    121   // We merge the occlusion at the top of the stack with the new current
    122   // subtree. This new target is pushed onto the stack if not already there.
    123   std::vector<StackObject> stack_;
    124 
    125  private:
    126   // Called when visiting a layer representing itself. If the target was not
    127   // already current, then this indicates we have entered a new surface subtree.
    128   void EnterRenderTarget(const LayerType* new_target);
    129 
    130   // Called when visiting a layer representing a target surface. This indicates
    131   // we have visited all the layers within the surface, and we may perform any
    132   // surface-wide operations.
    133   void FinishedRenderTarget(const LayerType* finished_target);
    134 
    135   // Called when visiting a layer representing a contributing surface. This
    136   // indicates that we are leaving our current surface, and entering the new
    137   // one. We then perform any operations required for merging results from the
    138   // child subtree into its parent.
    139   void LeaveToRenderTarget(const LayerType* new_target);
    140 
    141   // Add the layer's occlusion to the tracked state.
    142   void MarkOccludedBehindLayer(const LayerType* layer);
    143 
    144   gfx::Rect screen_space_clip_rect_;
    145   scoped_ptr<class OverdrawMetrics> overdraw_metrics_;
    146   gfx::Size minimum_tracking_size_;
    147 
    148   // This is used for visualizing the occlusion tracking process.
    149   std::vector<gfx::Rect>* occluding_screen_space_rects_;
    150   std::vector<gfx::Rect>* non_occluding_screen_space_rects_;
    151 
    152   DISALLOW_COPY_AND_ASSIGN(OcclusionTrackerBase);
    153 };
    154 
    155 typedef OcclusionTrackerBase<Layer, RenderSurface> OcclusionTracker;
    156 typedef OcclusionTrackerBase<LayerImpl, RenderSurfaceImpl> OcclusionTrackerImpl;
    157 #if !defined(COMPILER_MSVC)
    158 extern template class OcclusionTrackerBase<Layer, RenderSurface>;
    159 extern template class OcclusionTrackerBase<LayerImpl, RenderSurfaceImpl>;
    160 #endif
    161 
    162 }  // namespace cc
    163 
    164 #endif  // CC_TREES_OCCLUSION_TRACKER_H_
    165