Diff
Modified: trunk/Source/WebCore/ChangeLog (120836 => 120837)
--- trunk/Source/WebCore/ChangeLog 2012-06-20 17:51:07 UTC (rev 120836)
+++ trunk/Source/WebCore/ChangeLog 2012-06-20 17:58:09 UTC (rev 120837)
@@ -1,3 +1,39 @@
+2012-06-20 Ian Vollick <[email protected]>
+
+ [chromium] Make sure that render surfaces are not pixel doubled with a device scale factor of 2
+ https://bugs.webkit.org/show_bug.cgi?id=86882
+
+ Reviewed by Adrienne Walker.
+
+ To ensure that render surfaces are not pixel doubled when device scale factor is
+ two, the render surface's owning layer's draw transform is scaled by the
+ contents scale (in the same way that the parent matrix is scaled by the device
+ scale factor). The transformedLayerRect's dimensions also need to be in pixel
+ space. The surface origin transform should not scale, but needs to offset the
+ correct number of pixels, and the replica transforms need to be modified to
+ account for the scaling.
+
+ To accomplish this, CCLayerImpl's needed to be made aware of contentsScale.
+
+ Thanks to Adrienne Walker for the computation of the replica draw transform.
+
+ Unit test: CCLayerTreeHostCommonTest.verifyRenderSurfaceTranformsInHighDPI
+
+ * platform/graphics/chromium/LayerChromium.cpp:
+ (WebCore::LayerChromium::pushPropertiesTo):
+ * platform/graphics/chromium/LayerChromium.h:
+ (LayerChromium):
+ * platform/graphics/chromium/cc/CCLayerImpl.cpp:
+ (WebCore::CCLayerImpl::CCLayerImpl):
+ * platform/graphics/chromium/cc/CCLayerImpl.h:
+ (WebCore::CCLayerImpl::setContentsScale):
+ (WebCore::CCLayerImpl::contentsScale):
+ (CCLayerImpl):
+ * platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp:
+ (WebCore::calculateDrawTransformsInternal):
+ * platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp:
+ (WebCore::CCScrollbarLayerImpl::CCScrollbar::totalSize):
+
2012-06-20 Alexis Menard <[email protected]>
[CSS3 Backgrounds and Borders] Implement box-decoration-break rendering.
Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp (120836 => 120837)
--- trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp 2012-06-20 17:51:07 UTC (rev 120836)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp 2012-06-20 17:58:09 UTC (rev 120837)
@@ -533,6 +533,7 @@
layer->setBackgroundColor(m_backgroundColor);
layer->setBounds(m_bounds);
layer->setContentBounds(contentBounds());
+ layer->setContentsScale(contentsScale());
layer->setDebugBorderColor(m_debugBorderColor);
layer->setDebugBorderWidth(m_debugBorderWidth);
layer->setDebugName(m_debugName.isolatedCopy()); // We have to use isolatedCopy() here to safely pass ownership to another thread.
Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.h (120836 => 120837)
--- trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.h 2012-06-20 17:51:07 UTC (rev 120836)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerChromium.h 2012-06-20 17:58:09 UTC (rev 120837)
@@ -85,6 +85,9 @@
virtual void setOpacityFromAnimation(float) OVERRIDE;
virtual float opacity() const OVERRIDE { return m_opacity; }
virtual void setTransformFromAnimation(const WebKit::WebTransformationMatrix&) OVERRIDE;
+ // A layer's transform operates layer space. That is, entirely in logical,
+ // non-page-scaled pixels (that is, they have page zoom baked in, but not page scale).
+ // The root layer is a special case -- it operates in physical pixels.
virtual const WebKit::WebTransformationMatrix& transform() const OVERRIDE { return m_transform; }
const LayerChromium* rootLayer() const;
@@ -106,6 +109,8 @@
void setBackgroundColor(const Color&);
Color backgroundColor() const { return m_backgroundColor; }
+ // A layer's bounds are in logical, non-page-scaled pixels (however, the
+ // root layer's bounds are in physical pixels).
void setBounds(const IntSize&);
const IntSize& bounds() const { return m_bounds; }
virtual IntSize contentBounds() const { return bounds(); }
@@ -234,14 +239,19 @@
bool screenSpaceTransformIsAnimating() const { return m_screenSpaceTransformIsAnimating; }
void setScreenSpaceTransformIsAnimating(bool animating) { m_screenSpaceTransformIsAnimating = animating; }
- // This moves from layer space, with origin in the center to target space with origin in the top left
+ // This moves from layer space, with origin in the center to target space with origin in the top left.
+ // That is, it converts from logical, non-page-scaled, to target pixels (and if the target is the
+ // root render surface, then this converts to physical pixels).
const WebKit::WebTransformationMatrix& drawTransform() const { return m_drawTransform; }
void setDrawTransform(const WebKit::WebTransformationMatrix& matrix) { m_drawTransform = matrix; }
- // This moves from layer space, with origin the top left to screen space with origin in the top left
+ // This moves from layer space, with origin the top left to screen space with origin in the top left.
+ // It converts logical, non-page-scaled pixels to physical pixels.
const WebKit::WebTransformationMatrix& screenSpaceTransform() const { return m_screenSpaceTransform; }
void setScreenSpaceTransform(const WebKit::WebTransformationMatrix& matrix) { m_screenSpaceTransform = matrix; }
const IntRect& drawableContentRect() const { return m_drawableContentRect; }
void setDrawableContentRect(const IntRect& rect) { m_drawableContentRect = rect; }
+ // The contentsScale converts from logical, non-page-scaled pixels to target pixels.
+ // The contentsScale is 1 for the root layer as it is already in physical pixels.
float contentsScale() const { return m_contentsScale; }
void setContentsScale(float);
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp (120836 => 120837)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp 2012-06-20 17:51:07 UTC (rev 120836)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp 2012-06-20 17:58:09 UTC (rev 120837)
@@ -50,6 +50,7 @@
, m_layerTreeHostImpl(0)
, m_anchorPoint(0.5, 0.5)
, m_anchorPointZ(0)
+ , m_contentsScale(1)
, m_scrollable(false)
, m_shouldScrollOnMainThread(false)
, m_haveWheelEventHandlers(false)
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h (120836 => 120837)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h 2012-06-20 17:51:07 UTC (rev 120836)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h 2012-06-20 17:58:09 UTC (rev 120837)
@@ -187,6 +187,9 @@
const IntSize& contentBounds() const { return m_contentBounds; }
void setContentBounds(const IntSize&);
+ void setContentsScale(float contentsScale) { m_contentsScale = contentsScale; }
+ float contentsScale() const { return m_contentsScale; }
+
const IntPoint& scrollPosition() const { return m_scrollPosition; }
void setScrollPosition(const IntPoint&);
@@ -305,6 +308,7 @@
float m_anchorPointZ;
IntSize m_bounds;
IntSize m_contentBounds;
+ float m_contentsScale;
IntPoint m_scrollPosition;
bool m_scrollable;
bool m_shouldScrollOnMainThread;
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp (120836 => 120837)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp 2012-06-20 17:51:07 UTC (rev 120836)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp 2012-06-20 17:58:09 UTC (rev 120837)
@@ -481,18 +481,20 @@
// When a render surface has a replica layer, that layer's transform is used to draw a second copy of the surface.
// Transforms named here are relative to the surface, unless they specify they are relative to the replica layer.
//
+ // We will denote a scale by contents scale S[contentsScale]
+ //
// The render surface origin transform to its target surface origin is:
- // M[surfaceOrigin] = M[owningLayer->Draw] * Tr[origin2center].inverse()
+ // M[surfaceOrigin] = M[owningLayer->Draw] * S[contentsScale].inverse() * Tr[origin2centerInScreenSpace].inverse()
//
// The render surface origin transform to its the root (screen space) origin is:
- // M[surface2root] = M[owningLayer->screenspace]
+ // M[surface2root] = M[owningLayer->screenspace] * S[contentsScale].inverse()
//
// The replica draw transform is:
- // M[replicaDraw] = M[surfaceOrigin] * Tr[replica->position()] * Tr[replica] * Tr[anchor2center]
- // = M[owningLayer->draw] * Tr[origin2center].inverse() * Tr[replica->position()] * Tr[replica] * Tr[anchor2clippedCenter]
+ // M[replicaDraw] = M[surfaceOrigin] * S[contentsScale] * Tr[replica->position()] * Tr[replica] * Tr[anchor2center] * S[contentsScale].inverse()
+ // = M[owningLayer->draw] * Tr[origin2center].inverse() * S[contentsScale] * Tr[replica->position()] * Tr[replica] * Tr[anchor2clippedCenter] * S[contentsScale].inverse()
//
// The replica origin transform to its target surface origin is:
- // M[replicaOrigin] = M[surfaceOrigin] * Tr[replica->position()] * Tr[replica] * Tr[origin2anchor].inverse()
+ // M[replicaOrigin] = S[contentsScale] * M[surfaceOrigin] * Tr[replica->position()] * Tr[replica] * Tr[origin2anchor].inverse() * S[contentsScale].invers()
//
// The replica origin transform to the root (screen space) origin is:
// M[replica2root] = M[surface2root] * Tr[replica->position()] * Tr[replica] * Tr[origin2anchor].inverse()
@@ -545,6 +547,8 @@
animatingTransformToScreen |= layer->parent()->screenSpaceTransformIsAnimating();
}
+ float contentsScale = layer->contentsScale();
+
FloatRect layerRect(-0.5 * layer->bounds().width(), -0.5 * layer->bounds().height(), layer->bounds().width(), layer->bounds().height());
IntRect transformedLayerRect;
@@ -568,10 +572,11 @@
// The origin of the new surface is the upper left corner of the layer.
WebTransformationMatrix drawTransform;
+ drawTransform.scale(contentsScale);
drawTransform.translate3d(0.5 * bounds.width(), 0.5 * bounds.height(), 0);
layer->setDrawTransform(drawTransform);
- transformedLayerRect = IntRect(0, 0, bounds.width(), bounds.height());
+ transformedLayerRect = IntRect(0, 0, contentsScale * bounds.width(), contentsScale * bounds.height());
// The opacity value is moved from the layer to its surface, so that the entire subtree properly inherits opacity.
renderSurface->setDrawOpacity(drawOpacity);
@@ -580,7 +585,16 @@
layer->setDrawOpacityIsAnimating(false);
WebTransformationMatrix surfaceOriginTransform = combinedTransform;
- surfaceOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0);
+ // The surfaceOriginTransform transforms points in the surface's content space
+ // to its parent's content space. Distances in these spaces are both in physical
+ // pixels, so we need to 'undo' the scale by contentsScale. Ultimately, the
+ // transform should map (0, 0) to contentsScale * position, and preserve distances.
+ // Note, the following two lines are not equivalent to translating by (bounds.width(),
+ // bounds.height). The effect on m41 and m42 would be identical, but the scale
+ // affects the entire matrix. We need to scale these other entries to avoid
+ // double scaling; we must remain in physical pixels.
+ surfaceOriginTransform.scale(1 / contentsScale);
+ surfaceOriginTransform.translate3d(-0.5 * transformedLayerRect.width(), -0.5 * transformedLayerRect.height(), 0);
renderSurface->setOriginTransform(surfaceOriginTransform);
renderSurface->setTargetSurfaceTransformsAreAnimating(animatingTransformToTarget);
@@ -761,21 +775,33 @@
drawTransform.translate3d(surfaceCenter.x() + centerOffsetDueToClipping.width(), surfaceCenter.y() + centerOffsetDueToClipping.height(), 0);
renderSurface->setDrawTransform(drawTransform);
- // The layer's origin is equal to the surface's origin so the screenSpaceTransform is the same.
- renderSurface->setScreenSpaceTransform(layer->screenSpaceTransform());
+ WebTransformationMatrix screenSpaceTransform = layer->screenSpaceTransform();
+ // The layer's screen space transform operates on layer rects, but the surfaces
+ // screen space transform operates on surface rects, which are in physical pixels,
+ // so we have to 'undo' the scale here.
+ screenSpaceTransform.scale(1 / contentsScale);
+ renderSurface->setScreenSpaceTransform(screenSpaceTransform);
if (layer->replicaLayer()) {
// Compute the transformation matrix used to draw the surface's replica to the target surface.
WebTransformationMatrix replicaDrawTransform = renderSurface->originTransform();
+
+ replicaDrawTransform.scale(contentsScale);
replicaDrawTransform.translate(layer->replicaLayer()->position().x(), layer->replicaLayer()->position().y());
replicaDrawTransform.multiply(layer->replicaLayer()->transform());
- replicaDrawTransform.translate(surfaceCenter.x() - anchorPoint.x() * bounds.width(), surfaceCenter.y() - anchorPoint.y() * bounds.height());
+ FloatPoint layerSpaceSurfaceCenter = surfaceCenter;
+ layerSpaceSurfaceCenter.scale(1 / contentsScale, 1 / contentsScale);
+ replicaDrawTransform.translate(layerSpaceSurfaceCenter.x() - anchorPoint.x() * bounds.width(), layerSpaceSurfaceCenter.y() - anchorPoint.y() * bounds.height());
+ replicaDrawTransform.scale(1 / contentsScale);
+
renderSurface->setReplicaDrawTransform(replicaDrawTransform);
WebTransformationMatrix surfaceOriginToReplicaOriginTransform;
+ surfaceOriginToReplicaOriginTransform.scale(contentsScale);
surfaceOriginToReplicaOriginTransform.translate(layer->replicaLayer()->position().x(), layer->replicaLayer()->position().y());
surfaceOriginToReplicaOriginTransform.multiply(layer->replicaLayer()->transform());
surfaceOriginToReplicaOriginTransform.translate(-anchorPoint.x() * bounds.width(), -anchorPoint.y() * bounds.height());
+ surfaceOriginToReplicaOriginTransform.scale(1 / contentsScale);
// Compute the replica's "originTransform" that maps from the replica's origin space to the target surface origin space.
WebTransformationMatrix replicaOriginTransform = layer->renderSurface()->originTransform() * surfaceOriginToReplicaOriginTransform;
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp (120836 => 120837)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp 2012-06-20 17:51:07 UTC (rev 120836)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp 2012-06-20 17:58:09 UTC (rev 120837)
@@ -200,8 +200,8 @@
// FIXME: Hardcoding the first child here is weird. Think of
// a cleaner way to get the contentBounds on the Impl side.
if (orientation() == HorizontalScrollbar)
- return m_owner->m_scrollLayer->children()[0]->contentBounds().width();
- return m_owner->m_scrollLayer->children()[0]->contentBounds().height();
+ return m_owner->m_scrollLayer->children()[0]->bounds().width();
+ return m_owner->m_scrollLayer->children()[0]->bounds().height();
}
int CCScrollbarLayerImpl::CCScrollbar::maximum() const
Modified: trunk/Source/WebKit/chromium/ChangeLog (120836 => 120837)
--- trunk/Source/WebKit/chromium/ChangeLog 2012-06-20 17:51:07 UTC (rev 120836)
+++ trunk/Source/WebKit/chromium/ChangeLog 2012-06-20 17:58:09 UTC (rev 120837)
@@ -1,3 +1,20 @@
+2012-06-20 Ian Vollick <[email protected]>
+
+ [chromium] Make sure that render surfaces are not pixel doubled with a device scale factor of 2
+ https://bugs.webkit.org/show_bug.cgi?id=86882
+
+ Reviewed by Adrienne Walker.
+
+ To ensure that render surfaces are not pixel doubled when device scale factor is
+ two, the render surface's owning layer's draw transform is scaled by the
+ contents scale (in the same way that the parent matrix is scaled by the device
+ scale factor). The transformedLayerRect's dimensions also need to be in pixel
+ space. The surface origin transform should not scale, but needs to offset the
+ correct number of pixels, and the replica transforms need to be modified to
+ account for the scaling.
+
+ * tests/CCLayerTreeHostCommonTest.cpp:
+
2012-06-20 Joshua Bell <[email protected]>
Unreviewed build fix.
Modified: trunk/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp (120836 => 120837)
--- trunk/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp 2012-06-20 17:51:07 UTC (rev 120836)
+++ trunk/Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp 2012-06-20 17:58:09 UTC (rev 120837)
@@ -28,6 +28,7 @@
#include "CCAnimationTestCommon.h"
#include "CCLayerTreeTestCommon.h"
+#include "ContentLayerChromium.h"
#include "LayerChromium.h"
#include "TranslateTransformOperation.h"
#include "cc/CCLayerAnimationController.h"
@@ -3662,6 +3663,98 @@
EXPECT_EQ(4, resultLayer->id());
}
+class MockContentLayerDelegate : public ContentLayerDelegate {
+public:
+ MockContentLayerDelegate() { }
+ virtual ~MockContentLayerDelegate() { }
+ virtual void paintContents(SkCanvas*, const IntRect& clip, IntRect& opaque) { }
+};
+
+PassRefPtr<ContentLayerChromium> createDrawableContentLayerChromium(ContentLayerDelegate* delegate)
+{
+ RefPtr<ContentLayerChromium> toReturn = ContentLayerChromium::create(delegate);
+ toReturn->setIsDrawable(true);
+ return toReturn.release();
+}
+
+TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceTranformsInHighDPI)
+{
+ MockContentLayerDelegate delegate;
+ WebTransformationMatrix identityMatrix;
+ WebTransformationMatrix parentMatrix;
+
+ RefPtr<ContentLayerChromium> parent = createDrawableContentLayerChromium(&delegate);
+ setLayerPropertiesForTesting(parent.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(30, 30), true);
+
+ RefPtr<ContentLayerChromium> child = createDrawableContentLayerChromium(&delegate);
+ setLayerPropertiesForTesting(child.get(), identityMatrix, identityMatrix, FloatPoint(0, 0), FloatPoint(2, 2), IntSize(10, 10), true);
+
+ WebTransformationMatrix replicaTransform;
+ replicaTransform.scaleNonUniform(1, -1);
+ RefPtr<ContentLayerChromium> replica = createDrawableContentLayerChromium(&delegate);
+ setLayerPropertiesForTesting(replica.get(), replicaTransform, identityMatrix, FloatPoint(0, 0), FloatPoint(2, 2), IntSize(10, 10), true);
+
+ parent->addChild(child);
+ child->setReplicaLayer(replica.get());
+
+ Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
+ Vector<RefPtr<LayerChromium> > dummyLayerList;
+ int dummyMaxTextureSize = 512;
+
+ parent->createRenderSurface();
+ parent->renderSurface()->setContentRect(IntRect(IntPoint(), parent->bounds()));
+ parent->setClipRect(IntRect(IntPoint::zero(), parent->bounds()));
+ renderSurfaceLayerList.append(parent.get());
+
+ const double deviceScaleFactor = 1.5;
+ parentMatrix.scale(deviceScaleFactor);
+ parent->setContentsScale(deviceScaleFactor);
+ child->setContentsScale(deviceScaleFactor);
+ replica->setContentsScale(deviceScaleFactor);
+
+ CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent.get(), parentMatrix, identityMatrix, renderSurfaceLayerList, dummyLayerList, dummyMaxTextureSize);
+
+ // 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 expectedDrawTransform;
+ expectedDrawTransform.setM11(deviceScaleFactor);
+ expectedDrawTransform.setM22(deviceScaleFactor);
+ expectedDrawTransform.setM41(0.5 * deviceScaleFactor * child->bounds().width());
+ expectedDrawTransform.setM42(0.5 * deviceScaleFactor * child->bounds().height());
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedDrawTransform, child->drawTransform());
+
+ WebTransformationMatrix expectedRenderSurfaceDrawTransform;
+ expectedRenderSurfaceDrawTransform.translate(deviceScaleFactor * (child->position().x() + 0.5 * child->bounds().width()), deviceScaleFactor * (child->position().y() + 0.5 * child->bounds().height()));
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedRenderSurfaceDrawTransform, child->renderSurface()->drawTransform());
+
+ WebTransformationMatrix expectedOriginTransform;
+ expectedOriginTransform.translate(deviceScaleFactor * 2, deviceScaleFactor * 2);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedOriginTransform, child->renderSurface()->originTransform());
+
+ WebTransformationMatrix expectedScreenSpaceTransform;
+ expectedScreenSpaceTransform.translate(deviceScaleFactor * 2, deviceScaleFactor * 2);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedScreenSpaceTransform, child->renderSurface()->screenSpaceTransform());
+
+ WebTransformationMatrix expectedReplicaDrawTransform;
+ expectedReplicaDrawTransform.setM22(-1);
+ expectedReplicaDrawTransform.setM41(13.5);
+ expectedReplicaDrawTransform.setM42(-1.5);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedReplicaDrawTransform, child->renderSurface()->replicaDrawTransform());
+
+ WebTransformationMatrix expectedReplicaOriginTransform = expectedReplicaDrawTransform;
+ expectedReplicaOriginTransform.setM41(6);
+ expectedReplicaOriginTransform.setM42(6);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedReplicaOriginTransform, child->renderSurface()->replicaOriginTransform());
+
+ WebTransformationMatrix expectedReplicaScreenSpaceTransform;
+ expectedReplicaScreenSpaceTransform.setM22(-1);
+ expectedReplicaScreenSpaceTransform.setM41(6);
+ expectedReplicaScreenSpaceTransform.setM42(6);
+ EXPECT_TRANSFORMATION_MATRIX_EQ(expectedReplicaScreenSpaceTransform, child->renderSurface()->replicaScreenSpaceTransform());
+}
+
TEST(CCLayerTreeHostCommonTest, verifySubtreeSearch)
{
RefPtr<LayerChromium> root = LayerChromium::create();