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

Unified Diff: cc/layer_tree_host_common.cc

Issue 11534006: Reduce more matrix math in calculateDrawProperties (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698