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 17 namespace cc { 18 class LayerImpl; 19 class Region; 20 class RenderSurfaceImpl; 21 class Layer; 22 class 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(). 33 template <typename LayerType> 34 class 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) 131 extern template class OcclusionTracker<Layer>; 132 extern template class OcclusionTracker<LayerImpl>; 133 #endif 134 135 } // namespace cc 136 137 #endif // CC_TREES_OCCLUSION_TRACKER_H_ 138