Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1251)

Side by Side Diff: ui/cc/TiledLayerChromium.cpp

Issue 10701016: Initial import attempt, just to play with. Many things disabled/removed (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/cc/TiledLayerChromium.h ('k') | ui/cc/TilingData.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27
28 #if USE(ACCELERATED_COMPOSITING)
29
30 #include "TiledLayerChromium.h"
31
32 #include "GraphicsContext3D.h"
33 #include "ManagedTexture.h"
34 #include "Region.h"
35 #include "TextStream.h"
36
37 #include "cc/CCLayerImpl.h"
38 #include "cc/CCLayerTreeHost.h"
39 #include "cc/CCOverdrawMetrics.h"
40 #include "cc/CCTextureUpdater.h"
41 #include "cc/CCTiledLayerImpl.h"
42
43 #include <wtf/CurrentTime.h>
44 #include <wtf/MathExtras.h>
45
46 using namespace std;
47 using WebKit::WebTransformationMatrix;
48
49 namespace WebCore {
50
51 class UpdatableTile : public CCLayerTilingData::Tile {
52 WTF_MAKE_NONCOPYABLE(UpdatableTile);
53 public:
54 static PassOwnPtr<UpdatableTile> create(PassOwnPtr<LayerTextureUpdater::Text ure> texture)
55 {
56 return adoptPtr(new UpdatableTile(texture));
57 }
58
59 LayerTextureUpdater::Texture* texture() { return m_texture.get(); }
60 ManagedTexture* managedTexture() { return m_texture->texture(); }
61
62 bool isDirty() const { return !dirtyRect.isEmpty(); }
63 void copyAndClearDirty()
64 {
65 updateRect = dirtyRect;
66 dirtyRect = IntRect();
67 }
68 // Returns whether the layer was dirty and not updated in the current frame. For tiles that were not culled, the
69 // updateRect holds the area of the tile that was updated. Otherwise, the ar ea that would have been updated.
70 bool isDirtyForCurrentFrame() { return !dirtyRect.isEmpty() && (updateRect.i sEmpty() || !updated); }
71
72 IntRect dirtyRect;
73 IntRect updateRect;
74 bool partialUpdate;
75 bool updated;
76 bool isInUseOnImpl;
77 private:
78 explicit UpdatableTile(PassOwnPtr<LayerTextureUpdater::Texture> texture)
79 : partialUpdate(false)
80 , updated(false)
81 , isInUseOnImpl(false)
82 , m_texture(texture)
83 {
84 }
85
86 OwnPtr<LayerTextureUpdater::Texture> m_texture;
87 };
88
89 TiledLayerChromium::TiledLayerChromium()
90 : LayerChromium()
91 , m_textureFormat(GL_INVALID_ENUM)
92 , m_skipsDraw(false)
93 , m_skipsIdlePaint(false)
94 , m_sampledTexelFormat(LayerTextureUpdater::SampledTexelFormatInvalid)
95 , m_didPaint(false)
96 , m_tilingOption(AutoTile)
97 {
98 m_tiler = CCLayerTilingData::create(IntSize(), CCLayerTilingData::HasBorderT exels);
99 }
100
101 TiledLayerChromium::~TiledLayerChromium()
102 {
103 }
104
105 PassOwnPtr<CCLayerImpl> TiledLayerChromium::createCCLayerImpl()
106 {
107 return CCTiledLayerImpl::create(id());
108 }
109
110 void TiledLayerChromium::updateTileSizeAndTilingOption()
111 {
112 ASSERT(layerTreeHost());
113
114 const IntSize& defaultTileSize = layerTreeHost()->settings().defaultTileSize ;
115 const IntSize& maxUntiledLayerSize = layerTreeHost()->settings().maxUntiledL ayerSize;
116 int layerWidth = contentBounds().width();
117 int layerHeight = contentBounds().height();
118
119 const IntSize tileSize(min(defaultTileSize.width(), layerWidth), min(default TileSize.height(), layerHeight));
120
121 // Tile if both dimensions large, or any one dimension large and the other
122 // extends into a second tile but the total layer area isn't larger than tha t
123 // of the largest possible untiled layer. This heuristic allows for long ski nny layers
124 // (e.g. scrollbars) that are Nx1 tiles to minimize wasted texture space but still avoids
125 // creating very large tiles.
126 const bool anyDimensionLarge = layerWidth > maxUntiledLayerSize.width() || l ayerHeight > maxUntiledLayerSize.height();
127 const bool anyDimensionOneTile = (layerWidth <= defaultTileSize.width() || l ayerHeight <= defaultTileSize.height())
128 && (layerWidth * layerHeight) <= (maxUntil edLayerSize.width() * maxUntiledLayerSize.height());
129 const bool autoTiled = anyDimensionLarge && !anyDimensionOneTile;
130
131 bool isTiled;
132 if (m_tilingOption == AlwaysTile)
133 isTiled = true;
134 else if (m_tilingOption == NeverTile)
135 isTiled = false;
136 else
137 isTiled = autoTiled;
138
139 IntSize requestedSize = isTiled ? tileSize : contentBounds();
140 const int maxSize = layerTreeHost()->layerRendererCapabilities().maxTextureS ize;
141 IntSize clampedSize = requestedSize.shrunkTo(IntSize(maxSize, maxSize));
142 setTileSize(clampedSize);
143 }
144
145 void TiledLayerChromium::updateBounds()
146 {
147 IntSize oldBounds = m_tiler->bounds();
148 IntSize newBounds = contentBounds();
149 if (oldBounds == newBounds)
150 return;
151 m_tiler->setBounds(newBounds);
152
153 // Invalidate any areas that the new bounds exposes.
154 Region oldRegion(IntRect(IntPoint(), oldBounds));
155 Region newRegion(IntRect(IntPoint(), newBounds));
156 newRegion.subtract(oldRegion);
157 Vector<IntRect> rects = newRegion.rects();
158 for (size_t i = 0; i < rects.size(); ++i)
159 invalidateRect(rects[i]);
160 }
161
162 void TiledLayerChromium::setTileSize(const IntSize& size)
163 {
164 m_tiler->setTileSize(size);
165 }
166
167 void TiledLayerChromium::setBorderTexelOption(CCLayerTilingData::BorderTexelOpti on borderTexelOption)
168 {
169 m_tiler->setBorderTexelOption(borderTexelOption);
170 }
171
172 bool TiledLayerChromium::drawsContent() const
173 {
174 if (!LayerChromium::drawsContent())
175 return false;
176
177 bool hasMoreThanOneTile = m_tiler->numTilesX() > 1 || m_tiler->numTilesY() > 1;
178 if (m_tilingOption == NeverTile && hasMoreThanOneTile)
179 return false;
180
181 return true;
182 }
183
184 bool TiledLayerChromium::needsContentsScale() const
185 {
186 return true;
187 }
188
189 IntSize TiledLayerChromium::contentBounds() const
190 {
191 return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds() .height() * contentsScale()));
192 }
193
194 void TiledLayerChromium::setTilingOption(TilingOption tilingOption)
195 {
196 m_tilingOption = tilingOption;
197 }
198
199 void TiledLayerChromium::setIsMask(bool isMask)
200 {
201 setTilingOption(isMask ? NeverTile : AutoTile);
202 }
203
204 void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
205 {
206 LayerChromium::pushPropertiesTo(layer);
207
208 CCTiledLayerImpl* tiledLayer = static_cast<CCTiledLayerImpl*>(layer);
209
210 tiledLayer->setSkipsDraw(m_skipsDraw);
211 tiledLayer->setContentsSwizzled(m_sampledTexelFormat != LayerTextureUpdater: :SampledTexelFormatRGBA);
212 tiledLayer->setTilingData(*m_tiler);
213 Vector<UpdatableTile*> invalidTiles;
214
215 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) {
216 int i = iter->first.first;
217 int j = iter->first.second;
218 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
219 // FIXME: This should not ever be null.
220 if (!tile)
221 continue;
222 tile->isInUseOnImpl = false;
223 if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureForma t)) {
224 invalidTiles.append(tile);
225 continue;
226 }
227 if (tile->isDirtyForCurrentFrame())
228 continue;
229
230 tiledLayer->pushTileProperties(i, j, tile->managedTexture()->textureId() , tile->opaqueRect());
231 tile->isInUseOnImpl = true;
232 }
233 for (Vector<UpdatableTile*>::const_iterator iter = invalidTiles.begin(); ite r != invalidTiles.end(); ++iter)
234 m_tiler->takeTile((*iter)->i(), (*iter)->j());
235 }
236
237 TextureManager* TiledLayerChromium::textureManager() const
238 {
239 if (!layerTreeHost())
240 return 0;
241 return layerTreeHost()->contentsTextureManager();
242 }
243
244 void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
245 {
246 if (host && host != layerTreeHost()) {
247 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles(). begin(); iter != m_tiler->tiles().end(); ++iter) {
248 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get() );
249 // FIXME: This should not ever be null.
250 if (!tile)
251 continue;
252 tile->managedTexture()->setTextureManager(host->contentsTextureManag er());
253 }
254 }
255 LayerChromium::setLayerTreeHost(host);
256 }
257
258 UpdatableTile* TiledLayerChromium::tileAt(int i, int j) const
259 {
260 return static_cast<UpdatableTile*>(m_tiler->tileAt(i, j));
261 }
262
263 UpdatableTile* TiledLayerChromium::createTile(int i, int j)
264 {
265 OwnPtr<UpdatableTile> tile(UpdatableTile::create(textureUpdater()->createTex ture(textureManager())));
266 UpdatableTile* addedTile = tile.get();
267 m_tiler->addTile(tile.release(), i, j);
268
269 addedTile->dirtyRect = m_tiler->tileRect(addedTile);
270
271 // Temporary diagnostic crash.
272 if (!addedTile)
273 CRASH();
274 if (!tileAt(i, j))
275 CRASH();
276
277 return addedTile;
278 }
279
280 void TiledLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
281 {
282 FloatRect scaledDirtyRect(dirtyRect);
283 scaledDirtyRect.scale(contentsScale());
284 IntRect dirty = enclosingIntRect(scaledDirtyRect);
285 invalidateRect(dirty);
286 LayerChromium::setNeedsDisplayRect(dirtyRect);
287 }
288
289 void TiledLayerChromium::setIsNonCompositedContent(bool isNonCompositedContent)
290 {
291 LayerChromium::setIsNonCompositedContent(isNonCompositedContent);
292
293 CCLayerTilingData::BorderTexelOption borderTexelOption;
294 #if OS(ANDROID)
295 // Always want border texels and GL_LINEAR due to pinch zoom.
296 borderTexelOption = CCLayerTilingData::HasBorderTexels;
297 #else
298 borderTexelOption = isNonCompositedContent ? CCLayerTilingData::NoBorderTexe ls : CCLayerTilingData::HasBorderTexels;
299 #endif
300 setBorderTexelOption(borderTexelOption);
301 }
302
303 void TiledLayerChromium::invalidateRect(const IntRect& layerRect)
304 {
305 updateBounds();
306 if (m_tiler->isEmpty() || layerRect.isEmpty() || m_skipsDraw)
307 return;
308
309 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) {
310 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
311 ASSERT(tile);
312 // FIXME: This should not ever be null.
313 if (!tile)
314 continue;
315 IntRect bound = m_tiler->tileRect(tile);
316 bound.intersect(layerRect);
317 tile->dirtyRect.unite(bound);
318 }
319 }
320
321 void TiledLayerChromium::protectTileTextures(const IntRect& layerRect)
322 {
323 if (m_tiler->isEmpty() || layerRect.isEmpty())
324 return;
325
326 int left, top, right, bottom;
327 m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom);
328
329 for (int j = top; j <= bottom; ++j) {
330 for (int i = left; i <= right; ++i) {
331 UpdatableTile* tile = tileAt(i, j);
332 if (!tile || !tile->managedTexture()->isValid(m_tiler->tileSize(), m _textureFormat))
333 continue;
334
335 tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureFormat );
336 }
337 }
338 }
339
340 // Returns true if tile is dirty and only part of it needs to be updated.
341 bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile)
342 {
343 return !tile->dirtyRect.contains(m_tiler->tileRect(tile));
344 }
345
346 // Dirty tiles with valid textures needs buffered update to guarantee that
347 // we don't modify textures currently used for drawing by the impl thread.
348 bool TiledLayerChromium::tileNeedsBufferedUpdate(UpdatableTile* tile)
349 {
350 if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
351 return false;
352
353 if (!tile->isDirty())
354 return false;
355
356 if (!tile->isInUseOnImpl)
357 return false;
358
359 return true;
360 }
361
362 void TiledLayerChromium::updateTiles(bool idle, int left, int top, int right, in t bottom, CCTextureUpdater& updater, const CCOcclusionTracker* occlusion)
363 {
364 createTextureUpdaterIfNeeded();
365
366 // Create tiles as needed, expanding a dirty rect to contain all
367 // the dirty regions currently being drawn. All dirty tiles that are to be p ainted
368 // get their updateRect set to dirtyRect and dirtyRect cleared. This way if
369 // invalidateRect is invoked during updateLayerRect we don't lose the reques t.
370 IntRect paintRect;
371 for (int j = top; j <= bottom; ++j) {
372 for (int i = left; i <= right; ++i) {
373 UpdatableTile* tile = tileAt(i, j);
374 if (!tile)
375 tile = createTile(i, j);
376
377 // Temporary diagnostic crash
378 if (!m_tiler)
379 CRASH();
380
381 if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureF ormat)) {
382 // Sets the dirty rect to a full-sized tile with border texels.
383 tile->dirtyRect = m_tiler->tileRect(tile);
384 }
385
386 // When not idle painting, if the visible region of the tile is occl uded, don't reserve a texture or update the tile.
387 // If any part of the tile is visible, then we need to update it so the tile is pushed to the impl thread.
388 if (!idle && occlusion) {
389 IntRect visibleTileRect = intersection(m_tiler->tileBounds(i, j) , visibleLayerRect());
390 if (occlusion->occluded(this, visibleTileRect)) {
391 ASSERT(!tile->updated);
392 continue;
393 }
394 }
395
396 // We come through this function multiple times during a commit, and updated should be true if the tile is not culled
397 // any single time through the function.
398 tile->updated = true;
399
400 if (layerTreeHost() && layerTreeHost()->bufferedUpdates() && tileNee dsBufferedUpdate(tile)) {
401 // FIXME: Decide if partial update should be allowed based on co st
402 // of update. https://bugs.webkit.org/show_bug.cgi?id=77376
403 if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->request PartialTextureUpdate())
404 tile->partialUpdate = true;
405 else {
406 layerTreeHost()->deleteTextureAfterCommit(tile->managedTextu re()->steal());
407 // Sets the dirty rect to a full-sized tile with border texe ls.
408 tile->dirtyRect = m_tiler->tileRect(tile);
409 }
410 }
411
412 if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureF ormat)) {
413 m_skipsIdlePaint = true;
414 if (!idle) {
415 m_skipsDraw = true;
416 m_tiler->reset();
417 }
418 return;
419 }
420
421 paintRect.unite(tile->dirtyRect);
422 }
423 }
424
425 // For tiles that were not culled, we are going to update the area currently marked as dirty. So
426 // clear that dirty area and mark it for update instead.
427 for (int j = top; j <= bottom; ++j) {
428 for (int i = left; i <= right; ++i) {
429 UpdatableTile* tile = tileAt(i, j);
430 // FIXME: This should not ever be null.
431 if (!tile)
432 continue;
433 if (tile->updated)
434 tile->copyAndClearDirty();
435 else if (!idle && occlusion && tile->isDirty())
436 occlusion->overdrawMetrics().didCullTileForUpload();
437 }
438 }
439
440 if (paintRect.isEmpty())
441 return;
442
443 if (occlusion)
444 occlusion->overdrawMetrics().didPaint(paintRect);
445
446 // The updateRect should be in layer space. So we have to convert the paintR ect from content space to layer space.
447 m_updateRect = FloatRect(paintRect);
448 float widthScale = bounds().width() / static_cast<float>(contentBounds().wid th());
449 float heightScale = bounds().height() / static_cast<float>(contentBounds().h eight());
450 m_updateRect.scale(widthScale, heightScale);
451
452 // Calling prepareToUpdate() calls into WebKit to paint, which may have the side
453 // effect of disabling compositing, which causes our reference to the textur e updater to be deleted.
454 // However, we can't free the memory backing the SkCanvas until the paint fi nishes,
455 // so we grab a local reference here to hold the updater alive until the pai nt completes.
456 RefPtr<LayerTextureUpdater> protector(textureUpdater());
457 IntRect paintedOpaqueRect;
458 textureUpdater()->prepareToUpdate(paintRect, m_tiler->tileSize(), contentsSc ale(), paintedOpaqueRect);
459 m_didPaint = true;
460
461 for (int j = top; j <= bottom; ++j) {
462 for (int i = left; i <= right; ++i) {
463 UpdatableTile* tile = tileAt(i, j);
464 // FIXME: This should not ever be null.
465 if (!tile)
466 continue;
467
468 IntRect tileRect = m_tiler->tileBounds(i, j);
469
470 if (!tile->updated)
471 continue;
472
473 // Use updateRect as the above loop copied the dirty rect for this f rame to updateRect.
474 const IntRect& dirtyRect = tile->updateRect;
475 if (dirtyRect.isEmpty())
476 continue;
477
478 // Save what was painted opaque in the tile. Keep the old area if th e paint didn't touch it, and didn't paint some
479 // other part of the tile opaque.
480 IntRect tilePaintedRect = intersection(tileRect, paintRect);
481 IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaque Rect);
482 if (!tilePaintedRect.isEmpty()) {
483 IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRec t(), tilePaintedRect);
484 bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRe ct.contains(paintInsideTileOpaqueRect);
485 bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect .isEmpty() && !tile->opaqueRect().contains(tilePaintedOpaqueRect);
486
487 if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInside TileOpaqueRect)
488 tile->setOpaqueRect(tilePaintedOpaqueRect);
489 }
490
491 // sourceRect starts as a full-sized tile with border texels include d.
492 IntRect sourceRect = m_tiler->tileRect(tile);
493 sourceRect.intersect(dirtyRect);
494 // Paint rect not guaranteed to line up on tile boundaries, so
495 // make sure that sourceRect doesn't extend outside of it.
496 sourceRect.intersect(paintRect);
497
498 tile->updateRect = sourceRect;
499
500 if (sourceRect.isEmpty())
501 continue;
502
503 tile->texture()->prepareRect(sourceRect);
504 if (occlusion)
505 occlusion->overdrawMetrics().didUpload(WebTransformationMatrix() , sourceRect, tile->opaqueRect());
506
507 const IntPoint anchor = m_tiler->tileRect(tile).location();
508
509 // Calculate tile-space rectangle to upload into.
510 IntRect destRect(IntPoint(sourceRect.x() - anchor.x(), sourceRect.y( ) - anchor.y()), sourceRect.size());
511 if (destRect.x() < 0)
512 CRASH();
513 if (destRect.y() < 0)
514 CRASH();
515
516 // Offset from paint rectangle to this tile's dirty rectangle.
517 IntPoint paintOffset(sourceRect.x() - paintRect.x(), sourceRect.y() - paintRect.y());
518 if (paintOffset.x() < 0)
519 CRASH();
520 if (paintOffset.y() < 0)
521 CRASH();
522 if (paintOffset.x() + destRect.width() > paintRect.width())
523 CRASH();
524 if (paintOffset.y() + destRect.height() > paintRect.height())
525 CRASH();
526
527 if (tile->partialUpdate)
528 updater.appendPartialUpdate(tile->texture(), sourceRect, destRec t);
529 else
530 updater.appendUpdate(tile->texture(), sourceRect, destRect);
531 }
532 }
533 }
534
535 void TiledLayerChromium::reserveTextures()
536 {
537 updateBounds();
538
539 const IntRect& layerRect = visibleLayerRect();
540 if (layerRect.isEmpty() || m_tiler->hasEmptyBounds())
541 return;
542
543 int left, top, right, bottom;
544 m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom);
545
546 createTextureUpdaterIfNeeded();
547 for (int j = top; j <= bottom; ++j) {
548 for (int i = left; i <= right; ++i) {
549 UpdatableTile* tile = tileAt(i, j);
550 if (!tile)
551 tile = createTile(i, j);
552
553 if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureF ormat))
554 tile->dirtyRect = m_tiler->tileRect(tile);
555
556 if (!tile->managedTexture()->reserve(m_tiler->tileSize(), m_textureF ormat))
557 return;
558 }
559 }
560 }
561
562 Region TiledLayerChromium::visibleContentOpaqueRegion() const
563 {
564 if (m_skipsDraw)
565 return Region();
566 if (opaque())
567 return visibleLayerRect();
568 return m_tiler->opaqueRegionInLayerRect(visibleLayerRect());
569 }
570
571 void TiledLayerChromium::resetUpdateState()
572 {
573 CCLayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end();
574 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != end; ++iter) {
575 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
576 // FIXME: This should not ever be null.
577 if (!tile)
578 continue;
579 tile->updateRect = IntRect();
580 tile->partialUpdate = false;
581 tile->updated = false;
582 }
583 }
584
585 void TiledLayerChromium::updateLayerRect(CCTextureUpdater& updater, const IntRec t& layerRect, const CCOcclusionTracker* occlusion)
586 {
587 m_skipsDraw = false;
588 m_skipsIdlePaint = false;
589 m_didPaint = false;
590
591 updateBounds();
592
593 resetUpdateState();
594
595 if (layerRect.isEmpty() || m_tiler->hasEmptyBounds())
596 return;
597
598 int left, top, right, bottom;
599 m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom);
600
601 updateTiles(false, left, top, right, bottom, updater, occlusion);
602 }
603
604 void TiledLayerChromium::idleUpdateLayerRect(CCTextureUpdater& updater, const In tRect& layerRect, const CCOcclusionTracker* occlusion)
605 {
606 // Abort if we have already painted or run out of memory.
607 if (m_skipsIdlePaint || m_didPaint)
608 return;
609
610 ASSERT(m_tiler);
611
612 updateBounds();
613
614 if (m_tiler->hasEmptyBounds())
615 return;
616
617 IntRect idlePaintLayerRect = idlePaintRect(layerRect);
618 if (idlePaintLayerRect.isEmpty())
619 return;
620
621 // Protect any textures in the pre-paint area, as we would steal them from o ther layers
622 // over time anyhow. This ensures we don't lose tiles in the first rounds of idle painting
623 // that we have already painted.
624 protectTileTextures(idlePaintLayerRect);
625
626 int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom;
627 m_tiler->layerRectToTileIndices(idlePaintLayerRect, prepaintLeft, prepaintTo p, prepaintRight, prepaintBottom);
628
629 // If the layer is not visible, we have nothing to expand from, so instead w e prepaint the outer-most set of tiles.
630 if (layerRect.isEmpty()) {
631 updateTiles(true, prepaintLeft, prepaintTop, prepaintRight, prepaintTop, updater, 0);
632 if (m_didPaint || m_skipsIdlePaint)
633 return;
634 updateTiles(true, prepaintLeft, prepaintBottom, prepaintRight, prepaintB ottom, updater, 0);
635 if (m_didPaint || m_skipsIdlePaint)
636 return;
637 updateTiles(true, prepaintLeft, prepaintTop, prepaintLeft, prepaintBotto m, updater, 0);
638 if (m_didPaint || m_skipsIdlePaint)
639 return;
640 updateTiles(true, prepaintRight, prepaintTop, prepaintRight, prepaintBot tom, updater, 0);
641 return;
642 }
643
644 int left, top, right, bottom;
645 m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom);
646
647 // Otherwise, prepaint anything that was occluded but inside the layer's vis ible region.
648 updateTiles(true, left, top, right, bottom, updater, 0);
649 if (m_didPaint || m_skipsIdlePaint)
650 return;
651
652 // Then expand outwards from the visible area until we find a dirty row or c olumn to update.
653 while (!m_skipsIdlePaint && (left > prepaintLeft || top > prepaintTop || rig ht < prepaintRight || bottom < prepaintBottom)) {
654 if (bottom < prepaintBottom) {
655 ++bottom;
656 updateTiles(true, left, bottom, right, bottom, updater, 0);
657 if (m_didPaint || m_skipsIdlePaint)
658 break;
659 }
660 if (top > prepaintTop) {
661 --top;
662 updateTiles(true, left, top, right, top, updater, 0);
663 if (m_didPaint || m_skipsIdlePaint)
664 break;
665 }
666 if (left > prepaintLeft) {
667 --left;
668 updateTiles(true, left, top, left, bottom, updater, 0);
669 if (m_didPaint || m_skipsIdlePaint)
670 break;
671 }
672 if (right < prepaintRight) {
673 ++right;
674 updateTiles(true, right, top, right, bottom, updater, 0);
675 if (m_didPaint || m_skipsIdlePaint)
676 break;
677 }
678 }
679 }
680
681 bool TiledLayerChromium::needsIdlePaint(const IntRect& layerRect)
682 {
683 if (m_skipsIdlePaint)
684 return false;
685
686 if (m_tiler->hasEmptyBounds())
687 return false;
688
689 IntRect idlePaintLayerRect = idlePaintRect(layerRect);
690 if (idlePaintLayerRect.isEmpty())
691 return false;
692
693 int left, top, right, bottom;
694 m_tiler->layerRectToTileIndices(idlePaintLayerRect, left, top, right, bottom );
695 for (int j = top; j <= bottom; ++j) {
696 for (int i = left; i <= right; ++i) {
697 // If the layerRect is empty, then we are painting the outer-most se t of tiles only.
698 if (layerRect.isEmpty() && i != left && i != right && j != top && j != bottom)
699 continue;
700 UpdatableTile* tile = tileAt(i, j);
701 if (!tile || !tile->managedTexture()->isValid(m_tiler->tileSize(), m _textureFormat) || tile->isDirty())
702 return true;
703 }
704 }
705 return false;
706 }
707
708 IntRect TiledLayerChromium::idlePaintRect(const IntRect& visibleLayerRect)
709 {
710 // For layers that are animating transforms but not visible at all, we don't know what part
711 // of them is going to become visible. For small layers we return the entire layer, for larger
712 // ones we avoid prepainting the layer at all.
713 if (visibleLayerRect.isEmpty()) {
714 bool isSmallLayer = m_tiler->numTilesX() <= 9 && m_tiler->numTilesY() <= 9 && m_tiler->numTilesX() * m_tiler->numTilesY() <= 9;
715 if ((drawTransformIsAnimating() || screenSpaceTransformIsAnimating()) && isSmallLayer)
716 return IntRect(IntPoint(), contentBounds());
717 return IntRect();
718 }
719
720 IntRect prepaintRect = visibleLayerRect;
721 // FIXME: This can be made a lot larger if we can:
722 // - reserve memory at a lower priority than for visible content
723 // - only reserve idle paint tiles up to a memory reclaim threshold and
724 // - insure we play nicely with other layers
725 prepaintRect.inflateX(m_tiler->tileSize().width());
726 prepaintRect.inflateY(m_tiler->tileSize().height());
727 prepaintRect.intersect(IntRect(IntPoint::zero(), contentBounds()));
728 return prepaintRect;
729 }
730
731 }
732 #endif // USE(ACCELERATED_COMPOSITING)
OLDNEW
« no previous file with comments | « ui/cc/TiledLayerChromium.h ('k') | ui/cc/TilingData.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698