summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorwangxianzhu@chromium.org <wangxianzhu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-01 00:12:47 +0000
committerwangxianzhu@chromium.org <wangxianzhu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-01 00:12:47 +0000
commit904e9138fb2ca78ba6ae1f1054f9ce8cfe19eda5 (patch)
tree931236a109d66ef40f169888e95b47b17da6d9ea /cc
parente2946a407e60e0334292644310fb53a93badf70c (diff)
downloadchromium_src-904e9138fb2ca78ba6ae1f1054f9ce8cfe19eda5.zip
chromium_src-904e9138fb2ca78ba6ae1f1054f9ce8cfe19eda5.tar.gz
chromium_src-904e9138fb2ca78ba6ae1f1054f9ce8cfe19eda5.tar.bz2
Pass accurate contentsScale to LayerImpl.
This is the first part of fixing fuzzy content issue in composited layers in scaled pages. There are two reasons of fuzzy content: 1) Inaccurate scale: The scale in transformation is calculated with contentBounds.width / bounds.width contentBounds.height / bounds.height in layer_tree_host_common.cc and other places. However, contentBounds is a IntSize which is calculated from bounds and contentsScale in layer.cc: IntRect(lroundf(bounds.width * contentsScale), lroundf(bounds.height * contentsScale)) This causes the scale like 0.993 or 1.007 in the drawTransformation etc. where identity transformation is expected. To resolve the issue, instead of calculating scale using contentBounds, pass the accurate contentsScale from Layer to LayerImpl. 2) Pixel on surfaces are not aligned. Will describe this in the CL for the second part. (See https://bugs.webkit.org/show_bug.cgi?id=84187 for more details). Change-Id: I8f59f0460e1b212223e2c8c551b4127d8239e5cc BUG=bugs.webkit.org/show_bug.cgi?id=84187 TEST=ContentsScalingLayerTest.checkContentBounds, LayerTreeHostCommonTest.verifyLayerTransformsInHighDPIAccurateScaleZeroPosition, LayerTreeHostCommonTest.verifyRenderSurfaceTransformsInHighDPIAccurateScaleZeroPosition Review URL: https://chromiumcodereview.appspot.com/11276060 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@165269 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/cc.gyp2
-rw-r--r--cc/cc_tests.gyp1
-rw-r--r--cc/contents_scaling_layer.cc38
-rw-r--r--cc/contents_scaling_layer.h31
-rw-r--r--cc/contents_scaling_layer_unittest.cc76
-rw-r--r--cc/damage_tracker.cc8
-rw-r--r--cc/image_layer.cc14
-rw-r--r--cc/image_layer.h3
-rw-r--r--cc/layer.cc32
-rw-r--r--cc/layer.h12
-rw-r--r--cc/layer_impl.cc26
-rw-r--r--cc/layer_impl.h18
-rw-r--r--cc/layer_impl_unittest.cc2
-rw-r--r--cc/layer_tree_host_common.cc16
-rw-r--r--cc/layer_tree_host_common_unittest.cc203
-rw-r--r--cc/layer_tree_host_impl.cc8
-rw-r--r--cc/layer_tree_host_impl_unittest.cc1
-rw-r--r--cc/layer_tree_host_unittest.cc4
-rw-r--r--cc/layer_unittest.cc50
-rw-r--r--cc/render_surface_impl.cc4
-rw-r--r--cc/scrollbar_layer.cc33
-rw-r--r--cc/scrollbar_layer.h9
-rw-r--r--cc/scrollbar_layer_impl.cc13
-rw-r--r--cc/scrollbar_layer_impl.h2
-rw-r--r--cc/test/tiled_layer_test_common.cc15
-rw-r--r--cc/test/tiled_layer_test_common.h3
-rw-r--r--cc/tiled_layer.cc29
-rw-r--r--cc/tiled_layer.h7
-rw-r--r--cc/tiled_layer_unittest.cc3
29 files changed, 474 insertions, 189 deletions
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 35606e1..19f72ba 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -24,6 +24,8 @@
'checkerboard_draw_quad.cc',
'checkerboard_draw_quad.h',
'completion_event.h',
+ 'contents_scaling_layer.cc',
+ 'contents_scaling_layer.h',
'damage_tracker.cc',
'damage_tracker.h',
'debug_border_draw_quad.cc',
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 26fb00a..963f841 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -8,6 +8,7 @@
'cc_tests_source_files': [
'hash_pair_unittest.cc',
'active_animation_unittest.cc',
+ 'contents_scaling_layer_unittest.cc',
'damage_tracker_unittest.cc',
'delay_based_time_source_unittest.cc',
'draw_quad_unittest.cc',
diff --git a/cc/contents_scaling_layer.cc b/cc/contents_scaling_layer.cc
new file mode 100644
index 0000000..2e041a1
--- /dev/null
+++ b/cc/contents_scaling_layer.cc
@@ -0,0 +1,38 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+
+#include "cc/contents_scaling_layer.h"
+
+namespace cc {
+
+ContentsScalingLayer::ContentsScalingLayer()
+ : m_contentsScale(1.0) {
+}
+
+ContentsScalingLayer::~ContentsScalingLayer() {
+}
+
+IntSize ContentsScalingLayer::contentBounds() const {
+ return IntSize(ceil(bounds().width() * contentsScaleX()),
+ ceil(bounds().height() * contentsScaleY()));
+}
+
+float ContentsScalingLayer::contentsScaleX() const {
+ return m_contentsScale;
+}
+
+float ContentsScalingLayer::contentsScaleY() const {
+ return m_contentsScale;
+}
+
+void ContentsScalingLayer::setContentsScale(float contentsScale) {
+ if (m_contentsScale == contentsScale)
+ return;
+ m_contentsScale = contentsScale;
+ setNeedsDisplay();
+}
+
+} // namespace cc
diff --git a/cc/contents_scaling_layer.h b/cc/contents_scaling_layer.h
new file mode 100644
index 0000000..94e83a9
--- /dev/null
+++ b/cc/contents_scaling_layer.h
@@ -0,0 +1,31 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_CONTENTS_SCALING_LAYER_H
+#define CC_CONTENTS_SCALING_LAYER_H
+
+#include "cc/layer.h"
+
+namespace cc {
+
+// Base class for layers that need contents scale.
+// The content bounds are determined by bounds and scale of the contents.
+class ContentsScalingLayer : public Layer {
+ public:
+ virtual IntSize contentBounds() const OVERRIDE;
+ virtual float contentsScaleX() const OVERRIDE;
+ virtual float contentsScaleY() const OVERRIDE;
+ virtual void setContentsScale(float contentsScale) OVERRIDE;
+
+ protected:
+ ContentsScalingLayer();
+ virtual ~ContentsScalingLayer();
+
+ private:
+ float m_contentsScale;
+};
+
+} // namespace cc
+
+#endif // CC_CONTENTS_SCALING_LAYER_H
diff --git a/cc/contents_scaling_layer_unittest.cc b/cc/contents_scaling_layer_unittest.cc
new file mode 100644
index 0000000..4c79a90
--- /dev/null
+++ b/cc/contents_scaling_layer_unittest.cc
@@ -0,0 +1,76 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+
+#include "cc/contents_scaling_layer.h"
+
+#include "cc/test/geometry_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using namespace cc;
+
+class MockContentsScalingLayer : public ContentsScalingLayer {
+ public:
+ MockContentsScalingLayer()
+ : ContentsScalingLayer() {
+ }
+
+ virtual void setNeedsDisplayRect(const FloatRect& dirtyRect) OVERRIDE {
+ m_lastNeedsDisplayRect = dirtyRect;
+ ContentsScalingLayer::setNeedsDisplayRect(dirtyRect);
+ }
+
+ void resetNeedsDisplay() {
+ m_needsDisplay = false;
+ }
+
+ const FloatRect& lastNeedsDisplayRect() const {
+ return m_lastNeedsDisplayRect;
+ }
+
+ private:
+ virtual ~MockContentsScalingLayer() {
+ }
+
+ FloatRect m_lastNeedsDisplayRect;
+};
+
+TEST(ContentsScalingLayerTest, checkContentsBounds) {
+ scoped_refptr<MockContentsScalingLayer> testLayer =
+ make_scoped_refptr(new MockContentsScalingLayer());
+
+ testLayer->setBounds(IntSize(320, 240));
+ EXPECT_FLOAT_EQ(1.0, testLayer->contentsScaleX());
+ EXPECT_FLOAT_EQ(1.0, testLayer->contentsScaleY());
+ EXPECT_EQ(320, testLayer->contentBounds().width());
+ EXPECT_EQ(240, testLayer->contentBounds().height());
+
+ testLayer->setContentsScale(2.0f);
+ EXPECT_EQ(640, testLayer->contentBounds().width());
+ EXPECT_EQ(480, testLayer->contentBounds().height());
+
+ testLayer->setBounds(IntSize(10, 20));
+ EXPECT_EQ(20, testLayer->contentBounds().width());
+ EXPECT_EQ(40, testLayer->contentBounds().height());
+
+ testLayer->setContentsScale(1.33f);
+ EXPECT_EQ(14, testLayer->contentBounds().width());
+ EXPECT_EQ(27, testLayer->contentBounds().height());
+}
+
+TEST(ContentsScalingLayerTest, checkContentsScaleChangeTriggersNeedsDisplay) {
+ scoped_refptr<MockContentsScalingLayer> testLayer =
+ make_scoped_refptr(new MockContentsScalingLayer());
+
+ testLayer->setBounds(IntSize(320, 240));
+
+ testLayer->resetNeedsDisplay();
+ EXPECT_FALSE(testLayer->needsDisplay());
+
+ testLayer->setContentsScale(testLayer->contentsScaleX() + 1.f);
+ EXPECT_TRUE(testLayer->needsDisplay());
+ EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 320, 240),
+ testLayer->lastNeedsDisplayRect());
+}
diff --git a/cc/damage_tracker.cc b/cc/damage_tracker.cc
index 4c27d4d..400fe5f 100644
--- a/cc/damage_tracker.cc
+++ b/cc/damage_tracker.cc
@@ -265,13 +265,9 @@ void DamageTracker::extendDamageForLayer(LayerImpl* layer, FloatRect& targetDama
// Note oldRectInTargetSpace is already in target space.
targetDamageRect.uniteIfNonZero(oldRectInTargetSpace);
} else if (!layer->updateRect().isEmpty()) {
- // If the layer properties havent changed, then the the target surface is only
+ // If the layer properties haven't changed, then the the target surface is only
// affected by the layer's update area, which could be empty.
- FloatRect updateContentRect = layer->updateRect();
- float widthScale = layer->contentBounds().width() / static_cast<float>(layer->bounds().width());
- float heightScale = layer->contentBounds().height() / static_cast<float>(layer->bounds().height());
- updateContentRect.scale(widthScale, heightScale);
-
+ FloatRect updateContentRect = layer->layerRectToContentRect(layer->updateRect());
FloatRect updateRectInTargetSpace = MathUtil::mapClippedRect(layer->drawTransform(), updateContentRect);
targetDamageRect.uniteIfNonZero(updateRectInTargetSpace);
}
diff --git a/cc/image_layer.cc b/cc/image_layer.cc
index e162007..3c1712e 100644
--- a/cc/image_layer.cc
+++ b/cc/image_layer.cc
@@ -150,10 +150,18 @@ bool ImageLayer::drawsContent() const
return !m_bitmap.isNull() && TiledLayer::drawsContent();
}
-bool ImageLayer::needsContentsScale() const
+float ImageLayer::contentsScaleX() const
{
- // Contents scale is not need for image layer because this can be done in compositor more efficiently.
- return false;
+ if (bounds().isEmpty() || contentBounds().isEmpty())
+ return 1;
+ return static_cast<float>(m_bitmap.width()) / bounds().width();
+}
+
+float ImageLayer::contentsScaleY() const
+{
+ if (bounds().isEmpty() || contentBounds().isEmpty())
+ return 1;
+ return static_cast<float>(m_bitmap.height()) / bounds().height();
}
}
diff --git a/cc/image_layer.h b/cc/image_layer.h
index fcb3adb..6f25a21 100644
--- a/cc/image_layer.h
+++ b/cc/image_layer.h
@@ -20,7 +20,8 @@ public:
virtual bool drawsContent() const OVERRIDE;
virtual void setTexturePriorities(const PriorityCalculator&) OVERRIDE;
virtual void update(ResourceUpdateQueue&, const OcclusionTracker*, RenderingStats&) OVERRIDE;
- virtual bool needsContentsScale() const OVERRIDE;
+ virtual float contentsScaleX() const OVERRIDE;
+ virtual float contentsScaleY() const OVERRIDE;
void setBitmap(const SkBitmap& image);
diff --git a/cc/layer.cc b/cc/layer.cc
index 4c39126..b36589d 100644
--- a/cc/layer.cc
+++ b/cc/layer.cc
@@ -64,7 +64,6 @@ Layer::Layer()
, m_renderTarget(0)
, m_drawTransformIsAnimating(false)
, m_screenSpaceTransformIsAnimating(false)
- , m_contentsScale(1.0)
, m_rasterScale(1.0)
, m_automaticallyComputeRasterScale(false)
, m_boundsContainPageScale(false)
@@ -120,13 +119,15 @@ void Layer::setNeedsCommit()
m_layerTreeHost->setNeedsCommit();
}
-IntRect Layer::layerRectToContentRect(const WebKit::WebRect& layerRect)
+IntRect Layer::layerRectToContentRect(const FloatRect& layerRect) const
{
- float widthScale = static_cast<float>(contentBounds().width()) / bounds().width();
- float heightScale = static_cast<float>(contentBounds().height()) / bounds().height();
- FloatRect contentRect(layerRect.x, layerRect.y, layerRect.width, layerRect.height);
- contentRect.scale(widthScale, heightScale);
- return enclosingIntRect(contentRect);
+ FloatRect contentRect(layerRect);
+ contentRect.scale(contentsScaleX(), contentsScaleY());
+ IntRect intContentRect = enclosingIntRect(contentRect);
+ // Intersect with content rect to avoid the extra pixel because for some
+ // values x and y, ceil((x / y) * y) may be x + 1.
+ intContentRect.intersect(IntRect(IntPoint(), contentBounds()));
+ return intContentRect;
}
void Layer::setParent(Layer* layer)
@@ -557,6 +558,7 @@ void Layer::pushPropertiesTo(LayerImpl* layer)
layer->setBackgroundColor(m_backgroundColor);
layer->setBounds(m_bounds);
layer->setContentBounds(contentBounds());
+ layer->setContentsScale(contentsScaleX(), contentsScaleY());
layer->setDebugBorderColor(m_debugBorderColor);
layer->setDebugBorderWidth(m_debugBorderWidth);
layer->setDebugName(m_debugName);
@@ -630,11 +632,6 @@ bool Layer::needMoreUpdates()
return false;
}
-bool Layer::needsContentsScale() const
-{
- return false;
-}
-
void Layer::setDebugBorderColor(SkColor color)
{
m_debugBorderColor = color;
@@ -653,13 +650,14 @@ void Layer::setDebugName(const std::string& debugName)
setNeedsCommit();
}
-void Layer::setContentsScale(float contentsScale)
+float Layer::contentsScaleX() const
{
- if (!needsContentsScale() || m_contentsScale == contentsScale)
- return;
- m_contentsScale = contentsScale;
+ return 1.0;
+}
- setNeedsDisplay();
+float Layer::contentsScaleY() const
+{
+ return 1.0;
}
void Layer::setRasterScale(float scale)
diff --git a/cc/layer.h b/cc/layer.h
index 38a32dd..dda77d8 100644
--- a/cc/layer.h
+++ b/cc/layer.h
@@ -189,7 +189,6 @@ public:
virtual bool needMoreUpdates();
virtual void setIsMask(bool) { }
virtual void bindContentsTexture() { }
- virtual bool needsContentsScale() const;
void setDebugBorderColor(SkColor);
void setDebugBorderWidth(float);
@@ -229,8 +228,10 @@ public:
// 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);
+ // By default contentsScale is forced to be 1 except for subclasses of ContentsScalingLayer.
+ virtual float contentsScaleX() const;
+ virtual float contentsScaleY() const;
+ virtual void setContentsScale(float contentsScale) { }
// 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
@@ -280,6 +281,8 @@ public:
virtual ScrollbarLayer* toScrollbarLayer();
+ IntRect layerRectToContentRect(const FloatRect& layerRect) const;
+
protected:
friend class LayerImpl;
friend class TreeSynchronizer;
@@ -289,8 +292,6 @@ protected:
void setNeedsCommit();
- IntRect layerRectToContentRect(const WebKit::WebRect& layerRect);
-
// This flag is set when layer need repainting/updating.
bool m_needsDisplay;
@@ -390,7 +391,6 @@ private:
// Uses target surface space.
IntRect m_drawableContentRect;
- float m_contentsScale;
float m_rasterScale;
bool m_automaticallyComputeRasterScale;
bool m_boundsContainPageScale;
diff --git a/cc/layer_impl.cc b/cc/layer_impl.cc
index 3de9483..197e619 100644
--- a/cc/layer_impl.cc
+++ b/cc/layer_impl.cc
@@ -29,6 +29,8 @@ LayerImpl::LayerImpl(int id)
, m_layerTreeHostImpl(0)
, m_anchorPoint(0.5, 0.5)
, m_anchorPointZ(0)
+ , m_contentsScaleX(1.0)
+ , m_contentsScaleY(1.0)
, m_scrollable(false)
, m_shouldScrollOnMainThread(false)
, m_haveWheelEventHandlers(false)
@@ -233,13 +235,15 @@ bool LayerImpl::drawCheckerboardForMissingTiles() const
return m_drawCheckerboardForMissingTiles && !Settings::backgroundColorInsteadOfCheckerboard();
}
-IntRect LayerImpl::layerRectToContentRect(const WebKit::WebRect& layerRect)
+IntRect LayerImpl::layerRectToContentRect(const FloatRect& layerRect) const
{
- float widthScale = static_cast<float>(contentBounds().width()) / bounds().width();
- float heightScale = static_cast<float>(contentBounds().height()) / bounds().height();
- FloatRect contentRect(layerRect.x, layerRect.y, layerRect.width, layerRect.height);
- contentRect.scale(widthScale, heightScale);
- return enclosingIntRect(contentRect);
+ FloatRect contentRect(layerRect);
+ contentRect.scale(contentsScaleX(), contentsScaleY());
+ IntRect intContentRect = enclosingIntRect(contentRect);
+ // Intersect with content rect to avoid the extra pixel because for some
+ // values x and y, ceil((x / y) * y) may be x + 1.
+ intContentRect.intersect(IntRect(IntPoint(), contentBounds()));
+ return intContentRect;
}
std::string LayerImpl::indentString(int indent)
@@ -609,6 +613,16 @@ void LayerImpl::setContentBounds(const IntSize& contentBounds)
m_layerPropertyChanged = true;
}
+void LayerImpl::setContentsScale(float contentsScaleX, float contentsScaleY)
+{
+ if (m_contentsScaleX == contentsScaleX && m_contentsScaleY == contentsScaleY)
+ return;
+
+ m_contentsScaleX = contentsScaleX;
+ m_contentsScaleY = contentsScaleY;
+ m_layerPropertyChanged = true;
+}
+
void LayerImpl::setScrollPosition(const IntPoint& scrollPosition)
{
if (m_scrollPosition == scrollPosition)
diff --git a/cc/layer_impl.h b/cc/layer_impl.h
index 05f3b44..f1fae67 100644
--- a/cc/layer_impl.h
+++ b/cc/layer_impl.h
@@ -167,11 +167,21 @@ public:
LayerImpl* renderTarget() const { DCHECK(!m_renderTarget || m_renderTarget->renderSurface()); return m_renderTarget; }
void setRenderTarget(LayerImpl* target) { m_renderTarget = target; }
+ // The client should be responsible for setting bounds, contentBounds and
+ // contentsScale to appropriate values. LayerImpl doesn't calculate any of
+ // them from the other values.
+
void setBounds(const IntSize&);
const IntSize& bounds() const { return m_bounds; }
- const IntSize& contentBounds() const { return m_contentBounds; }
+ // ContentBounds may be [0, 1) pixels larger than bounds * contentsScale.
+ // Don't calculate scale from it. Use contentsScale instead for accuracy.
void setContentBounds(const IntSize&);
+ IntSize contentBounds() const { return m_contentBounds; }
+
+ float contentsScaleX() const { return m_contentsScaleX; }
+ float contentsScaleY() const { return m_contentsScaleY; }
+ void setContentsScale(float contentsScaleX, float contentsScaleY);
const IntPoint& scrollPosition() const { return m_scrollPosition; }
void setScrollPosition(const IntPoint&);
@@ -260,13 +270,13 @@ public:
ScrollbarLayerImpl* verticalScrollbarLayer() const;
void setVerticalScrollbarLayer(ScrollbarLayerImpl*);
+ IntRect layerRectToContentRect(const FloatRect& layerRect) const;
+
protected:
explicit LayerImpl(int);
void appendDebugBorderQuad(QuadSink&, const SharedQuadState*, AppendQuadsData&) const;
- IntRect layerRectToContentRect(const WebKit::WebRect& layerRect);
-
virtual void dumpLayerProperties(std::string*, int indent) const;
static std::string indentString(int indent);
@@ -300,6 +310,8 @@ private:
float m_anchorPointZ;
IntSize m_bounds;
IntSize m_contentBounds;
+ float m_contentsScaleX;
+ float m_contentsScaleY;
IntPoint m_scrollPosition;
bool m_scrollable;
bool m_shouldScrollOnMainThread;
diff --git a/cc/layer_impl_unittest.cc b/cc/layer_impl_unittest.cc
index def19a9..3640185 100644
--- a/cc/layer_impl_unittest.cc
+++ b/cc/layer_impl_unittest.cc
@@ -116,6 +116,7 @@ TEST(LayerImplTest, verifyLayerChangesAreTrackedProperly)
// Changing these properties only affects the layer itself.
EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->setContentBounds(arbitraryIntSize));
+ EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->setContentsScale(arbitraryNumber, arbitraryNumber));
EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->setDebugBorderColor(arbitraryColor));
EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->setDebugBorderWidth(arbitraryNumber));
EXECUTE_AND_VERIFY_ONLY_LAYER_CHANGED(root->setDrawsContent(true));
@@ -152,6 +153,7 @@ TEST(LayerImplTest, verifyLayerChangesAreTrackedProperly)
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->setScrollPosition(arbitraryIntPoint));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->setImplTransform(arbitraryTransform));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->setContentBounds(arbitraryIntSize));
+ EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->setContentsScale(arbitraryNumber, arbitraryNumber));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->setContentsOpaque(true));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->setOpacity(arbitraryNumber));
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->setDebugBorderColor(arbitraryColor));
diff --git a/cc/layer_tree_host_common.cc b/cc/layer_tree_host_common.cc
index b51fd00..65db168 100644
--- a/cc/layer_tree_host_common.cc
+++ b/cc/layer_tree_host_common.cc
@@ -525,8 +525,8 @@ static void calculateDrawTransformsInternal(LayerType* layer, const WebTransform
WebTransformationMatrix drawTransform = combinedTransform;
if (!layer->contentBounds().isEmpty() && !layer->bounds().isEmpty()) {
// M[draw] = M[parent] * LT * S[layer2content]
- drawTransform.scaleNonUniform(layer->bounds().width() / static_cast<double>(layer->contentBounds().width()),
- layer->bounds().height() / static_cast<double>(layer->contentBounds().height()));
+ drawTransform.scaleNonUniform(1.0 / layer->contentsScaleX(),
+ 1.0 / layer->contentsScaleY());
}
// layerScreenSpaceTransform represents the transform between root layer's "screen space" and local content space.
@@ -566,8 +566,8 @@ static void calculateDrawTransformsInternal(LayerType* layer, const WebTransform
// 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(layer->contentsScaleX(),
+ layer->contentsScaleY());
}
drawTransform.scaleNonUniform(1 / renderSurfaceSublayerScale.x(), 1 / renderSurfaceSublayerScale.y());
renderSurface->setDrawTransform(drawTransform);
@@ -576,8 +576,8 @@ static void calculateDrawTransformsInternal(LayerType* layer, const WebTransform
WebTransformationMatrix layerDrawTransform;
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()));
+ layerDrawTransform.scaleNonUniform(1.0 / layer->contentsScaleX(),
+ 1.0 / layer->contentsScaleY());
}
layer->setDrawTransform(layerDrawTransform);
@@ -751,8 +751,8 @@ static void calculateDrawTransformsInternal(LayerType* layer, const WebTransform
// 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(layer->contentsScaleX(),
+ layer->contentsScaleY());
}
screenSpaceTransform.scaleNonUniform(1 / renderSurfaceSublayerScale.x(), 1 / renderSurfaceSublayerScale.y());
renderSurface->setScreenSpaceTransform(screenSpaceTransform);
diff --git a/cc/layer_tree_host_common_unittest.cc b/cc/layer_tree_host_common_unittest.cc
index 21b323a..ce08617 100644
--- a/cc/layer_tree_host_common_unittest.cc
+++ b/cc/layer_tree_host_common_unittest.cc
@@ -142,6 +142,12 @@ scoped_refptr<ContentLayer> createDrawableContentLayer(ContentLayerClient* deleg
return toReturn;
}
+#define EXPECT_CONTENTS_SCALE_EQ(expected, layer) \
+ do { \
+ EXPECT_FLOAT_EQ(expected, layer->contentsScaleX()); \
+ EXPECT_FLOAT_EQ(expected, layer->contentsScaleY()); \
+ } while (false)
+
TEST(LayerTreeHostCommonTest, verifyTransformsForNoOpLayer)
{
// Sanity check: For layers positioned at zero, with zero size,
@@ -2967,8 +2973,9 @@ TEST(LayerTreeHostCommonTest, verifyHitTestingForSingleLayerWithScaledContents)
scoped_ptr<LayerImpl> testLayer = LayerImpl::create(12345);
setLayerPropertiesForTesting(testLayer.get(), identityMatrix, identityMatrix, anchor, position, bounds, false);
- // override contentBounds
+ // override contentBounds and contentsScale
testLayer->setContentBounds(IntSize(100, 100));
+ testLayer->setContentsScale(2, 2);
testLayer->setDrawsContent(true);
root->addChild(testLayer.Pass());
@@ -3461,7 +3468,9 @@ 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; }
+ virtual IntSize contentBounds() const OVERRIDE { return bounds(); }
+ virtual float contentsScaleX() const OVERRIDE { return 1.0; }
+ virtual float contentsScaleY() const OVERRIDE { return 1.0; }
protected:
explicit NoScaleContentLayer(ContentLayerClient* client) : ContentLayer(client) { }
@@ -3501,9 +3510,9 @@ TEST(LayerTreeHostCommonTest, verifyLayerTransformsInHighDPI)
LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, pageScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList);
- EXPECT_EQ(deviceScaleFactor * pageScaleFactor, parent->contentsScale());
- EXPECT_EQ(deviceScaleFactor * pageScaleFactor, child->contentsScale());
- EXPECT_EQ(1, childNoScale->contentsScale());
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor, parent);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor, child);
+ EXPECT_CONTENTS_SCALE_EQ(1, childNoScale);
EXPECT_EQ(1u, renderSurfaceLayerList.size());
@@ -3550,6 +3559,83 @@ TEST(LayerTreeHostCommonTest, verifyLayerTransformsInHighDPI)
EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildNoScaleTransform, childNoScale->screenSpaceTransform());
}
+TEST(LayerTreeHostCommonTest, verifyLayerTransformsInHighDPIAccurateScaleZeroChildPosition)
+{
+ // Verify draw and screen space transforms of layers not in a surface.
+ MockContentLayerClient delegate;
+ WebTransformationMatrix identityMatrix;
+
+ scoped_refptr<ContentLayer> parent = createDrawableContentLayer(&delegate);
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(133, 133), true);
+
+ scoped_refptr<ContentLayer> child = createDrawableContentLayer(&delegate);
+ setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(13, 13), true);
+
+ scoped_refptr<NoScaleContentLayer> childNoScale = createNoScaleDrawableContentLayer(&delegate);
+ setLayerPropertiesForTesting(childNoScale.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(13, 13), true);
+
+ parent->addChild(child);
+ parent->addChild(childNoScale);
+
+ std::vector<scoped_refptr<Layer> > renderSurfaceLayerList;
+ int dummyMaxTextureSize = 512;
+
+ const float deviceScaleFactor = 1.7f;
+ const float pageScaleFactor = 1;
+
+ LayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), deviceScaleFactor, pageScaleFactor, dummyMaxTextureSize, renderSurfaceLayerList);
+
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor, parent);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor, child);
+ EXPECT_CONTENTS_SCALE_EQ(1, childNoScale);
+
+ EXPECT_EQ(1u, renderSurfaceLayerList.size());
+
+ // Verify parent transforms
+ WebTransformationMatrix expectedParentTransform;
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedParentTransform, parent->screenSpaceTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedParentTransform, parent->drawTransform());
+
+ // Verify results of transformed parent rects
+ FloatRect parentContentBounds(FloatPoint(), FloatSize(parent->contentBounds()));
+
+ FloatRect parentDrawRect = MathUtil::mapClippedRect(parent->drawTransform(), parentContentBounds);
+ FloatRect parentScreenSpaceRect = MathUtil::mapClippedRect(parent->screenSpaceTransform(), parentContentBounds);
+
+ FloatRect expectedParentDrawRect(FloatPoint(), parent->bounds());
+ expectedParentDrawRect.scale(deviceScaleFactor);
+ expectedParentDrawRect.setWidth(ceil(expectedParentDrawRect.width()));
+ expectedParentDrawRect.setHeight(ceil(expectedParentDrawRect.height()));
+ EXPECT_FLOAT_RECT_EQ(expectedParentDrawRect, parentDrawRect);
+ EXPECT_FLOAT_RECT_EQ(expectedParentDrawRect, parentScreenSpaceRect);
+
+ // Verify child transforms
+ WebTransformationMatrix expectedChildTransform;
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->drawTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildTransform, child->screenSpaceTransform());
+
+ // Verify results of transformed child rects
+ FloatRect childContentBounds(FloatPoint(), FloatSize(child->contentBounds()));
+
+ FloatRect childDrawRect = MathUtil::mapClippedRect(child->drawTransform(), childContentBounds);
+ FloatRect childScreenSpaceRect = MathUtil::mapClippedRect(child->screenSpaceTransform(), childContentBounds);
+
+ FloatRect expectedChildDrawRect(FloatPoint(), child->bounds());
+ expectedChildDrawRect.scale(deviceScaleFactor);
+ expectedChildDrawRect.setWidth(ceil(expectedChildDrawRect.width()));
+ expectedChildDrawRect.setHeight(ceil(expectedChildDrawRect.height()));
+ EXPECT_FLOAT_RECT_EQ(expectedChildDrawRect, childDrawRect);
+ EXPECT_FLOAT_RECT_EQ(expectedChildDrawRect, childScreenSpaceRect);
+
+ // Verify childNoScale transforms
+ WebTransformationMatrix expectedChildNoScaleTransform = child->drawTransform();
+ // All transforms operate on content rects. The child's content rect
+ // incorporates device scale, but the childNoScale does not; add it here.
+ expectedChildNoScaleTransform.scale(deviceScaleFactor);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildNoScaleTransform, childNoScale->drawTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedChildNoScaleTransform, childNoScale->screenSpaceTransform());
+}
+
TEST(LayerTreeHostCommonTest, verifyContentsScale)
{
MockContentLayerClient delegate;
@@ -3600,10 +3686,10 @@ TEST(LayerTreeHostCommonTest, verifyContentsScale)
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());
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * initialParentScale, parent);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, childScale);
+ EXPECT_CONTENTS_SCALE_EQ(1, childNoScale);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor * fixedRasterScale, childNoAutoScale);
// 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.
@@ -3623,9 +3709,9 @@ TEST(LayerTreeHostCommonTest, verifyContentsScale)
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_CONTENTS_SCALE_EQ(deviceScaleFactor * initialParentScale, parent);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, childScale);
+ EXPECT_CONTENTS_SCALE_EQ(1, childNoScale);
// But if the deviceScaleFactor or pageScaleFactor changes, then it should be updated, but using the initial transform.
deviceScaleFactor = 2.25;
@@ -3639,10 +3725,10 @@ TEST(LayerTreeHostCommonTest, verifyContentsScale)
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());
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * initialParentScale, parent);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, childScale);
+ EXPECT_CONTENTS_SCALE_EQ(1, childNoScale);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor * fixedRasterScale, childNoAutoScale);
}
TEST(LayerTreeHostCommonTest, verifyContentsScaleForSurfaces)
@@ -3725,17 +3811,17 @@ TEST(LayerTreeHostCommonTest, verifyContentsScaleForSurfaces)
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_CONTENTS_SCALE_EQ(deviceScaleFactor * initialParentScale, parent);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale, surfaceScale);
+ EXPECT_CONTENTS_SCALE_EQ(1, surfaceNoScale);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor * fixedRasterScale, surfaceNoAutoScale);
- 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());
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceScaleChildScale);
+ EXPECT_CONTENTS_SCALE_EQ(1, surfaceScaleChildNoScale);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceNoScaleChildScale);
+ EXPECT_CONTENTS_SCALE_EQ(1, surfaceNoScaleChildNoScale);
+ EXPECT_CONTENTS_SCALE_EQ(deviceScaleFactor * pageScaleFactor * initialParentScale * initialChildScale * initialChildScale, surfaceNoAutoScaleChildScale);
+ EXPECT_CONTENTS_SCALE_EQ(1, surfaceNoAutoScaleChildNoScale);
// The parent is scaled up and shouldn't need to scale during draw.
EXPECT_FLOAT_EQ(1, parent->drawTransform().m11());
@@ -3870,6 +3956,71 @@ TEST(LayerTreeHostCommonTest, verifyRenderSurfaceTransformsInHighDPI)
expectedReplicaScreenSpaceTransform.setM41(6);
expectedReplicaScreenSpaceTransform.setM42(6);
EXPECT_TRANSFORMATION_MATRIX_EQ(expectedReplicaScreenSpaceTransform, child->renderSurface()->replicaScreenSpaceTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedReplicaScreenSpaceTransform, child->renderSurface()->replicaScreenSpaceTransform());
+}
+
+TEST(LayerTreeHostCommonTest, verifyRenderSurfaceTransformsInHighDPIAccurateScaleZeroPosition)
+{
+ MockContentLayerClient delegate;
+ WebTransformationMatrix identityMatrix;
+
+ scoped_refptr<ContentLayer> parent = createDrawableContentLayer(&delegate);
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(33, 31), true);
+
+ scoped_refptr<ContentLayer> child = createDrawableContentLayer(&delegate);
+ setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(13, 11), true);
+
+ WebTransformationMatrix replicaTransform;
+ replicaTransform.scaleNonUniform(1, -1);
+ scoped_refptr<ContentLayer> replica = createDrawableContentLayer(&delegate);
+ setLayerPropertiesForTesting(replica.get(), replicaTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(13, 11), true);
+
+ // This layer should end up in the same surface as child, with the same draw
+ // and screen space transforms.
+ scoped_refptr<ContentLayer> duplicateChildNonOwner = createDrawableContentLayer(&delegate);
+ setLayerPropertiesForTesting(duplicateChildNonOwner.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(13, 11), true);
+
+ parent->addChild(child);
+ child->addChild(duplicateChildNonOwner);
+ child->setReplicaLayer(replica.get());
+
+ std::vector<scoped_refptr<Layer> > renderSurfaceLayerList;
+ int dummyMaxTextureSize = 512;
+
+ const float deviceScaleFactor = 1.7f;
+ parent->setContentsScale(deviceScaleFactor);
+ child->setContentsScale(deviceScaleFactor);
+ duplicateChildNonOwner->setContentsScale(deviceScaleFactor);
+ replica->setContentsScale(deviceScaleFactor);
+
+ 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).
+ EXPECT_EQ(2u, renderSurfaceLayerList.size());
+
+ WebTransformationMatrix identityTransform;
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(identityTransform, parent->screenSpaceTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(identityTransform, parent->drawTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(identityTransform, child->drawTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(identityTransform, child->screenSpaceTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(identityTransform, duplicateChildNonOwner->drawTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(identityTransform, duplicateChildNonOwner->screenSpaceTransform());
+ EXPECT_RECT_EQ(child->drawableContentRect(), duplicateChildNonOwner->drawableContentRect());
+ EXPECT_EQ(child->contentBounds(), duplicateChildNonOwner->contentBounds());
+
+ EXPECT_TRANSFORMATION_MATRIX_EQ(identityTransform, child->renderSurface()->drawTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(identityTransform, child->renderSurface()->drawTransform());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(identityTransform, child->renderSurface()->screenSpaceTransform());
+
+ WebTransformationMatrix expectedReplicaDrawTransform;
+ expectedReplicaDrawTransform.setM22(-1);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedReplicaDrawTransform, child->renderSurface()->replicaDrawTransform());
+
+ WebTransformationMatrix expectedReplicaScreenSpaceTransform;
+ expectedReplicaScreenSpaceTransform.setM22(-1);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedReplicaScreenSpaceTransform, child->renderSurface()->replicaScreenSpaceTransform());
}
TEST(LayerTreeHostCommonTest, verifySubtreeSearch)
diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc
index 581377e..1add8df 100644
--- a/cc/layer_tree_host_impl.cc
+++ b/cc/layer_tree_host_impl.cc
@@ -1102,12 +1102,8 @@ static FloatSize scrollLayerWithViewportSpaceDelta(PinchZoomViewport* viewport,
return FloatSize();
// localStartPoint and localEndPoint are in content space but we want to move them to layer space for scrolling.
- float widthScale = 1;
- float heightScale = 1;
- if (!layerImpl.contentBounds().isEmpty() && !layerImpl.bounds().isEmpty()) {
- widthScale = layerImpl.bounds().width() / static_cast<float>(layerImpl.contentBounds().width());
- heightScale = layerImpl.bounds().height() / static_cast<float>(layerImpl.contentBounds().height());
- }
+ float widthScale = 1.0 / layerImpl.contentsScaleX();
+ float heightScale = 1.0 / layerImpl.contentsScaleY();
localStartPoint.scale(widthScale, heightScale);
localEndPoint.scale(widthScale, heightScale);
diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc
index e2ecdce..79bc896 100644
--- a/cc/layer_tree_host_impl_unittest.cc
+++ b/cc/layer_tree_host_impl_unittest.cc
@@ -1045,6 +1045,7 @@ TEST_P(LayerTreeHostImplTest, scrollNonCompositedRoot)
contentLayer->setAnchorPoint(FloatPoint(0, 0));
contentLayer->setBounds(surfaceSize);
contentLayer->setContentBounds(IntSize(surfaceSize.width() * 2, surfaceSize.height() * 2));
+ contentLayer->setContentsScale(2, 2);
scoped_ptr<LayerImpl> scrollLayer = LayerImpl::create(2);
scrollLayer->setScrollable(true);
diff --git a/cc/layer_tree_host_unittest.cc b/cc/layer_tree_host_unittest.cc
index 86be122..1117356 100644
--- a/cc/layer_tree_host_unittest.cc
+++ b/cc/layer_tree_host_unittest.cc
@@ -1224,7 +1224,9 @@ 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; }
+ virtual IntSize contentBounds() const OVERRIDE { return bounds(); }
+ virtual float contentsScaleX() const OVERRIDE { return 1.0; }
+ virtual float contentsScaleY() const OVERRIDE { return 1.0; }
private:
explicit NoScaleContentLayer(ContentLayerClient* client)
diff --git a/cc/layer_unittest.cc b/cc/layer_unittest.cc
index e2cb6b2..a4a0725 100644
--- a/cc/layer_unittest.cc
+++ b/cc/layer_unittest.cc
@@ -549,56 +549,6 @@ TEST_F(LayerTest, verifyPushPropertiesAccumulatesUpdateRect)
EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint(10, 10), FloatSize(5, 5)), implLayer->updateRect());
}
-class LayerWithContentScaling : public Layer {
-public:
- explicit LayerWithContentScaling()
- : Layer()
- {
- }
-
- virtual bool needsContentsScale() const OVERRIDE
- {
- return true;
- }
-
- virtual void setNeedsDisplayRect(const FloatRect& dirtyRect) OVERRIDE
- {
- m_lastNeedsDisplayRect = dirtyRect;
- Layer::setNeedsDisplayRect(dirtyRect);
- }
-
- void resetNeedsDisplay()
- {
- m_needsDisplay = false;
- }
-
- const FloatRect& lastNeedsDisplayRect() const { return m_lastNeedsDisplayRect; }
-
-private:
- virtual ~LayerWithContentScaling()
- {
- }
-
- FloatRect m_lastNeedsDisplayRect;
-};
-
-TEST_F(LayerTest, checkContentsScaleChangeTriggersNeedsDisplay)
-{
- scoped_refptr<LayerWithContentScaling> testLayer = make_scoped_refptr(new LayerWithContentScaling());
- testLayer->setIsDrawable(true);
- testLayer->setLayerTreeHost(m_layerTreeHost.get());
-
- IntSize testBounds = IntSize(320, 240);
- EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setBounds(testBounds));
-
- testLayer->resetNeedsDisplay();
- EXPECT_FALSE(testLayer->needsDisplay());
-
- EXECUTE_AND_VERIFY_SET_NEEDS_COMMIT_BEHAVIOR(1, testLayer->setContentsScale(testLayer->contentsScale() + 1.f));
- EXPECT_TRUE(testLayer->needsDisplay());
- EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 320, 240), testLayer->lastNeedsDisplayRect());
-}
-
class FakeLayerImplTreeHost : public LayerTreeHost {
public:
static scoped_ptr<FakeLayerImplTreeHost> create()
diff --git a/cc/render_surface_impl.cc b/cc/render_surface_impl.cc
index ece1d10..40c0dea 100644
--- a/cc/render_surface_impl.cc
+++ b/cc/render_surface_impl.cc
@@ -236,8 +236,8 @@ void RenderSurfaceImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQ
float maskTexCoordOffsetX = 0;
float maskTexCoordOffsetY = 0;
if (maskLayer) {
- maskTexCoordScaleX = static_cast<float>(contentRect().width()) / maskLayer->contentBounds().width();
- maskTexCoordScaleY = static_cast<float>(contentRect().height()) / maskLayer->contentBounds().height();
+ maskTexCoordScaleX = contentRect().width() / maskLayer->contentsScaleX() / maskLayer->bounds().width();
+ maskTexCoordScaleY = contentRect().height() / maskLayer->contentsScaleY() / maskLayer->bounds().height();
maskTexCoordOffsetX = static_cast<float>(contentRect().x()) / contentRect().width() * maskTexCoordScaleX;
maskTexCoordOffsetY = static_cast<float>(contentRect().y()) / contentRect().height() * maskTexCoordScaleY;
}
diff --git a/cc/scrollbar_layer.cc b/cc/scrollbar_layer.cc
index baecc14..87b9e6b 100644
--- a/cc/scrollbar_layer.cc
+++ b/cc/scrollbar_layer.cc
@@ -43,7 +43,7 @@ ScrollbarLayer::~ScrollbarLayer()
void ScrollbarLayer::pushPropertiesTo(LayerImpl* layer)
{
- Layer::pushPropertiesTo(layer);
+ ContentsScalingLayer::pushPropertiesTo(layer);
ScrollbarLayerImpl* scrollbarLayer = static_cast<ScrollbarLayerImpl*>(layer);
@@ -130,16 +130,6 @@ private:
DISALLOW_COPY_AND_ASSIGN(ScrollbarBackgroundPainter);
};
-bool ScrollbarLayer::needsContentsScale() const
-{
- return true;
-}
-
-IntSize ScrollbarLayer::contentBounds() const
-{
- return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds().height() * contentsScale()));
-}
-
class ScrollbarThumbPainter : public LayerPainter {
public:
static scoped_ptr<ScrollbarThumbPainter> create(WebKit::WebScrollbar* scrollbar, WebKit::WebScrollbarThemePainter painter, WebKit::WebScrollbarThemeGeometry* geometry)
@@ -182,7 +172,7 @@ void ScrollbarLayer::setLayerTreeHost(LayerTreeHost* host)
m_thumb.reset();
}
- Layer::setLayerTreeHost(host);
+ ContentsScalingLayer::setLayerTreeHost(host);
}
void ScrollbarLayer::createUpdaterIfNeeded()
@@ -223,10 +213,8 @@ void ScrollbarLayer::updatePart(CachingBitmapContentLayerUpdater* painter, Layer
return;
// Paint and upload the entire part.
- float widthScale = static_cast<float>(contentBounds().width()) / bounds().width();
- float heightScale = static_cast<float>(contentBounds().height()) / bounds().height();
gfx::Rect paintedOpaqueRect;
- painter->prepareToUpdate(rect, rect.size(), widthScale, heightScale, paintedOpaqueRect, stats);
+ painter->prepareToUpdate(rect, rect.size(), contentsScaleX(), contentsScaleY(), paintedOpaqueRect, stats);
if (!painter->pixelsDidChange() && texture->texture()->haveBackingTexture()) {
TRACE_EVENT_INSTANT0("cc","ScrollbarLayer::updatePart no texture upload needed");
return;
@@ -236,6 +224,14 @@ void ScrollbarLayer::updatePart(CachingBitmapContentLayerUpdater* painter, Layer
texture->update(queue, rect, destOffset, false, stats);
}
+IntRect ScrollbarLayer::scrollbarLayerRectToContentRect(const WebRect& layerRect) const
+{
+ // Don't intersect with the bounds as in layerRectToContentRect() because
+ // layerRect here might be in coordinates of the containing layer.
+ FloatRect contentRect(layerRect.x, layerRect.y, layerRect.width, layerRect.height);
+ contentRect.scale(contentsScaleX(), contentsScaleY());
+ return enclosingIntRect(contentRect);
+}
void ScrollbarLayer::setTexturePriorities(const PriorityCalculator&)
{
@@ -254,7 +250,7 @@ void ScrollbarLayer::setTexturePriorities(const PriorityCalculator&)
m_foreTrack->texture()->setRequestPriority(PriorityCalculator::uiPriority(drawsToRoot));
}
if (m_thumb) {
- IntSize thumbSize = layerRectToContentRect(m_geometry->thumbRect(m_scrollbar.get())).size();
+ IntSize thumbSize = scrollbarLayerRectToContentRect(m_geometry->thumbRect(m_scrollbar.get())).size();
m_thumb->texture()->setDimensions(thumbSize, m_textureFormat);
m_thumb->texture()->setRequestPriority(PriorityCalculator::uiPriority(drawsToRoot));
}
@@ -267,15 +263,14 @@ void ScrollbarLayer::update(ResourceUpdateQueue& queue, const OcclusionTracker*,
createUpdaterIfNeeded();
- IntPoint scrollbarOrigin(m_scrollbar->location().x, m_scrollbar->location().y);
- IntRect contentRect = layerRectToContentRect(WebKit::WebRect(scrollbarOrigin.x(), scrollbarOrigin.y(), bounds().width(), bounds().height()));
+ IntRect contentRect = scrollbarLayerRectToContentRect(WebRect(m_scrollbar->location().x, m_scrollbar->location().y, bounds().width(), bounds().height()));
updatePart(m_backTrackUpdater.get(), m_backTrack.get(), contentRect, queue, stats);
if (m_foreTrack && m_foreTrackUpdater)
updatePart(m_foreTrackUpdater.get(), m_foreTrack.get(), contentRect, queue, stats);
// Consider the thumb to be at the origin when painting.
WebKit::WebRect thumbRect = m_geometry->thumbRect(m_scrollbar.get());
- IntRect originThumbRect = layerRectToContentRect(WebKit::WebRect(0, 0, thumbRect.width, thumbRect.height));
+ IntRect originThumbRect = scrollbarLayerRectToContentRect(WebRect(0, 0, thumbRect.width, thumbRect.height));
if (!originThumbRect.isEmpty())
updatePart(m_thumbUpdater.get(), m_thumb.get(), originThumbRect, queue, stats);
}
diff --git a/cc/scrollbar_layer.h b/cc/scrollbar_layer.h
index 95847a9..035d3ee 100644
--- a/cc/scrollbar_layer.h
+++ b/cc/scrollbar_layer.h
@@ -6,8 +6,8 @@
#ifndef ScrollbarLayerChromium_h
#define ScrollbarLayerChromium_h
-#include "caching_bitmap_content_layer_updater.h"
-#include "cc/layer.h"
+#include "cc/caching_bitmap_content_layer_updater.h"
+#include "cc/contents_scaling_layer.h"
#include <public/WebScrollbar.h>
#include <public/WebScrollbarThemeGeometry.h>
#include <public/WebScrollbarThemePainter.h>
@@ -18,15 +18,13 @@ class ResourceUpdateQueue;
class Scrollbar;
class ScrollbarThemeComposite;
-class ScrollbarLayer : public Layer {
+class ScrollbarLayer : public ContentsScalingLayer {
public:
virtual scoped_ptr<LayerImpl> createLayerImpl() OVERRIDE;
static scoped_refptr<ScrollbarLayer> create(scoped_ptr<WebKit::WebScrollbar>, WebKit::WebScrollbarThemePainter, scoped_ptr<WebKit::WebScrollbarThemeGeometry>, int scrollLayerId);
// Layer interface
- virtual bool needsContentsScale() const OVERRIDE;
- virtual IntSize contentBounds() const OVERRIDE;
virtual void setTexturePriorities(const PriorityCalculator&) OVERRIDE;
virtual void update(ResourceUpdateQueue&, const OcclusionTracker*, RenderingStats&) OVERRIDE;
virtual void setLayerTreeHost(LayerTreeHost*) OVERRIDE;
@@ -44,6 +42,7 @@ protected:
private:
void updatePart(CachingBitmapContentLayerUpdater*, LayerUpdater::Resource*, const IntRect&, ResourceUpdateQueue&, RenderingStats&);
void createUpdaterIfNeeded();
+ IntRect scrollbarLayerRectToContentRect(const WebKit::WebRect& layerRect) const;
scoped_ptr<WebKit::WebScrollbar> m_scrollbar;
WebKit::WebScrollbarThemePainter m_painter;
diff --git a/cc/scrollbar_layer_impl.cc b/cc/scrollbar_layer_impl.cc
index fcb8f38..180fd82 100644
--- a/cc/scrollbar_layer_impl.cc
+++ b/cc/scrollbar_layer_impl.cc
@@ -72,6 +72,15 @@ static FloatRect toUVRect(const WebRect& r, const IntRect& bounds)
static_cast<float>(r.width) / bounds.width(), static_cast<float>(r.height) / bounds.height());
}
+IntRect ScrollbarLayerImpl::scrollbarLayerRectToContentRect(const WebRect& layerRect) const
+{
+ // Don't intersect with the bounds as in layerRectToContentRect() because
+ // layerRect here might be in coordinates of the containing layer.
+ FloatRect contentRect(layerRect.x, layerRect.y, layerRect.width, layerRect.height);
+ contentRect.scale(contentsScaleX(), contentsScaleY());
+ return enclosingIntRect(contentRect);
+}
+
void ScrollbarLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuadsData)
{
bool premultipledAlpha = false;
@@ -89,7 +98,7 @@ void ScrollbarLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& append
thumbRect = WebRect();
if (m_thumbResourceId && !thumbRect.isEmpty()) {
- scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::create(sharedQuadState, layerRectToContentRect(thumbRect), m_thumbResourceId, premultipledAlpha, uvRect, flipped);
+ scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::create(sharedQuadState, scrollbarLayerRectToContentRect(thumbRect), m_thumbResourceId, premultipledAlpha, uvRect, flipped);
quad->setNeedsBlending();
quadSink.append(quad.PassAs<DrawQuad>(), appendQuadsData);
}
@@ -99,7 +108,7 @@ void ScrollbarLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& append
// We only paint the track in two parts if we were given a texture for the forward track part.
if (m_foreTrackResourceId && !foreTrackRect.isEmpty())
- quadSink.append(TextureDrawQuad::create(sharedQuadState, layerRectToContentRect(foreTrackRect), m_foreTrackResourceId, premultipledAlpha, toUVRect(foreTrackRect, boundsRect), flipped).PassAs<DrawQuad>(), appendQuadsData);
+ quadSink.append(TextureDrawQuad::create(sharedQuadState, scrollbarLayerRectToContentRect(foreTrackRect), m_foreTrackResourceId, premultipledAlpha, toUVRect(foreTrackRect, boundsRect), flipped).PassAs<DrawQuad>(), appendQuadsData);
// Order matters here: since the back track texture is being drawn to the entire contents rect, we must append it after the thumb and
// fore track quads. The back track texture contains (and displays) the buttons.
diff --git a/cc/scrollbar_layer_impl.h b/cc/scrollbar_layer_impl.h
index b44770a..5ed2281 100644
--- a/cc/scrollbar_layer_impl.h
+++ b/cc/scrollbar_layer_impl.h
@@ -77,6 +77,8 @@ private:
virtual const char* layerTypeAsString() const OVERRIDE;
+ IntRect scrollbarLayerRectToContentRect(const WebKit::WebRect& layerRect) const;
+
Scrollbar m_scrollbar;
ResourceProvider::ResourceId m_backTrackResourceId;
diff --git a/cc/test/tiled_layer_test_common.cc b/cc/test/tiled_layer_test_common.cc
index 9757617..56b3049 100644
--- a/cc/test/tiled_layer_test_common.cc
+++ b/cc/test/tiled_layer_test_common.cc
@@ -139,4 +139,19 @@ cc::IntSize FakeTiledLayerWithScaledBounds::contentBounds() const
return m_forcedContentBounds;
}
+float FakeTiledLayerWithScaledBounds::contentsScaleX() const
+{
+ return static_cast<float>(m_forcedContentBounds.width()) / bounds().width();
+}
+
+float FakeTiledLayerWithScaledBounds::contentsScaleY() const
+{
+ return static_cast<float>(m_forcedContentBounds.height()) / bounds().height();
+}
+
+void FakeTiledLayerWithScaledBounds::setContentsScale(float)
+{
+ NOTREACHED();
+}
+
} // namespace
diff --git a/cc/test/tiled_layer_test_common.h b/cc/test/tiled_layer_test_common.h
index 6c77c9d..3dac556 100644
--- a/cc/test/tiled_layer_test_common.h
+++ b/cc/test/tiled_layer_test_common.h
@@ -116,6 +116,9 @@ public:
void setContentBounds(const cc::IntSize& contentBounds) { m_forcedContentBounds = contentBounds; }
virtual cc::IntSize contentBounds() const OVERRIDE;
+ virtual float contentsScaleX() const OVERRIDE;
+ virtual float contentsScaleY() const OVERRIDE;
+ virtual void setContentsScale(float) OVERRIDE;
protected:
virtual ~FakeTiledLayerWithScaledBounds();
diff --git a/cc/tiled_layer.cc b/cc/tiled_layer.cc
index b21d911..7232042 100644
--- a/cc/tiled_layer.cc
+++ b/cc/tiled_layer.cc
@@ -84,7 +84,7 @@ private:
};
TiledLayer::TiledLayer()
- : Layer()
+ : ContentsScalingLayer()
, m_textureFormat(GL_INVALID_ENUM)
, m_skipsDraw(false)
, m_failedUpdate(false)
@@ -166,7 +166,7 @@ void TiledLayer::setBorderTexelOption(LayerTilingData::BorderTexelOption borderT
bool TiledLayer::drawsContent() const
{
- if (!Layer::drawsContent())
+ if (!ContentsScalingLayer::drawsContent())
return false;
bool hasMoreThanOneTile = m_tiler->numTilesX() > 1 || m_tiler->numTilesY() > 1;
@@ -176,16 +176,6 @@ bool TiledLayer::drawsContent() const
return true;
}
-bool TiledLayer::needsContentsScale() const
-{
- return true;
-}
-
-IntSize TiledLayer::contentBounds() const
-{
- return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds().height() * contentsScale()));
-}
-
void TiledLayer::setTilingOption(TilingOption tilingOption)
{
m_tilingOption = tilingOption;
@@ -198,7 +188,7 @@ void TiledLayer::setIsMask(bool isMask)
void TiledLayer::pushPropertiesTo(LayerImpl* layer)
{
- Layer::pushPropertiesTo(layer);
+ ContentsScalingLayer::pushPropertiesTo(layer);
TiledLayerImpl* tiledLayer = static_cast<TiledLayerImpl*>(layer);
@@ -250,7 +240,7 @@ void TiledLayer::setLayerTreeHost(LayerTreeHost* host)
tile->managedTexture()->setTextureManager(host->contentsTextureManager());
}
}
- Layer::setLayerTreeHost(host);
+ ContentsScalingLayer::setLayerTreeHost(host);
}
UpdatableTile* TiledLayer::tileAt(int i, int j) const
@@ -281,18 +271,13 @@ UpdatableTile* TiledLayer::createTile(int i, int j)
void TiledLayer::setNeedsDisplayRect(const FloatRect& dirtyRect)
{
- float contentsWidthScale = static_cast<float>(contentBounds().width()) / bounds().width();
- float contentsHeightScale = static_cast<float>(contentBounds().height()) / bounds().height();
- FloatRect scaledDirtyRect(dirtyRect);
- scaledDirtyRect.scale(contentsWidthScale, contentsHeightScale);
- IntRect dirty = enclosingIntRect(scaledDirtyRect);
- invalidateContentRect(dirty);
- Layer::setNeedsDisplayRect(dirtyRect);
+ invalidateContentRect(layerRectToContentRect(dirtyRect));
+ ContentsScalingLayer::setNeedsDisplayRect(dirtyRect);
}
void TiledLayer::setUseLCDText(bool useLCDText)
{
- Layer::setUseLCDText(useLCDText);
+ ContentsScalingLayer::setUseLCDText(useLCDText);
LayerTilingData::BorderTexelOption borderTexelOption;
#if OS(ANDROID)
diff --git a/cc/tiled_layer.h b/cc/tiled_layer.h
index c6cb541..7994d2c 100644
--- a/cc/tiled_layer.h
+++ b/cc/tiled_layer.h
@@ -5,14 +5,14 @@
#ifndef TiledLayerChromium_h
#define TiledLayerChromium_h
-#include "cc/layer.h"
+#include "cc/contents_scaling_layer.h"
#include "cc/layer_updater.h"
#include "cc/layer_tiling_data.h"
namespace cc {
class UpdatableTile;
-class TiledLayer : public Layer {
+class TiledLayer : public ContentsScalingLayer {
public:
enum TilingOption { AlwaysTile, NeverTile, AutoTile };
@@ -21,9 +21,6 @@ public:
virtual void pushPropertiesTo(LayerImpl*) OVERRIDE;
virtual bool drawsContent() const OVERRIDE;
- virtual bool needsContentsScale() const OVERRIDE;
-
- virtual IntSize contentBounds() const OVERRIDE;
virtual void setNeedsDisplayRect(const FloatRect&) OVERRIDE;
diff --git a/cc/tiled_layer_unittest.cc b/cc/tiled_layer_unittest.cc
index d219114..2b5e4bd 100644
--- a/cc/tiled_layer_unittest.cc
+++ b/cc/tiled_layer_unittest.cc
@@ -1164,9 +1164,10 @@ TEST_F(TiledLayerTest, tilesPaintedWithOcclusionAndScaling)
// a different layer space. In this case tiles are scaled to be 200x200
// pixels, which means none should be occluded.
layer->setContentsScale(0.5);
+ EXPECT_FLOAT_EQ(layer->contentsScaleX(), layer->contentsScaleY());
layer->setBounds(IntSize(600, 600));
WebTransformationMatrix drawTransform;
- drawTransform.scale(1 / layer->contentsScale());
+ drawTransform.scale(1 / layer->contentsScaleX());
layer->setDrawTransform(drawTransform);
layer->setScreenSpaceTransform(drawTransform);