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/simple_enclosed_region.h"
13#include "cc/layers/layer_iterator.h"
14#include "cc/trees/occlusion.h"
15#include "ui/gfx/rect.h"
16
17namespace cc {
18class LayerImpl;
19class Region;
20class RenderSurfaceImpl;
21class Layer;
22class RenderSurface;
23
24// This class is used to track occlusion of layers while traversing them in a
25// front-to-back order. As each layer is visited, one of the methods in this
26// class is called to notify it about the current target surface. Then,
27// occlusion in the content space of the current layer may be queried, via
28// Occlusion from GetCurrentOcclusionForLayer(). If the current layer owns a
29// RenderSurfaceImpl, then occlusion on that RenderSurfaceImpl may also be
30// queried via surfaceOccluded() and surfaceUnoccludedContentRect(). Finally,
31// once finished with the layer, occlusion behind the layer should be marked by
32// calling MarkOccludedBehindLayer().
33template <typename LayerType>
34class CC_EXPORT OcclusionTracker {
35 public:
36  explicit OcclusionTracker(const gfx::Rect& screen_space_clip_rect);
37  ~OcclusionTracker();
38
39  // Return an occlusion that retains the current state of the tracker
40  // and can be used outside of a layer walk to check occlusion.
41  Occlusion GetCurrentOcclusionForLayer(
42      const gfx::Transform& draw_transform) const;
43
44  // Called at the beginning of each step in the LayerIterator's front-to-back
45  // traversal.
46  void EnterLayer(const LayerIteratorPosition<LayerType>& layer_iterator);
47  // Called at the end of each step in the LayerIterator's front-to-back
48  // traversal.
49  void LeaveLayer(const LayerIteratorPosition<LayerType>& layer_iterator);
50
51  // Gives an unoccluded sub-rect of |content_rect| in the content space of the
52  // render_target owned by the layer. Used when considering occlusion for a
53  // contributing surface that is rendering into another target.
54  gfx::Rect UnoccludedContributingSurfaceContentRect(
55      const gfx::Rect& content_rect,
56      const gfx::Transform& draw_transform) const;
57
58  // Gives the region of the screen that is not occluded by something opaque.
59  Region ComputeVisibleRegionInScreen() const;
60
61  void set_minimum_tracking_size(const gfx::Size& size) {
62    minimum_tracking_size_ = size;
63  }
64
65  // The following is used for visualization purposes.
66  void set_occluding_screen_space_rects_container(
67      std::vector<gfx::Rect>* rects) {
68    occluding_screen_space_rects_ = rects;
69  }
70  void set_non_occluding_screen_space_rects_container(
71      std::vector<gfx::Rect>* rects) {
72    non_occluding_screen_space_rects_ = rects;
73  }
74
75 protected:
76  struct StackObject {
77    StackObject() : target(0) {}
78    explicit StackObject(const LayerType* target) : target(target) {}
79    const LayerType* target;
80    SimpleEnclosedRegion occlusion_from_outside_target;
81    SimpleEnclosedRegion occlusion_from_inside_target;
82  };
83
84  // The stack holds occluded regions for subtrees in the
85  // RenderSurfaceImpl-Layer tree, so that when we leave a subtree we may apply
86  // a mask to it, but not to the parts outside the subtree.
87  // - The first time we see a new subtree under a target, we add that target to
88  // the top of the stack. This can happen as a layer representing itself, or as
89  // a target surface.
90  // - When we visit a target surface, we apply its mask to its subtree, which
91  // is at the top of the stack.
92  // - When we visit a layer representing itself, we add its occlusion to the
93  // current subtree, which is at the top of the stack.
94  // - When we visit a layer representing a contributing surface, the current
95  // target will never be the top of the stack since we just came from the
96  // contributing surface.
97  // We merge the occlusion at the top of the stack with the new current
98  // subtree. This new target is pushed onto the stack if not already there.
99  std::vector<StackObject> stack_;
100
101 private:
102  // Called when visiting a layer representing itself. If the target was not
103  // already current, then this indicates we have entered a new surface subtree.
104  void EnterRenderTarget(const LayerType* new_target);
105
106  // Called when visiting a layer representing a target surface. This indicates
107  // we have visited all the layers within the surface, and we may perform any
108  // surface-wide operations.
109  void FinishedRenderTarget(const LayerType* finished_target);
110
111  // Called when visiting a layer representing a contributing surface. This
112  // indicates that we are leaving our current surface, and entering the new
113  // one. We then perform any operations required for merging results from the
114  // child subtree into its parent.
115  void LeaveToRenderTarget(const LayerType* new_target);
116
117  // Add the layer's occlusion to the tracked state.
118  void MarkOccludedBehindLayer(const LayerType* layer);
119
120  gfx::Rect screen_space_clip_rect_;
121  gfx::Size minimum_tracking_size_;
122
123  // This is used for visualizing the occlusion tracking process.
124  std::vector<gfx::Rect>* occluding_screen_space_rects_;
125  std::vector<gfx::Rect>* non_occluding_screen_space_rects_;
126
127  DISALLOW_COPY_AND_ASSIGN(OcclusionTracker);
128};
129
130#if !defined(COMPILER_MSVC)
131extern template class OcclusionTracker<Layer>;
132extern template class OcclusionTracker<LayerImpl>;
133#endif
134
135}  // namespace cc
136
137#endif  // CC_TREES_OCCLUSION_TRACKER_H_
138