summaryrefslogtreecommitdiffstats
path: root/chromium/cc/layers/layer_iterator.h
blob: fbdb53a25c23c3130890885cfe0e5a16ddee7e40 (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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
// 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_LAYERS_LAYER_ITERATOR_H_
#define CC_LAYERS_LAYER_ITERATOR_H_

#include "cc/base/cc_export.h"
#include "cc/trees/layer_tree_host_common.h"

namespace cc {

// These classes provide means to iterate over the
// RenderSurface-Layer tree.

// Example code follows, for a tree of Layer/RenderSurface objects.
// See below for details.
//
// void DoStuffOnLayers(
//     const RenderSurfaceLayerList& render_surface_layer_list) {
//   typedef LayerIterator<Layer> LayerIteratorType;
//
//   LayerIteratorType end =
//       LayerIteratorType::End(&render_surface_layer_list);
//   for (LayerIteratorType
//            it = LayerIteratorType::Begin(&render_surface_layer_list);
//        it != end;
//        ++it) {
//     // Only one of these will be true
//     if (it.represents_target_render_surface())
//       foo(*it);  // *it is a layer representing a target RenderSurface
//     if (it.represents_contributing_render_surface())
//       bar(*it);  // *it is a layer representing a RenderSurface that
//                  // contributes to the layer's target RenderSurface
//     if (it.represents_itself())
//       baz(*it);  // *it is a layer representing itself,
//                  // as it contributes to its own target RenderSurface
//   }
// }

// A RenderSurface R may be referred to in one of two different contexts.
// One RenderSurface is "current" at any time, for whatever operation
// is being performed. This current surface is referred to as a target surface.
// For example, when R is being painted it would be the target surface.
// Once R has been painted, its contents may be included into another
// surface S. While S is considered the target surface when it is being
// painted, R is called a contributing surface in this context as it
// contributes to the content of the target surface S.
//
// The iterator's current position in the tree always points to some layer.
// The state of the iterator indicates the role of the layer,
// and will be one of the following three states.
// A single layer L will appear in the iteration process in at least one,
// and possibly all, of these states.
// 1. Representing the target surface: The iterator in this state,
// pointing at layer L, indicates that the target RenderSurface
// is now the surface owned by L. This will occur exactly once for each
// RenderSurface in the tree.
// 2. Representing a contributing surface: The iterator in this state,
// pointing at layer L, refers to the RenderSurface owned
// by L as a contributing surface, without changing the current
// target RenderSurface.
// 3. Representing itself: The iterator in this state, pointing at layer L,
// refers to the layer itself, as a child of the
// current target RenderSurface.
//
// The FrontToBack iterator will iterate over children layers of a surface
// before the layer representing the surface as a target surface.
//
// To use the iterators:
//
// Create a stepping iterator and end iterator by calling
// LayerIterator::Begin() and LayerIterator::End() and passing in the
// list of layers owning target RenderSurfaces. Step through the tree
// by incrementing the stepping iterator while it is != to
// the end iterator. At each step the iterator knows what the layer
// is representing, and you can query the iterator to decide
// what actions to perform with the layer given what it represents.

////////////////////////////////////////////////////////////////////////////////

// Non-templated constants
struct LayerIteratorValue {
  static const int kInvalidTargetRenderSurfaceLayerIndex = -1;
  // This must be -1 since the iterator action code assumes that this value can
  // be reached by subtracting one from the position of the first layer in the
  // current target surface's child layer list, which is 0.
  static const int kLayerIndexRepresentingTargetRenderSurface = -1;
};

// The position of a layer iterator that is independent
// of its many template types.
template <typename LayerType> struct LayerIteratorPosition {
  bool represents_target_render_surface;
  bool represents_contributing_render_surface;
  bool represents_itself;
  LayerType* target_render_surface_layer;
  LayerType* current_layer;
};

// An iterator class for walking over layers in the
// RenderSurface-Layer tree.
template <typename LayerType>
class LayerIterator {
  typedef LayerIterator<LayerType> LayerIteratorType;
  typedef typename LayerType::LayerListType LayerList;
  typedef typename LayerType::RenderSurfaceListType RenderSurfaceLayerList;
  typedef typename LayerType::RenderSurfaceType RenderSurfaceType;

 public:
  LayerIterator() : render_surface_layer_list_(NULL) {}

  static LayerIteratorType Begin(
      const RenderSurfaceLayerList* render_surface_layer_list) {
    return LayerIteratorType(render_surface_layer_list, true);
  }
  static LayerIteratorType End(
      const RenderSurfaceLayerList* render_surface_layer_list) {
    return LayerIteratorType(render_surface_layer_list, false);
  }

  LayerIteratorType& operator++() {
    MoveToNext();
    return *this;
  }
  bool operator==(const LayerIterator& other) const {
    return target_render_surface_layer_index_ ==
           other.target_render_surface_layer_index_ &&
           current_layer_index_ == other.current_layer_index_;
  }
  bool operator!=(const LayerIteratorType& other) const {
    return !(*this == other);
  }

  LayerType* operator->() const { return current_layer(); }
  LayerType* operator*() const { return current_layer(); }

  bool represents_target_render_surface() const {
    return current_layer_represents_target_render_surface();
  }
  bool represents_contributing_render_surface() const {
    return !represents_target_render_surface() &&
           current_layer_represents_contributing_render_surface();
  }
  bool represents_itself() const {
    return !represents_target_render_surface() &&
           !represents_contributing_render_surface();
  }

  LayerType* target_render_surface_layer() const {
    return render_surface_layer_list_->at(target_render_surface_layer_index_);
  }

  operator const LayerIteratorPosition<LayerType>() const {
    LayerIteratorPosition<LayerType> position;
    position.represents_target_render_surface =
        represents_target_render_surface();
    position.represents_contributing_render_surface =
        represents_contributing_render_surface();
    position.represents_itself = represents_itself();
    position.target_render_surface_layer = target_render_surface_layer();
    position.current_layer = current_layer();
    return position;
  }

 private:
  LayerIterator(const RenderSurfaceLayerList* render_surface_layer_list,
                bool start)
      : render_surface_layer_list_(render_surface_layer_list),
        target_render_surface_layer_index_(0) {
    for (size_t i = 0; i < render_surface_layer_list->size(); ++i) {
      if (!render_surface_layer_list->at(i)->render_surface()) {
        NOTREACHED();
        MoveToEnd();
        return;
      }
    }

    if (start && !render_surface_layer_list->empty())
      MoveToBegin();
    else
      MoveToEnd();
  }

  void MoveToBegin() {
    target_render_surface_layer_index_ = 0;
    current_layer_index_ = target_render_surface_children().size() - 1;
    MoveToHighestInSubtree();
  }

  void MoveToEnd() {
    target_render_surface_layer_index_ =
        LayerIteratorValue::kInvalidTargetRenderSurfaceLayerIndex;
    current_layer_index_ = 0;
  }

  void MoveToNext() {
    // Moves to the previous layer in the current RS layer list.
    // Then we check if the new current layer has its own RS,
    // in which case there are things in that RS layer list that are higher,
    // so we find the highest layer in that subtree.
    // If we move back past the front of the list,
    // we jump up to the previous RS layer list, picking up again where we
    // had previously recursed into the current RS layer list.

    if (!current_layer_represents_target_render_surface()) {
      // Subtracting one here will eventually cause the current layer
      // to become that layer representing the target render surface.
      --current_layer_index_;
      MoveToHighestInSubtree();
    } else {
      while (current_layer_represents_target_render_surface()) {
        if (!target_render_surface_layer_index_) {
          // End of the list.
          target_render_surface_layer_index_ =
              LayerIteratorValue::kInvalidTargetRenderSurfaceLayerIndex;
          current_layer_index_ = 0;
          return;
        }
        target_render_surface_layer_index_ =
            target_render_surface()->target_render_surface_layer_index_history_;
        current_layer_index_ =
            target_render_surface()->current_layer_index_history_;
      }
    }
  }

  void MoveToHighestInSubtree() {
    if (current_layer_represents_target_render_surface())
      return;
    while (current_layer_represents_contributing_render_surface()) {
      // Save where we were in the current target surface, move to the next one,
      // and save the target surface that we came from there
      // so we can go back to it.
      target_render_surface()->current_layer_index_history_ =
          current_layer_index_;
      int previous_target_render_surface_layer =
          target_render_surface_layer_index_;

      for (LayerType* layer = current_layer();
           target_render_surface_layer() != layer;
           ++target_render_surface_layer_index_) {
      }
      current_layer_index_ = target_render_surface_children().size() - 1;

      target_render_surface()->target_render_surface_layer_index_history_ =
          previous_target_render_surface_layer;
    }
  }

  inline LayerType* current_layer() const {
    return current_layer_represents_target_render_surface()
               ? target_render_surface_layer()
               : LayerTreeHostCommon::get_layer_as_raw_ptr(
                     target_render_surface_children(), current_layer_index_);
  }

  inline bool current_layer_represents_contributing_render_surface() const {
    return LayerTreeHostCommon::RenderSurfaceContributesToTarget<LayerType>(
        current_layer(), target_render_surface_layer()->id());
  }
  inline bool current_layer_represents_target_render_surface() const {
    return current_layer_index_ ==
           LayerIteratorValue::kLayerIndexRepresentingTargetRenderSurface;
  }

  inline RenderSurfaceType* target_render_surface() const {
    return target_render_surface_layer()->render_surface();
  }
  inline const LayerList& target_render_surface_children() const {
    return target_render_surface()->layer_list();
  }

  const RenderSurfaceLayerList* render_surface_layer_list_;

  // The iterator's current position.

  // A position in the render_surface_layer_list. This points to a layer which
  // owns the current target surface. This is a value from 0 to n-1
  // (n = size of render_surface_layer_list = number of surfaces).
  // A value outside of this range
  // (for example, LayerIteratorValue::kInvalidTargetRenderSurfaceLayerIndex)
  // is used to indicate a position outside the bounds of the tree.
  int target_render_surface_layer_index_;
  // A position in the list of layers that are children of the
  // current target surface. When pointing to one of these layers,
  // this is a value from 0 to n-1 (n = number of children).
  // Since the iterator must also stop at the layers representing
  // the target surface, this is done by setting the current_layerIndex
  // to a value of LayerIteratorValue::LayerRepresentingTargetRenderSurface.
  int current_layer_index_;
};

}  // namespace cc

#endif  // CC_LAYERS_LAYER_ITERATOR_H_