GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / cc / resources / tiling_set_raster_queue_all.cc
blob2ccba67eeb31e637ff39644507d23e1c0bf83d31
1 // Copyright 2014 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.
5 #include "cc/resources/tiling_set_raster_queue_all.h"
7 #include <utility>
9 #include "cc/resources/picture_layer_tiling_set.h"
10 #include "cc/resources/tile.h"
11 #include "cc/resources/tile_priority.h"
13 namespace cc {
15 TilingSetRasterQueueAll::TilingSetRasterQueueAll(
16 PictureLayerTilingSet* tiling_set,
17 bool prioritize_low_res)
18 : tiling_set_(tiling_set), current_stage_(0) {
19 DCHECK(tiling_set_);
21 // Early out if the tiling set has no tilings.
22 if (!tiling_set_->num_tilings()) {
23 current_stage_ = arraysize(stages_);
24 return;
27 // Find high and low res tilings and initialize the iterators.
28 for (size_t i = 0; i < tiling_set_->num_tilings(); ++i) {
29 PictureLayerTiling* tiling = tiling_set_->tiling_at(i);
30 if (tiling->resolution() == HIGH_RESOLUTION)
31 iterators_[HIGH_RES] = TilingIterator(tiling, &tiling->tiling_data_);
32 if (prioritize_low_res && tiling->resolution() == LOW_RESOLUTION)
33 iterators_[LOW_RES] = TilingIterator(tiling, &tiling->tiling_data_);
36 if (prioritize_low_res) {
37 stages_[0].iterator_type = LOW_RES;
38 stages_[0].tile_type = TilePriority::NOW;
40 stages_[1].iterator_type = HIGH_RES;
41 stages_[1].tile_type = TilePriority::NOW;
42 } else {
43 stages_[0].iterator_type = HIGH_RES;
44 stages_[0].tile_type = TilePriority::NOW;
46 stages_[1].iterator_type = LOW_RES;
47 stages_[1].tile_type = TilePriority::NOW;
50 stages_[2].iterator_type = HIGH_RES;
51 stages_[2].tile_type = TilePriority::SOON;
53 stages_[3].iterator_type = HIGH_RES;
54 stages_[3].tile_type = TilePriority::EVENTUALLY;
56 IteratorType index = stages_[current_stage_].iterator_type;
57 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
58 if (iterators_[index].done() || iterators_[index].type() != tile_type)
59 AdvanceToNextStage();
62 TilingSetRasterQueueAll::~TilingSetRasterQueueAll() {
65 bool TilingSetRasterQueueAll::IsEmpty() const {
66 return current_stage_ >= arraysize(stages_);
69 void TilingSetRasterQueueAll::Pop() {
70 IteratorType index = stages_[current_stage_].iterator_type;
71 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
73 // First advance the iterator.
74 DCHECK(!iterators_[index].done());
75 DCHECK(iterators_[index].type() == tile_type);
76 ++iterators_[index];
78 if (iterators_[index].done() || iterators_[index].type() != tile_type)
79 AdvanceToNextStage();
82 Tile* TilingSetRasterQueueAll::Top() {
83 DCHECK(!IsEmpty());
85 IteratorType index = stages_[current_stage_].iterator_type;
86 DCHECK(!iterators_[index].done());
87 DCHECK(iterators_[index].type() == stages_[current_stage_].tile_type);
89 return *iterators_[index];
92 const Tile* TilingSetRasterQueueAll::Top() const {
93 DCHECK(!IsEmpty());
95 IteratorType index = stages_[current_stage_].iterator_type;
96 DCHECK(!iterators_[index].done());
97 DCHECK(iterators_[index].type() == stages_[current_stage_].tile_type);
99 return *iterators_[index];
102 void TilingSetRasterQueueAll::AdvanceToNextStage() {
103 DCHECK_LT(current_stage_, arraysize(stages_));
104 ++current_stage_;
105 while (current_stage_ < arraysize(stages_)) {
106 IteratorType index = stages_[current_stage_].iterator_type;
107 TilePriority::PriorityBin tile_type = stages_[current_stage_].tile_type;
109 if (!iterators_[index].done() && iterators_[index].type() == tile_type)
110 break;
111 ++current_stage_;
115 // OnePriorityRectIterator
116 TilingSetRasterQueueAll::OnePriorityRectIterator::OnePriorityRectIterator()
117 : tile_(nullptr), tiling_(nullptr), tiling_data_(nullptr) {
120 TilingSetRasterQueueAll::OnePriorityRectIterator::OnePriorityRectIterator(
121 PictureLayerTiling* tiling,
122 TilingData* tiling_data)
123 : tile_(nullptr), tiling_(tiling), tiling_data_(tiling_data) {
126 template <typename TilingIteratorType>
127 void TilingSetRasterQueueAll::OnePriorityRectIterator::AdvanceToNextTile(
128 TilingIteratorType* iterator) {
129 tile_ = nullptr;
130 while (!tile_ || !TileNeedsRaster(tile_)) {
131 ++(*iterator);
132 if (!(*iterator)) {
133 tile_ = nullptr;
134 return;
136 tile_ = tiling_->TileAt(iterator->index_x(), iterator->index_y());
138 tiling_->UpdateTileAndTwinPriority(tile_);
141 template <typename TilingIteratorType>
142 bool TilingSetRasterQueueAll::OnePriorityRectIterator::
143 GetFirstTileAndCheckIfValid(TilingIteratorType* iterator) {
144 tile_ = tiling_->TileAt(iterator->index_x(), iterator->index_y());
145 if (!tile_ || !TileNeedsRaster(tile_)) {
146 tile_ = nullptr;
147 return false;
149 tiling_->UpdateTileAndTwinPriority(tile_);
150 return true;
153 // VisibleTilingIterator.
154 TilingSetRasterQueueAll::VisibleTilingIterator::VisibleTilingIterator(
155 PictureLayerTiling* tiling,
156 TilingData* tiling_data)
157 : OnePriorityRectIterator(tiling, tiling_data) {
158 if (!tiling_->has_visible_rect_tiles())
159 return;
160 iterator_ =
161 TilingData::Iterator(tiling_data_, tiling_->current_visible_rect(),
162 false /* include_borders */);
163 if (!iterator_)
164 return;
165 if (!GetFirstTileAndCheckIfValid(&iterator_))
166 ++(*this);
169 TilingSetRasterQueueAll::VisibleTilingIterator&
170 TilingSetRasterQueueAll::VisibleTilingIterator::
171 operator++() {
172 AdvanceToNextTile(&iterator_);
173 return *this;
176 // SkewportTilingIterator.
177 TilingSetRasterQueueAll::SkewportTilingIterator::SkewportTilingIterator(
178 PictureLayerTiling* tiling,
179 TilingData* tiling_data)
180 : OnePriorityRectIterator(tiling, tiling_data) {
181 if (!tiling_->has_skewport_rect_tiles())
182 return;
183 iterator_ = TilingData::SpiralDifferenceIterator(
184 tiling_data_, tiling_->current_skewport_rect(),
185 tiling_->current_visible_rect(), tiling_->current_visible_rect());
186 if (!iterator_)
187 return;
188 if (!GetFirstTileAndCheckIfValid(&iterator_))
189 ++(*this);
192 TilingSetRasterQueueAll::SkewportTilingIterator&
193 TilingSetRasterQueueAll::SkewportTilingIterator::
194 operator++() {
195 AdvanceToNextTile(&iterator_);
196 return *this;
199 // SoonBorderTilingIterator.
200 TilingSetRasterQueueAll::SoonBorderTilingIterator::SoonBorderTilingIterator(
201 PictureLayerTiling* tiling,
202 TilingData* tiling_data)
203 : OnePriorityRectIterator(tiling, tiling_data) {
204 if (!tiling_->has_soon_border_rect_tiles())
205 return;
206 iterator_ = TilingData::SpiralDifferenceIterator(
207 tiling_data_, tiling_->current_soon_border_rect(),
208 tiling_->current_skewport_rect(), tiling_->current_visible_rect());
209 if (!iterator_)
210 return;
211 if (!GetFirstTileAndCheckIfValid(&iterator_))
212 ++(*this);
215 TilingSetRasterQueueAll::SoonBorderTilingIterator&
216 TilingSetRasterQueueAll::SoonBorderTilingIterator::
217 operator++() {
218 AdvanceToNextTile(&iterator_);
219 return *this;
222 // EventuallyTilingIterator.
223 TilingSetRasterQueueAll::EventuallyTilingIterator::EventuallyTilingIterator(
224 PictureLayerTiling* tiling,
225 TilingData* tiling_data)
226 : OnePriorityRectIterator(tiling, tiling_data) {
227 if (!tiling_->has_eventually_rect_tiles())
228 return;
229 iterator_ = TilingData::SpiralDifferenceIterator(
230 tiling_data_, tiling_->current_eventually_rect(),
231 tiling_->current_skewport_rect(), tiling_->current_soon_border_rect());
232 if (!iterator_)
233 return;
234 if (!GetFirstTileAndCheckIfValid(&iterator_))
235 ++(*this);
238 TilingSetRasterQueueAll::EventuallyTilingIterator&
239 TilingSetRasterQueueAll::EventuallyTilingIterator::
240 operator++() {
241 AdvanceToNextTile(&iterator_);
242 return *this;
245 // TilingIterator
246 TilingSetRasterQueueAll::TilingIterator::TilingIterator()
247 : tiling_(NULL), current_tile_(NULL) {
250 TilingSetRasterQueueAll::TilingIterator::TilingIterator(
251 PictureLayerTiling* tiling,
252 TilingData* tiling_data)
253 : tiling_(tiling),
254 tiling_data_(tiling_data),
255 phase_(VISIBLE_RECT),
256 current_tile_(NULL) {
257 visible_iterator_ = VisibleTilingIterator(tiling_, tiling_data_);
258 if (visible_iterator_.done()) {
259 AdvancePhase();
260 return;
262 current_tile_ = *visible_iterator_;
265 void TilingSetRasterQueueAll::TilingIterator::AdvancePhase() {
266 DCHECK_LT(phase_, EVENTUALLY_RECT);
268 current_tile_ = nullptr;
269 while (!current_tile_ && phase_ < EVENTUALLY_RECT) {
270 phase_ = static_cast<Phase>(phase_ + 1);
271 switch (phase_) {
272 case VISIBLE_RECT:
273 NOTREACHED();
274 return;
275 case SKEWPORT_RECT:
276 skewport_iterator_ = SkewportTilingIterator(tiling_, tiling_data_);
277 if (!skewport_iterator_.done())
278 current_tile_ = *skewport_iterator_;
279 break;
280 case SOON_BORDER_RECT:
281 soon_border_iterator_ = SoonBorderTilingIterator(tiling_, tiling_data_);
282 if (!soon_border_iterator_.done())
283 current_tile_ = *soon_border_iterator_;
284 break;
285 case EVENTUALLY_RECT:
286 eventually_iterator_ = EventuallyTilingIterator(tiling_, tiling_data_);
287 if (!eventually_iterator_.done())
288 current_tile_ = *eventually_iterator_;
289 break;
294 TilingSetRasterQueueAll::TilingIterator&
295 TilingSetRasterQueueAll::TilingIterator::
296 operator++() {
297 switch (phase_) {
298 case VISIBLE_RECT:
299 ++visible_iterator_;
300 if (visible_iterator_.done()) {
301 AdvancePhase();
302 return *this;
304 current_tile_ = *visible_iterator_;
305 break;
306 case SKEWPORT_RECT:
307 ++skewport_iterator_;
308 if (skewport_iterator_.done()) {
309 AdvancePhase();
310 return *this;
312 current_tile_ = *skewport_iterator_;
313 break;
314 case SOON_BORDER_RECT:
315 ++soon_border_iterator_;
316 if (soon_border_iterator_.done()) {
317 AdvancePhase();
318 return *this;
320 current_tile_ = *soon_border_iterator_;
321 break;
322 case EVENTUALLY_RECT:
323 ++eventually_iterator_;
324 if (eventually_iterator_.done()) {
325 current_tile_ = nullptr;
326 return *this;
328 current_tile_ = *eventually_iterator_;
329 break;
331 return *this;
334 } // namespace cc