Index: cc/TiledLayerChromium.cpp |
diff --git a/cc/TiledLayerChromium.cpp b/cc/TiledLayerChromium.cpp |
deleted file mode 100644 |
index f2219e624fe7189ded6505c913ae683e0efbe19f..0000000000000000000000000000000000000000 |
--- a/cc/TiledLayerChromium.cpp |
+++ /dev/null |
@@ -1,820 +0,0 @@ |
-// Copyright 2011 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. |
- |
-#include "config.h" |
- |
-#if USE(ACCELERATED_COMPOSITING) |
- |
-#include "base/basictypes.h" |
-#include "TiledLayerChromium.h" |
- |
-#include "CCLayerImpl.h" |
-#include "CCLayerTreeHost.h" |
-#include "CCOverdrawMetrics.h" |
-#include "CCTextureUpdateQueue.h" |
-#include "CCTiledLayerImpl.h" |
-#include "GraphicsContext3D.h" |
-#include "Region.h" |
-#include <wtf/CurrentTime.h> |
-#include <wtf/MathExtras.h> |
- |
-using namespace std; |
-using WebKit::WebTransformationMatrix; |
- |
-namespace cc { |
- |
-class UpdatableTile : public CCLayerTilingData::Tile { |
-public: |
- static PassOwnPtr<UpdatableTile> create(PassOwnPtr<LayerTextureUpdater::Texture> texture) |
- { |
- return adoptPtr(new UpdatableTile(texture)); |
- } |
- |
- LayerTextureUpdater::Texture* texture() { return m_texture.get(); } |
- CCPrioritizedTexture* managedTexture() { return m_texture->texture(); } |
- |
- bool isDirty() const { return !dirtyRect.isEmpty(); } |
- |
- // Reset update state for the current frame. This should occur before painting |
- // for all layers. Since painting one layer can invalidate another layer |
- // after it has already painted, mark all non-dirty tiles as valid before painting |
- // such that invalidations during painting won't prevent them from being pushed. |
- void resetUpdateState() |
- { |
- updateRect = IntRect(); |
- occluded = false; |
- partialUpdate = false; |
- validForFrame = !isDirty(); |
- } |
- |
- // This promises to update the tile and therefore also guarantees the tile |
- // will be valid for this frame. dirtyRect is copied into updateRect so |
- // we can continue to track re-entrant invalidations that occur during painting. |
- void markForUpdate() |
- { |
- validForFrame = true; |
- updateRect = dirtyRect; |
- dirtyRect = IntRect(); |
- } |
- |
- IntRect dirtyRect; |
- IntRect updateRect; |
- bool partialUpdate; |
- bool validForFrame; |
- bool occluded; |
- bool isInUseOnImpl; |
-private: |
- explicit UpdatableTile(PassOwnPtr<LayerTextureUpdater::Texture> texture) |
- : partialUpdate(false) |
- , validForFrame(false) |
- , occluded(false) |
- , isInUseOnImpl(false) |
- , m_texture(texture) |
- { |
- } |
- |
- OwnPtr<LayerTextureUpdater::Texture> m_texture; |
- |
- DISALLOW_COPY_AND_ASSIGN(UpdatableTile); |
-}; |
- |
-TiledLayerChromium::TiledLayerChromium() |
- : LayerChromium() |
- , m_textureFormat(GraphicsContext3D::INVALID_ENUM) |
- , m_skipsDraw(false) |
- , m_failedUpdate(false) |
- , m_sampledTexelFormat(LayerTextureUpdater::SampledTexelFormatInvalid) |
- , m_tilingOption(AutoTile) |
-{ |
- m_tiler = CCLayerTilingData::create(IntSize(), CCLayerTilingData::HasBorderTexels); |
-} |
- |
-TiledLayerChromium::~TiledLayerChromium() |
-{ |
-} |
- |
-scoped_ptr<CCLayerImpl> TiledLayerChromium::createCCLayerImpl() |
-{ |
- return CCTiledLayerImpl::create(id()).PassAs<CCLayerImpl>(); |
-} |
- |
-void TiledLayerChromium::updateTileSizeAndTilingOption() |
-{ |
- ASSERT(layerTreeHost()); |
- |
- const IntSize& defaultTileSize = layerTreeHost()->settings().defaultTileSize; |
- const IntSize& maxUntiledLayerSize = layerTreeHost()->settings().maxUntiledLayerSize; |
- int layerWidth = contentBounds().width(); |
- int layerHeight = contentBounds().height(); |
- |
- const IntSize tileSize(min(defaultTileSize.width(), layerWidth), min(defaultTileSize.height(), layerHeight)); |
- |
- // Tile if both dimensions large, or any one dimension large and the other |
- // extends into a second tile but the total layer area isn't larger than that |
- // of the largest possible untiled layer. This heuristic allows for long skinny layers |
- // (e.g. scrollbars) that are Nx1 tiles to minimize wasted texture space but still avoids |
- // creating very large tiles. |
- const bool anyDimensionLarge = layerWidth > maxUntiledLayerSize.width() || layerHeight > maxUntiledLayerSize.height(); |
- const bool anyDimensionOneTile = (layerWidth <= defaultTileSize.width() || layerHeight <= defaultTileSize.height()) |
- && (layerWidth * layerHeight) <= (maxUntiledLayerSize.width() * maxUntiledLayerSize.height()); |
- const bool autoTiled = anyDimensionLarge && !anyDimensionOneTile; |
- |
- bool isTiled; |
- if (m_tilingOption == AlwaysTile) |
- isTiled = true; |
- else if (m_tilingOption == NeverTile) |
- isTiled = false; |
- else |
- isTiled = autoTiled; |
- |
- IntSize requestedSize = isTiled ? tileSize : contentBounds(); |
- const int maxSize = layerTreeHost()->rendererCapabilities().maxTextureSize; |
- IntSize clampedSize = requestedSize.shrunkTo(IntSize(maxSize, maxSize)); |
- setTileSize(clampedSize); |
-} |
- |
-void TiledLayerChromium::updateBounds() |
-{ |
- IntSize oldBounds = m_tiler->bounds(); |
- IntSize newBounds = contentBounds(); |
- if (oldBounds == newBounds) |
- return; |
- m_tiler->setBounds(newBounds); |
- |
- // Invalidate any areas that the new bounds exposes. |
- Region oldRegion(IntRect(IntPoint(), oldBounds)); |
- Region newRegion(IntRect(IntPoint(), newBounds)); |
- newRegion.subtract(oldRegion); |
- Vector<WebCore::IntRect> rects = newRegion.rects(); |
- for (size_t i = 0; i < rects.size(); ++i) |
- invalidateContentRect(rects[i]); |
-} |
- |
-void TiledLayerChromium::setTileSize(const IntSize& size) |
-{ |
- m_tiler->setTileSize(size); |
-} |
- |
-void TiledLayerChromium::setBorderTexelOption(CCLayerTilingData::BorderTexelOption borderTexelOption) |
-{ |
- m_tiler->setBorderTexelOption(borderTexelOption); |
-} |
- |
-bool TiledLayerChromium::drawsContent() const |
-{ |
- if (!LayerChromium::drawsContent()) |
- return false; |
- |
- bool hasMoreThanOneTile = m_tiler->numTilesX() > 1 || m_tiler->numTilesY() > 1; |
- if (m_tilingOption == NeverTile && hasMoreThanOneTile) |
- return false; |
- |
- return true; |
-} |
- |
-bool TiledLayerChromium::needsContentsScale() const |
-{ |
- return true; |
-} |
- |
-IntSize TiledLayerChromium::contentBounds() const |
-{ |
- return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds().height() * contentsScale())); |
-} |
- |
-void TiledLayerChromium::setTilingOption(TilingOption tilingOption) |
-{ |
- m_tilingOption = tilingOption; |
-} |
- |
-void TiledLayerChromium::setIsMask(bool isMask) |
-{ |
- setTilingOption(isMask ? NeverTile : AutoTile); |
-} |
- |
-void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer) |
-{ |
- LayerChromium::pushPropertiesTo(layer); |
- |
- CCTiledLayerImpl* tiledLayer = static_cast<CCTiledLayerImpl*>(layer); |
- |
- tiledLayer->setSkipsDraw(m_skipsDraw); |
- tiledLayer->setContentsSwizzled(m_sampledTexelFormat != LayerTextureUpdater::SampledTexelFormatRGBA); |
- tiledLayer->setTilingData(*m_tiler); |
- Vector<UpdatableTile*> invalidTiles; |
- |
- for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { |
-#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE |
- int i = iter->key.first; |
- int j = iter->key.second; |
- UpdatableTile* tile = static_cast<UpdatableTile*>(iter->value.get()); |
-#else |
- int i = iter->first.first; |
- int j = iter->first.second; |
- UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); |
-#endif |
- // FIXME: This should not ever be null. |
- if (!tile) |
- continue; |
- |
- tile->isInUseOnImpl = false; |
- |
- if (!tile->managedTexture()->haveBackingTexture()) { |
- // Evicted tiles get deleted from both layers |
- invalidTiles.append(tile); |
- continue; |
- } |
- |
- if (!tile->validForFrame) { |
- // Invalidated tiles are set so they can get different debug colors. |
- tiledLayer->pushInvalidTile(i, j); |
- continue; |
- } |
- |
- tiledLayer->pushTileProperties(i, j, tile->managedTexture()->resourceId(), tile->opaqueRect()); |
- tile->isInUseOnImpl = true; |
- } |
- for (Vector<UpdatableTile*>::const_iterator iter = invalidTiles.begin(); iter != invalidTiles.end(); ++iter) |
- m_tiler->takeTile((*iter)->i(), (*iter)->j()); |
-} |
- |
-CCPrioritizedTextureManager* TiledLayerChromium::textureManager() const |
-{ |
- if (!layerTreeHost()) |
- return 0; |
- return layerTreeHost()->contentsTextureManager(); |
-} |
- |
-void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) |
-{ |
- if (host && host != layerTreeHost()) { |
- for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { |
-#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE |
- UpdatableTile* tile = static_cast<UpdatableTile*>(iter->value.get()); |
-#else |
- UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); |
-#endif |
- // FIXME: This should not ever be null. |
- if (!tile) |
- continue; |
- tile->managedTexture()->setTextureManager(host->contentsTextureManager()); |
- } |
- } |
- LayerChromium::setLayerTreeHost(host); |
-} |
- |
-UpdatableTile* TiledLayerChromium::tileAt(int i, int j) const |
-{ |
- return static_cast<UpdatableTile*>(m_tiler->tileAt(i, j)); |
-} |
- |
-UpdatableTile* TiledLayerChromium::createTile(int i, int j) |
-{ |
- createTextureUpdaterIfNeeded(); |
- |
- OwnPtr<UpdatableTile> tile(UpdatableTile::create(textureUpdater()->createTexture(textureManager()))); |
- tile->managedTexture()->setDimensions(m_tiler->tileSize(), m_textureFormat); |
- |
- UpdatableTile* addedTile = tile.get(); |
- m_tiler->addTile(tile.release(), i, j); |
- |
- addedTile->dirtyRect = m_tiler->tileRect(addedTile); |
- |
- // Temporary diagnostic crash. |
- if (!addedTile) |
- CRASH(); |
- if (!tileAt(i, j)) |
- CRASH(); |
- |
- return addedTile; |
-} |
- |
-void TiledLayerChromium::setNeedsDisplayRect(const FloatRect& dirtyRect) |
-{ |
- float contentsWidthScale = static_cast<float>(contentBounds().width()) / bounds().width(); |
- float contentsHeightScale = static_cast<float>(contentBounds().height()) / bounds().height(); |
- FloatRect scaledDirtyRect(dirtyRect); |
- scaledDirtyRect.scale(contentsWidthScale, contentsHeightScale); |
- IntRect dirty = enclosingIntRect(scaledDirtyRect); |
- invalidateContentRect(dirty); |
- LayerChromium::setNeedsDisplayRect(dirtyRect); |
-} |
- |
-void TiledLayerChromium::setUseLCDText(bool useLCDText) |
-{ |
- LayerChromium::setUseLCDText(useLCDText); |
- |
- CCLayerTilingData::BorderTexelOption borderTexelOption; |
-#if OS(ANDROID) |
- // Always want border texels and GL_LINEAR due to pinch zoom. |
- borderTexelOption = CCLayerTilingData::HasBorderTexels; |
-#else |
- borderTexelOption = useLCDText ? CCLayerTilingData::NoBorderTexels : CCLayerTilingData::HasBorderTexels; |
-#endif |
- setBorderTexelOption(borderTexelOption); |
-} |
- |
-void TiledLayerChromium::invalidateContentRect(const IntRect& contentRect) |
-{ |
- updateBounds(); |
- if (m_tiler->isEmpty() || contentRect.isEmpty() || m_skipsDraw) |
- return; |
- |
- for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { |
-#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE |
- UpdatableTile* tile = static_cast<UpdatableTile*>(iter->value.get()); |
-#else |
- UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); |
-#endif |
- ASSERT(tile); |
- // FIXME: This should not ever be null. |
- if (!tile) |
- continue; |
- IntRect bound = m_tiler->tileRect(tile); |
- bound.intersect(contentRect); |
- tile->dirtyRect.unite(bound); |
- } |
-} |
- |
-// Returns true if tile is dirty and only part of it needs to be updated. |
-bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) |
-{ |
- return !tile->dirtyRect.contains(m_tiler->tileRect(tile)); |
-} |
- |
-// Dirty tiles with valid textures needs buffered update to guarantee that |
-// we don't modify textures currently used for drawing by the impl thread. |
-bool TiledLayerChromium::tileNeedsBufferedUpdate(UpdatableTile* tile) |
-{ |
- if (!tile->managedTexture()->haveBackingTexture()) |
- return false; |
- |
- if (!tile->isDirty()) |
- return false; |
- |
- if (!tile->isInUseOnImpl) |
- return false; |
- |
- return true; |
-} |
- |
- |
-bool TiledLayerChromium::updateTiles(int left, int top, int right, int bottom, CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats, bool& didPaint) |
-{ |
- didPaint = false; |
- createTextureUpdaterIfNeeded(); |
- |
- bool ignoreOcclusions = !occlusion; |
- if (!haveTexturesForTiles(left, top, right, bottom, ignoreOcclusions)) { |
- m_failedUpdate = true; |
- return false; |
- } |
- |
- IntRect paintRect = markTilesForUpdate(left, top, right, bottom, ignoreOcclusions); |
- |
- if (occlusion) |
- occlusion->overdrawMetrics().didPaint(paintRect); |
- |
- if (paintRect.isEmpty()) |
- return true; |
- |
- didPaint = true; |
- updateTileTextures(paintRect, left, top, right, bottom, queue, occlusion, stats); |
- return true; |
-} |
- |
-void TiledLayerChromium::markOcclusionsAndRequestTextures(int left, int top, int right, int bottom, const CCOcclusionTracker* occlusion) |
-{ |
- // There is some difficult dependancies between occlusions, recording occlusion metrics |
- // and requesting memory so those are encapsulated in this function: |
- // - We only want to call requestLate on unoccluded textures (to preserve |
- // memory for other layers when near OOM). |
- // - We only want to record occlusion metrics if all memory requests succeed. |
- |
- int occludedTileCount = 0; |
- bool succeeded = true; |
- for (int j = top; j <= bottom; ++j) { |
- for (int i = left; i <= right; ++i) { |
- UpdatableTile* tile = tileAt(i, j); |
- ASSERT(tile); // Did setTexturePriorities get skipped? |
- // FIXME: This should not ever be null. |
- if (!tile) |
- continue; |
- ASSERT(!tile->occluded); // Did resetUpdateState get skipped? Are we doing more than one occlusion pass? |
- IntRect visibleTileRect = intersection(m_tiler->tileBounds(i, j), visibleContentRect()); |
- if (occlusion && occlusion->occluded(this, visibleTileRect)) { |
- tile->occluded = true; |
- occludedTileCount++; |
- } else { |
- succeeded &= tile->managedTexture()->requestLate(); |
- } |
- } |
- } |
- |
- if (!succeeded) |
- return; |
- |
- // FIXME: Remove the loop and just pass the count! |
- for (int i = 0; i < occludedTileCount; i++) |
- occlusion->overdrawMetrics().didCullTileForUpload(); |
-} |
- |
-bool TiledLayerChromium::haveTexturesForTiles(int left, int top, int right, int bottom, bool ignoreOcclusions) |
-{ |
- for (int j = top; j <= bottom; ++j) { |
- for (int i = left; i <= right; ++i) { |
- UpdatableTile* tile = tileAt(i, j); |
- ASSERT(tile); // Did setTexturePriorites get skipped? |
- // FIXME: This should not ever be null. |
- if (!tile) |
- continue; |
- |
- // Ensure the entire tile is dirty if we don't have the texture. |
- if (!tile->managedTexture()->haveBackingTexture()) |
- tile->dirtyRect = m_tiler->tileRect(tile); |
- |
- // If using occlusion and the visible region of the tile is occluded, |
- // don't reserve a texture or update the tile. |
- if (tile->occluded && !ignoreOcclusions) |
- continue; |
- |
- if (!tile->managedTexture()->canAcquireBackingTexture()) |
- return false; |
- } |
- } |
- return true; |
-} |
- |
-IntRect TiledLayerChromium::markTilesForUpdate(int left, int top, int right, int bottom, bool ignoreOcclusions) |
-{ |
- IntRect paintRect; |
- for (int j = top; j <= bottom; ++j) { |
- for (int i = left; i <= right; ++i) { |
- UpdatableTile* tile = tileAt(i, j); |
- ASSERT(tile); // Did setTexturePriorites get skipped? |
- // FIXME: This should not ever be null. |
- if (!tile) |
- continue; |
- if (tile->occluded && !ignoreOcclusions) |
- continue; |
- paintRect.unite(tile->dirtyRect); |
- tile->markForUpdate(); |
- } |
- } |
- return paintRect; |
-} |
- |
-void TiledLayerChromium::updateTileTextures(const IntRect& paintRect, int left, int top, int right, int bottom, CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats) |
-{ |
- // The updateRect should be in layer space. So we have to convert the paintRect from content space to layer space. |
- m_updateRect = FloatRect(paintRect); |
- float widthScale = bounds().width() / static_cast<float>(contentBounds().width()); |
- float heightScale = bounds().height() / static_cast<float>(contentBounds().height()); |
- m_updateRect.scale(widthScale, heightScale); |
- |
- // Calling prepareToUpdate() calls into WebKit to paint, which may have the side |
- // effect of disabling compositing, which causes our reference to the texture updater to be deleted. |
- // However, we can't free the memory backing the SkCanvas until the paint finishes, |
- // so we grab a local reference here to hold the updater alive until the paint completes. |
- RefPtr<LayerTextureUpdater> protector(textureUpdater()); |
- IntRect paintedOpaqueRect; |
- textureUpdater()->prepareToUpdate(paintRect, m_tiler->tileSize(), 1 / widthScale, 1 / heightScale, paintedOpaqueRect, stats); |
- |
- for (int j = top; j <= bottom; ++j) { |
- for (int i = left; i <= right; ++i) { |
- UpdatableTile* tile = tileAt(i, j); |
- ASSERT(tile); // Did setTexturePriorites get skipped? |
- // FIXME: This should not ever be null. |
- if (!tile) |
- continue; |
- |
- IntRect tileRect = m_tiler->tileBounds(i, j); |
- |
- // Use updateRect as the above loop copied the dirty rect for this frame to updateRect. |
- const IntRect& dirtyRect = tile->updateRect; |
- if (dirtyRect.isEmpty()) |
- continue; |
- |
- // Save what was painted opaque in the tile. Keep the old area if the paint didn't touch it, and didn't paint some |
- // other part of the tile opaque. |
- IntRect tilePaintedRect = intersection(tileRect, paintRect); |
- IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaqueRect); |
- if (!tilePaintedRect.isEmpty()) { |
- IntRect paintInsideTileOpaqueRect = intersection(tile->opaqueRect(), tilePaintedRect); |
- bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRect.contains(paintInsideTileOpaqueRect); |
- bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect.isEmpty() && !tile->opaqueRect().contains(tilePaintedOpaqueRect); |
- |
- if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInsideTileOpaqueRect) |
- tile->setOpaqueRect(tilePaintedOpaqueRect); |
- } |
- |
- // sourceRect starts as a full-sized tile with border texels included. |
- IntRect sourceRect = m_tiler->tileRect(tile); |
- sourceRect.intersect(dirtyRect); |
- // Paint rect not guaranteed to line up on tile boundaries, so |
- // make sure that sourceRect doesn't extend outside of it. |
- sourceRect.intersect(paintRect); |
- |
- tile->updateRect = sourceRect; |
- |
- if (sourceRect.isEmpty()) |
- continue; |
- |
- tile->texture()->prepareRect(sourceRect, stats); |
- if (occlusion) |
- occlusion->overdrawMetrics().didUpload(WebTransformationMatrix(), sourceRect, tile->opaqueRect()); |
- |
- const IntPoint anchor = m_tiler->tileRect(tile).location(); |
- |
- // Calculate tile-space rectangle to upload into. |
- IntSize destOffset(sourceRect.x() - anchor.x(), sourceRect.y() - anchor.y()); |
- if (destOffset.width() < 0) |
- CRASH(); |
- if (destOffset.height() < 0) |
- CRASH(); |
- |
- // Offset from paint rectangle to this tile's dirty rectangle. |
- IntPoint paintOffset(sourceRect.x() - paintRect.x(), sourceRect.y() - paintRect.y()); |
- if (paintOffset.x() < 0) |
- CRASH(); |
- if (paintOffset.y() < 0) |
- CRASH(); |
- if (paintOffset.x() + sourceRect.width() > paintRect.width()) |
- CRASH(); |
- if (paintOffset.y() + sourceRect.height() > paintRect.height()) |
- CRASH(); |
- |
- TextureUploader::Parameters upload = { tile->texture(), sourceRect, destOffset }; |
- if (tile->partialUpdate) |
- queue.appendPartialUpload(upload); |
- else |
- queue.appendFullUpload(upload); |
- } |
- } |
-} |
- |
-namespace { |
-// This picks a small animated layer to be anything less than one viewport. This |
-// is specifically for page transitions which are viewport-sized layers. The extra |
-// 64 pixels is due to these layers being slightly larger than the viewport in some cases. |
-bool isSmallAnimatedLayer(TiledLayerChromium* layer) |
-{ |
- if (!layer->drawTransformIsAnimating() && !layer->screenSpaceTransformIsAnimating()) |
- return false; |
- IntSize viewportSize = layer->layerTreeHost() ? layer->layerTreeHost()->deviceViewportSize() : IntSize(); |
- IntRect contentRect(IntPoint::zero(), layer->contentBounds()); |
- return contentRect.width() <= viewportSize.width() + 64 |
- && contentRect.height() <= viewportSize.height() + 64; |
-} |
- |
-// FIXME: Remove this and make this based on distance once distance can be calculated |
-// for offscreen layers. For now, prioritize all small animated layers after 512 |
-// pixels of pre-painting. |
-void setPriorityForTexture(const IntRect& visibleRect, |
- const IntRect& tileRect, |
- bool drawsToRoot, |
- bool isSmallAnimatedLayer, |
- CCPrioritizedTexture* texture) |
-{ |
- int priority = CCPriorityCalculator::lowestPriority(); |
- if (!visibleRect.isEmpty()) |
- priority = CCPriorityCalculator::priorityFromDistance(visibleRect, tileRect, drawsToRoot); |
- if (isSmallAnimatedLayer) |
- priority = CCPriorityCalculator::maxPriority(priority, CCPriorityCalculator::smallAnimatedLayerMinPriority()); |
- if (priority != CCPriorityCalculator::lowestPriority()) |
- texture->setRequestPriority(priority); |
-} |
-} |
- |
-void TiledLayerChromium::setTexturePriorities(const CCPriorityCalculator& priorityCalc) |
-{ |
- updateBounds(); |
- resetUpdateState(); |
- |
- if (m_tiler->hasEmptyBounds()) |
- return; |
- |
- bool drawsToRoot = !renderTarget()->parent(); |
- bool smallAnimatedLayer = isSmallAnimatedLayer(this); |
- |
- // Minimally create the tiles in the desired pre-paint rect. |
- IntRect createTilesRect = idlePaintRect(); |
- if (!createTilesRect.isEmpty()) { |
- int left, top, right, bottom; |
- m_tiler->contentRectToTileIndices(createTilesRect, left, top, right, bottom); |
- for (int j = top; j <= bottom; ++j) { |
- for (int i = left; i <= right; ++i) { |
- if (!tileAt(i, j)) |
- createTile(i, j); |
- } |
- } |
- } |
- |
- // Also, minimally create all tiles for small animated layers and also |
- // double-buffer them since we have limited their size to be reasonable. |
- IntRect doubleBufferedRect = visibleContentRect(); |
- if (smallAnimatedLayer) |
- doubleBufferedRect = IntRect(IntPoint::zero(), contentBounds()); |
- |
- // Create additional textures for double-buffered updates when needed. |
- // These textures must stay alive while the updated textures are incrementally |
- // uploaded, swapped atomically via pushProperties, and finally deleted |
- // after the commit is complete, after which they can be recycled. |
- if (!doubleBufferedRect.isEmpty()) { |
- int left, top, right, bottom; |
- m_tiler->contentRectToTileIndices(doubleBufferedRect, left, top, right, bottom); |
- for (int j = top; j <= bottom; ++j) { |
- for (int i = left; i <= right; ++i) { |
- UpdatableTile* tile = tileAt(i, j); |
- if (!tile) |
- tile = createTile(i, j); |
- // We need an additional texture if the tile needs a buffered-update and it's not a partial update. |
- // FIXME: Decide if partial update should be allowed based on cost |
- // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 |
- if (!layerTreeHost() || !layerTreeHost()->bufferedUpdates() || !tileNeedsBufferedUpdate(tile)) |
- continue; |
- if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost()->requestPartialTextureUpdate()) { |
- tile->partialUpdate = true; |
- continue; |
- } |
- |
- IntRect tileRect = m_tiler->tileRect(tile); |
- tile->dirtyRect = tileRect; |
- LayerTextureUpdater::Texture* backBuffer = tile->texture(); |
- setPriorityForTexture(visibleContentRect(), tile->dirtyRect, drawsToRoot, smallAnimatedLayer, backBuffer->texture()); |
- scoped_ptr<CCPrioritizedTexture> frontBuffer = CCPrioritizedTexture::create(backBuffer->texture()->textureManager(), |
- backBuffer->texture()->size(), |
- backBuffer->texture()->format()); |
- // Swap backBuffer into frontBuffer and add it to delete after commit queue. |
- backBuffer->swapTextureWith(frontBuffer); |
- layerTreeHost()->deleteTextureAfterCommit(frontBuffer.Pass()); |
- } |
- } |
- } |
- |
- // Now update priorities on all tiles we have in the layer, no matter where they are. |
- for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { |
-#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE |
- UpdatableTile* tile = static_cast<UpdatableTile*>(iter->value.get()); |
-#else |
- UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); |
-#endif |
- // FIXME: This should not ever be null. |
- if (!tile) |
- continue; |
- IntRect tileRect = m_tiler->tileRect(tile); |
- setPriorityForTexture(visibleContentRect(), tileRect, drawsToRoot, smallAnimatedLayer, tile->managedTexture()); |
- } |
-} |
- |
-Region TiledLayerChromium::visibleContentOpaqueRegion() const |
-{ |
- if (m_skipsDraw) |
- return Region(); |
- if (contentsOpaque()) |
- return visibleContentRect(); |
- return m_tiler->opaqueRegionInContentRect(visibleContentRect()); |
-} |
- |
-void TiledLayerChromium::resetUpdateState() |
-{ |
- m_skipsDraw = false; |
- m_failedUpdate = false; |
- |
- CCLayerTilingData::TileMap::const_iterator end = m_tiler->tiles().end(); |
- for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != end; ++iter) { |
-#if WTF_NEW_HASHMAP_ITERATORS_INTERFACE |
- UpdatableTile* tile = static_cast<UpdatableTile*>(iter->value.get()); |
-#else |
- UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); |
-#endif |
- // FIXME: This should not ever be null. |
- if (!tile) |
- continue; |
- tile->resetUpdateState(); |
- } |
-} |
- |
-void TiledLayerChromium::update(CCTextureUpdateQueue& queue, const CCOcclusionTracker* occlusion, CCRenderingStats& stats) |
-{ |
- ASSERT(!m_skipsDraw && !m_failedUpdate); // Did resetUpdateState get skipped? |
- updateBounds(); |
- if (m_tiler->hasEmptyBounds() || !drawsContent()) |
- return; |
- |
- bool didPaint = false; |
- |
- // Animation pre-paint. If the layer is small, try to paint it all |
- // immediately whether or not it is occluded, to avoid paint/upload |
- // hiccups while it is animating. |
- if (isSmallAnimatedLayer(this)) { |
- int left, top, right, bottom; |
- m_tiler->contentRectToTileIndices(IntRect(IntPoint::zero(), contentBounds()), left, top, right, bottom); |
- updateTiles(left, top, right, bottom, queue, 0, stats, didPaint); |
- if (didPaint) |
- return; |
- // This was an attempt to paint the entire layer so if we fail it's okay, |
- // just fallback on painting visible etc. below. |
- m_failedUpdate = false; |
- } |
- |
- if (visibleContentRect().isEmpty()) |
- return; |
- |
- // Visible painting. First occlude visible tiles and paint the non-occluded tiles. |
- int left, top, right, bottom; |
- m_tiler->contentRectToTileIndices(visibleContentRect(), left, top, right, bottom); |
- markOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); |
- m_skipsDraw = !updateTiles(left, top, right, bottom, queue, occlusion, stats, didPaint); |
- if (m_skipsDraw) |
- m_tiler->reset(); |
- if (m_skipsDraw || didPaint) |
- return; |
- |
- // If we have already painting everything visible. Do some pre-painting while idle. |
- IntRect idlePaintContentRect = idlePaintRect(); |
- if (idlePaintContentRect.isEmpty()) |
- return; |
- |
- // Prepaint anything that was occluded but inside the layer's visible region. |
- if (!updateTiles(left, top, right, bottom, queue, 0, stats, didPaint) || didPaint) |
- return; |
- |
- int prepaintLeft, prepaintTop, prepaintRight, prepaintBottom; |
- m_tiler->contentRectToTileIndices(idlePaintContentRect, prepaintLeft, prepaintTop, prepaintRight, prepaintBottom); |
- |
- // Then expand outwards from the visible area until we find a dirty row or column to update. |
- while (left > prepaintLeft || top > prepaintTop || right < prepaintRight || bottom < prepaintBottom) { |
- if (bottom < prepaintBottom) { |
- ++bottom; |
- if (!updateTiles(left, bottom, right, bottom, queue, 0, stats, didPaint) || didPaint) |
- return; |
- } |
- if (top > prepaintTop) { |
- --top; |
- if (!updateTiles(left, top, right, top, queue, 0, stats, didPaint) || didPaint) |
- return; |
- } |
- if (left > prepaintLeft) { |
- --left; |
- if (!updateTiles(left, top, left, bottom, queue, 0, stats, didPaint) || didPaint) |
- return; |
- } |
- if (right < prepaintRight) { |
- ++right; |
- if (!updateTiles(right, top, right, bottom, queue, 0, stats, didPaint) || didPaint) |
- return; |
- } |
- } |
-} |
- |
-bool TiledLayerChromium::needsIdlePaint() |
-{ |
- // Don't trigger more paints if we failed (as we'll just fail again). |
- if (m_failedUpdate || visibleContentRect().isEmpty() || m_tiler->hasEmptyBounds() || !drawsContent()) |
- return false; |
- |
- IntRect idlePaintContentRect = idlePaintRect(); |
- if (idlePaintContentRect.isEmpty()) |
- return false; |
- |
- int left, top, right, bottom; |
- m_tiler->contentRectToTileIndices(idlePaintContentRect, left, top, right, bottom); |
- |
- for (int j = top; j <= bottom; ++j) { |
- for (int i = left; i <= right; ++i) { |
- UpdatableTile* tile = tileAt(i, j); |
- ASSERT(tile); // Did setTexturePriorities get skipped? |
- if (!tile) |
- continue; |
- |
- bool updated = !tile->updateRect.isEmpty(); |
- bool canAcquire = tile->managedTexture()->canAcquireBackingTexture(); |
- bool dirty = tile->isDirty() || !tile->managedTexture()->haveBackingTexture(); |
- if (!updated && canAcquire && dirty) |
- return true; |
- } |
- } |
- return false; |
-} |
- |
-IntRect TiledLayerChromium::idlePaintRect() |
-{ |
- // Don't inflate an empty rect. |
- if (visibleContentRect().isEmpty()) |
- return IntRect(); |
- |
- // FIXME: This can be made a lot larger now! We should increase |
- // this slowly while insuring it doesn't cause any perf issues. |
- IntRect prepaintRect = visibleContentRect(); |
- prepaintRect.inflateX(m_tiler->tileSize().width()); |
- prepaintRect.inflateY(m_tiler->tileSize().height() * 2); |
- IntRect contentRect(IntPoint::zero(), contentBounds()); |
- prepaintRect.intersect(contentRect); |
- |
- return prepaintRect; |
-} |
- |
-} |
-#endif // USE(ACCELERATED_COMPOSITING) |