Add a way to update GraphicsLayerCA visibleRects without having to do a flush

https://bugs.webkit.org/show_bug.cgi?id=113459

Reviewed by Tim Horton.

Some platforms need to update TiledBacking visible rects from
outside of WebKit, for example if they use delegated scrolling.
They want to avoid forcing layout to be up-to-date when doing this.

Currently, updating the visibleRect happens when the GraphicsLayerCA
layer are being flushed, but that makes some assumptions about
layout being up-to-date.

To fix this, add a light-weight pass over the layer tree that
uses TransformState to compute the visibleRect for each
layer, and only if the visibleRect would cause a change in the
tiles in a TiledBacking trigger a layer flush.

* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::recomputeVisibleRects):
* platform/graphics/TiledBacking.h:
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::recursiveComputeVisibleRect):
(WebCore::GraphicsLayerCA::recomputeVisibleRects):
(WebCore::GraphicsLayerCA::computeVisibleRect):
* platform/graphics/ca/GraphicsLayerCA.h:
* platform/graphics/ca/mac/TileController.h:
* platform/graphics/ca/mac/TileController.mm:
(WebCore::TileController::tilesWouldChangeForVisibleRect):
(WebCore::TileController::computeTileCoverageRect):
(WebCore::TileController::revalidateTiles):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@147058 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b38b6ff0
2013-03-27 Simon Fraser <simon.fraser@apple.com>
Add a way to update GraphicsLayerCA visibleRects without having to do a flush
https://bugs.webkit.org/show_bug.cgi?id=113459
Reviewed by Tim Horton.
Some platforms need to update TiledBacking visible rects from
outside of WebKit, for example if they use delegated scrolling.
They want to avoid forcing layout to be up-to-date when doing this.
Currently, updating the visibleRect happens when the GraphicsLayerCA
layer are being flushed, but that makes some assumptions about
layout being up-to-date.
To fix this, add a light-weight pass over the layer tree that
uses TransformState to compute the visibleRect for each
layer, and only if the visibleRect would cause a change in the
tiles in a TiledBacking trigger a layer flush.
* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::recomputeVisibleRects):
* platform/graphics/TiledBacking.h:
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::recursiveComputeVisibleRect):
(WebCore::GraphicsLayerCA::recomputeVisibleRects):
(WebCore::GraphicsLayerCA::computeVisibleRect):
* platform/graphics/ca/GraphicsLayerCA.h:
* platform/graphics/ca/mac/TileController.h:
* platform/graphics/ca/mac/TileController.mm:
(WebCore::TileController::tilesWouldChangeForVisibleRect):
(WebCore::TileController::computeTileCoverageRect):
(WebCore::TileController::revalidateTiles):
2013-03-27 Philip Rogers <pdr@google.com>
Rename toScriptElement -> toScriptElementIfPossible
......@@ -408,8 +408,11 @@ public:
// and descendant layers, and this layer only.
virtual void flushCompositingState(const FloatRect& /* clipRect */) { }
virtual void flushCompositingStateForThisLayerOnly() { }
// Return a string with a human readable form of the layer tree, If debug is true
// Walk the layer tree, recomputing the visible rects of layer with TiledBacking, on platforms that use it.
virtual void recomputeVisibleRects(const FloatRect& /* clipRect */) { }
// Return a string with a human readable form of the layer tree, If debug is true
// pointers for the layers and timing data will be included in the returned string.
String layerTreeAsText(LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const;
......
......@@ -46,6 +46,7 @@ public:
virtual void setVisibleRect(const FloatRect&) = 0;
virtual FloatRect visibleRect() const = 0;
virtual bool tilesWouldChangeForVisibleRect(const FloatRect&) const = 0;
virtual void setExposedRect(const FloatRect&) = 0;
virtual void setClipsToExposedRect(bool) = 0;
......
......@@ -907,25 +907,66 @@ void GraphicsLayerCA::flushCompositingStateForThisLayerOnly()
client()->didCommitChangesForLayer(this);
}
void GraphicsLayerCA::recursiveComputeVisibleRect(const TransformState& state)
{
TransformState localState = state;
// This may be called at times when layout has not been updated, so we want to avoid calling out to the client
// for animating transforms.
FloatRect visibleRect = computeVisibleRect(localState, 0);
if (visibleRect != m_visibleRect) {
m_visibleRect = visibleRect;
if (TiledBacking* tiledBacking = this->tiledBacking()) {
if (tiledBacking->tilesWouldChangeForVisibleRect(m_visibleRect))
noteLayerPropertyChanged(VisibleRectChanged);
}
}
if (m_maskLayer) {
GraphicsLayerCA* maskLayerCA = static_cast<GraphicsLayerCA*>(m_maskLayer);
maskLayerCA->recursiveComputeVisibleRect(localState);
}
const Vector<GraphicsLayer*>& childLayers = children();
size_t numChildren = childLayers.size();
for (size_t i = 0; i < numChildren; ++i) {
GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
curChild->recursiveComputeVisibleRect(localState);
}
if (m_replicaLayer)
static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveComputeVisibleRect(localState);
}
void GraphicsLayerCA::recomputeVisibleRects(const FloatRect& clipRect)
{
TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(clipRect));
recursiveComputeVisibleRect(state);
}
TiledBacking* GraphicsLayerCA::tiledBacking() const
{
return m_layer->tiledBacking();
}
FloatRect GraphicsLayerCA::computeVisibleRect(TransformState& state) const
FloatRect GraphicsLayerCA::computeVisibleRect(TransformState& state, ComputeVisibleRectFlags flags) const
{
bool preserve3D = preserves3D() || (parent() ? parent()->preserves3D() : false);
TransformState::TransformAccumulation accumulation = preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform;
TransformationMatrix layerTransform;
FloatPoint position = m_position;
if (m_client)
m_client->customPositionForVisibleRectComputation(this, position);
if (client())
client()->customPositionForVisibleRectComputation(this, position);
layerTransform.translate(position.x(), position.y());
TransformationMatrix currentTransform;
if (client() && client()->getCurrentTransform(this, currentTransform) && !currentTransform.isIdentity()) {
if (!(flags & RespectAnimatingTransforms) || !client() || !client()->getCurrentTransform(this, currentTransform))
currentTransform = m_transform;
if (!currentTransform.isIdentity()) {
FloatPoint3D absoluteAnchorPoint(anchorPoint());
absoluteAnchorPoint.scale(size().width(), size().height(), 1);
layerTransform.translate3d(absoluteAnchorPoint.x(), absoluteAnchorPoint.y(), absoluteAnchorPoint.z());
......
......@@ -142,6 +142,9 @@ public:
virtual void flushCompositingState(const FloatRect&);
virtual void flushCompositingStateForThisLayerOnly();
void recursiveComputeVisibleRect(const TransformState&);
virtual void recomputeVisibleRects(const FloatRect& clipRect);
virtual TiledBacking* tiledBacking() const OVERRIDE;
bool allowTiledLayer() const { return m_allowTiledLayer; }
......@@ -243,7 +246,9 @@ private:
void computePixelAlignment(float pixelAlignmentScale, const FloatPoint& positionRelativeToBase,
FloatPoint& position, FloatSize&, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset) const;
FloatRect computeVisibleRect(TransformState&) const;
enum ComputeVisibleRectFlag { RespectAnimatingTransforms = 1 << 0 };
typedef unsigned ComputeVisibleRectFlags;
FloatRect computeVisibleRect(TransformState&, ComputeVisibleRectFlags = RespectAnimatingTransforms) const;
const FloatRect& visibleRect() const { return m_visibleRect; }
FloatRect adjustTiledLayerVisibleRect(TiledBacking*, const FloatRect& oldVisibleRect, const FloatSize& oldSize) const;
......
......@@ -107,6 +107,7 @@ private:
// TiledBacking member functions.
virtual void setVisibleRect(const FloatRect&) OVERRIDE;
virtual bool tilesWouldChangeForVisibleRect(const FloatRect&) const OVERRIDE;
virtual void setExposedRect(const FloatRect&) OVERRIDE;
virtual bool clipsToExposedRect() OVERRIDE { return m_clipsToExposedRect; }
virtual void setClipsToExposedRect(bool) OVERRIDE;
......@@ -133,7 +134,7 @@ private:
IntRect rectForTileIndex(const TileIndex&) const;
void getTileIndexRangeForRect(const IntRect&, TileIndex& topLeft, TileIndex& bottomRight) const;
FloatRect computeTileCoverageRect(const FloatRect& previousVisibleRect) const;
FloatRect computeTileCoverageRect(const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect) const;
IntSize tileSizeForCoverageRect(const FloatRect&) const;
void scheduleTileRevalidation(double interval);
......
......@@ -306,6 +306,35 @@ void TileController::setVisibleRect(const FloatRect& visibleRect)
revalidateTiles();
}
bool TileController::tilesWouldChangeForVisibleRect(const FloatRect& newVisibleRect) const
{
FloatRect visibleRect = newVisibleRect;
if (m_clipsToExposedRect)
visibleRect.intersect(m_exposedRect);
if (visibleRect.isEmpty() || bounds().isEmpty())
return false;
FloatRect currentTileCoverageRect = computeTileCoverageRect(m_visibleRect, newVisibleRect);
FloatRect scaledRect(currentTileCoverageRect);
scaledRect.scale(m_scale);
IntRect currentCoverageRectInTileCoords(enclosingIntRect(scaledRect));
IntSize newTileSize = tileSizeForCoverageRect(currentTileCoverageRect);
bool tileSizeChanged = newTileSize != m_tileSize;
if (tileSizeChanged)
return true;
TileIndex topLeft;
TileIndex bottomRight;
getTileIndexRangeForRect(currentCoverageRectInTileCoords, topLeft, bottomRight);
IntRect coverageRect = rectForTileIndex(topLeft);
coverageRect.unite(rectForTileIndex(bottomRight));
return coverageRect != m_primaryTileCoverageRect;
}
void TileController::setExposedRect(const FloatRect& exposedRect)
{
if (m_exposedRect == exposedRect)
......@@ -417,9 +446,9 @@ void TileController::getTileIndexRangeForRect(const IntRect& rect, TileIndex& to
bottomRight.setY(max(bottomYRatio - 1, 0));
}
FloatRect TileController::computeTileCoverageRect(const FloatRect& previousVisibleRect) const
FloatRect TileController::computeTileCoverageRect(const FloatRect& previousVisibleRect, const FloatRect& currentVisibleRect) const
{
FloatRect visibleRect = m_visibleRect;
FloatRect visibleRect = currentVisibleRect;
if (m_clipsToExposedRect)
visibleRect.intersect(m_exposedRect);
......@@ -591,7 +620,7 @@ void TileController::revalidateTiles(TileValidationPolicyFlags foregroundValidat
TileValidationPolicyFlags validationPolicy = m_isInWindow ? foregroundValidationPolicy : backgroundValidationPolicy;
FloatRect tileCoverageRect = computeTileCoverageRect(m_visibleRectAtLastRevalidate);
FloatRect tileCoverageRect = computeTileCoverageRect(m_visibleRectAtLastRevalidate, m_visibleRect);
FloatRect scaledRect(tileCoverageRect);
scaledRect.scale(m_scale);
IntRect coverageRectInTileCoords(enclosingIntRect(scaledRect));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment