summaryrefslogtreecommitdiffstats
path: root/cc/trees/occlusion_tracker.h
blob: 85334bca2c19ec304bd4268b2801046103f01e1c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// Copyright 2012 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_TRACKER_H_
#define CC_TREES_OCCLUSION_TRACKER_H_

#include <vector>

#include "base/basictypes.h"
#include "cc/base/cc_export.h"
#include "cc/base/region.h"
#include "cc/layers/layer_iterator.h"
#include "ui/gfx/rect.h"

namespace cc {
class OverdrawMetrics;
class LayerImpl;
class RenderSurfaceImpl;
class Layer;
class RenderSurface;

// This class is used to track occlusion of layers while traversing them in a
// front-to-back order. As each layer is visited, one of the methods in this
// class is called to notify it about the current target surface. Then,
// occlusion in the content space of the current layer may be queried, via
// methods such as Occluded() and UnoccludedContentRect(). If the current layer
// owns a RenderSurfaceImpl, then occlusion on that RenderSurfaceImpl may also
// be queried via surfaceOccluded() and surfaceUnoccludedContentRect(). Finally,
// once finished with the layer, occlusion behind the layer should be marked by
// calling MarkOccludedBehindLayer().
template <typename LayerType, typename RenderSurfaceType>
class CC_EXPORT OcclusionTrackerBase {
 public:
  OcclusionTrackerBase(const gfx::Rect& screen_space_clip_rect,
                       bool record_metrics_for_frame);
  ~OcclusionTrackerBase();

  // Called at the beginning of each step in the LayerIterator's front-to-back
  // traversal.
  void EnterLayer(const LayerIteratorPosition<LayerType>& layer_iterator);
  // Called at the end of each step in the LayerIterator's front-to-back
  // traversal.
  void LeaveLayer(const LayerIteratorPosition<LayerType>& layer_iterator);

  // Returns true if the given rect in content space for a layer is fully
  // occluded in either screen space or the layer's target surface.
  // |render_target| is the contributing layer's render target, and
  // |draw_transform| and |impl_draw_transform_is_unknown| are relative to that.
  bool Occluded(const LayerType* render_target,
                const gfx::Rect& content_rect,
                const gfx::Transform& draw_transform,
                bool impl_draw_transform_is_unknown) const;

  // Gives an unoccluded sub-rect of |content_rect| in the content space of a
  // layer. Used when considering occlusion for a layer that paints/draws
  // something. |render_target| is the contributing layer's render target, and
  // |draw_transform| and |impl_draw_transform_is_unknown| are relative to that.
  gfx::Rect UnoccludedContentRect(
      const LayerType* render_target,
      const gfx::Rect& content_rect,
      const gfx::Transform& draw_transform,
      bool impl_draw_transform_is_unknown) const;

  // Gives an unoccluded sub-rect of |content_rect| in the content space of the
  // render_target owned by the layer. Used when considering occlusion for a
  // contributing surface that is rendering into another target.
  gfx::Rect UnoccludedContributingSurfaceContentRect(
      const LayerType* layer,
      bool for_replica,
      const gfx::Rect& content_rect) const;

  // Report operations for recording overdraw metrics.
  OverdrawMetrics* overdraw_metrics() const {
    return overdraw_metrics_.get();
  }

  // Gives the region of the screen that is not occluded by something opaque.
  Region ComputeVisibleRegionInScreen() const {
    DCHECK(!stack_.back().target->parent());
    return SubtractRegions(screen_space_clip_rect_,
                           stack_.back().occlusion_from_inside_target);
  }

  void set_minimum_tracking_size(gfx::Size size) {
    minimum_tracking_size_ = size;
  }

  // The following is used for visualization purposes.
  void set_occluding_screen_space_rects_container(
      std::vector<gfx::Rect>* rects) {
    occluding_screen_space_rects_ = rects;
  }
  void set_non_occluding_screen_space_rects_container(
      std::vector<gfx::Rect>* rects) {
    non_occluding_screen_space_rects_ = rects;
  }

 protected:
  struct StackObject {
    StackObject() : target(0) {}
    explicit StackObject(const LayerType* target) : target(target) {}
    const LayerType* target;
    Region occlusion_from_outside_target;
    Region occlusion_from_inside_target;
  };

  // The stack holds occluded regions for subtrees in the
  // RenderSurfaceImpl-Layer tree, so that when we leave a subtree we may apply
  // a mask to it, but not to the parts outside the subtree.
  // - The first time we see a new subtree under a target, we add that target to
  // the top of the stack. This can happen as a layer representing itself, or as
  // a target surface.
  // - When we visit a target surface, we apply its mask to its subtree, which
  // is at the top of the stack.
  // - When we visit a layer representing itself, we add its occlusion to the
  // current subtree, which is at the top of the stack.
  // - When we visit a layer representing a contributing surface, the current
  // target will never be the top of the stack since we just came from the
  // contributing surface.
  // We merge the occlusion at the top of the stack with the new current
  // subtree. This new target is pushed onto the stack if not already there.
  std::vector<StackObject> stack_;

 private:
  // Called when visiting a layer representing itself. If the target was not
  // already current, then this indicates we have entered a new surface subtree.
  void EnterRenderTarget(const LayerType* new_target);

  // Called when visiting a layer representing a target surface. This indicates
  // we have visited all the layers within the surface, and we may perform any
  // surface-wide operations.
  void FinishedRenderTarget(const LayerType* finished_target);

  // Called when visiting a layer representing a contributing surface. This
  // indicates that we are leaving our current surface, and entering the new
  // one. We then perform any operations required for merging results from the
  // child subtree into its parent.
  void LeaveToRenderTarget(const LayerType* new_target);

  // Add the layer's occlusion to the tracked state.
  void MarkOccludedBehindLayer(const LayerType* layer);

  gfx::Rect screen_space_clip_rect_;
  scoped_ptr<class OverdrawMetrics> overdraw_metrics_;
  gfx::Size minimum_tracking_size_;

  // This is used for visualizing the occlusion tracking process.
  std::vector<gfx::Rect>* occluding_screen_space_rects_;
  std::vector<gfx::Rect>* non_occluding_screen_space_rects_;

  DISALLOW_COPY_AND_ASSIGN(OcclusionTrackerBase);
};

typedef OcclusionTrackerBase<Layer, RenderSurface> OcclusionTracker;
typedef OcclusionTrackerBase<LayerImpl, RenderSurfaceImpl> OcclusionTrackerImpl;
#if !defined(COMPILER_MSVC)
extern template class OcclusionTrackerBase<Layer, RenderSurface>;
extern template class OcclusionTrackerBase<LayerImpl, RenderSurfaceImpl>;
#endif

}  // namespace cc

#endif  // CC_TREES_OCCLUSION_TRACKER_H_