Chromium Code Reviews| 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); |