Index: cc/layer_tree_host_common.cc |
diff --git a/cc/layer_tree_host_common.cc b/cc/layer_tree_host_common.cc |
index 4af5717b71987c790e4fba3a16999fbd1841d134..1428f3e6ea57648a8d5d3a815ff1b069ab6b5af9 100644 |
--- a/cc/layer_tree_host_common.cc |
+++ b/cc/layer_tree_host_common.cc |
@@ -40,18 +40,17 @@ static void sortLayers(std::vector<LayerImpl*>::iterator first, std::vector<Laye |
layerSorter->sort(first, end); |
} |
-gfx::Rect LayerTreeHostCommon::calculateVisibleRect(const gfx::Rect& targetSurfaceRect, const gfx::Rect& layerBoundRect, const gfx::Transform& transform) |
+static inline gfx::Rect calculateVisibleRectWithCachedLayerRect(const gfx::Rect& targetSurfaceRect, const gfx::Rect& layerBoundRect, const gfx::Rect& layerRectInTargetSpace, const gfx::Transform& transform) |
jamesr
2012/12/11 19:13:21
i think the 'static' and 'inline' here are redunda
shawnsingh
2012/12/11 22:33:18
Done.
|
{ |
// Is this layer fully contained within the target surface? |
- gfx::Rect layerInSurfaceSpace = MathUtil::mapClippedRect(transform, layerBoundRect); |
- if (targetSurfaceRect.Contains(layerInSurfaceSpace)) |
+ if (targetSurfaceRect.Contains(layerRectInTargetSpace)) |
return layerBoundRect; |
// If the layer doesn't fill up the entire surface, then find the part of |
// the surface rect where the layer could be visible. This avoids trying to |
// project surface rect points that are behind the projection point. |
gfx::Rect minimalSurfaceRect = targetSurfaceRect; |
- minimalSurfaceRect.Intersect(layerInSurfaceSpace); |
+ minimalSurfaceRect.Intersect(layerRectInTargetSpace); |
// Project the corners of the target surface rect into the layer space. |
// This bounding rectangle may be larger than it needs to be (being |
@@ -63,6 +62,12 @@ gfx::Rect LayerTreeHostCommon::calculateVisibleRect(const gfx::Rect& targetSurfa |
return layerRect; |
} |
+gfx::Rect LayerTreeHostCommon::calculateVisibleRect(const gfx::Rect& targetSurfaceRect, const gfx::Rect& layerBoundRect, const gfx::Transform& transform) |
+{ |
+ gfx::Rect layerInSurfaceSpace = MathUtil::mapClippedRect(transform, layerBoundRect); |
+ return calculateVisibleRectWithCachedLayerRect(targetSurfaceRect, layerBoundRect, layerInSurfaceSpace, transform); |
+} |
+ |
template <typename LayerType> |
static inline bool isRootLayer(LayerType* layer) |
{ |
@@ -126,7 +131,7 @@ static inline bool layerClipsSubtree(LayerType* layer) |
} |
template<typename LayerType> |
-static gfx::Rect calculateVisibleContentRect(LayerType* layer) |
+static gfx::Rect calculateVisibleContentRect(LayerType* layer, const gfx::Rect& ancestorClipRectInDescendantSurfaceSpace, const gfx::Rect& layerRectInTargetSpace) |
{ |
DCHECK(layer->renderTarget()); |
@@ -134,23 +139,25 @@ static gfx::Rect calculateVisibleContentRect(LayerType* layer) |
if (!layer->drawsContent() || layer->contentBounds().IsEmpty() || layer->drawableContentRect().IsEmpty()) |
return gfx::Rect(); |
- gfx::Rect targetSurfaceClipRect; |
+ // Compute visible bounds in target surface space. |
+ gfx::Rect visibleRectInTargetSurfaceSpace = layer->drawableContentRect(); |
+ |
+ if (!layer->renderTarget()->renderSurface()->clipRect().IsEmpty()) { |
+ //gfx::Rect ancestorSurfaceClipRect = gfx::ToEnclosingRect(MathUtil::projectClippedRect(MathUtil::inverse(layer->renderTarget()->renderSurface()->drawTransform()), layer->renderTarget()->renderSurface()->clipRect())); |
jamesr
2012/12/11 19:13:21
?
shawnsingh
2012/12/11 22:33:18
residue from debugging =) it's removed now
|
+ //visibleRectInTargetSurfaceSpace.Intersect(ancestorSurfaceClipRect); |
- // First, compute visible bounds in target surface space. |
- if (layer->renderTarget()->renderSurface()->clipRect().IsEmpty()) |
- targetSurfaceClipRect = layer->drawableContentRect(); |
- else { |
// In this case the target surface does clip layers that contribute to it. So, we |
// have convert the current surface's clipRect from its ancestor surface space to |
// the current surface space. |
- targetSurfaceClipRect = gfx::ToEnclosingRect(MathUtil::projectClippedRect(MathUtil::inverse(layer->renderTarget()->renderSurface()->drawTransform()), layer->renderTarget()->renderSurface()->clipRect())); |
- targetSurfaceClipRect.Intersect(layer->drawableContentRect()); |
+ //gfx::Rect ancestorSurfaceClipRect = gfx::ToEnclosingRect(MathUtil::projectClippedRect(MathUtil::inverse(layer->renderTarget()->renderSurface()->drawTransform()), layer->renderTarget()->renderSurface()->clipRect())); |
+ |
+ visibleRectInTargetSurfaceSpace.Intersect(ancestorClipRectInDescendantSurfaceSpace); |
} |
- if (targetSurfaceClipRect.IsEmpty()) |
+ if (visibleRectInTargetSurfaceSpace.IsEmpty()) |
return gfx::Rect(); |
- return LayerTreeHostCommon::calculateVisibleRect(targetSurfaceClipRect, gfx::Rect(gfx::Point(), layer->contentBounds()), layer->drawTransform()); |
+ return calculateVisibleRectWithCachedLayerRect(visibleRectInTargetSurfaceSpace, gfx::Rect(gfx::Point(), layer->contentBounds()), layerRectInTargetSpace, layer->drawTransform()); |
} |
static inline bool transformToParentIsKnown(LayerImpl*) |
@@ -401,12 +408,31 @@ static inline void updateLayerContentsScale(Layer* layer, const gfx::Transform& |
replicaMaskLayer->setContentsScale(contentsScale); |
} |
+template<typename LayerType, typename LayerList> |
+static inline void removeSurfaceForEarlyExit(LayerType* layerToRemove, LayerList& renderSurfaceLayerList) |
+{ |
+ DCHECK(layerToRemove->renderSurface()); |
+ // Technically, we know that the layer we want to remove should be |
+ // at the back of the renderSurfaceLayerList. However, we have had |
+ // bugs before that added unnecessary layers here |
+ // (https://bugs.webkit.org/show_bug.cgi?id=74147), but that causes |
+ // things to crash. So here we proactively remove any additional |
+ // layers from the end of the list. |
+ while (renderSurfaceLayerList.back() != layerToRemove) { |
+ renderSurfaceLayerList.back()->clearRenderSurface(); |
+ renderSurfaceLayerList.pop_back(); |
+ } |
+ DCHECK(renderSurfaceLayerList.back() == layerToRemove); |
+ renderSurfaceLayerList.pop_back(); |
+ layerToRemove->clearRenderSurface(); |
+} |
+ |
// Recursively walks the layer tree starting at the given node and computes all the |
// necessary transformations, clipRects, render surfaces, etc. |
template<typename LayerType, typename LayerList, typename RenderSurfaceType> |
static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transform& parentMatrix, |
const gfx::Transform& fullHierarchyMatrix, const gfx::Transform& currentScrollCompensationMatrix, |
- const gfx::Rect& clipRectFromAncestor, bool ancestorClipsSubtree, |
+ const gfx::Rect& clipRectFromAncestor, const gfx::Rect& clipRectFromAncestorInDescendantSpace, bool ancestorClipsSubtree, |
RenderSurfaceType* nearestAncestorThatMovesPixels, LayerList& renderSurfaceLayerList, LayerList& layerList, |
LayerSorter* layerSorter, int maxTextureSize, float deviceScaleFactor, float pageScaleFactor, gfx::Rect& drawableContentRectOfSubtree) |
{ |
@@ -508,6 +534,13 @@ static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo |
gfx::Rect clipRectForSubtree; |
bool subtreeShouldBeClipped = false; |
+ // This value is cached on the stack so that we don't have to inverse-project |
+ // the surface's clipRect redundantly for every layer. This value is the |
+ // same as the surface's clipRect, except that instead of being described |
+ // in the target surface space (i.e. the ancestor surface space), it is |
+ // described in the current surface space. |
+ gfx::Rect clipRectForSubtreeInDescendantSpace; |
+ |
float accumulatedDrawOpacity = layer->opacity(); |
bool drawOpacityIsAnimating = layer->opacityIsAnimating(); |
if (layer->parent()) { |
@@ -527,12 +560,16 @@ static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo |
gfx::PointF position = layer->position() - layer->scrollDelta(); |
gfx::Transform combinedTransform = parentMatrix; |
- // LT = Tr[origin] * Tr[origin2anchor] |
- combinedTransform.Translate3d(position.x() + anchorPoint.x() * bounds.width(), position.y() + anchorPoint.y() * bounds.height(), layer->anchorPointZ()); |
- // LT = Tr[origin] * Tr[origin2anchor] * M[layer] |
- combinedTransform.PreconcatTransform(layer->transform()); |
- // LT = Tr[origin] * Tr[origin2anchor] * M[layer] * Tr[anchor2origin] |
- combinedTransform.Translate3d(-anchorPoint.x() * bounds.width(), -anchorPoint.y() * bounds.height(), -layer->anchorPointZ()); |
+ if (!layer->transform().IsIdentity()) { |
+ // LT = Tr[origin] * Tr[origin2anchor] |
+ combinedTransform.Translate3d(position.x() + anchorPoint.x() * bounds.width(), position.y() + anchorPoint.y() * bounds.height(), layer->anchorPointZ()); |
+ // LT = Tr[origin] * Tr[origin2anchor] * M[layer] |
+ combinedTransform.PreconcatTransform(layer->transform()); |
+ // LT = Tr[origin] * Tr[origin2anchor] * M[layer] * Tr[anchor2origin] |
+ combinedTransform.Translate3d(-anchorPoint.x() * bounds.width(), -anchorPoint.y() * bounds.height(), -layer->anchorPointZ()); |
+ } else { |
+ combinedTransform.Translate(position.x(), position.y()); |
+ } |
// The layer's contentsSize is determined from the combinedTransform, which then informs the |
// layer's drawTransform. |
@@ -643,10 +680,13 @@ static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo |
// The render surface clipRect is expressed in the space where this surface draws, i.e. the same space as clipRectFromAncestor. |
renderSurface->setIsClipped(ancestorClipsSubtree); |
- if (ancestorClipsSubtree) |
+ if (ancestorClipsSubtree) { |
renderSurface->setClipRect(clipRectFromAncestor); |
- else |
+ clipRectForSubtreeInDescendantSpace = gfx::ToEnclosingRect(MathUtil::projectClippedRect(MathUtil::inverse(renderSurface->drawTransform()), renderSurface->clipRect())); |
+ } else { |
renderSurface->setClipRect(gfx::Rect()); |
+ clipRectForSubtreeInDescendantSpace = clipRectFromAncestorInDescendantSpace; |
+ } |
renderSurface->setNearestAncestorThatMovesPixels(nearestAncestorThatMovesPixels); |
@@ -669,6 +709,9 @@ static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo |
if (ancestorClipsSubtree) |
clipRectForSubtree = clipRectFromAncestor; |
+ // The surface's cached clipRect value propagates regardless of what clipping goes on between layers here. |
+ clipRectForSubtreeInDescendantSpace = clipRectFromAncestorInDescendantSpace; |
+ |
// Layers that are not their own renderTarget will render into the target of their nearest ancestor. |
layerDrawProperties.render_target = layer->parent()->renderTarget(); |
} |
@@ -710,7 +753,7 @@ static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo |
LayerType* child = LayerTreeHostCommon::getChildAsRawPtr(layer->children(), i); |
gfx::Rect drawableContentRectOfChildSubtree; |
calculateDrawPropertiesInternal<LayerType, LayerList, RenderSurfaceType>(child, sublayerMatrix, nextHierarchyMatrix, nextScrollCompensationMatrix, |
- clipRectForSubtree, subtreeShouldBeClipped, nearestAncestorThatMovesPixels, |
+ clipRectForSubtree, clipRectForSubtreeInDescendantSpace, subtreeShouldBeClipped, nearestAncestorThatMovesPixels, |
renderSurfaceLayerList, descendants, layerSorter, maxTextureSize, deviceScaleFactor, pageScaleFactor, drawableContentRectOfChildSubtree); |
if (!drawableContentRectOfChildSubtree.IsEmpty()) { |
accumulatedDrawableContentRectOfChildren.Union(drawableContentRectOfChildSubtree); |
@@ -719,6 +762,11 @@ static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo |
} |
} |
+ if (layer->renderSurface() && !isRootLayer(layer) && !layer->renderSurface()->layerList().size()) { |
+ removeSurfaceForEarlyExit(layer, renderSurfaceLayerList); |
+ return; |
+ } |
+ |
// Compute the total drawableContentRect for this subtree (the rect is in targetSurface space) |
gfx::Rect localDrawableContentRectOfSubtree = accumulatedDrawableContentRectOfChildren; |
if (layer->drawsContent()) |
@@ -745,7 +793,7 @@ static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo |
} |
// Compute the layer's visible content rect (the rect is in content space) |
- layerDrawProperties.visible_content_rect = calculateVisibleContentRect(layer); |
+ layerDrawProperties.visible_content_rect = calculateVisibleContentRect(layer, clipRectForSubtreeInDescendantSpace, rectInTargetSpace); |
// Compute the remaining properties for the render surface, if the layer has one. |
if (isRootLayer(layer)) { |
@@ -773,9 +821,12 @@ static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo |
clippedContentRect.set_width(std::min(clippedContentRect.width(), maxTextureSize)); |
clippedContentRect.set_height(std::min(clippedContentRect.height(), maxTextureSize)); |
- if (clippedContentRect.IsEmpty()) |
+ if (clippedContentRect.IsEmpty()) { |
renderSurface->clearLayerLists(); |
- |
+ removeSurfaceForEarlyExit(layer, renderSurfaceLayerList); |
+ return; |
+ } |
+ |
renderSurface->setContentRect(clippedContentRect); |
// The owning layer's screenSpaceTransform has a scale from content to layer space which we need to undo and |
@@ -801,23 +852,6 @@ static void calculateDrawPropertiesInternal(LayerType* layer, const gfx::Transfo |
gfx::Transform replicaScreenSpaceTransform = layer->renderSurface()->screenSpaceTransform() * surfaceOriginToReplicaOriginTransform; |
renderSurface->setReplicaScreenSpaceTransform(replicaScreenSpaceTransform); |
} |
- |
- // If a render surface has no layer list, then it and none of its children needed to get drawn. |
- if (!layer->renderSurface()->layerList().size()) { |
- // FIXME: Originally we asserted that this layer was already at the end of the |
- // list, and only needed to remove that layer. For now, we remove the |
- // entire subtree of surfaces to fix a crash bug. The root cause is |
- // https://bugs.webkit.org/show_bug.cgi?id=74147 and we should be able |
- // to put the original assert after fixing that. |
- while (renderSurfaceLayerList.back() != layer) { |
- renderSurfaceLayerList.back()->clearRenderSurface(); |
- renderSurfaceLayerList.pop_back(); |
- } |
- DCHECK(renderSurfaceLayerList.back() == layer); |
- renderSurfaceLayerList.pop_back(); |
- layer->clearRenderSurface(); |
- return; |
- } |
} |
markLayerAsUpdated(layer); |
@@ -858,7 +892,7 @@ void LayerTreeHostCommon::calculateDrawProperties(Layer* rootLayer, const gfx::S |
cc::calculateDrawPropertiesInternal<Layer, std::vector<scoped_refptr<Layer> >, RenderSurface>( |
rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, |
- deviceViewportRect, subtreeShouldBeClipped, 0, renderSurfaceLayerList, |
+ deviceViewportRect, deviceViewportRect, subtreeShouldBeClipped, 0, renderSurfaceLayerList, |
dummyLayerList, 0, maxTextureSize, |
deviceScaleFactor, pageScaleFactor, totalDrawableContentRect); |
@@ -886,7 +920,7 @@ void LayerTreeHostCommon::calculateDrawProperties(LayerImpl* rootLayer, const gf |
cc::calculateDrawPropertiesInternal<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl>( |
rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, |
- deviceViewportRect, subtreeShouldBeClipped, 0, renderSurfaceLayerList, |
+ deviceViewportRect, deviceViewportRect, subtreeShouldBeClipped, 0, renderSurfaceLayerList, |
dummyLayerList, &layerSorter, maxTextureSize, |
deviceScaleFactor, pageScaleFactor, totalDrawableContentRect); |