[GTK] Support HiDPI Properly in WebKitGtk+ with the TextureMapper
authoryoon@igalia.com <yoon@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Sep 2015 09:55:59 +0000 (09:55 +0000)
committeryoon@igalia.com <yoon@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Sep 2015 09:55:59 +0000 (09:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=141782

Reviewed by Carlos Garcia Campos.

Source/WebCore:

This patch fixes HiDPI issue in the TextureMapper.
To support HiDPI in the TextureMapper, we need to draw scaled contents
in the TextureMapperTile, and apply the global scale in the root layer
to apply transforms correctly.

Supporting the device scale is handled at LayerTreeHostGtk and
TextureMapperBackingStore, and GraphicsLayerTextureMapper doesn't handle
the device scale directly.

From the TextureMapperLayer, deviceScale and pageScale do not have to be
handled differently. These are multiplied and provided to
TextureMapperBackingStore.

* platform/graphics/texmap/TextureMapperTile.cpp:
(WebCore::TextureMapperTile::updateContents):
* platform/graphics/texmap/TextureMapperTile.h:
* platform/graphics/texmap/TextureMapperTiledBackingStore.cpp:

    Modified to increase the cover rect for tiles creation. For the image
    contents, it just creates texture with a image size, regardless of the
    contents scale.

* platform/graphics/texmap/BitmapTexture.cpp:
(WebCore::BitmapTexture::updateContents):

    Apply the device scale to the graphics context before painting contents.

* platform/graphics/texmap/GraphicsLayerTextureMapper.cpp:
(WebCore::GraphicsLayerTextureMapper::setContentsToImage):
(WebCore::GraphicsLayerTextureMapper::updateBackingStoreIfNeeded):

    Apply the device scale and the page scale to the backing store

Source/WebKit2:

* UIProcess/API/gtk/WebKitWebViewBase.cpp:
* UIProcess/gtk/RedirectedXCompositeWindow.cpp:

    Modified to create scaled size of window.

* WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp:
(WebKit::LayerTreeHostGtk::initialize):
(WebKit::LayerTreeHostGtk::deviceOrPageScaleFactorChanged):

    We should apply device scale factor to the root layer to apply
    the scale matrix before applying other transform matrices.

(WebKit::LayerTreeHostGtk::deviceScaleFactor): Added.
(WebKit::LayerTreeHostGtk::pageScaleFactor): Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@190344 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/texmap/BitmapTexture.cpp
Source/WebCore/platform/graphics/texmap/BitmapTexture.h
Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp
Source/WebCore/platform/graphics/texmap/TextureMapperTile.cpp
Source/WebCore/platform/graphics/texmap/TextureMapperTile.h
Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.cpp
Source/WebCore/platform/graphics/texmap/TextureMapperTiledBackingStore.h
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
Source/WebKit2/UIProcess/gtk/RedirectedXCompositeWindow.cpp
Source/WebKit2/UIProcess/gtk/RedirectedXCompositeWindow.h
Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp
Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.h

index 10e36da..d3df5e7 100644 (file)
@@ -1,3 +1,43 @@
+2015-09-30  Gwang Yoon Hwang  <yoon@igalia.com>
+
+        [GTK] Support HiDPI Properly in WebKitGtk+ with the TextureMapper
+        https://bugs.webkit.org/show_bug.cgi?id=141782
+
+        Reviewed by Carlos Garcia Campos.
+
+        This patch fixes HiDPI issue in the TextureMapper.
+        To support HiDPI in the TextureMapper, we need to draw scaled contents
+        in the TextureMapperTile, and apply the global scale in the root layer
+        to apply transforms correctly.
+
+        Supporting the device scale is handled at LayerTreeHostGtk and
+        TextureMapperBackingStore, and GraphicsLayerTextureMapper doesn't handle
+        the device scale directly.
+
+        From the TextureMapperLayer, deviceScale and pageScale do not have to be
+        handled differently. These are multiplied and provided to
+        TextureMapperBackingStore.
+
+        * platform/graphics/texmap/TextureMapperTile.cpp:
+        (WebCore::TextureMapperTile::updateContents):
+        * platform/graphics/texmap/TextureMapperTile.h:
+        * platform/graphics/texmap/TextureMapperTiledBackingStore.cpp:
+
+            Modified to increase the cover rect for tiles creation. For the image
+            contents, it just creates texture with a image size, regardless of the
+            contents scale.
+
+        * platform/graphics/texmap/BitmapTexture.cpp:
+        (WebCore::BitmapTexture::updateContents):
+
+            Apply the device scale to the graphics context before painting contents.
+
+        * platform/graphics/texmap/GraphicsLayerTextureMapper.cpp:
+        (WebCore::GraphicsLayerTextureMapper::setContentsToImage):
+        (WebCore::GraphicsLayerTextureMapper::updateBackingStoreIfNeeded):
+
+            Apply the device scale and the page scale to the backing store
+
 2015-09-29  Ryosuke Niwa  <rniwa@webkit.org>
 
         ASSERTION FAILED: !isUnreachableNode(m_target.get()) when hovering over any input element
index a47089f..f99e9c1 100644 (file)
@@ -33,7 +33,7 @@
 
 namespace WebCore {
 
-void BitmapTexture::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag)
+void BitmapTexture::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag, float scale)
 {
     // Making an unconditionally unaccelerated buffer here is OK because this code
     // isn't used by any platforms that respect the accelerated bit.
@@ -48,7 +48,10 @@ void BitmapTexture::updateContents(TextureMapper* textureMapper, GraphicsLayer*
 
     IntRect sourceRect(targetRect);
     sourceRect.setLocation(offset);
-    context.translate(-offset.x(), -offset.y());
+    sourceRect.scale(1 / scale);
+    context.applyDeviceScaleFactor(scale);
+    context.translate(-sourceRect.x(), -sourceRect.y());
+
     sourceLayer->paintGraphicsLayerContents(context, sourceRect);
 
     RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);
index 6625f2f..7d6172e 100644 (file)
@@ -69,7 +69,7 @@ public:
 
     virtual IntSize size() const = 0;
     virtual void updateContents(Image*, const IntRect&, const IntPoint& offset, UpdateContentsFlag) = 0;
-    virtual void updateContents(TextureMapper*, GraphicsLayer*, const IntRect& target, const IntPoint& offset, UpdateContentsFlag);
+    virtual void updateContents(TextureMapper*, GraphicsLayer*, const IntRect& target, const IntPoint& offset, UpdateContentsFlag, float scale = 1);
     virtual void updateContents(const void*, const IntRect& target, const IntPoint& offset, int bytesPerLine, UpdateContentsFlag) = 0;
     virtual bool isValid() const = 0;
     inline Flags flags() const { return m_flags; }
index d534704..501d2a8 100644 (file)
@@ -300,6 +300,7 @@ void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
         if (!m_compositedImage)
             m_compositedImage = TextureMapperTiledBackingStore::create();
         m_compositedImage->setContentsToImage(image);
+        m_compositedImage->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
     } else {
         m_compositedNativeImagePtr = nullptr;
         m_compositedImage = nullptr;
@@ -545,7 +546,9 @@ void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded()
         return;
 
     TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());
