summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);