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

Side by Side Diff: cc/TiledLayerChromium.cpp

Issue 11122003: [cc] Rename all cc/ filenames to Chromium style (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 2 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 | « cc/TiledLayerChromium.h ('k') | cc/TreeSynchronizer.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 // Copyright 2011 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 #include "config.h"
6
7 #if USE(ACCELERATED_COMPOSITING)
8
9 #include "base/basictypes.h"
10 #include "TiledLayerChromium.h"
11
12 #include "CCLayerImpl.h"
13 #include "CCLayerTreeHost.h"
14 #include "CCOverdrawMetrics.h"
15 #include "CCTextureUpdateQueue.h"
16 #include "CCTiledLayerImpl.h"
17 #include "GraphicsContext3D.h"
18 #include "Region.h"
19 #include <wtf/CurrentTime.h>
20 #include <wtf/MathExtras.h>
21
22 using namespace std;
23 using WebKit::WebTransformationMatrix;
24
25 namespace cc {
26
27 class UpdatableTile : public CCLayerTilingData::Tile {
28 public:
29 static PassOwnPtr<UpdatableTile> create(PassOwnPtr<LayerTextureUpdater::Text ure> texture)
30 {
31 return adoptPtr(new UpdatableTile(texture));
32 }
33
34 LayerTextureUpdater::Texture* texture() { return m_texture.get(); }
35 CCPrioritizedTexture* managedTexture() { return m_texture->texture(); }
36
37 bool isDirty() const { return !dirtyRect.isEmpty(); }
38
39 // Reset update state for the current frame. This should occur before painti ng
40 // for all layers. Since painting one layer can invalidate another layer
41 // after it has already painted, mark all non-dirty tiles as valid before pa inting
42 // such that invalidations during painting won't prevent them from being pus hed.
43 void resetUpdateState()
44 {
45 updateRect = IntRect();
46 occluded = false;
47 partialUpdate = false;
48 validForFrame = !isDirty();
49 }
50
51 // This promises to update the tile and therefore also guarantees the tile
52 // will be valid for this frame. dirtyRect is copied into updateRect so
53 // we can continue to track re-entrant invalidations that occur during paint ing.
54 void markForUpdate()
55 {
56 validForFrame = true;
57 updateRect = dirtyRect;
58 dirtyRect = IntRect();
59 }
60
61 IntRect dirtyRect;
62 IntRect updateRect;
63 bool partialUpdate;
64 bool validForFrame;
65 bool occluded;
66 bool isInUseOnImpl;
67 private:
68 explicit UpdatableTile(PassOwnPtr<LayerTextureUpdater::Texture> texture)
69 : partialUpdate(false)
70 , validForFrame(false)
71 , occluded(false)
72 , isInUseOnImpl(false)
73 , m_texture(texture)
74 {
75 }
76
77 OwnPtr<LayerTextureUpdater::Texture> m_texture;
78
79 DISALLOW_COPY_AND_ASSIGN(UpdatableTile);
80 };
81
82 TiledLayerChromium::TiledLayerChromium()
83 : LayerChromium()
84 , m_textureFormat(GraphicsContext3D::INVALID_ENUM)
85 , m_skipsDraw(false)
86 , m_failedUpdate(false)
87 , m_sampledTexelFormat(LayerTextureUpdater::SampledTexelFormatInvalid)
88 , m_tilingOption(AutoTile)
89 {
90 m_tiler = CCLayerTilingData::create(IntSize(), CCLayerTilingData::HasBorderT exels);
91 }
92
93 TiledLayerChromium::~TiledLayerChromium()
94 {
95 }
96
97 scoped_ptr<CCLayerImpl> TiledLayerChromium::createCCLayerImpl()
98 {
99 return CCTiledLayerImpl::create(id()).PassAs<CCLayerImpl>();
100 }
101
102 void TiledLayerChromium::updateTileSizeAndTilingOption()
103 {
104 ASSERT(layerTreeHost());
105
106 const IntSize& defaultTileSize = layerTreeHost()->settings().defaultTileSize ;
107 const IntSize& maxUntiledLayerSize = layerTreeHost()->settings().maxUntiledL ayerSize;
108 int layerWidth = contentBounds().width();
109 int layerHeight = contentBounds().height();
110
111 const IntSize tileSize(min(defaultTileSize.width(), layerWidth), min(default TileSize.height(), layerHeight));
112
113 // Tile if both dimensions large, or any one dimension large and the other
114 // extends into a second tile but the total layer area isn't larger than tha t
115 // of the largest possible untiled layer. This heuristic allows for long ski nny layers
116 // (e.g. scrollbars) that are Nx1 tiles to minimize wasted texture space but still avoids
117 // creating very large tiles.
118 const bool anyDimensionLarge = layerWidth > maxUntiledLayerSize.width() || l ayerHeight > maxUntiledLayerSize.height();
119 const bool anyDimensionOneTile = (layerWidth <= defaultTileSize.width() || l ayerHeight <= defaultTileSize.height())
120 && (layerWidth * layerHeight) <= (maxUntil edLayerSize.width() * maxUntiledLayerSize.height());
121 const bool autoTiled = anyDimensionLarge && !anyDimensionOneTile;
122
123 bool isTiled;
124 if (m_tilingOption == AlwaysTile)
125 isTiled = true;
126 else if (m_tilingOption == NeverTile)
127 isTiled = false;
128 else
129 isTiled = autoTiled;
130
131 IntSize requestedSize = isTiled ? tileSize : contentBounds();
132 const int maxSize = layerTreeHost()->rendererCapabilities().maxTextureSize;
133 IntSize clampedSize = requestedSize.shrunkTo(IntSize(maxSize, maxSize));
134 setTileSize(clampedSize);
135 }
136
137 void TiledLayerChromium::updateBounds()
138 {
139 IntSize oldBounds = m_tiler->bounds();
140 IntSize newBounds = contentBounds();
141 if (oldBounds == newBounds)
142 return;
143 m_tiler->setBounds(newBounds);
144
145 // Invalidate any areas that the new bounds exposes.
146 Region oldRegion(IntRect(IntPoint(), oldBounds));
147 Region newRegion(IntRect(IntPoint(), newBounds));
148 newRegion.subtract(oldRegion);
149 Vector<WebCore::IntRect> rects = newRegion.rects();
150 for (size_t i = 0; i < rects.size(); ++i)
151 invalidateContentRect(rects[i]);
152 }
153
154 void TiledLayerChromium::setTileSize(const IntSize& size)
155 {
156 m_tiler->setTileSize(size);
157 }
158
159 void TiledLayerChromium::setBorderTexelOption(CCLayerTilingData::BorderTexelOpti on borderTexelOption)
160 {
161 m_tiler->setBorderTexelOption(borderTexelOption);
162 }
163
164 bool TiledLayerChromium::drawsContent() const
165 {
166 if (!LayerChromium::drawsContent())
167 return false;
168
169 bool hasMoreThanOneTile = m_tiler->numTilesX() > 1 || m_tiler->numTilesY() > 1;
170 if (m_tilingOption == NeverTile && hasMoreThanOneTile)
171 return false;
172
173 return true;
174 }
175
176 bool TiledLayerChromium::needsContentsScale() const
177 {
178 return true;
179 }
180
181 IntSize TiledLayerChromium::contentBounds() const
182 {
183 return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds() .height() * contentsScale()));
184 }
185
186 void TiledLayerChromium::setTilingOption(TilingOption tilingOption)
187 {
188 m_tilingOption = tilingOption;
189 }
190
191 void TiledLayerChromium::setIsMask(bool isMask)
192 {
193 setTilingOption(isMask ? NeverTile : AutoTile);
194 }
195
196 void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer)
197 {
198 LayerChromium::pushPropertiesTo(layer);
199
200 CCTiledLayerImpl* tiledLayer = static_cast<CCTiledLayerImpl*>(layer);
201
202 tiledLayer->setSkipsDraw(m_skipsDraw);
203 tiledLayer->setContentsSwizzled(m_sampledTexelFormat != LayerTextureUpdater: :SampledTexelFormatRGBA);
204 tiledLayer->setTilingData(*m_tiler);
205 Vector<UpdatableTile*> invalidTiles;
206
207 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) {
208 #if WTF_NEW_HASHMAP_ITERATORS_INTERFACE
209 int i = iter->key.first;
210 int j = iter->key.second;
211 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->value.get());
212 #else
213 int i = iter->first.first;
214 int j = iter->first.second;
215 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
216 #endif
217 // FIXME: This should not ever be null.
218 if (!tile)
219 continue;
220
221 tile->isInUseOnImpl = false;
222
223 if (!tile->managedTexture()->haveBackingTexture()) {
224 // Evicted tiles get deleted from both layers
225 invalidTiles.append(tile);
226 continue;
227 }
228
229 if (!tile->validForFrame) {
230 // Invalidated tiles are set so they can get different debug colors.
231 tiledLayer->pushInvalidTile(i, j);
232 continue;
233 }
234
235 tiledLayer->pushTileProperties(i, j, tile->managedTexture()->resourceId( ), tile->opaqueRect());
236 tile->isInUseOnImpl = true;
237 }
238 for (Vector<UpdatableTile*>::const_iterator iter = invalidTiles.begin(); ite r != invalidTiles.end(); ++iter)
239 m_tiler->takeTile((*iter)->i(), (*iter)->j());
240 }
241
242 CCPrioritizedTextureManager* TiledLayerChromium::textureManager() const
243 {
244 if (!layerTreeHost())
245 return 0;
246 return layerTreeHost()->contentsTextureManager();
247 }
248
249 void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host)
250 {
251 if (host && host != layerTreeHost()) {
252 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles(). begin(); iter != m_tiler->tiles().end(); ++iter) {
253 #if WTF_NEW_HASHMAP_ITERATORS_INTERFACE
254 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->value.get()) ;
255 #else
256 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get() );
257 #endif
258 // FIXME: This should not ever be null.
259 if (!tile)
260 continue;
261 tile->managedTexture()->setTextureManager(host->contentsTextureManag er());
262 }
263 }
264 LayerChromium::setLayerTreeHost(host);
265 }
266
267 UpdatableTile* TiledLayerChromium::tileAt(int i, int j) const
268 {
269 return static_cast<UpdatableTile*>(m_tiler->tileAt(i, j));
270 }
271
272 UpdatableTile* TiledLayerChromium::createTile(int i, int j)
273 {
274 createTextureUpdaterIfNeeded();
275
276 OwnPtr<UpdatableTile> tile(UpdatableTile::create(textureUpdater()->createTex ture(textureManager())));
277 tile->managedTexture()->setDimensions(m_tiler->tileSize(), m_textureFormat);
278
279 UpdatableTile* addedTile = tile.get();
280 m_tiler->addTile(tile.release(), i, j);
281
282 addedTile->dirtyRect = m_tiler->tileRect(addedTile);
283
284 // Temporary diagnostic crash.
285 if (!addedTile)
286 CRASH();
287 if (!tileAt(i, j))
288 CRASH();
289
290 return addedTile;
291 }
292
293 void TiledLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect)
294 {
295 float contentsWidthScale = static_cast<float>(contentBounds().width()) / bou nds().width();
296 float contentsHeightScale = static_cast<float>(contentBounds().height()) / b ounds().height();
297 FloatRect scaledDirtyRect(dirtyRect);
298 scaledDirtyRect.scale(contentsWidthScale, contentsHeightScale);
299 IntRect dirty = enclosingIntRect(scaledDirtyRect);
300 invalidateContentRect(dirty);
301 LayerChromium::setNeedsDisplayRect(dirtyRect);
302 }
303
304 void TiledLayerChromium::setUseLCDText(bool useLCDText)
305 {
306 LayerChromium::setUseLCDText(useLCDText);
307
308 CCLayerTilingData::BorderTexelOption borderTexelOption;
309 #if OS(ANDROID)
310 // Always want border texels and GL_LINEAR due to pinch zoom.
311 borderTexelOption = CCLayerTilingData::HasBorderTexels;
312 #else
313 borderTexelOption = useLCDText ? CCLayerTilingData::NoBorderTexels : CCLayer TilingData::HasBorderTexels;
314 #endif
315 setBorderTexelOption(borderTexelOption);
316 }
317
318 void TiledLayerChromium::invalidateContentRect(const IntRect& contentRect)
319 {
320 updateBounds();
321 if (m_tiler->isEmpty() || contentRect.isEmpty() || m_skipsDraw)
322 return;
323
324 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) {
325 #if WTF_NEW_HASHMAP_ITERATORS_INTERFACE
326 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->value.get());
327 #else
328 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
329 #endif
330 ASSERT(tile);
331 // FIXME: This should not ever be null.
332 if (!tile)
333 continue;
334 IntRect bound = m_tiler->tileRect(tile);
335 bound.intersect(contentRect);
336 tile->dirtyRect.unite(bound);
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()->haveBackingTexture())
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
363 bool TiledLayerChromium::updateTiles(int left, int top, int right, int bottom, C CTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStat s& stats, bool& didPaint)
364 {
365 didPaint = false;
366 createTextureUpdaterIfNeeded();
367
368 bool ignoreOcclusions = !occlusion;
369 if (!haveTexturesForTiles(left, top, right, bottom, ignoreOcclusions)) {
370 m_failedUpdate = true;
371 return false;
372 }
373
374 IntRect paintRect = markTilesForUpdate(left, top, right, bottom, ignoreOcclu sions);
375
376 if (occlusion)
377 occlusion->overdrawMetrics().didPaint(paintRect);
378
379 if (paintRect.isEmpty())
380 return true;
381
382 didPaint = true;
383 updateTileTextures(paintRect, left, top, right, bottom, queue, occlusion, st ats);
384 return true;
385 }
386
387 void TiledLayerChromium::markOcclusionsAndRequestTextures(int left, int top, int right, int bottom, const CCOcclusionTracker* occlusion)
388 {
389 // There is some difficult dependancies between occlusions, recording occlus ion metrics
390 // and requesting memory so those are encapsulated in this function:
391 // - We only want to call requestLate on unoccluded textures (to preserve
392 // memory for other layers when near OOM).
393 // - We only want to record occlusion metrics if all memory requests succeed .
394
395 int occludedTileCount = 0;
396 bool succeeded = true;
397 for (int j = top; j <= bottom; ++j) {
398 for (int i = left; i <= right; ++i) {
399 UpdatableTile* tile = tileAt(i, j);
400 ASSERT(tile); // Did setTexturePriorities get skipped?
401 // FIXME: This should not ever be null.
402 if (!tile)
403 continue;
404 ASSERT(!tile->occluded); // Did resetUpdateState get skipped? Are we doing more than one occlusion pass?
405 IntRect visibleTileRect = intersection(m_tiler->tileBounds(i, j), vi sibleContentRect());
406 if (occlusion && occlusion->occluded(this, visibleTileRect)) {
407 tile->occluded = true;
408 occludedTileCount++;
409 } else {
410 succeeded &= tile->managedTexture()->requestLate();
411 }
412 }
413 }
414
415 if (!succeeded)
416 return;
417
418 // FIXME: Remove the loop and just pass the count!
419 for (int i = 0; i < occludedTileCount; i++)
420 occlusion->overdrawMetrics().didCullTileForUpload();
421 }
422
423 bool TiledLayerChromium::haveTexturesForTiles(int left, int top, int right, int bottom, bool ignoreOcclusions)
424 {
425 for (int j = top; j <= bottom; ++j) {
426 for (int i = left; i <= right; ++i) {
427 UpdatableTile* tile = tileAt(i, j);
428 ASSERT(tile); // Did setTexturePriorites get skipped?
429 // FIXME: This should not ever be null.
430 if (!tile)
431 continue;
432
433 // Ensure the entire tile is dirty if we don't have the texture.
434 if (!tile->managedTexture()->haveBackingTexture())
435 tile->dirtyRect = m_tiler->tileRect(tile);
436
437 // If using occlusion and the visible region of the tile is occluded ,
438 // don't reserve a texture or update the tile.
439 if (tile->occluded && !ignoreOcclusions)
440 continue;
441
442 if (!tile->managedTexture()->canAcquireBackingTexture())
443 return false;
444 }
445 }
446 return true;
447 }
448
449 IntRect TiledLayerChromium::markTilesForUpdate(int left, int top, int right, int bottom, bool ignoreOcclusions)
450 {
451 IntRect paintRect;
452 for (int j = top; j <= bottom; ++j) {
453 for (int i = left; i <= right; ++i) {
454 UpdatableTile* tile = tileAt(i, j);
455 ASSERT(tile); // Did setTexturePriorites get skipped?
456 // FIXME: This should not ever be null.
457 if (!tile)
458 continue;
459 if (tile->occluded && !ignoreOcclusions)
460 continue;
461 paintRect.unite(tile->dirtyRect);
462 tile->markForUpdate();
463 }
464 }
465 return paintRect;
466 }
467
468 void TiledLayerChromium::updateTileTextures(const IntRect& paintRect, int left, int top, int right, int bottom, CCTextureUpdateQueue& queue, const CCOcclusionTr acker* occlusion, CCRenderingStats& stats)
469 {
470 // The updateRect should be in layer space. So we have to convert the paintR ect from content space to layer space.
471 m_updateRect = FloatRect(paintRect);
472 float widthScale = bounds().width() / static_cast<float>(contentBounds().wid th());
473 float heightScale = bounds().height() / static_cast<float>(contentBounds().h eight());
474 m_updateRect.scale(widthScale, heightScale);
475
476 // Calling prepareToUpdate() calls into WebKit to paint, which may have the side
477 // effect of disabling compositing, which causes our reference to the textur e updater to be deleted.
478 // However, we can't free the memory backing the SkCanvas until the paint fi nishes,
479 // so we grab a local reference here to hold the updater alive until the pai nt completes.
480 RefPtr<LayerTextureUpdater> protector(textureUpdater());
481 IntRect paintedOpaqueRect;
482 textureUpdater()->prepareToUpdate(paintRect, m_tiler->tileSize(), 1 / widthS cale, 1 / heightScale, paintedOpaqueRect, stats);
483
484 for (int j = top; j <= bottom; ++j) {
485 for (int i = left; i <= right; ++i) {
486 UpdatableTile* tile = tileAt(i, j);
487 ASSERT(tile); // Did setTexturePriorites get skipped?
488 // FIXME: This should not ever be null.
489 if (!tile)
490 continue;
491
492 IntRect tileRect = m_tiler->tileBounds(i, j);
493
494 // Use updateRect as the above loop copied the dirty rect for this f rame to updateRect.
495 const IntRect& dirtyRect = tile->updateRect;
496 if (dirtyRect.isEmpty())
497 continue;
498
499 // 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
500 // other part of the tile opaque.
501 IntRect tilePaintedRect = intersection(tileRect, paintRect);
502 IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaque Rect);
503 if (!tilePaintedRect.isEmpty()) {
504 IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRec t(), tilePaintedRect);
505 bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRe ct.contains(paintInsideTileOpaqueRect);
506 bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect .isEmpty() && !tile->opaqueRect().contains(tilePaintedOpaqueRect);
507
508 if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInside TileOpaqueRect)
509 tile->setOpaqueRect(tilePaintedOpaqueRect);
510 }
511
512 // sourceRect starts as a full-sized tile with border texels include d.
513 IntRect sourceRect = m_tiler->tileRect(tile);
514 sourceRect.intersect(dirtyRect);
515 // Paint rect not guaranteed to line up on tile boundaries, so
516 // make sure that sourceRect doesn't extend outside of it.
517 sourceRect.intersect(paintRect);
518
519 tile->updateRect = sourceRect;
520
521 if (sourceRect.isEmpty())
522 continue;
523
524 tile->texture()->prepareRect(sourceRect, stats);
525 if (occlusion)
526 occlusion->overdrawMetrics().didUpload(WebTransformationMatrix() , sourceRect, tile->opaqueRect());
527
528 const IntPoint anchor = m_tiler->tileRect(tile).location();
529
530 // Calculate tile-space rectangle to upload into.
531 IntSize destOffset(sourceRect.x() - anchor.x(), sourceRect.y() - anc hor.y());
532 if (destOffset.width() < 0)
533 CRASH();
534 if (destOffset.height() < 0)
535 CRASH();
536
537 // Offset from paint rectangle to this tile's dirty rectangle.
538 IntPoint paintOffset(sourceRect.x() - paintRect.x(), sourceRect.y() - paintRect.y());
539 if (paintOffset.x() < 0)
540 CRASH();
541 if (paintOffset.y() < 0)
542 CRASH();
543 if (paintOffset.x() + sourceRect.width() > paintRect.width())
544 CRASH();
545 if (paintOffset.y() + sourceRect.height() > paintRect.height())
546 CRASH();
547
548 TextureUploader::Parameters upload = { tile->texture(), sourceRect, destOffset };
549 if (tile->partialUpdate)
550 queue.appendPartialUpload(upload);
551 else
552 queue.appendFullUpload(upload);
553 }
554 }
555 }
556
557 namespace {
558 // This picks a small animated layer to be anything less than one viewport. This
559 // is specifically for page transitions which are viewport-sized layers. The ext ra
560 // 64 pixels is due to these layers being slightly larger than the viewport in s ome cases.
561 bool isSmallAnimatedLayer(TiledLayerChromium* layer)
562 {
563 if (!layer->drawTransformIsAnimating() && !layer->screenSpaceTransformIsAnim ating())
564 return false;
565 IntSize viewportSize = layer->layerTreeHost() ? layer->layerTreeHost()->devi ceViewportSize() : IntSize();
566 IntRect contentRect(IntPoint::zero(), layer->contentBounds());
567 return contentRect.width() <= viewportSize.width() + 64
568 && contentRect.height() <= viewportSize.height() + 64;
569 }
570
571 // FIXME: Remove this and make this based on distance once distance can be calcu lated
572 // for offscreen layers. For now, prioritize all small animated layers after 512
573 // pixels of pre-painting.
574 void setPriorityForTexture(const IntRect& visibleRect,
575 const IntRect& tileRect,
576 bool drawsToRoot,
577 bool isSmallAnimatedLayer,
578 CCPrioritizedTexture* texture)
579 {
580 int priority = CCPriorityCalculator::lowestPriority();
581 if (!visibleRect.isEmpty())
582 priority = CCPriorityCalculator::priorityFromDistance(visibleRect, tileR ect, drawsToRoot);
583 if (isSmallAnimatedLayer)
584 priority = CCPriorityCalculator::maxPriority(priority, CCPriorityCalcula tor::smallAnimatedLayerMinPriority());
585 if (priority != CCPriorityCalculator::lowestPriority())
586 texture->setRequestPriority(priority);
587 }
588 }
589
590 void TiledLayerChromium::setTexturePriorities(const CCPriorityCalculator& priori tyCalc)
591 {
592 updateBounds();
593 resetUpdateState();
594
595 if (m_tiler->hasEmptyBounds())
596 return;
597
598 bool drawsToRoot = !renderTarget()->parent();
599 bool smallAnimatedLayer = isSmallAnimatedLayer(this);
600
601 // Minimally create the tiles in the desired pre-paint rect.
602 IntRect createTilesRect = idlePaintRect();
603 if (!createTilesRect.isEmpty()) {
604 int left, top, right, bottom;
605 m_tiler->contentRectToTileIndices(createTilesRect, left, top, right, bot tom);
606 for (int j = top; j <= bottom; ++j) {
607 for (int i = left; i <= right; ++i) {
608 if (!tileAt(i, j))
609 createTile(i, j);
610 }
611 }
612 }
613
614 // Also, minimally create all tiles for small animated layers and also
615 // double-buffer them since we have limited their size to be reasonable.
616 IntRect doubleBufferedRect = visibleContentRect();
617 if (smallAnimatedLayer)
618 doubleBufferedRect = IntRect(IntPoint::zero(), contentBounds());
619
620 // Create additional textures for double-buffered updates when needed.
621 // These textures must stay alive while the updated textures are incremental ly
622 // uploaded, swapped atomically via pushProperties, and finally deleted
623 // after the commit is complete, after which they can be recycled.
624 if (!doubleBufferedRect.isEmpty()) {
625 int left, top, right, bottom;
626 m_tiler->contentRectToTileIndices(doubleBufferedRect, left, top, right, bottom);
627 for (int j = top; j <= bottom; ++j) {
628 for (int i = left; i <= right; ++i) {
629 UpdatableTile* tile = tileAt(i, j);
630 if (!tile)
631 tile = createTile(i, j);
632 // We need an additional texture if the tile needs a buffered-up date and it's not a partial update.
633 // FIXME: Decide if partial update should be allowed based on co st
634 // of update. https://bugs.webkit.org/show_bug.cgi?id=77376
635 if (!layerTreeHost() || !layerTreeHost()->bufferedUpdates() || ! tileNeedsBufferedUpdate(tile))
636 continue;
637 if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->request PartialTextureUpdate()) {
638 tile->partialUpdate = true;
639 continue;
640 }
641
642 IntRect tileRect = m_tiler->tileRect(tile);
643 tile->dirtyRect = tileRect;
644 LayerTextureUpdater::Texture* backBuffer = tile->texture();
645 setPriorityForTexture(visibleContentRect(), tile->dirtyRect, dra wsToRoot, smallAnimatedLayer, backBuffer->texture());
646 scoped_ptr<CCPrioritizedTexture> frontBuffer = CCPrioritizedText ure::create(backBuffer->texture()->textureManager(),
647 backBuffer->texture()->size(),
648 backBuffer->texture()->format());
649 // Swap backBuffer into frontBuffer and add it to delete after c ommit queue.
650 backBuffer->swapTextureWith(frontBuffer);
651 layerTreeHost()->deleteTextureAfterCommit(frontBuffer.Pass());
652 }
653 }
654 }
655
656 // Now update priorities on all tiles we have in the layer, no matter where they are.
657 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != m_tiler->tiles().end(); ++iter) {
658 #if WTF_NEW_HASHMAP_ITERATORS_INTERFACE
659 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->value.get());
660 #else
661 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
662 #endif
663 // FIXME: This should not ever be null.
664 if (!tile)
665 continue;
666 IntRect tileRect = m_tiler->tileRect(tile);
667 setPriorityForTexture(visibleContentRect(), tileRect, drawsToRoot, small AnimatedLayer, tile->managedTexture());
668 }
669 }
670
671 Region TiledLayerChromium::visibleContentOpaqueRegion() const
672 {
673 if (m_skipsDraw)
674 return Region();
675 if (contentsOpaque())
676 return visibleContentRect();
677 return m_tiler->opaqueRegionInContentRect(visibleContentRect());
678 }
679
680 void TiledLayerChromium::resetUpdateState()
681 {
682 m_skipsDraw = false;
683 m_failedUpdate = false;
684
685 CCLayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end();
686 for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begi n(); iter != end; ++iter) {
687 #if WTF_NEW_HASHMAP_ITERATORS_INTERFACE
688 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->value.get());
689 #else
690 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
691 #endif
692 // FIXME: This should not ever be null.
693 if (!tile)
694 continue;
695 tile->resetUpdateState();
696 }
697 }
698
699 void TiledLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTr acker* occlusion, CCRenderingStats& stats)
700 {
701 ASSERT(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped ?
702 updateBounds();
703 if (m_tiler->hasEmptyBounds() || !drawsContent())
704 return;
705
706 bool didPaint = false;
707
708 // Animation pre-paint. If the layer is small, try to paint it all
709 // immediately whether or not it is occluded, to avoid paint/upload
710 // hiccups while it is animating.
711 if (isSmallAnimatedLayer(this)) {
712 int left, top, right, bottom;
713 m_tiler->contentRectToTileIndices(IntRect(IntPoint::zero(), contentBound s()), left, top, right, bottom);
714 updateTiles(left, top, right, bottom, queue, 0, stats, didPaint);
715 if (didPaint)
716 return;
717 // This was an attempt to paint the entire layer so if we fail it's okay ,
718 // just fallback on painting visible etc. below.
719 m_failedUpdate = false;
720 }
721
722 if (visibleContentRect().isEmpty())
723 return;
724
725 // Visible painting. First occlude visible tiles and paint the non-occluded tiles.
726 int left, top, right, bottom;
727 m_tiler->contentRectToTileIndices(visibleContentRect(), left, top, right, bo ttom);
728 markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion);
729 m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats , didPaint);
730 if (m_skipsDraw)
731 m_tiler->reset();
732 if (m_skipsDraw || didPaint)
733 return;
734
735 // If we have already painting everything visible. Do some pre-painting whil e idle.
736 IntRect idlePaintContentRect = idlePaintRect();
737 if (idlePaintContentRect.isEmpty())
738 return;
739
740 // Prepaint anything that was occluded but inside the layer's visible region .
741 if (!updateTiles(left, top, right, bottom, queue, 0, stats, didPaint) || did Paint)
742 return;
743
744 int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom;
745 m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepai ntTop, prepaintRight, prepaintBottom);
746
747 // Then expand outwards from the visible area until we find a dirty row or c olumn to update.
748 while (left > prepaintLeft || top > prepaintTop || right < prepaintRight || bottom < prepaintBottom) {
749 if (bottom < prepaintBottom) {
750 ++bottom;
751 if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, didPa int) || didPaint)
752 return;
753 }
754 if (top > prepaintTop) {
755 --top;
756 if (!updateTiles(left, top, right, top, queue, 0, stats, didPaint) | | didPaint)
757 return;
758 }
759 if (left > prepaintLeft) {
760 --left;
761 if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPaint) || didPaint)
762 return;
763 }
764 if (right < prepaintRight) {
765 ++right;
766 if (!updateTiles(right, top, right, bottom, queue, 0, stats, didPain t) || didPaint)
767 return;
768 }
769 }
770 }
771
772 bool TiledLayerChromium::needsIdlePaint()
773 {
774 // Don't trigger more paints if we failed (as we'll just fail again).
775 if (m_failedUpdate || visibleContentRect().isEmpty() || m_tiler->hasEmptyBou nds() || !drawsContent())
776 return false;
777
778 IntRect idlePaintContentRect = idlePaintRect();
779 if (idlePaintContentRect.isEmpty())
780 return false;
781
782 int left, top, right, bottom;
783 m_tiler->contentRectToTileIndices(idlePaintContentRect, left, top, right, bo ttom);
784
785 for (int j = top; j <= bottom; ++j) {
786 for (int i = left; i <= right; ++i) {
787 UpdatableTile* tile = tileAt(i, j);
788 ASSERT(tile); // Did setTexturePriorities get skipped?
789 if (!tile)
790 continue;
791
792 bool updated = !tile->updateRect.isEmpty();
793 bool canAcquire = tile->managedTexture()->canAcquireBackingTexture() ;
794 bool dirty = tile->isDirty() || !tile->managedTexture()->haveBacking Texture();
795 if (!updated && canAcquire && dirty)
796 return true;
797 }
798 }
799 return false;
800 }
801
802 IntRect TiledLayerChromium::idlePaintRect()
803 {
804 // Don't inflate an empty rect.
805 if (visibleContentRect().isEmpty())
806 return IntRect();
807
808 // FIXME: This can be made a lot larger now! We should increase
809 // this slowly while insuring it doesn't cause any perf issues.
810 IntRect prepaintRect = visibleContentRect();
811 prepaintRect.inflateX(m_tiler->tileSize().width());
812 prepaintRect.inflateY(m_tiler->tileSize().height() * 2);
813 IntRect contentRect(IntPoint::zero(), contentBounds());
814 prepaintRect.intersect(contentRect);
815
816 return prepaintRect;
817 }
818
819 }
820 #endif // USE(ACCELERATED_COMPOSITING)
OLDNEW
« no previous file with comments | « cc/TiledLayerChromium.h ('k') | cc/TreeSynchronizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698