+    backingStore->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
 
+    dirtyRect.scale(pageScaleFactor() * deviceScaleFactor());
     backingStore->updateContents(textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
 
     m_needsDisplay = false;
index e6f3fe8..1bb0a4f 100644 (file)
@@ -50,7 +50,7 @@ void TextureMapperTile::updateContents(TextureMapper* textureMapper, Image* imag
     m_texture->updateContents(image, targetRect, sourceOffset, updateContentsFlag);
 }
 
-void TextureMapperTile::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag)
+void TextureMapperTile::updateContents(TextureMapper* textureMapper, GraphicsLayer* sourceLayer, const IntRect& dirtyRect, BitmapTexture::UpdateContentsFlag updateContentsFlag, float scale)
 {
     IntRect targetRect = enclosingIntRect(m_rect);
     targetRect.intersect(dirtyRect);
@@ -66,7 +66,7 @@ void TextureMapperTile::updateContents(TextureMapper* textureMapper, GraphicsLay
         m_texture->reset(targetRect.size(), BitmapTexture::SupportsAlpha);
     }
 
-    m_texture->updateContents(textureMapper, sourceLayer, targetRect, sourceOffset, updateContentsFlag);
+    m_texture->updateContents(textureMapper, sourceLayer, targetRect, sourceOffset, updateContentsFlag, scale);
 }
 
 void TextureMapperTile::paint(TextureMapper* textureMapper, const TransformationMatrix& transform, float opacity, const unsigned exposedEdges)
index 7e2212e..79d73ee 100644 (file)
@@ -40,7 +40,7 @@ public:
     inline void setRect(const FloatRect& rect) { m_rect = rect; }
 
     void updateContents(TextureMapper*, Image*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData);
-    void updateContents(TextureMapper*, GraphicsLayer*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData);
+    void updateContents(TextureMapper*, GraphicsLayer*, const IntRect&, BitmapTexture::UpdateContentsFlag UpdateCanModifyOriginalImageData, float scale = 1);
     virtual void paint(TextureMapper*, const TransformationMatrix&, float, const unsigned exposedEdges);
     virtual ~TextureMapperTile() { }
 
