diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-24 18:29:44 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-24 18:29:44 +0000 |
commit | 518ee58ff2ed4f72e313fce4f3c29d2688b3ade1 (patch) | |
tree | a021a76da13a66e64057d65d3420660687a54a5a /cc | |
parent | 50b03123bf40bec1277f63a3720d6849d2e90fc8 (diff) | |
download | chromium_src-518ee58ff2ed4f72e313fce4f3c29d2688b3ade1.zip chromium_src-518ee58ff2ed4f72e313fce4f3c29d2688b3ade1.tar.gz chromium_src-518ee58ff2ed4f72e313fce4f3c29d2688b3ade1.tar.bz2 |
cc: Apply the layer's initial CSS scale to the contentsScale to render text at the right resolution.
Currently the transform does not affect the scale of a layer's contents. This
means that when a layer with a scale on it becomes composited, its text is
rendered at 1x and then scaled up during rendering, which makes for very fuzzy
text.
This change applies the scale from the layer's CSS transform to the
contentsScale so that text is rendered at the same pixel resolution
as it will be drawn on screen.
Tests:
cc_unittests:CCLayerTreeHostCommonTest.verifyContentsScale
cc_unittests:CCLayerTreeHostCommonTest.verifyContentsScaleForSurfaces
BUG=149943
R=enne
Review URL: https://codereview.chromium.org/11230033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@163873 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/damage_tracker_unittest.cc | 2 | ||||
-rw-r--r-- | cc/layer.cc | 35 | ||||
-rw-r--r-- | cc/layer.h | 16 | ||||
-rw-r--r-- | cc/layer_iterator_unittest.cc | 6 | ||||
-rw-r--r-- | cc/layer_tree_host.cc | 29 | ||||
-rw-r--r-- | cc/layer_tree_host_common.cc | 106 | ||||
-rw-r--r-- | cc/layer_tree_host_common.h | 4 | ||||
-rw-r--r-- | cc/layer_tree_host_common_unittest.cc | 400 | ||||
-rw-r--r-- | cc/layer_tree_host_impl.cc | 3 | ||||
-rw-r--r-- | cc/layer_tree_host_impl_unittest.cc | 8 | ||||
-rw-r--r-- | cc/math_util.cc | 15 | ||||
-rw-r--r-- | cc/math_util.h | 2 | ||||
-rw-r--r-- | cc/occlusion_tracker_unittest.cc | 18 |
13 files changed, 516 insertions, 128 deletions
diff --git a/cc/damage_tracker_unittest.cc b/cc/damage_tracker_unittest.cc index 69b474b..d7a8dabc 100644 --- a/cc/damage_tracker_unittest.cc +++ b/cc/damage_tracker_unittest.cc @@ -34,7 +34,7 @@ void executeCalculateDrawTransformsAndVisibility(LayerImpl* root, std::vector<La ASSERT_TRUE(root->renderSurface()); ASSERT_FALSE(renderSurfaceLayerList.size()); - LayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, &layerSorter, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, 1, &layerSorter, dummyMaxTextureSize, renderSurfaceLayerList); } void clearDamageForAllSurfaces(LayerImpl* layer) diff --git a/cc/layer.cc b/cc/layer.cc index 62e5c86..afa35e8 100644 --- a/cc/layer.cc +++ b/cc/layer.cc @@ -65,6 +65,8 @@ Layer::Layer() , m_drawTransformIsAnimating(false) , m_screenSpaceTransformIsAnimating(false) , m_contentsScale(1.0) + , m_rasterScale(1.0) + , m_automaticallyComputeRasterScale(false) , m_boundsContainPageScale(false) , m_layerAnimationDelegate(0) , m_layerScrollClient(0) @@ -132,6 +134,8 @@ void Layer::setParent(Layer* layer) DCHECK(!layer || !layer->hasAncestor(this)); m_parent = layer; setLayerTreeHost(m_parent ? m_parent->layerTreeHost() : 0); + + forceAutomaticRasterScaleToBeRecomputed(); } bool Layer::hasAncestor(Layer* ancestor) const @@ -657,6 +661,37 @@ void Layer::setContentsScale(float contentsScale) setNeedsDisplay(); } +void Layer::setRasterScale(float scale) +{ + if (m_rasterScale == scale) + return; + m_rasterScale = scale; + + if (!m_automaticallyComputeRasterScale) + return; + setNeedsDisplay(); +} + +void Layer::setAutomaticallyComputeRasterScale(bool automatic) +{ + if (m_automaticallyComputeRasterScale == automatic) + return; + m_automaticallyComputeRasterScale = automatic; + + if (m_automaticallyComputeRasterScale) + forceAutomaticRasterScaleToBeRecomputed(); + else + setRasterScale(1); +} + +void Layer::forceAutomaticRasterScaleToBeRecomputed() +{ + if (!m_automaticallyComputeRasterScale) + return; + m_rasterScale = 0; + setNeedsDisplay(); +} + void Layer::setBoundsContainPageScale(bool boundsContainPageScale) { for (size_t i = 0; i < m_children.size(); ++i) @@ -226,11 +226,25 @@ public: void setScreenSpaceTransform(const WebKit::WebTransformationMatrix& matrix) { m_screenSpaceTransform = matrix; } const IntRect& drawableContentRect() const { return m_drawableContentRect; } void setDrawableContentRect(const IntRect& rect) { m_drawableContentRect = rect; } + // The contentsScale converts from logical, non-page-scaled pixels to target pixels. // The contentsScale is 1 for the root layer as it is already in physical pixels. float contentsScale() const { return m_contentsScale; } void setContentsScale(float); + // The scale at which contents should be rastered, to match the scale at + // which they will drawn to the screen. This scale is a component of the + // contentsScale() but does not include page/device scale factors. + float rasterScale() const { return m_rasterScale; } + void setRasterScale(float scale); + + // When true, the rasterScale() will be set by the compositor. If false, it + // will use whatever value is given to it by the embedder. + bool automaticallyComputeRasterScale() { return m_automaticallyComputeRasterScale; } + void setAutomaticallyComputeRasterScale(bool); + + void forceAutomaticRasterScaleToBeRecomputed(); + // When true, the layer's contents are not scaled by the current page scale factor. // setBoundsContainPageScale recursively sets the value on all child layers. void setBoundsContainPageScale(bool); @@ -377,6 +391,8 @@ private: // Uses target surface space. IntRect m_drawableContentRect; float m_contentsScale; + float m_rasterScale; + bool m_automaticallyComputeRasterScale; bool m_boundsContainPageScale; WebKit::WebTransformationMatrix m_implTransform; diff --git a/cc/layer_iterator_unittest.cc b/cc/layer_iterator_unittest.cc index bb3878d..471d322 100644 --- a/cc/layer_iterator_unittest.cc +++ b/cc/layer_iterator_unittest.cc @@ -130,7 +130,7 @@ TEST(LayerIteratorTest, simpleTree) rootLayer->addChild(fourth); std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; - LayerTreeHostCommon::calculateDrawTransforms(rootLayer.get(), rootLayer->bounds(), 1, 256, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(rootLayer.get(), rootLayer->bounds(), 1, 1, 256, renderSurfaceLayerList); iterateBackToFront(&renderSurfaceLayerList); EXPECT_COUNT(rootLayer, 0, -1, 1); @@ -172,7 +172,7 @@ TEST(LayerIteratorTest, complexTree) root23->addChild(root231); std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; - LayerTreeHostCommon::calculateDrawTransforms(rootLayer.get(), rootLayer->bounds(), 1, 256, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(rootLayer.get(), rootLayer->bounds(), 1, 1, 256, renderSurfaceLayerList); iterateBackToFront(&renderSurfaceLayerList); EXPECT_COUNT(rootLayer, 0, -1, 1); @@ -227,7 +227,7 @@ TEST(LayerIteratorTest, complexTreeMultiSurface) root23->addChild(root231); std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; - LayerTreeHostCommon::calculateDrawTransforms(rootLayer.get(), rootLayer->bounds(), 1, 256, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(rootLayer.get(), rootLayer->bounds(), 1, 1, 256, renderSurfaceLayerList); iterateBackToFront(&renderSurfaceLayerList); EXPECT_COUNT(rootLayer, 0, -1, 1); diff --git a/cc/layer_tree_host.cc b/cc/layer_tree_host.cc index cde1075..4426ceb 100644 --- a/cc/layer_tree_host.cc +++ b/cc/layer_tree_host.cc @@ -495,14 +495,6 @@ void LayerTreeHost::updateLayers(TextureUpdateQueue& queue, size_t memoryAllocat updateLayers(rootLayer(), queue); } -static void setScale(Layer* layer, float deviceScaleFactor, float pageScaleFactor) -{ - if (layer->boundsContainPageScale()) - layer->setContentsScale(deviceScaleFactor); - else - layer->setContentsScale(deviceScaleFactor * pageScaleFactor); -} - static Layer* findFirstScrollableLayer(Layer* layer) { if (!layer) @@ -520,29 +512,10 @@ static Layer* findFirstScrollableLayer(Layer* layer) return 0; } -static void updateLayerScale(Layer* layer, float deviceScaleFactor, float pageScaleFactor) -{ - setScale(layer, deviceScaleFactor, pageScaleFactor); - - Layer* maskLayer = layer->maskLayer(); - if (maskLayer) - setScale(maskLayer, deviceScaleFactor, pageScaleFactor); - - Layer* replicaMaskLayer = layer->replicaLayer() ? layer->replicaLayer()->maskLayer() : 0; - if (replicaMaskLayer) - setScale(replicaMaskLayer, deviceScaleFactor, pageScaleFactor); - - const std::vector<scoped_refptr<Layer> >& children = layer->children(); - for (unsigned int i = 0; i < children.size(); ++i) - updateLayerScale(children[i].get(), deviceScaleFactor, pageScaleFactor); -} - void LayerTreeHost::updateLayers(Layer* rootLayer, TextureUpdateQueue& queue) { TRACE_EVENT0("cc", "LayerTreeHost::updateLayers"); - updateLayerScale(rootLayer, m_deviceScaleFactor, m_pageScaleFactor); - LayerList updateList; { @@ -553,7 +526,7 @@ void LayerTreeHost::updateLayers(Layer* rootLayer, TextureUpdateQueue& queue) } TRACE_EVENT0("cc", "LayerTreeHost::updateLayers::calcDrawEtc"); - LayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize(), m_deviceScaleFactor, rendererCapabilities().maxTextureSize, updateList); + LayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize(), m_deviceScaleFactor, m_pageScaleFactor, rendererCapabilities().maxTextureSize, updateList); } // Reset partial texture update requests. diff --git a/cc/layer_tree_host_common.cc b/cc/layer_tree_host_common.cc index 6975c9f..92b44d1 100644 --- a/cc/layer_tree_host_common.cc +++ b/cc/layer_tree_host_common.cc @@ -15,6 +15,7 @@ #include "cc/math_util.h" #include "cc/render_surface.h" #include "cc/render_surface_impl.h" +#include <algorithm> #include <public/WebTransformationMatrix.h> using WebKit::WebTransformationMatrix; @@ -343,6 +344,39 @@ WebTransformationMatrix computeScrollCompensationMatrixForChildren(LayerImpl* la return nextScrollCompensationMatrix; } +// There is no contentsScale on impl thread. +static inline void updateLayerContentsScale(LayerImpl*, const WebTransformationMatrix&, float, float) { } + +static inline void updateLayerContentsScale(Layer* layer, const WebTransformationMatrix& combinedTransform, float deviceScaleFactor, float pageScaleFactor) +{ + float rasterScale = layer->rasterScale(); + if (!rasterScale) { + rasterScale = 1; + + if (layer->automaticallyComputeRasterScale()) { + FloatPoint transformScale = MathUtil::computeTransform2dScaleComponents(combinedTransform); + float combinedScale = std::max(transformScale.x(), transformScale.y()); + rasterScale = combinedScale / deviceScaleFactor; + if (!layer->boundsContainPageScale()) + rasterScale /= pageScaleFactor; + layer->setRasterScale(rasterScale); + } + } + + float contentsScale = rasterScale * deviceScaleFactor; + if (!layer->boundsContainPageScale()) + contentsScale *= pageScaleFactor; + layer->setContentsScale(contentsScale); + + Layer* maskLayer = layer->maskLayer(); + if (maskLayer) + maskLayer->setContentsScale(contentsScale); + + Layer* replicaMaskLayer = layer->replicaLayer() ? layer->replicaLayer()->maskLayer() : 0; + if (replicaMaskLayer) + replicaMaskLayer->setContentsScale(contentsScale); +} + // Should be called just before the recursive calculateDrawTransformsInternal(). template<typename LayerType, typename LayerList> void setupRootLayerAndSurfaceForRecursion(LayerType* rootLayer, LayerList& renderSurfaceLayerList, const IntSize& deviceViewportSize) @@ -364,7 +398,7 @@ static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay const WebTransformationMatrix& fullHierarchyMatrix, const WebTransformationMatrix& currentScrollCompensationMatrix, const IntRect& clipRectFromAncestor, bool ancestorClipsSubtree, RenderSurfaceType* nearestAncestorThatMovesPixels, LayerList& renderSurfaceLayerList, LayerList& layerList, - LayerSorter* layerSorter, int maxTextureSize, float deviceScaleFactor, IntRect& drawableContentRectOfSubtree) + LayerSorter* layerSorter, int maxTextureSize, float deviceScaleFactor, float pageScaleFactor, IntRect& drawableContentRectOfSubtree) { // This function computes the new matrix transformations recursively for this // layer and all its descendants. It also computes the appropriate render surfaces. @@ -469,18 +503,24 @@ static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay FloatPoint position = layer->position() - layer->scrollDelta(); WebTransformationMatrix layerLocalTransform; - // LT = M[impl transformation] - layerLocalTransform.multiply(layer->implTransform()); - // LT = M[impl transformation] * Tr[origin] * Tr[origin2anchor] + // LT = Tr[origin] * Tr[origin2anchor] layerLocalTransform.translate3d(position.x() + anchorPoint.x() * bounds.width(), position.y() + anchorPoint.y() * bounds.height(), layer->anchorPointZ()); - // LT = M[impl transformation] * Tr[origin] * Tr[origin2anchor] * M[layer] + // LT = Tr[origin] * Tr[origin2anchor] * M[layer] layerLocalTransform.multiply(layer->transform()); - // LT = S[impl transformation] * Tr[origin] * Tr[origin2anchor] * M[layer] * Tr[anchor2origin] + // LT = Tr[origin] * Tr[origin2anchor] * M[layer] * Tr[anchor2origin] layerLocalTransform.translate3d(-anchorPoint.x() * bounds.width(), -anchorPoint.y() * bounds.height(), -layer->anchorPointZ()); WebTransformationMatrix combinedTransform = parentMatrix; combinedTransform.multiply(layerLocalTransform); + // The layer's contentsSize is determined from the combinedTransform, which then informs the + // layer's drawTransform. + updateLayerContentsScale(layer, combinedTransform, deviceScaleFactor, pageScaleFactor); + + // If there is a tranformation from the impl thread then it should be at the + // start of the combinedTransform, but we don't want it to affect the contentsScale. + combinedTransform = layer->implTransform() * combinedTransform; + if (layer->fixedToContainerLayer()) { // Special case: this layer is a composited fixed-position layer; we need to // explicitly compensate for all ancestors' nonzero scrollDeltas to keep this layer @@ -518,6 +558,8 @@ static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay WebTransformationMatrix nextHierarchyMatrix = fullHierarchyMatrix; WebTransformationMatrix sublayerMatrix; + FloatPoint renderSurfaceSublayerScale = MathUtil::computeTransform2dScaleComponents(combinedTransform); + if (subtreeShouldRenderToSeparateSurface(layer, isScaleOrTranslation(combinedTransform))) { // Check back-face visibility before continuing with this surface and its subtree if (!layer->doubleSided() && transformToParentIsKnown(layer) && isSurfaceBackFaceVisible(layer, combinedTransform)) @@ -529,20 +571,29 @@ static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay RenderSurfaceType* renderSurface = layer->renderSurface(); renderSurface->clearLayerLists(); - // The origin of the new surface is the upper left corner of the layer. + // The owning layer's draw transform has a scale from content to layer space which we need to undo and + // replace with a scale from the surface's subtree into layer space. + if (!layer->contentBounds().isEmpty() && !layer->bounds().isEmpty()) { + drawTransform.scaleNonUniform(layer->contentBounds().width() / static_cast<double>(layer->bounds().width()), + layer->contentBounds().height() / static_cast<double>(layer->bounds().height())); + } + drawTransform.scaleNonUniform(1 / renderSurfaceSublayerScale.x(), 1 / renderSurfaceSublayerScale.y()); renderSurface->setDrawTransform(drawTransform); + + // The origin of the new surface is the upper left corner of the layer. WebTransformationMatrix layerDrawTransform; - layerDrawTransform.scale(deviceScaleFactor); + layerDrawTransform.scaleNonUniform(renderSurfaceSublayerScale.x(), renderSurfaceSublayerScale.y()); if (!layer->contentBounds().isEmpty() && !layer->bounds().isEmpty()) { layerDrawTransform.scaleNonUniform(layer->bounds().width() / static_cast<double>(layer->contentBounds().width()), layer->bounds().height() / static_cast<double>(layer->contentBounds().height())); } layer->setDrawTransform(layerDrawTransform); + // Inside the surface's subtree, we scale everything to the owning layer's scale. // The sublayer matrix transforms centered layer rects into target // surface content space. sublayerMatrix.makeIdentity(); - sublayerMatrix.scale(deviceScaleFactor); + sublayerMatrix.scaleNonUniform(renderSurfaceSublayerScale.x(), renderSurfaceSublayerScale.y()); // The opacity value is moved from the layer to its surface, so that the entire subtree properly inherits opacity. renderSurface->setDrawOpacity(drawOpacity); @@ -656,7 +707,7 @@ static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay IntRect drawableContentRectOfChildSubtree; calculateDrawTransformsInternal<LayerType, LayerList, RenderSurfaceType, LayerSorter>(child, rootLayer, sublayerMatrix, nextHierarchyMatrix, nextScrollCompensationMatrix, clipRectForSubtree, subtreeShouldBeClipped, nearestAncestorThatMovesPixels, - renderSurfaceLayerList, descendants, layerSorter, maxTextureSize, deviceScaleFactor, drawableContentRectOfChildSubtree); + renderSurfaceLayerList, descendants, layerSorter, maxTextureSize, deviceScaleFactor, pageScaleFactor, drawableContentRectOfChildSubtree); if (!drawableContentRectOfChildSubtree.isEmpty()) { accumulatedDrawableContentRectOfChildren.unite(drawableContentRectOfChildSubtree); if (child->renderSurface()) @@ -707,16 +758,25 @@ static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay renderSurface->clearLayerLists(); renderSurface->setContentRect(clippedContentRect); - renderSurface->setScreenSpaceTransform(layer->screenSpaceTransform()); + + // The owning layer's screenSpaceTransform has a scale from content to layer space which we need to undo and + // replace with a scale from the surface's subtree into layer space. + WebTransformationMatrix screenSpaceTransform = layer->screenSpaceTransform(); + if (!layer->contentBounds().isEmpty() && !layer->bounds().isEmpty()) { + screenSpaceTransform.scaleNonUniform(layer->contentBounds().width() / static_cast<double>(layer->bounds().width()), + layer->contentBounds().height() / static_cast<double>(layer->bounds().height())); + } + screenSpaceTransform.scaleNonUniform(1 / renderSurfaceSublayerScale.x(), 1 / renderSurfaceSublayerScale.y()); + renderSurface->setScreenSpaceTransform(screenSpaceTransform); if (layer->replicaLayer()) { WebTransformationMatrix surfaceOriginToReplicaOriginTransform; - surfaceOriginToReplicaOriginTransform.scale(deviceScaleFactor); + surfaceOriginToReplicaOriginTransform.scaleNonUniform(renderSurfaceSublayerScale.x(), renderSurfaceSublayerScale.y()); surfaceOriginToReplicaOriginTransform.translate(layer->replicaLayer()->position().x() + layer->replicaLayer()->anchorPoint().x() * bounds.width(), layer->replicaLayer()->position().y() + layer->replicaLayer()->anchorPoint().y() * bounds.height()); surfaceOriginToReplicaOriginTransform.multiply(layer->replicaLayer()->transform()); surfaceOriginToReplicaOriginTransform.translate(-layer->replicaLayer()->anchorPoint().x() * bounds.width(), -layer->replicaLayer()->anchorPoint().y() * bounds.height()); - surfaceOriginToReplicaOriginTransform.scale(1 / deviceScaleFactor); + surfaceOriginToReplicaOriginTransform.scaleNonUniform(1 / renderSurfaceSublayerScale.x(), 1 / renderSurfaceSublayerScale.y()); // Compute the replica's "originTransform" that maps from the replica's origin space to the target surface origin space. WebTransformationMatrix replicaOriginTransform = layer->renderSurface()->drawTransform() * surfaceOriginToReplicaOriginTransform; @@ -764,7 +824,7 @@ static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay layer->renderTarget()->renderSurface()->addContributingDelegatedRenderPassLayer(layer); } -void LayerTreeHostCommon::calculateDrawTransforms(Layer* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, int maxTextureSize, std::vector<scoped_refptr<Layer> >& renderSurfaceLayerList) +void LayerTreeHostCommon::calculateDrawTransforms(Layer* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, float pageScaleFactor, int maxTextureSize, std::vector<scoped_refptr<Layer> >& renderSurfaceLayerList) { IntRect totalDrawableContentRect; WebTransformationMatrix identityMatrix; @@ -773,12 +833,14 @@ void LayerTreeHostCommon::calculateDrawTransforms(Layer* rootLayer, const IntSiz setupRootLayerAndSurfaceForRecursion<Layer, std::vector<scoped_refptr<Layer> > >(rootLayer, renderSurfaceLayerList, deviceViewportSize); - cc::calculateDrawTransformsInternal<Layer, std::vector<scoped_refptr<Layer> >, RenderSurface, void>(rootLayer, rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, - rootLayer->renderSurface()->contentRect(), true, 0, renderSurfaceLayerList, - rootLayer->renderSurface()->layerList(), 0, maxTextureSize, deviceScaleFactor, totalDrawableContentRect); + cc::calculateDrawTransformsInternal<Layer, std::vector<scoped_refptr<Layer> >, RenderSurface, void>( + rootLayer, rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, + rootLayer->renderSurface()->contentRect(), true, 0, renderSurfaceLayerList, + rootLayer->renderSurface()->layerList(), 0, maxTextureSize, + deviceScaleFactor, pageScaleFactor, totalDrawableContentRect); } -void LayerTreeHostCommon::calculateDrawTransforms(LayerImpl* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, LayerSorter* layerSorter, int maxTextureSize, std::vector<LayerImpl*>& renderSurfaceLayerList) +void LayerTreeHostCommon::calculateDrawTransforms(LayerImpl* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, float pageScaleFactor, LayerSorter* layerSorter, int maxTextureSize, std::vector<LayerImpl*>& renderSurfaceLayerList) { IntRect totalDrawableContentRect; WebTransformationMatrix identityMatrix; @@ -787,9 +849,11 @@ void LayerTreeHostCommon::calculateDrawTransforms(LayerImpl* rootLayer, const In setupRootLayerAndSurfaceForRecursion<LayerImpl, std::vector<LayerImpl*> >(rootLayer, renderSurfaceLayerList, deviceViewportSize); - cc::calculateDrawTransformsInternal<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerSorter>(rootLayer, rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, - rootLayer->renderSurface()->contentRect(), true, 0, renderSurfaceLayerList, - rootLayer->renderSurface()->layerList(), layerSorter, maxTextureSize, deviceScaleFactor, totalDrawableContentRect); + cc::calculateDrawTransformsInternal<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerSorter>( + rootLayer, rootLayer, deviceScaleTransform, identityMatrix, identityMatrix, + rootLayer->renderSurface()->contentRect(), true, 0, renderSurfaceLayerList, + rootLayer->renderSurface()->layerList(), layerSorter, maxTextureSize, + deviceScaleFactor, pageScaleFactor, totalDrawableContentRect); } static bool pointHitsRect(const IntPoint& screenSpacePoint, const WebTransformationMatrix& localSpaceToScreenSpaceTransform, FloatRect localSpaceRect) diff --git a/cc/layer_tree_host_common.h b/cc/layer_tree_host_common.h index 4be3ae1..506274d 100644 --- a/cc/layer_tree_host_common.h +++ b/cc/layer_tree_host_common.h @@ -22,8 +22,8 @@ class LayerTreeHostCommon { public: static IntRect calculateVisibleRect(const IntRect& targetSurfaceRect, const IntRect& layerBoundRect, const WebKit::WebTransformationMatrix&); - static void calculateDrawTransforms(Layer* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, int maxTextureSize, std::vector<scoped_refptr<Layer> >& renderSurfaceLayerList); - static void calculateDrawTransforms(LayerImpl* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, LayerSorter*, int maxTextureSize, std::vector<LayerImpl*>& renderSurfaceLayerList); + static void calculateDrawTransforms(Layer* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, float pageScaleFactor, int maxTextureSize, std::vector<scoped_refptr<Layer> >& renderSurfaceLayerList); + static void calculateDrawTransforms(LayerImpl* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, float pageScaleFactor, LayerSorter*, int maxTextureSize, std::vector<LayerImpl*>& renderSurfaceLayerList); // Performs hit testing for a given renderSurfaceLayerList. static LayerImpl* findLayerThatIsHitByPoint(const IntPoint& screenSpacePoint, std::vector<LayerImpl*>& renderSurfaceLayerList); diff --git a/cc/layer_tree_host_common_unittest.cc b/cc/layer_tree_host_common_unittest.cc index 2f8d0f2..8e924f6 100644 --- a/cc/layer_tree_host_common_unittest.cc +++ b/cc/layer_tree_host_common_unittest.cc @@ -29,7 +29,7 @@ using WebKit::WebTransformationMatrix; namespace { template<typename LayerType> -void setLayerPropertiesForTesting(LayerType* layer, const WebTransformationMatrix& transform, const WebTransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool preserves3D) +void setLayerPropertiesForTestingInternal(LayerType* layer, const WebTransformationMatrix& transform, const WebTransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool preserves3D) { layer->setTransform(transform); layer->setSublayerTransform(sublayerTransform); @@ -41,16 +41,17 @@ void setLayerPropertiesForTesting(LayerType* layer, const WebTransformationMatri void setLayerPropertiesForTesting(Layer* layer, const WebTransformationMatrix& transform, const WebTransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool preserves3D) { - setLayerPropertiesForTesting<Layer>(layer, transform, sublayerTransform, anchor, position, bounds, preserves3D); + setLayerPropertiesForTestingInternal<Layer>(layer, transform, sublayerTransform, anchor, position, bounds, preserves3D); + layer->setAutomaticallyComputeRasterScale(true); } void setLayerPropertiesForTesting(LayerImpl* layer, const WebTransformationMatrix& transform, const WebTransformationMatrix& sublayerTransform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool preserves3D) { - setLayerPropertiesForTesting<LayerImpl>(layer, transform, sublayerTransform, anchor, position, bounds, preserves3D); + setLayerPropertiesForTestingInternal<LayerImpl>(layer, transform, sublayerTransform, anchor, position, bounds, preserves3D); layer->setContentBounds(bounds); } -void executeCalculateDrawTransformsAndVisibility(Layer* rootLayer, float deviceScaleFactor = 1) +void executeCalculateDrawTransformsAndVisibility(Layer* rootLayer, float deviceScaleFactor = 1, float pageScaleFactor = 1) { WebTransformationMatrix identityMatrix; std::vector<scoped_refptr<Layer> > dummyRenderSurfaceLayerList; @@ -59,10 +60,10 @@ void executeCalculateDrawTransformsAndVisibility(Layer* rootLayer, float deviceS // We are probably not testing what is intended if the rootLayer bounds are empty. DCHECK(!rootLayer->bounds().isEmpty()); - LayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize, deviceScaleFactor, dummyMaxTextureSize, dummyRenderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize, deviceScaleFactor, pageScaleFactor, dummyMaxTextureSize, dummyRenderSurfaceLayerList); } -void executeCalculateDrawTransformsAndVisibility(LayerImpl* rootLayer, float deviceScaleFactor = 1) +void executeCalculateDrawTransformsAndVisibility(LayerImpl* rootLayer, float deviceScaleFactor = 1, float pageScaleFactor = 1) { // Note: this version skips layer sorting. @@ -73,7 +74,7 @@ void executeCalculateDrawTransformsAndVisibility(LayerImpl* rootLayer, float dev // We are probably not testing what is intended if the rootLayer bounds are empty. DCHECK(!rootLayer->bounds().isEmpty()); - LayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize, deviceScaleFactor, 0, dummyMaxTextureSize, dummyRenderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize, deviceScaleFactor, pageScaleFactor, 0, dummyMaxTextureSize, dummyRenderSurfaceLayerList); } WebTransformationMatrix remove3DComponentOfMatrix(const WebTransformationMatrix& mat) @@ -332,6 +333,10 @@ TEST(LayerTreeHostCommonTest, verifyTransformsForSingleRenderSurface) parentTranslationToCenter.translate(50, 60); WebTransformationMatrix parentCompositeTransform = parentTranslationToAnchor * parentLayerTransform * parentTranslationToAnchor.inverse() * parentTranslationToCenter * parentSublayerMatrix * parentTranslationToCenter.inverse(); + FloatPoint parentCompositeScale = MathUtil::computeTransform2dScaleComponents(parentCompositeTransform); + WebTransformationMatrix surfaceSublayerTransform; + surfaceSublayerTransform.scaleNonUniform(parentCompositeScale.x(), parentCompositeScale.y()); + WebTransformationMatrix surfaceSublayerCompositeTransform = parentCompositeTransform * surfaceSublayerTransform.inverse(); // Child's render surface should not exist yet. ASSERT_FALSE(child->renderSurface()); @@ -347,14 +352,15 @@ TEST(LayerTreeHostCommonTest, verifyTransformsForSingleRenderSurface) // The child layer's draw transform should refer to its new render surface. // The screen-space transform, however, should still refer to the root. - EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, child->drawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(surfaceSublayerTransform, child->drawTransform()); EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->screenSpaceTransform()); // Because the grandChild is the only drawable content, the child's renderSurface will tighten its bounds to the grandChild. - EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->renderTarget()->renderSurface()->drawTransform()); + // The scale at which the surface's subtree is drawn must be removed from the composite transform. + EXPECT_TRANSFORMATION_MATRIX_EQ(surfaceSublayerCompositeTransform, child->renderTarget()->renderSurface()->drawTransform()); // The screen space is the same as the target since the child surface draws into the root. - EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->renderTarget()->renderSurface()->screenSpaceTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(surfaceSublayerCompositeTransform, child->renderTarget()->renderSurface()->screenSpaceTransform()); } TEST(LayerTreeHostCommonTest, verifyTransformsForReplica) @@ -385,7 +391,10 @@ TEST(LayerTreeHostCommonTest, verifyTransformsForReplica) childTranslationToCenter.translate(8, 9); WebTransformationMatrix replicaLayerTransform; replicaLayerTransform.scale3d(3, 3, 1); - WebTransformationMatrix replicaCompositeTransform = parentCompositeTransform * replicaLayerTransform; + FloatPoint parentCompositeScale = MathUtil::computeTransform2dScaleComponents(parentCompositeTransform); + WebTransformationMatrix surfaceSublayerTransform; + surfaceSublayerTransform.scaleNonUniform(parentCompositeScale.x(), parentCompositeScale.y()); + WebTransformationMatrix replicaCompositeTransform = parentCompositeTransform * replicaLayerTransform * surfaceSublayerTransform.inverse(); // Child's render surface should not exist yet. ASSERT_FALSE(child->renderSurface()); @@ -462,6 +471,24 @@ TEST(LayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy) WebTransformationMatrix R = A * translationToAnchor * replicaLayerTransform * translationToAnchor.inverse(); WebTransformationMatrix identityMatrix; + FloatPoint surface1ParentTransformScale = MathUtil::computeTransform2dScaleComponents(A * B); + WebTransformationMatrix surface1SublayerTransform; + surface1SublayerTransform.scaleNonUniform(surface1ParentTransformScale.x(), surface1ParentTransformScale.y()); + + // SS1 = transform given to the subtree of renderSurface1 + WebTransformationMatrix SS1 = surface1SublayerTransform; + // S1 = transform to move from renderSurface1 pixels to the layer space of the owning layer + WebTransformationMatrix S1 = surface1SublayerTransform.inverse(); + + FloatPoint surface2ParentTransformScale = MathUtil::computeTransform2dScaleComponents(SS1 * A * B); + WebTransformationMatrix surface2SublayerTransform; + surface2SublayerTransform.scaleNonUniform(surface2ParentTransformScale.x(), surface2ParentTransformScale.y()); + + // SS2 = transform given to the subtree of renderSurface2 + WebTransformationMatrix SS2 = surface2SublayerTransform; + // S2 = transform to move from renderSurface2 pixels to the layer space of the owning layer + WebTransformationMatrix S2 = surface2SublayerTransform.inverse(); + setLayerPropertiesForTesting(parent.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false); setLayerPropertiesForTesting(renderSurface1.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false); setLayerPropertiesForTesting(renderSurface2.get(), layerTransform, sublayerTransform, FloatPoint(0.25, 0), FloatPoint(0, 0), IntSize(10, 10), false); @@ -512,13 +539,13 @@ TEST(LayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy) EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, childOfRoot->drawTransform()); EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, grandChildOfRoot->drawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, renderSurface1->drawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(B * A, childOfRS1->drawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(B * A * B * A, grandChildOfRS1->drawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(SS1, renderSurface1->drawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(SS1 * B * A, childOfRS1->drawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(SS1 * B * A * B * A, grandChildOfRS1->drawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(identityMatrix, renderSurface2->drawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(B * A, childOfRS2->drawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(B * A * B * A, grandChildOfRS2->drawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(SS2, renderSurface2->drawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(SS2 * B * A, childOfRS2->drawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(SS2 * B * A * B * A, grandChildOfRS2->drawTransform()); // Verify layer screen-space transforms // @@ -537,15 +564,15 @@ TEST(LayerTreeHostCommonTest, verifyTransformsForRenderSurfaceHierarchy) // Verify render surface transforms. // // Draw transform of render surface 1 is described with respect to root. - EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, renderSurface1->renderSurface()->drawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * R, renderSurface1->renderSurface()->replicaDrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A, renderSurface1->renderSurface()->screenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * R, renderSurface1->renderSurface()->replicaScreenSpaceTransform()); - // Draw transform of render surface 2 is described with respect to render surface 2. - EXPECT_TRANSFORMATION_MATRIX_EQ(B * A, renderSurface2->renderSurface()->drawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(B * R, renderSurface2->renderSurface()->replicaDrawTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A, renderSurface2->renderSurface()->screenSpaceTransform()); - EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * R, renderSurface2->renderSurface()->replicaScreenSpaceTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * S1, renderSurface1->renderSurface()->drawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * R * S1, renderSurface1->renderSurface()->replicaDrawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * S1, renderSurface1->renderSurface()->screenSpaceTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * R * S1, renderSurface1->renderSurface()->replicaScreenSpaceTransform()); + // Draw transform of render surface 2 is described with respect to render surface 1. + EXPECT_TRANSFORMATION_MATRIX_EQ(SS1 * B * A * S2, renderSurface2->renderSurface()->drawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(SS1 * B * R * S2, renderSurface2->renderSurface()->replicaDrawTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * A * S2, renderSurface2->renderSurface()->screenSpaceTransform()); + EXPECT_TRANSFORMATION_MATRIX_EQ(A * B * A * B * R * S2, renderSurface2->renderSurface()->replicaScreenSpaceTransform()); // Sanity check. If these fail there is probably a bug in the test itself. // It is expected that we correctly set up transforms so that the y-component of the screen-space transform @@ -656,7 +683,7 @@ TEST(LayerTreeHostCommonTest, verifyRenderSurfaceListForRenderSurfaceWithClipped std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); // The child layer's content is entirely outside the parent's clip rect, so the intermediate // render surface should not be listed here, even if it was forced to be created. Render surfaces without children or visible @@ -683,7 +710,7 @@ TEST(LayerTreeHostCommonTest, verifyRenderSurfaceListForTransparentChild) std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); // Since the layer is transparent, renderSurface1->renderSurface() should not have gotten added anywhere. // Also, the drawable content rect should not have been extended by the children. @@ -715,7 +742,7 @@ TEST(LayerTreeHostCommonTest, verifyForceRenderSurface) std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); // The root layer always creates a renderSurface EXPECT_TRUE(parent->renderSurface()); @@ -724,7 +751,7 @@ TEST(LayerTreeHostCommonTest, verifyForceRenderSurface) renderSurfaceLayerList.clear(); renderSurface1->setForceRenderSurface(false); - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); EXPECT_TRUE(parent->renderSurface()); EXPECT_FALSE(renderSurface1->renderSurface()); EXPECT_EQ(1U, renderSurfaceLayerList.size()); @@ -1338,7 +1365,7 @@ TEST(LayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces) std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); ASSERT_EQ(2U, renderSurfaceLayerList.size()); EXPECT_EQ(parent->id(), renderSurfaceLayerList[0]->id()); @@ -1383,7 +1410,7 @@ TEST(LayerTreeHostCommonTest, verifyClipRectCullsSurfaceWithoutVisibleContent) std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); // Without an animation, we should cull child and grandChild from the renderSurfaceLayerList. ASSERT_EQ(1U, renderSurfaceLayerList.size()); @@ -1397,7 +1424,7 @@ TEST(LayerTreeHostCommonTest, verifyClipRectCullsSurfaceWithoutVisibleContent) grandChild->clearRenderSurface(); renderSurfaceLayerList.clear(); - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); // With an animating transform, we should keep child and grandChild in the renderSurfaceLayerList. ASSERT_EQ(3U, renderSurfaceLayerList.size()); @@ -1449,7 +1476,7 @@ TEST(LayerTreeHostCommonTest, verifyDrawableContentRectForLayers) std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); EXPECT_RECT_EQ(IntRect(IntPoint(5, 5), IntSize(10, 10)), grandChild1->drawableContentRect()); EXPECT_RECT_EQ(IntRect(IntPoint(15, 15), IntSize(5, 5)), grandChild3->drawableContentRect()); @@ -1514,7 +1541,7 @@ TEST(LayerTreeHostCommonTest, verifyClipRectIsPropagatedCorrectlyToSurfaces) std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); ASSERT_TRUE(grandChild1->renderSurface()); ASSERT_TRUE(grandChild2->renderSurface()); @@ -2356,7 +2383,7 @@ TEST(LayerTreeHostCommonTest, verifyBackFaceCullingWithoutPreserves3d) std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); // Verify which renderSurfaces were created. EXPECT_FALSE(frontFacingChild->renderSurface()); @@ -2455,7 +2482,7 @@ TEST(LayerTreeHostCommonTest, verifyBackFaceCullingWithPreserves3d) std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); // Verify which renderSurfaces were created. EXPECT_FALSE(frontFacingChild->renderSurface()); @@ -2535,7 +2562,7 @@ TEST(LayerTreeHostCommonTest, verifyBackFaceCullingWithAnimatingTransforms) std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); EXPECT_FALSE(child->renderSurface()); EXPECT_TRUE(animatingSurface->renderSurface()); @@ -2601,7 +2628,7 @@ TEST(LayerTreeHostCommonTest, verifyBackFaceCullingWithPreserves3dForFlatteningS std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, 1, dummyMaxTextureSize, renderSurfaceLayerList); // Verify which renderSurfaces were created. EXPECT_TRUE(frontFacingSurface->renderSurface()); @@ -2655,7 +2682,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForSingleLayer) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. ASSERT_EQ(1u, renderSurfaceLayerList.size()); @@ -2704,7 +2731,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForUninvertibleTransform) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. ASSERT_EQ(1u, renderSurfaceLayerList.size()); @@ -2758,7 +2785,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForSinglePositionedLayer) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. ASSERT_EQ(1u, renderSurfaceLayerList.size()); @@ -2805,7 +2832,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForSingleRotatedLayer) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. ASSERT_EQ(1u, renderSurfaceLayerList.size()); @@ -2861,7 +2888,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForSinglePerspectiveLayer) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. ASSERT_EQ(1u, renderSurfaceLayerList.size()); @@ -2925,7 +2952,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForSingleLayerWithScaledContents) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. // The visibleContentRect for testLayer is actually 100x100, even though its layout size is 50x50, positioned at 25x25. @@ -2989,7 +3016,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForSimpleClippedLayer) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. ASSERT_EQ(1u, renderSurfaceLayerList.size()); @@ -3079,7 +3106,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForMultiClippedRotatedLayer) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. // The grandChild is expected to create a renderSurface because it masksToBounds and is not axis aligned. @@ -3161,7 +3188,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForNonClippingIntermediateLayer) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. ASSERT_EQ(1u, renderSurfaceLayerList.size()); @@ -3241,7 +3268,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForMultipleLayers) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. ASSERT_TRUE(child1); @@ -3349,7 +3376,7 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForMultipleLayerLists) std::vector<LayerImpl*> renderSurfaceLayerList; int dummyMaxTextureSize = 512; - LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 1, 0, dummyMaxTextureSize, renderSurfaceLayerList); // Sanity check the scenario we just created. ASSERT_TRUE(child1); @@ -3405,6 +3432,25 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForMultipleLayerLists) EXPECT_EQ(4, resultLayer->id()); } +class NoScaleContentLayer : public ContentLayer +{ +public: + static scoped_refptr<NoScaleContentLayer> create(ContentLayerClient* client) { return make_scoped_refptr(new NoScaleContentLayer(client)); } + + virtual bool needsContentsScale() const OVERRIDE { return false; } + +protected: + explicit NoScaleContentLayer(ContentLayerClient* client) : ContentLayer(client) { } + virtual ~NoScaleContentLayer() { } +}; + +scoped_refptr<NoScaleContentLayer> createNoScaleDrawableContentLayer(ContentLayerClient* delegate) +{ + scoped_refptr<NoScaleContentLayer> toReturn = NoScaleContentLayer::create(delegate); + toReturn->setIsDrawable(true); + return toReturn; +} + TEST(LayerTreeHostCommonTest, verifyLayerTransformsInHighDPI) { // Verify draw and screen space transforms of layers not in a surface. @@ -3417,7 +3463,7 @@ TEST(LayerTreeHostCommonTest, verifyLayerTransformsInHighDPI) scoped_refptr<ContentLayer> child = createDrawableContentLayer(&delegate); setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(2, 2), IntSize(10, 10), true); - scoped_refptr<ContentLayer> childNoScale = createDrawableContentLayer(&delegate); + scoped_refptr<NoScaleContentLayer> childNoScale = createNoScaleDrawableContentLayer(&delegate); setLayerPropertiesForTesting(childNoScale.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(2, 2), IntSize(10, 10), true); parent->addChild(child); @@ -3427,11 +3473,13 @@ TEST(LayerTreeHostCommonTest, verifyLayerTransformsInHighDPI) int dummyMaxTextureSize = 512; const double deviceScaleFactor = 2.5; - parent->setContentsScale(deviceScaleFactor); - child->setContentsScale(deviceScaleFactor); - EXPECT_EQ(childNoScale->contentsScale(), 1); + const double pageScaleFactor = 1; + + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, pageScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList); - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList); + EXPECT_EQ(deviceScaleFactor * pageScaleFactor, parent->contentsScale()); + EXPECT_EQ(deviceScaleFactor * pageScaleFactor, child->contentsScale()); + EXPECT_EQ(1, childNoScale->contentsScale()); EXPECT_EQ(1u, renderSurfaceLayerList.size()); @@ -3478,6 +3526,246 @@ TEST(LayerTreeHostCommonTest, verifyLayerTransformsInHighDPI) EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildNoScaleTransform, childNoScale->screenSpaceTransform()); } +TEST(LayerTreeHostCommonTest, verifyContentsScale) +{ + MockContentLayerClient delegate; + WebTransformationMatrix identityMatrix; + + WebTransformationMatrix parentScaleMatrix; + const double initialParentScale = 1.75; + parentScaleMatrix.scale(initialParentScale); + + WebTransformationMatrix childScaleMatrix; + const double initialChildScale = 1.25; + childScaleMatrix.scale(initialChildScale); + + float fixedRasterScale = 2.5; + + scoped_refptr<ContentLayer> parent = createDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(parent.get(), parentScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true); + + scoped_refptr<ContentLayer> childScale = createDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(childScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(2, 2), IntSize(10, 10), true); + + scoped_refptr<NoScaleContentLayer> childNoScale = createNoScaleDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(childNoScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(12, 12), IntSize(10, 10), true); + + scoped_refptr<ContentLayer> childNoAutoScale = createDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(childNoAutoScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(22, 22), IntSize(10, 10), true); + childNoAutoScale->setAutomaticallyComputeRasterScale(false); + childNoAutoScale->setRasterScale(fixedRasterScale); + + // FIXME: Remove this when pageScaleFactor is applied in the compositor. + // Page scale should not apply to the parent. + parent->setBoundsContainPageScale(true); + + parent->addChild(childScale); + parent->addChild(childNoScale); + parent->addChild(childNoAutoScale); + + std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; + int dummyMaxTextureSize = 512; + + double deviceScaleFactor = 2.5; + double pageScaleFactor = 1.5; + + // FIXME: Remove this when pageScaleFactor is applied in the compositor. + WebTransformationMatrix pageScaleMatrix; + pageScaleMatrix.scale(pageScaleFactor); + parent->setSublayerTransform(pageScaleMatrix); + + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, pageScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList); + + EXPECT_FLOAT_EQ(deviceScaleFactor * initialParentScale, parent->contentsScale()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, childScale->contentsScale()); + EXPECT_FLOAT_EQ(1, childNoScale->contentsScale()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * fixedRasterScale, childNoAutoScale->contentsScale()); + + // The parent is scaled up and shouldn't need to scale during draw. The child that can scale its contents should + // also not need to scale during draw. The other should. + // There is some rounding error due to contentBounds being a rounded integer. + EXPECT_NEAR(parent->drawTransform().m11(), 1, 0.01); + EXPECT_NEAR(parent->drawTransform().m22(), 1, 0.01); + EXPECT_NEAR(childScale->drawTransform().m11(), 1, 0.01); + EXPECT_NEAR(childScale->drawTransform().m22(), 1, 0.01); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, childNoScale->drawTransform().m11()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, childNoScale->drawTransform().m22()); + EXPECT_NEAR(childNoAutoScale->drawTransform().m11(), initialParentScale * initialChildScale / fixedRasterScale, 0.01); + EXPECT_NEAR(childNoAutoScale->drawTransform().m22(), initialParentScale * initialChildScale / fixedRasterScale, 0.01); + + // If the transform changes, we expect the contentsScale to remain unchanged. + childScale->setTransform(identityMatrix); + + renderSurfaceLayerList.clear(); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, pageScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList); + + EXPECT_FLOAT_EQ(deviceScaleFactor * initialParentScale, parent->contentsScale()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, childScale->contentsScale()); + EXPECT_FLOAT_EQ(1, childNoScale->contentsScale()); + + // But if the deviceScaleFactor or pageScaleFactor changes, then it should be updated, but using the initial transform. + deviceScaleFactor = 2.25; + pageScaleFactor = 1.25; + + // FIXME: Remove this when pageScaleFactor is applied in the compositor. + pageScaleMatrix = identityMatrix; + pageScaleMatrix.scale(pageScaleFactor); + parent->setSublayerTransform(pageScaleMatrix); + + renderSurfaceLayerList.clear(); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, pageScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList); + + EXPECT_FLOAT_EQ(deviceScaleFactor * initialParentScale, parent->contentsScale()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, childScale->contentsScale()); + EXPECT_FLOAT_EQ(1, childNoScale->contentsScale()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * fixedRasterScale, childNoAutoScale->contentsScale()); +} + +TEST(LayerTreeHostCommonTest, verifyContentsScaleForSurfaces) +{ + MockContentLayerClient delegate; + WebTransformationMatrix identityMatrix; + + WebTransformationMatrix parentScaleMatrix; + const double initialParentScale = 2; + parentScaleMatrix.scale(initialParentScale); + + WebTransformationMatrix childScaleMatrix; + const double initialChildScale = 3; + childScaleMatrix.scale(initialChildScale); + + float fixedRasterScale = 4; + + scoped_refptr<ContentLayer> parent = createDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(parent.get(), parentScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true); + + scoped_refptr<ContentLayer> surfaceScale = createDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(surfaceScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(2, 2), IntSize(10, 10), true); + + scoped_refptr<ContentLayer> surfaceScaleChildScale = createDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(surfaceScaleChildScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), true); + + scoped_refptr<NoScaleContentLayer> surfaceScaleChildNoScale = createNoScaleDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(surfaceScaleChildNoScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), true); + + scoped_refptr<NoScaleContentLayer> surfaceNoScale = createNoScaleDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(surfaceNoScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(12, 12), IntSize(10, 10), true); + + scoped_refptr<ContentLayer> surfaceNoScaleChildScale = createDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(surfaceNoScaleChildScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), true); + + scoped_refptr<NoScaleContentLayer> surfaceNoScaleChildNoScale = createNoScaleDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(surfaceNoScaleChildNoScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), true); + + scoped_refptr<ContentLayer> surfaceNoAutoScale = createDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(surfaceNoAutoScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(22, 22), IntSize(10, 10), true); + surfaceNoAutoScale->setAutomaticallyComputeRasterScale(false); + surfaceNoAutoScale->setRasterScale(fixedRasterScale); + + scoped_refptr<ContentLayer> surfaceNoAutoScaleChildScale = createDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(surfaceNoAutoScaleChildScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), true); + + scoped_refptr<NoScaleContentLayer> surfaceNoAutoScaleChildNoScale = createNoScaleDrawableContentLayer(&delegate); + setLayerPropertiesForTesting(surfaceNoAutoScaleChildNoScale.get(), childScaleMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(10, 10), true); + + // FIXME: Remove this when pageScaleFactor is applied in the compositor. + // Page scale should not apply to the parent. + parent->setBoundsContainPageScale(true); + + parent->addChild(surfaceScale); + parent->addChild(surfaceNoScale); + parent->addChild(surfaceNoAutoScale); + + surfaceScale->setForceRenderSurface(true); + surfaceScale->addChild(surfaceScaleChildScale); + surfaceScale->addChild(surfaceScaleChildNoScale); + + surfaceNoScale->setForceRenderSurface(true); + surfaceNoScale->addChild(surfaceNoScaleChildScale); + surfaceNoScale->addChild(surfaceNoScaleChildNoScale); + + surfaceNoAutoScale->setForceRenderSurface(true); + surfaceNoAutoScale->addChild(surfaceNoAutoScaleChildScale); + surfaceNoAutoScale->addChild(surfaceNoAutoScaleChildNoScale); + + std::vector<scoped_refptr<Layer> > renderSurfaceLayerList; + int dummyMaxTextureSize = 512; + + double deviceScaleFactor = 5; + double pageScaleFactor = 7; + + // FIXME: Remove this when pageScaleFactor is applied in the compositor. + WebTransformationMatrix pageScaleMatrix; + pageScaleMatrix.scale(pageScaleFactor); + parent->setSublayerTransform(pageScaleMatrix); + + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, pageScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList); + + EXPECT_EQ(deviceScaleFactor * initialParentScale, parent->contentsScale()); + EXPECT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, surfaceScale->contentsScale()); + EXPECT_EQ(1, surfaceNoScale->contentsScale()); + EXPECT_EQ(deviceScaleFactor * pageScaleFactor * fixedRasterScale, surfaceNoAutoScale->contentsScale()); + + EXPECT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceScaleChildScale->contentsScale()); + EXPECT_EQ(1, surfaceScaleChildNoScale->contentsScale()); + EXPECT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceNoScaleChildScale->contentsScale()); + EXPECT_EQ(1, surfaceNoScaleChildNoScale->contentsScale()); + EXPECT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceNoAutoScaleChildScale->contentsScale()); + EXPECT_EQ(1, surfaceNoAutoScaleChildNoScale->contentsScale()); + + // The parent is scaled up and shouldn't need to scale during draw. + EXPECT_FLOAT_EQ(1, parent->drawTransform().m11()); + EXPECT_FLOAT_EQ(1, parent->drawTransform().m22()); + + // RenderSurfaces should always be 1:1 with their target. + EXPECT_FLOAT_EQ(1, surfaceScale->renderSurface()->drawTransform().m11()); + EXPECT_FLOAT_EQ(1, surfaceScale->renderSurface()->drawTransform().m22()); + + // The surfaceScale can apply contents scale so the layer shouldn't need to scale during draw. + EXPECT_FLOAT_EQ(1, surfaceScale->drawTransform().m11()); + EXPECT_FLOAT_EQ(1, surfaceScale->drawTransform().m22()); + + // The surfaceScaleChildScale can apply contents scale so it shouldn't need to scale during draw. + EXPECT_FLOAT_EQ(1, surfaceScaleChildScale->drawTransform().m11()); + EXPECT_FLOAT_EQ(1, surfaceScaleChildScale->drawTransform().m22()); + + // The surfaceScaleChildNoScale can not apply contents scale, so it needs to be scaled during draw. + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceScaleChildNoScale->drawTransform().m11()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceScaleChildNoScale->drawTransform().m22()); + + // RenderSurfaces should always be 1:1 with their target. + EXPECT_FLOAT_EQ(1, surfaceNoScale->renderSurface()->drawTransform().m11()); + EXPECT_FLOAT_EQ(1, surfaceNoScale->renderSurface()->drawTransform().m22()); + + // The surfaceNoScale layer can not apply contents scale, so it needs to be scaled during draw. + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, surfaceNoScale->drawTransform().m11()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, surfaceNoScale->drawTransform().m22()); + + // The surfaceScaleChildScale can apply contents scale so it shouldn't need to scale during draw. + EXPECT_FLOAT_EQ(1, surfaceNoScaleChildScale->drawTransform().m11()); + EXPECT_FLOAT_EQ(1, surfaceNoScaleChildScale->drawTransform().m22()); + + // The surfaceScaleChildNoScale can not apply contents scale, so it needs to be scaled during draw. + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceNoScaleChildNoScale->drawTransform().m11()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceNoScaleChildNoScale->drawTransform().m22()); + + // RenderSurfaces should always be 1:1 with their target. + EXPECT_FLOAT_EQ(1, surfaceNoAutoScale->renderSurface()->drawTransform().m11()); + EXPECT_FLOAT_EQ(1, surfaceNoAutoScale->renderSurface()->drawTransform().m22()); + + // The surfaceNoAutoScale layer has a fixed contents scale, so it needs to be scaled during draw. + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale / (deviceScaleFactor * pageScaleFactor * fixedRasterScale), surfaceNoAutoScale->drawTransform().m11()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale / (deviceScaleFactor * pageScaleFactor * fixedRasterScale), surfaceNoAutoScale->drawTransform().m22()); + + // The surfaceScaleChildScale can apply contents scale so it shouldn't need to scale during draw. + EXPECT_FLOAT_EQ(1, surfaceNoAutoScaleChildScale->drawTransform().m11()); + EXPECT_FLOAT_EQ(1, surfaceNoAutoScaleChildScale->drawTransform().m22()); + + // The surfaceScaleChildNoScale can not apply contents scale, so it needs to be scaled during draw. + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceNoAutoScaleChildNoScale->drawTransform().m11()); + EXPECT_FLOAT_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceNoAutoScaleChildNoScale->drawTransform().m22()); +} + TEST(LayerTreeHostCommonTest, verifyRenderSurfaceTransformsInHighDPI) { MockContentLayerClient delegate; @@ -3512,7 +3800,7 @@ TEST(LayerTreeHostCommonTest, verifyRenderSurfaceTransformsInHighDPI) duplicateChildNonOwner->setContentsScale(deviceScaleFactor); replica->setContentsScale(deviceScaleFactor); - LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, 1, dummyMaxTextureSize, renderSurfaceLayerList); // We should have two render surfaces. The root's render surface and child's // render surface (it needs one because it has a replica layer). diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc index af13254..d228ba1 100644 --- a/cc/layer_tree_host_impl.cc +++ b/cc/layer_tree_host_impl.cc @@ -359,7 +359,8 @@ void LayerTreeHostImpl::calculateRenderSurfaceLayerList(LayerList& renderSurface updateRootScrollLayerImplTransform(); TRACE_EVENT0("cc", "LayerTreeHostImpl::calcDrawEtc"); - LayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList); + float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor(); + LayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, pageScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList); trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList); } diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc index f178224..5817af4 100644 --- a/cc/layer_tree_host_impl_unittest.cc +++ b/cc/layer_tree_host_impl_unittest.cc @@ -3837,9 +3837,9 @@ TEST_P(LayerTreeHostImplTest, surfaceTextureCaching) myHostImpl->didDrawAllLayers(frame); } - // Change opacity on the intermediate layer + // Change location of the intermediate layer WebTransformationMatrix transform = intermediateLayerPtr->transform(); - transform.setM11(1.0001); + transform.setM41(1.0001); intermediateLayerPtr->setTransform(transform); { LayerTreeHostImpl::FrameData frame; @@ -4000,9 +4000,9 @@ TEST_P(LayerTreeHostImplTest, surfaceTextureCachingNoPartialSwap) myHostImpl->didDrawAllLayers(frame); } - // Change opacity on the intermediate layer + // Change location of the intermediate layer WebTransformationMatrix transform = intermediateLayerPtr->transform(); - transform.setM11(1.0001); + transform.setM41(1.0001); intermediateLayerPtr->setTransform(transform); { LayerTreeHostImpl::FrameData frame; diff --git a/cc/math_util.cc b/cc/math_util.cc index 76b2f54..7e3cba6 100644 --- a/cc/math_util.cc +++ b/cc/math_util.cc @@ -9,6 +9,7 @@ #include "FloatPoint.h" #include "FloatQuad.h" #include "IntRect.h" +#include <cmath> #include <public/WebTransformationMatrix.h> using WebKit::WebTransformationMatrix; @@ -361,6 +362,20 @@ void MathUtil::flattenTransformTo2d(WebTransformationMatrix& transform) transform.setM43(0); } +static inline float scaleOnAxis(double a, double b, double c) +{ + return std::sqrt(a * a + b * b + c * c); +} + +FloatPoint MathUtil::computeTransform2dScaleComponents(const WebTransformationMatrix& transform) +{ + if (transform.hasPerspective()) + return FloatPoint(1, 1); + float xScale = scaleOnAxis(transform.m11(), transform.m12(), transform.m13()); + float yScale = scaleOnAxis(transform.m21(), transform.m22(), transform.m23()); + return FloatPoint(xScale, yScale); +} + float MathUtil::smallestAngleBetweenVectors(const FloatSize& v1, const FloatSize& v2) { float dotProduct = (v1.width() * v2.width() + v1.height() * v2.height()) / (v1.diagonalLength() * v2.diagonalLength()); diff --git a/cc/math_util.h b/cc/math_util.h index da3ba08..199c851 100644 --- a/cc/math_util.h +++ b/cc/math_util.h @@ -95,6 +95,8 @@ public: static void flattenTransformTo2d(WebKit::WebTransformationMatrix&); + static FloatPoint computeTransform2dScaleComponents(const WebKit::WebTransformationMatrix&); + // Returns the smallest angle between the given two vectors in degrees. Neither vector is // assumed to be normalized. static float smallestAngleBetweenVectors(const FloatSize&, const FloatSize&); diff --git a/cc/occlusion_tracker_unittest.cc b/cc/occlusion_tracker_unittest.cc index 478c2cc..f4dba9e 100644 --- a/cc/occlusion_tracker_unittest.cc +++ b/cc/occlusion_tracker_unittest.cc @@ -270,7 +270,7 @@ protected: DCHECK(!root->renderSurface()); - LayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, &layerSorter, dummyMaxTextureSize, m_renderSurfaceLayerListImpl); + LayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, 1, &layerSorter, dummyMaxTextureSize, m_renderSurfaceLayerListImpl); m_layerIterator = m_layerIteratorBegin = Types::TestLayerIterator::begin(&m_renderSurfaceLayerListImpl); } @@ -282,7 +282,7 @@ protected: DCHECK(!root->renderSurface()); - LayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, dummyMaxTextureSize, m_renderSurfaceLayerList); + LayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, 1, dummyMaxTextureSize, m_renderSurfaceLayerList); m_layerIterator = m_layerIteratorBegin = Types::TestLayerIterator::begin(&m_renderSurfaceLayerList); } @@ -2710,7 +2710,7 @@ protected: // Filters make the layers own surfaces. WebFilterOperations filters; - filters.append(WebFilterOperation::createBlurFilter(3)); + filters.append(WebFilterOperation::createBlurFilter(1)); filteredSurface1->setBackgroundFilters(filters); filteredSurface2->setBackgroundFilters(filters); @@ -2726,7 +2726,7 @@ protected: this->visitLayer(occludingLayerAbove, occlusion); EXPECT_RECT_EQ(IntRect(100 / 2, 100 / 2, 50 / 2, 50 / 2), occlusion.occlusionInScreenSpace().bounds()); EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size()); - EXPECT_RECT_EQ(IntRect(100, 100, 50, 50), occlusion.occlusionInTargetSurface().bounds()); + EXPECT_RECT_EQ(IntRect(100 / 2, 100 / 2, 50 / 2, 50 / 2), occlusion.occlusionInTargetSurface().bounds()); EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); this->visitLayer(filteredSurface2, occlusion); @@ -2738,16 +2738,10 @@ protected: ASSERT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size()); // Test expectations in the target. - IntRect expectedOcclusion = IntRect(100 + outsetRight * 2, 100 + outsetBottom * 2, 50 - (outsetLeft + outsetRight) * 2, 50 - (outsetTop + outsetBottom) * 2); + IntRect expectedOcclusion = IntRect(100 / 2 + outsetRight * 2, 100 / 2 + outsetBottom * 2, 50 / 2 - (outsetLeft + outsetRight) * 2, 50 / 2 - (outsetTop + outsetBottom) * 2); EXPECT_RECT_EQ(expectedOcclusion, occlusion.occlusionInTargetSurface().rects()[0]); - // Test expectations in the screen. Take the ceiling of half of the outsets. - outsetTop = (outsetTop + 1) / 2; - outsetRight = (outsetRight + 1) / 2; - outsetBottom = (outsetBottom + 1) / 2; - outsetLeft = (outsetLeft + 1) / 2; - expectedOcclusion = IntRect(100 / 2 + outsetRight * 2, 100 / 2 + outsetBottom * 2, 50 / 2 - (outsetLeft + outsetRight) * 2, 50 /2 - (outsetTop + outsetBottom) * 2); - + // Test expectations in the screen are the same as in the target, as the render surface is 1:1 with the screen. EXPECT_RECT_EQ(expectedOcclusion, occlusion.occlusionInScreenSpace().rects()[0]); } }; |