diff options
author | skaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-30 18:24:57 +0000 |
---|---|---|
committer | skaslev@chromium.org <skaslev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-30 18:24:57 +0000 |
commit | 498ec6e0ebe1a042f35dc51c000a80de34eb17ef (patch) | |
tree | ab0fc2f9684b5df9afdb325d8b105dd9c45f53b7 /cc | |
parent | 4e28d8043881bff74b1473d622513c8cb07fe35d (diff) | |
download | chromium_src-498ec6e0ebe1a042f35dc51c000a80de34eb17ef.zip chromium_src-498ec6e0ebe1a042f35dc51c000a80de34eb17ef.tar.gz chromium_src-498ec6e0ebe1a042f35dc51c000a80de34eb17ef.tar.bz2 |
Don't create render passes for transparent images.
That patch speeds up Google Maps use-case smoke test by a factor of 10x.
It also reduces memory pressure on the GPU. See the related bugs for more info.
BUG=161434,160871
Review URL: https://chromiumcodereview.appspot.com/11316171
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@170487 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/damage_tracker_unittest.cc | 3 | ||||
-rw-r--r-- | cc/delegated_renderer_layer_impl.cc | 4 | ||||
-rw-r--r-- | cc/delegated_renderer_layer_impl.h | 2 | ||||
-rw-r--r-- | cc/layer.cc | 12 | ||||
-rw-r--r-- | cc/layer.h | 6 | ||||
-rw-r--r-- | cc/layer_impl.cc | 12 | ||||
-rw-r--r-- | cc/layer_impl.h | 12 | ||||
-rw-r--r-- | cc/layer_iterator_unittest.cc | 3 | ||||
-rw-r--r-- | cc/layer_tree_host_common.cc | 13 | ||||
-rw-r--r-- | cc/layer_tree_host_common_unittest.cc | 29 | ||||
-rw-r--r-- | cc/layer_tree_host_impl_unittest.cc | 7 |
11 files changed, 77 insertions, 26 deletions
diff --git a/cc/damage_tracker_unittest.cc b/cc/damage_tracker_unittest.cc index 42eaaaf..167c4c1 100644 --- a/cc/damage_tracker_unittest.cc +++ b/cc/damage_tracker_unittest.cc @@ -113,6 +113,7 @@ scoped_ptr<LayerImpl> createTestTreeWithTwoSurfaces() child1->setContentBounds(gfx::Size(30, 30)); child1->setOpacity(0.5); // with a child that drawsContent, this will cause the layer to create its own renderSurface. child1->setDrawsContent(false); // this layer does not draw, but is intended to create its own renderSurface. + child1->setForceRenderSurface(true); child2->setPosition(gfx::PointF(11, 11)); child2->setAnchorPoint(gfx::PointF()); @@ -723,6 +724,7 @@ TEST_F(DamageTrackerTest, verifyDamageForAddingAndRemovingRenderSurfaces) // clearDamageForAllSurfaces(root.get()); child1->setOpacity(1); + child1->setForceRenderSurface(false); emulateDrawingOneFrame(root.get()); // Sanity check that there is only one surface now. @@ -743,6 +745,7 @@ TEST_F(DamageTrackerTest, verifyDamageForAddingAndRemovingRenderSurfaces) // Then change the tree so that the render surface is added back. clearDamageForAllSurfaces(root.get()); child1->setOpacity(0.5); + child1->setForceRenderSurface(true); emulateDrawingOneFrame(root.get()); // Sanity check that there is a new surface now. diff --git a/cc/delegated_renderer_layer_impl.cc b/cc/delegated_renderer_layer_impl.cc index 8528edf..7907454 100644 --- a/cc/delegated_renderer_layer_impl.cc +++ b/cc/delegated_renderer_layer_impl.cc @@ -22,14 +22,14 @@ DelegatedRendererLayerImpl::~DelegatedRendererLayerImpl() clearRenderPasses(); } -bool DelegatedRendererLayerImpl::descendantDrawsContent() +int DelegatedRendererLayerImpl::descendantsDrawContent() { // FIXME: This could possibly return false even though there are some // quads present as they could all be from a single layer (or set of // layers without children). If this happens, then make a test that // ensures the opacity is being changed on quads in the root RenderPass // when this layer doesn't own a RenderSurfaceImpl. - return !m_renderPassesInDrawOrder.isEmpty(); + return m_renderPassesInDrawOrder.isEmpty() ? 0 : 2; } bool DelegatedRendererLayerImpl::hasContributingDelegatedRenderPasses() const diff --git a/cc/delegated_renderer_layer_impl.h b/cc/delegated_renderer_layer_impl.h index 7e7caa5..0e1dfd9 100644 --- a/cc/delegated_renderer_layer_impl.h +++ b/cc/delegated_renderer_layer_impl.h @@ -16,7 +16,7 @@ public: static scoped_ptr<DelegatedRendererLayerImpl> create(int id) { return make_scoped_ptr(new DelegatedRendererLayerImpl(id)); } virtual ~DelegatedRendererLayerImpl(); - virtual bool descendantDrawsContent() OVERRIDE; + virtual int descendantsDrawContent() OVERRIDE; virtual bool hasContributingDelegatedRenderPasses() const OVERRIDE; // This gives ownership of the RenderPasses to the layer. diff --git a/cc/layer.cc b/cc/layer.cc index c7b7ebc..242ad76 100644 --- a/cc/layer.cc +++ b/cc/layer.cc @@ -698,13 +698,17 @@ void Layer::createRenderSurface() setRenderTarget(this); } -bool Layer::descendantDrawsContent() +int Layer::descendantsDrawContent() { + int result = 0; for (size_t i = 0; i < m_children.size(); ++i) { - if (m_children[i]->drawsContent() || m_children[i]->descendantDrawsContent()) - return true; + if (m_children[i]->drawsContent()) + ++result; + result += m_children[i]->descendantsDrawContent(); + if (result > 1) + return result; } - return false; + return result; } int Layer::id() const @@ -267,8 +267,10 @@ public: void setBoundsContainPageScale(bool); bool boundsContainPageScale() const { return m_boundsContainPageScale; } - // Returns true if any of the layer's descendants has content to draw. - bool descendantDrawsContent(); + // Returns 0 if none of the layer's descendants has content to draw, + // 1 if exactly one descendant has content to draw, or a number >1 + // (but necessary the exact number of descendants) otherwise. + int descendantsDrawContent(); LayerTreeHost* layerTreeHost() const { return m_layerTreeHost; } diff --git a/cc/layer_impl.cc b/cc/layer_impl.cc index feee4f4..a1dffea 100644 --- a/cc/layer_impl.cc +++ b/cc/layer_impl.cc @@ -112,13 +112,17 @@ void LayerImpl::createRenderSurface() setRenderTarget(this); } -bool LayerImpl::descendantDrawsContent() +int LayerImpl::descendantsDrawContent() { + int result = 0; for (size_t i = 0; i < m_children.size(); ++i) { - if (m_children[i]->drawsContent() || m_children[i]->descendantDrawsContent()) - return true; + if (m_children[i]->drawsContent()) + ++result; + result += m_children[i]->descendantsDrawContent(); + if (result > 1) + return result; } - return false; + return result; } scoped_ptr<SharedQuadState> LayerImpl::createSharedQuadState() const diff --git a/cc/layer_impl.h b/cc/layer_impl.h index 6cc4d12..3e72d20 100644 --- a/cc/layer_impl.h +++ b/cc/layer_impl.h @@ -38,6 +38,8 @@ struct AppendQuadsData; class CC_EXPORT LayerImpl : public LayerAnimationControllerClient { public: + typedef ScopedPtrVector<LayerImpl> LayerList; + static scoped_ptr<LayerImpl> create(int id) { return make_scoped_ptr(new LayerImpl(id)); @@ -55,7 +57,7 @@ public: // Tree structure. LayerImpl* parent() { return m_parent; } const LayerImpl* parent() const { return m_parent; } - const ScopedPtrVector<LayerImpl>& children() const { return m_children; } + const LayerList& children() const { return m_children; } void addChild(scoped_ptr<LayerImpl>); void removeFromParent(); void removeAllChildren(); @@ -97,8 +99,10 @@ public: bool forceRenderSurface() const { return m_forceRenderSurface; } void setForceRenderSurface(bool force) { m_forceRenderSurface = force; } - // Returns true if any of the layer's descendants has content to draw. - virtual bool descendantDrawsContent(); + // Returns 0 if none of the layer's descendants has content to draw, + // 1 if exactly one descendant has content to draw, or a number >1 + // (but necessary the exact number of descendants) otherwise. + virtual int descendantsDrawContent(); void setAnchorPoint(const gfx::PointF&); const gfx::PointF& anchorPoint() const { return m_anchorPoint; } @@ -314,7 +318,7 @@ private: // Properties internal to LayerImpl LayerImpl* m_parent; - ScopedPtrVector<LayerImpl> m_children; + LayerList m_children; // m_maskLayer can be temporarily stolen during tree sync, we need this ID to confirm newly assigned layer is still the previous one int m_maskLayerId; scoped_ptr<LayerImpl> m_maskLayer; diff --git a/cc/layer_iterator_unittest.cc b/cc/layer_iterator_unittest.cc index cdcbec1..1dfe9b2 100644 --- a/cc/layer_iterator_unittest.cc +++ b/cc/layer_iterator_unittest.cc @@ -214,7 +214,8 @@ TEST(LayerIteratorTest, complexTreeMultiSurface) rootLayer->addChild(root2); rootLayer->addChild(root3); root2->setDrawsContent(false); - root2->setOpacity(0.5); // Force the layer to own a new surface. + root2->setOpacity(0.5); + root2->setForceRenderSurface(true); // Force the layer to own a new surface. root2->addChild(root21); root2->addChild(root22); root2->addChild(root23); diff --git a/cc/layer_tree_host_common.cc b/cc/layer_tree_host_common.cc index 0d6909c..8aff202 100644 --- a/cc/layer_tree_host_common.cc +++ b/cc/layer_tree_host_common.cc @@ -250,19 +250,20 @@ static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlig return true; // Cache this value, because otherwise it walks the entire subtree several times. - bool descendantDrawsContent = layer->descendantDrawsContent(); + int descendantsDrawContent = layer->descendantsDrawContent(); // If the layer flattens its subtree (i.e. the layer doesn't preserve-3d), but it is // treated as a 3D object by its parent (i.e. parent does preserve-3d). - if (layerIsInExisting3DRenderingContext(layer) && !layer->preserves3D() && descendantDrawsContent) + if (layerIsInExisting3DRenderingContext(layer) && !layer->preserves3D() && descendantsDrawContent > 0) return true; // If the layer clips its descendants but it is not axis-aligned with respect to its parent. - if (layerClipsSubtree(layer) && !axisAlignedWithRespectToParent && descendantDrawsContent) + if (layerClipsSubtree(layer) && !axisAlignedWithRespectToParent && descendantsDrawContent > 0) return true; // If the layer has opacity != 1 and does not have a preserves-3d transform style. - if (layer->opacity() != 1 && !layer->preserves3D() && descendantDrawsContent) + if (layer->opacity() != 1 && !layer->preserves3D() && descendantsDrawContent > 0 + && (layer->drawsContent() || descendantsDrawContent > 1)) return true; return false; @@ -487,10 +488,10 @@ static void calculateDrawTransformsInternal(LayerType* layer, const gfx::Transfo gfx::Rect clipRectForSubtree; bool subtreeShouldBeClipped = false; - + float drawOpacity = layer->opacity(); bool drawOpacityIsAnimating = layer->opacityIsAnimating(); - if (layer->parent() && layer->parent()->preserves3D()) { + if (layer->parent()) { drawOpacity *= layer->parent()->drawOpacity(); drawOpacityIsAnimating |= layer->parent()->drawOpacityIsAnimating(); } diff --git a/cc/layer_tree_host_common_unittest.cc b/cc/layer_tree_host_common_unittest.cc index 6933335..a1f6923 100644 --- a/cc/layer_tree_host_common_unittest.cc +++ b/cc/layer_tree_host_common_unittest.cc @@ -327,6 +327,7 @@ TEST(LayerTreeHostCommonTest, verifyTransformsForSingleRenderSurface) // Child is set up so that a new render surface should be created. child->setOpacity(0.5); + child->setForceRenderSurface(true); gfx::Transform parentLayerTransform; parentLayerTransform.Scale3d(1, 0.9, 1); @@ -1355,6 +1356,7 @@ TEST(LayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces) child->setMasksToBounds(true); child->setOpacity(0.4f); + child->setForceRenderSurface(true); grandChild->setOpacity(0.5); greatGrandChild->setOpacity(0.4f); @@ -1401,7 +1403,9 @@ TEST(LayerTreeHostCommonTest, verifyClipRectCullsSurfaceWithoutVisibleContent) parent->setMasksToBounds(true); child->setOpacity(0.4f); + child->setForceRenderSurface(true); grandChild->setOpacity(0.4f); + grandChild->setForceRenderSurface(true); std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; @@ -1629,10 +1633,15 @@ TEST(LayerTreeHostCommonTest, verifyClipRectIsPropagatedCorrectlyToSurfaces) // Force everyone to be a render surface. child->setOpacity(0.4f); + child->setForceRenderSurface(true); grandChild1->setOpacity(0.5); + grandChild1->setForceRenderSurface(true); grandChild2->setOpacity(0.5); + grandChild2->setForceRenderSurface(true); grandChild3->setOpacity(0.5); + grandChild3->setForceRenderSurface(true); grandChild4->setOpacity(0.5); + grandChild4->setForceRenderSurface(true); std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; @@ -4611,5 +4620,25 @@ TEST(LayerTreeHostCommonTest, verifySubtreeSearch) EXPECT_EQ(0, LayerTreeHostCommon::findLayerInSubtree(root.get(), nonexistentId)); } +TEST(LayerTreeHostCommonTest, verifyTransparentChildRenderSurfaceCreation) +{ + scoped_refptr<Layer> root = Layer::create(); + scoped_refptr<Layer> child = Layer::create(); + scoped_refptr<LayerWithForcedDrawsContent> grandChild = make_scoped_refptr(new LayerWithForcedDrawsContent()); + + const gfx::Transform identityMatrix; + setLayerPropertiesForTesting(root.get(), identityMatrix, identityMatrix, gfx::PointF(), gfx::PointF(), gfx::Size(100, 100), false); + setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, gfx::PointF(), gfx::PointF(), gfx::Size(10, 10), false); + setLayerPropertiesForTesting(grandChild.get(), identityMatrix, identityMatrix, gfx::PointF(), gfx::PointF(), gfx::Size(10, 10), false); + + root->addChild(child); + child->addChild(grandChild); + child->setOpacity(0.5f); + + executeCalculateDrawTransformsAndVisibility(root.get()); + + EXPECT_FALSE(child->renderSurface()); +} + } // namespace } // namespace cc diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc index a85ff1d..58e361e 100644 --- a/cc/layer_tree_host_impl_unittest.cc +++ b/cc/layer_tree_host_impl_unittest.cc @@ -2389,6 +2389,7 @@ static scoped_ptr<LayerTreeHostImpl> setupLayersForOpacity(bool partialSwap, Lay child->setContentBounds(child->bounds()); child->setVisibleContentRect(childRect); child->setDrawsContent(false); + child->setForceRenderSurface(true); grandChild->setAnchorPoint(gfx::PointF(0, 0)); grandChild->setPosition(gfx::Point(grandChildRect.x(), grandChildRect.y())); @@ -3138,7 +3139,8 @@ static void setupLayersForTextureCaching(LayerTreeHostImpl* layerTreeHostImpl, L // It will contain other layers that draw content. addDrawingLayerTo(intermediateLayerPtr, 3, gfx::Rect(10, 10, rootSize.width(), rootSize.height()), &surfaceLayerPtr); surfaceLayerPtr->setDrawsContent(false); // only children draw content - surfaceLayerPtr->setOpacity(0.5f); // This will cause it to have a surface + surfaceLayerPtr->setOpacity(0.5f); + surfaceLayerPtr->setForceRenderSurface(true); // This will cause it to have a surface // Child of the surface layer will produce some quads addDrawingLayerTo(surfaceLayerPtr, 4, gfx::Rect(5, 5, rootSize.width() - 25, rootSize.height() - 25), &childPtr); @@ -3182,7 +3184,8 @@ TEST_P(LayerTreeHostImplTest, textureCachingWithClipping) // Surface layer is the layer that changes its opacity // It will contain other layers that draw content. - surfaceLayerPtr->setOpacity(0.5f); // This will cause it to have a surface + surfaceLayerPtr->setOpacity(0.5f); + surfaceLayerPtr->setForceRenderSurface(true); // This will cause it to have a surface addDrawingLayerTo(surfaceLayerPtr, 4, gfx::Rect(0, 0, 100, 3), 0); addDrawingLayerTo(surfaceLayerPtr, 5, gfx::Rect(0, 97, 100, 3), 0); |