index 3625c14..c2985b3 100644 (file)
@@ -29,10 +29,6 @@ namespace WebCore {
 
 class GraphicsLayer;
 
-TextureMapperTiledBackingStore::TextureMapperTiledBackingStore()
-{
-}
-
 void TextureMapperTiledBackingStore::updateContentsFromImageIfNeeded(TextureMapper* textureMapper)
 {
     if (!m_image)
@@ -69,12 +65,26 @@ void TextureMapperTiledBackingStore::drawRepaintCounter(TextureMapper* textureMa
         textureMapper->drawNumber(repaintCount, borderColor, tile.rect().location(), adjustedTransform);
 }
 
+void TextureMapperTiledBackingStore::updateContentsScale(float scale)
+{
+    if (m_contentsScale == scale)
+        return;
+
+    m_isScaleDirty = true;
+    m_contentsScale = scale;
+}
+
 void TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded(const FloatSize& size, const IntSize& tileSize, bool hasAlpha)
 {
-    if (size == m_size)
+    if (size == m_size && !m_isScaleDirty)
         return;
 
     m_size = size;
+    m_isScaleDirty = false;
+
+    FloatSize scaledSize(m_size);
+    if (!m_image)
+        scaledSize.scale(m_contentsScale);
 
     Vector<FloatRect> tileRectsToAdd;
     Vector<int> tileIndicesToRemove;
@@ -82,8 +92,8 @@ void TextureMapperTiledBackingStore::createOrDestroyTilesIfNeeded(const FloatSiz
 
     // This method recycles tiles. We check which tiles we need to add, which to remove, and use as many
     // removable tiles as replacement for new tiles when possible.
-    for (float y = 0; y < m_size.height(); y += tileSize.height()) {
-        for (float x = 0; x < m_size.width(); x += tileSize.width()) {
+    for (float y = 0; y < scaledSize.height(); y += tileSize.height()) {
+        for (float x = 0; x < scaledSize.width(); x += tileSize.width()) {
             FloatRect tileRect(x, y, tileSize.width(), tileSize.height());
             tileRect.intersect(rect());
             tileRectsToAdd.append(tileRect);
@@ -147,7 +157,7 @@ void TextureMapperTiledBackingStore::updateContents(TextureMapper* textureMapper
 {
     createOrDestroyTilesIfNeeded(totalSize, textureMapper->maxTextureSize(), true);
     for (auto& tile : m_tiles)
-        tile.updateContents(textureMapper, sourceLayer, dirtyRect, updateContentsFlag);
+        tile.updateContents(textureMapper, sourceLayer, dirtyRect, updateContentsFlag, m_contentsScale);
 }
 
 RefPtr<BitmapTexture> TextureMapperTiledBackingStore::texture() const
index 4f3cce8..4be2149 100644 (file)
@@ -41,21 +41,31 @@ public:
     virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float) override;
     virtual void drawBorder(TextureMapper*, const Color&, float borderWidth, const FloatRect&, const TransformationMatrix&) override;
     virtual void drawRepaintCounter(TextureMapper*, int repaintCount, const Color&, const FloatRect&, const TransformationMatrix&) override;
+
+    void updateContentsScale(float);
     void updateContents(TextureMapper*, Image*, const FloatSize&, const IntRect&, BitmapTexture::UpdateContentsFlag);
     void updateContents(TextureMapper*, GraphicsLayer*, const FloatSize&, const IntRect&, BitmapTexture::UpdateContentsFlag);
 
     void setContentsToImage(Image* image) { m_image = image; }
 
 private:
-    TextureMapperTiledBackingStore();
+    TextureMapperTiledBackingStore() { }
+
     void createOrDestroyTilesIfNeeded(const FloatSize& backingStoreSize, const IntSize& tileSize, bool hasAlpha);
     void updateContentsFromImageIfNeeded(TextureMapper*);
     TransformationMatrix adjustedTransformForRect(const FloatRect&);
-    inline FloatRect rect() const { return FloatRect(FloatPoint::zero(), m_size); }
+    inline FloatRect rect() const
+    {
+        FloatRect rect(FloatPoint::zero(), m_size);
+        rect.scale(m_contentsScale);
+        return rect;
+    }
 
     Vector<TextureMapperTile> m_tiles;
     FloatSize m_size;
     RefPtr<Image> m_image;
+    float m_contentsScale { 1 };
+    bool m_isScaleDirty { false };
 };
 
 } // namespace WebCore
index e3d3712..bd8a90a 100644 (file)
@@ -1,3 +1,25 @@
+2015-09-30  Gwang Yoon Hwang  <yoon@igalia.com>
+
+        [GTK] Support HiDPI Properly in WebKitGtk+ with the TextureMapper
+        https://bugs.webkit.org/show_bug.cgi?id=141782
+
+        Reviewed by Carlos Garcia Campos.
+
+        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+        * UIProcess/gtk/RedirectedXCompositeWindow.cpp:
+
+            Modified to create scaled size of window.
+
+        * WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp:
+        (WebKit::LayerTreeHostGtk::initialize):
+        (WebKit::LayerTreeHostGtk::deviceOrPageScaleFactorChanged):
+
+            We should apply device scale factor to the root layer to apply
+            the scale matrix before applying other transform matrices.
+
+        (WebKit::LayerTreeHostGtk::deviceScaleFactor): Added.
+        (WebKit::LayerTreeHostGtk::pageScaleFactor): Added.
+
 2015-09-29  Daniel Bates  <dabates@apple.com>
 
         Make WebKit for iOS Simulator build with the public iOS 9 SDK
index 8bd83c4..687934a 100644 (file)
@@ -487,6 +487,7 @@ static bool webkitWebViewRenderAcceleratedCompositingResults(WebKitWebViewBase*
     if (!priv->redirectedWindow)
         return false;
 
+    priv->redirectedWindow->setDeviceScaleFactor(webViewBase->priv->pageProxy->deviceScaleFactor());
     priv->redirectedWindow->resize(drawingArea->size());
 
     if (cairo_surface_t* surface = priv->redirectedWindow->surface()) {
@@ -1063,6 +1064,10 @@ WebPageProxy* webkitWebViewBaseGetPage(WebKitWebViewBase* webkitWebViewBase)
 #if HAVE(GTK_SCALE_FACTOR)
 static void deviceScaleFactorChanged(WebKitWebViewBase* webkitWebViewBase)
 {
+#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
+    if (webkitWebViewBase->priv->redirectedWindow)
+        webkitWebViewBase->priv->redirectedWindow->setDeviceScaleFactor(webkitWebViewBase->priv->pageProxy->deviceScaleFactor());
+#endif
     webkitWebViewBase->priv->pageProxy->setIntrinsicDeviceScaleFactor(gtk_widget_get_scale_factor(GTK_WIDGET(webkitWebViewBase)));
 }
 #endif // HAVE(GTK_SCALE_FACTOR)
@@ -1339,6 +1344,7 @@ void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitW
     if (!drawingArea)
         return;
 
+    priv->redirectedWindow->setDeviceScaleFactor(webkitWebViewBase->priv->pageProxy->deviceScaleFactor());
     priv->redirectedWindow->resize(drawingArea->size());
     // Force a resize to ensure the new redirected window size is used by the WebProcess.
     drawingArea->forceResize();
index 21562cd..1b4968d 100644 (file)
@@ -29,6 +29,7 @@
 
 #if USE(REDIRECTED_XCOMPOSITE_WINDOW)
 
+#include <WebCore/CairoUtilities.h>
 #include <WebCore/PlatformDisplayX11.h>
 #include <X11/Xlib.h>
 #include <X11/extensions/Xcomposite.h>
@@ -138,6 +139,7 @@ std::unique_ptr<RedirectedXCompositeWindow> RedirectedXCompositeWindow::create(G
 RedirectedXCompositeWindow::RedirectedXCompositeWindow(GdkWindow* parentWindow, std::function<void()> damageNotify)
     : m_display(GDK_DISPLAY_XDISPLAY(gdk_window_get_display(parentWindow)))
     , m_needsNewPixmapAfterResize(false)
+    , m_deviceScale(1)
 {
     ASSERT(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native() == m_display);
     Screen* screen = DefaultScreenOfDisplay(m_display);
@@ -211,14 +213,17 @@ RedirectedXCompositeWindow::~RedirectedXCompositeWindow()
 
 void RedirectedXCompositeWindow::resize(const IntSize& size)
 {
-    if (size == m_size)
+    IntSize scaledSize(size);
+    scaledSize.scale(m_deviceScale);
+
+    if (scaledSize == m_size)
         return;
 
     // Resize the window to at last 1x1 since X doesn't allow to create empty windows.
-    XResizeWindow(m_display, m_window.get(), std::max(1, size.width()), std::max(1, size.height()));
+    XResizeWindow(m_display, m_window.get(), std::max(1, scaledSize.width()), std::max(1, scaledSize.height()));
     XFlush(m_display);
 
-    m_size = size;
+    m_size = scaledSize;
     m_needsNewPixmapAfterResize = true;
     if (m_size.isEmpty())
         cleanupPixmapAndPixmapSurface();
@@ -256,6 +261,7 @@ cairo_surface_t* RedirectedXCompositeWindow::surface()
     }
 
     RefPtr<cairo_surface_t> newSurface = adoptRef(cairo_xlib_surface_create(m_display, newPixmap.get(), windowAttributes.visual, m_size.width(), m_size.height()));
+    cairoSurfaceSetDeviceScale(newSurface.get(), m_deviceScale, m_deviceScale);
 
     // Nvidia drivers seem to prepare their redirected window pixmap asynchronously, so for a few fractions
     // of a second after each resize, while doing continuous resizing (which constantly destroys and creates
index 88a7e08..bfc2a14 100644 (file)
@@ -47,6 +47,7 @@ public:
 
     Window windowID() const { return m_window.get(); }
     void resize(const WebCore::IntSize&);
+    void setDeviceScaleFactor(float scale) { m_deviceScale = scale; }
     cairo_surface_t* surface();
 
 private:
@@ -61,6 +62,7 @@ private:
     WebCore::XUniqueDamage m_damage;
     RefPtr<cairo_surface_t> m_surface;
     bool m_needsNewPixmapAfterResize;
+    float m_deviceScale;
 };
 
 } // namespace WebKit
index c1081a1..69ef6ab 100644 (file)
@@ -98,6 +98,11 @@ void LayerTreeHostGtk::initialize()
     m_rootLayer->setDrawsContent(false);
     m_rootLayer->setSize(m_webPage->size());
 
+    m_scaleMatrix.makeIdentity();
+    m_scaleMatrix.scale(m_webPage->deviceScaleFactor() * m_webPage->pageScaleFactor());
+    downcast<GraphicsLayerTextureMapper>(*m_rootLayer).layer().setAnchorPoint(FloatPoint3D());
+    downcast<GraphicsLayerTextureMapper>(*m_rootLayer).layer().setTransform(m_scaleMatrix);
+
     // The non-composited contents are a child of the root layer.
     m_nonCompositedContentLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
     m_nonCompositedContentLayer->setDrawsContent(true);
@@ -205,6 +210,10 @@ void LayerTreeHostGtk::deviceOrPageScaleFactorChanged()
 {
     // Other layers learn of the scale factor change via WebPage::setDeviceScaleFactor.
     m_nonCompositedContentLayer->deviceOrPageScaleFactorChanged();
+
+    m_scaleMatrix.makeIdentity();
+    m_scaleMatrix.scale(m_webPage->deviceScaleFactor() * m_webPage->pageScaleFactor());
+    downcast<GraphicsLayerTextureMapper>(*m_rootLayer).layer().setTransform(m_scaleMatrix);
 }
 
 void LayerTreeHostGtk::forceRepaint()
@@ -218,6 +227,16 @@ void LayerTreeHostGtk::paintContents(const GraphicsLayer* graphicsLayer, Graphic
         m_webPage->drawRect(graphicsContext, enclosingIntRect(clipRect));
 }
 
+float LayerTreeHostGtk::deviceScaleFactor() const
+{
+    return m_webPage->deviceScaleFactor();
+}
+
+float LayerTreeHostGtk::pageScaleFactor() const
+{
+    return m_webPage->pageScaleFactor();
+}
+
 static inline bool shouldSkipNextFrameBecauseOfContinousImmediateFlushes(double current, double lastImmediateFlushTime)
 {
     // 100ms is about a perceptable delay in UI, so when scheduling layer flushes immediately for more than 100ms,
index d0acd84..9c67a67 100644 (file)
@@ -34,6 +34,7 @@
 #include "TextureMapperLayer.h"
 #include <WebCore/GLContext.h>
 #include <WebCore/GraphicsLayerClient.h>
+#include <WebCore/TransformationMatrix.h>
 #include <wtf/glib/GMainLoopSource.h>
 
 namespace WebKit {
@@ -75,6 +76,8 @@ private:
 
     // GraphicsLayerClient
     virtual void paintContents(const WebCore::GraphicsLayer*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, const WebCore::FloatRect& clipRect) override;
+    virtual float deviceScaleFactor() const override;
+    virtual float pageScaleFactor() const override;
 
     bool flushPendingLayerChanges();
 
@@ -99,6 +102,7 @@ private:
     bool m_layerFlushSchedulingEnabled;
     GMainLoopSource m_layerFlushTimerCallback;
     WebCore::GraphicsLayer* m_viewOverlayRootLayer;
+    WebCore::TransformationMatrix m_scaleMatrix;
 };
 
 } // namespace WebKit