[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.19-706-ge5415e9

oliver at apple.com oliver at apple.com
Thu Feb 4 21:33:48 UTC 2010


The following commit has been merged in the webkit-1.1 branch:
commit 5fd0dd2797e6b687370a34e62e7202aa2d1a66bc
Author: oliver at apple.com <oliver at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sun Jan 31 23:01:03 2010 +0000

    2010-01-31  Oliver Hunt  <oliver at apple.com>
    
            Reviewed by Simon Fraser.
    
            Animated scaling of background-image is too slow
            https://bugs.webkit.org/show_bug.cgi?id=33808
    
            Update checksum.
    
            * platform/mac/fast/backgrounds/size/backgroundSize16-expected.checksum:
    2010-01-31  Oliver Hunt  <oliver at apple.com>
    
            Reviewed by Simon Fraser.
    
            Animated scaling of background-image is too slow
            https://bugs.webkit.org/show_bug.cgi?id=33808
    
            Implement a version of the RenderImage animated scaling optimisation
            for background images. Due to the possibility of arbitrary transforms
            being applied to containing elements we explicitly check the current
            CTM of the context for scaling or rotation.
    
            * platform/graphics/GraphicsContext.cpp:
            (WebCore::GraphicsContext::drawTiledImage):
            * platform/graphics/GraphicsContext.h:
            * platform/graphics/transforms/TransformationMatrix.h:
            (WebCore::TransformationMatrix::isIdentityOrTranslation):
            * rendering/RenderBoxModelObject.cpp:
            (WebCore::RenderBoxModelScaleData::RenderBoxModelScaleData):
            (WebCore::RenderBoxModelScaleData::~RenderBoxModelScaleData):
            (WebCore::RenderBoxModelScaleData::hiqhQualityRepaintTimer):
            (WebCore::RenderBoxModelScaleData::size):
            (WebCore::RenderBoxModelScaleData::setSize):
            (WebCore::RenderBoxModelScaleData::lastPaintTime):
            (WebCore::RenderBoxModelScaleData::setLastPaintTime):
            (WebCore::RenderBoxModelScaleData::useLowQualityScale):
            (WebCore::RenderBoxModelScaleData::transform):
            (WebCore::RenderBoxModelScaleData::setTransform):
            (WebCore::RenderBoxModelScaleData::setUseLowQualityScale):
            (WebCore::RenderBoxModelScaleObserver::boxModelObjectDestroyed):
            (WebCore::RenderBoxModelScaleObserver::highQualityRepaintTimerFired):
            (WebCore::RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality):
            (WebCore::RenderBoxModelObject::highQualityRepaintTimerFired):
            (WebCore::RenderBoxModelObject::~RenderBoxModelObject):
            (WebCore::RenderBoxModelObject::paintFillLayerExtended):
            * rendering/RenderBoxModelObject.h:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@54113 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 14a29c6..563e660 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2010-01-31  Oliver Hunt  <oliver at apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Animated scaling of background-image is too slow
+        https://bugs.webkit.org/show_bug.cgi?id=33808
+
+        Update checksum.
+
+        * platform/mac/fast/backgrounds/size/backgroundSize16-expected.checksum:
+
 2010-01-30  Simon Fraser  <simon.fraser at apple.com>
 
         Reviewed by Adele Peterson.
diff --git a/LayoutTests/platform/mac/fast/backgrounds/size/backgroundSize16-expected.checksum b/LayoutTests/platform/mac/fast/backgrounds/size/backgroundSize16-expected.checksum
index 488349e..23f42cd 100644
--- a/LayoutTests/platform/mac/fast/backgrounds/size/backgroundSize16-expected.checksum
+++ b/LayoutTests/platform/mac/fast/backgrounds/size/backgroundSize16-expected.checksum
@@ -1 +1 @@
-22f0d818aa277e9b1f449a4dafaca35f
\ No newline at end of file
+f515f98e1fbcaff744f69733836b2b0b
\ No newline at end of file
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 52ac692..aabf53a 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,40 @@
+2010-01-31  Oliver Hunt  <oliver at apple.com>
+
+        Reviewed by Simon Fraser.
+
+        Animated scaling of background-image is too slow
+        https://bugs.webkit.org/show_bug.cgi?id=33808
+
+        Implement a version of the RenderImage animated scaling optimisation
+        for background images. Due to the possibility of arbitrary transforms
+        being applied to containing elements we explicitly check the current
+        CTM of the context for scaling or rotation.
+
+        * platform/graphics/GraphicsContext.cpp:
+        (WebCore::GraphicsContext::drawTiledImage):
+        * platform/graphics/GraphicsContext.h:
+        * platform/graphics/transforms/TransformationMatrix.h:
+        (WebCore::TransformationMatrix::isIdentityOrTranslation):
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelScaleData::RenderBoxModelScaleData):
+        (WebCore::RenderBoxModelScaleData::~RenderBoxModelScaleData):
+        (WebCore::RenderBoxModelScaleData::hiqhQualityRepaintTimer):
+        (WebCore::RenderBoxModelScaleData::size):
+        (WebCore::RenderBoxModelScaleData::setSize):
+        (WebCore::RenderBoxModelScaleData::lastPaintTime):
+        (WebCore::RenderBoxModelScaleData::setLastPaintTime):
+        (WebCore::RenderBoxModelScaleData::useLowQualityScale):
+        (WebCore::RenderBoxModelScaleData::transform):
+        (WebCore::RenderBoxModelScaleData::setTransform):
+        (WebCore::RenderBoxModelScaleData::setUseLowQualityScale):
+        (WebCore::RenderBoxModelScaleObserver::boxModelObjectDestroyed):
+        (WebCore::RenderBoxModelScaleObserver::highQualityRepaintTimerFired):
+        (WebCore::RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality):
+        (WebCore::RenderBoxModelObject::highQualityRepaintTimerFired):
+        (WebCore::RenderBoxModelObject::~RenderBoxModelObject):
+        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
+        * rendering/RenderBoxModelObject.h:
+
 2010-01-31  Dirk Schulze  <krit at webkit.org>
 
         Reviewed by Simon Fraser.
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
index 7e9ffd9..1763911 100644
--- a/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -411,24 +411,35 @@ void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const
         restore();
 }
 
-void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op)
+void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, bool useLowQualityScale)
 {
     if (paintingDisabled() || !image)
         return;
-
+    if (useLowQualityScale) {
+        save();
+        setImageInterpolationQuality(InterpolationLow);
+    }
     image->drawTiled(this, rect, srcPoint, tileSize, styleColorSpace, op);
+    if (useLowQualityScale)
+        restore();
 }
 
-void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op)
+void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op, bool useLowQualityScale)
 {
     if (paintingDisabled() || !image)
         return;
 
+    if (useLowQualityScale) {
+        save();
+        setImageInterpolationQuality(InterpolationLow);
+    }
     if (hRule == Image::StretchTile && vRule == Image::StretchTile)
         // Just do a scale.
-        return drawImage(image, styleColorSpace, dest, srcRect, op);
-
-    image->drawTiled(this, dest, srcRect, hRule, vRule, styleColorSpace, op);
+        drawImage(image, styleColorSpace, dest, srcRect, op);
+    else
+        image->drawTiled(this, dest, srcRect, hRule, vRule, styleColorSpace, op);
+    if (useLowQualityScale)
+        restore();
 }
 
 void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index ee9602f..03c706e 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -226,10 +226,10 @@ namespace WebCore {
         void drawImage(Image*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
                        CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
         void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
-                       CompositeOperator = CompositeSourceOver);
+                       CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
         void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect,
                             Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
-                            CompositeOperator = CompositeSourceOver);
+                            CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
 
         void setImageInterpolationQuality(InterpolationQuality);
         InterpolationQuality imageInterpolationQuality() const;
diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.h b/WebCore/platform/graphics/transforms/TransformationMatrix.h
index 9dd538a..9e724d5 100644
--- a/WebCore/platform/graphics/transforms/TransformationMatrix.h
+++ b/WebCore/platform/graphics/transforms/TransformationMatrix.h
@@ -323,27 +323,27 @@ public:
     operator XFORM() const;
 #endif
 
+    bool isIdentityOrTranslation() const
+    {
+        return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0
+            && m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0
+            && m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0
+            && m_matrix[3][3] == 1;
+    }
+
 private:
     // multiply passed 2D point by matrix (assume z=0)
     void multVecMatrix(double x, double y, double& dstX, double& dstY) const;
-    
+
     // multiply passed 3D point by matrix
     void multVecMatrix(double x, double y, double z, double& dstX, double& dstY, double& dstZ) const;
-    
+
     void setMatrix(const Matrix4 m)
     {
         if (m && m != m_matrix)
             memcpy(m_matrix, m, sizeof(Matrix4));
     }
-    
-    bool isIdentityOrTranslation() const
-    {
-        return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 &&
-               m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 &&
-               m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 &&
-               m_matrix[3][3] == 1;
-    }
-    
+
     Matrix4 m_matrix;
 };
 
diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp
index af94524..f2cd9bd 100644
--- a/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/WebCore/rendering/RenderBoxModelObject.cpp
@@ -33,6 +33,7 @@
 #include "RenderInline.h"
 #include "RenderLayer.h"
 #include "RenderView.h"
+#include <wtf/CurrentTime.h>
 
 using namespace std;
 
@@ -44,6 +45,140 @@ bool RenderBoxModelObject::s_wasFloating = false;
 bool RenderBoxModelObject::s_hadLayer = false;
 bool RenderBoxModelObject::s_layerWasSelfPainting = false;
 
+static const double cInterpolationCutoff = 800. * 800.;
+static const double cLowQualityTimeThreshold = 0.500; // 500 ms
+
+class RenderBoxModelScaleData : public Noncopyable {
+public:
+    RenderBoxModelScaleData(RenderBoxModelObject* object, const IntSize& size, const TransformationMatrix& transform, double time, bool lowQualityScale)
+        : m_size(size)
+        , m_transform(transform)
+        , m_lastPaintTime(time)
+        , m_lowQualityScale(lowQualityScale)
+        , m_highQualityRepaintTimer(object, &RenderBoxModelObject::highQualityRepaintTimerFired)
+    {
+    }
+
+    ~RenderBoxModelScaleData()
+    {
+        m_highQualityRepaintTimer.stop();
+    }
+
+    Timer<RenderBoxModelObject>& hiqhQualityRepaintTimer() { return m_highQualityRepaintTimer; }
+
+    const IntSize& size() const { return m_size; }
+    void setSize(const IntSize& s) { m_size = s; }
+    double lastPaintTime() const { return m_lastPaintTime; }
+    void setLastPaintTime(double t) { m_lastPaintTime = t; }
+    bool useLowQualityScale() const { return m_lowQualityScale; }
+    const TransformationMatrix& transform() const { return m_transform; }
+    void setTransform(const TransformationMatrix& transform) { m_transform = transform; }
+    void setUseLowQualityScale(bool b)
+    {
+        m_highQualityRepaintTimer.stop();
+        m_lowQualityScale = b;
+        if (b)
+            m_highQualityRepaintTimer.startOneShot(cLowQualityTimeThreshold);
+    }
+
+private:
+    IntSize m_size;
+    TransformationMatrix m_transform;
+    double m_lastPaintTime;
+    bool m_lowQualityScale;
+    Timer<RenderBoxModelObject> m_highQualityRepaintTimer;
+};
+
+class RenderBoxModelScaleObserver {
+public:
+    static bool shouldPaintBackgroundAtLowQuality(GraphicsContext*, RenderBoxModelObject*, Image*, const IntSize&);
+
+    static void boxModelObjectDestroyed(RenderBoxModelObject* object)
+    {
+        if (gBoxModelObjects) {
+            RenderBoxModelScaleData* data = gBoxModelObjects->take(object);
+            delete data;
+            if (!gBoxModelObjects->size()) {
+                delete gBoxModelObjects;
+                gBoxModelObjects = 0;
+            }
+        }
+    }
+
+    static void highQualityRepaintTimerFired(RenderBoxModelObject* object)
+    {
+        RenderBoxModelScaleObserver::boxModelObjectDestroyed(object);
+        object->repaint();
+    }
+
+    static HashMap<RenderBoxModelObject*, RenderBoxModelScaleData*>* gBoxModelObjects;
+};
+
+bool RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality(GraphicsContext* context, RenderBoxModelObject* object, Image* image, const IntSize& size)
+{
+    // If the image is not a bitmap image, then none of this is relevant and we just paint at high
+    // quality.
+    if (!image->isBitmapImage())
+        return false;
+
+    // Make sure to use the unzoomed image size, since if a full page zoom is in effect, the image
+    // is actually being scaled.
+    IntSize imageSize(image->width(), image->height());
+
+    // Look ourselves up in the hashtable.
+    RenderBoxModelScaleData* data = 0;
+    if (gBoxModelObjects)
+        data = gBoxModelObjects->get(object);
+
+    const TransformationMatrix& currentTransform = context->getCTM();
+    bool contextIsScaled = !currentTransform.isIdentityOrTranslation();
+    if (!contextIsScaled && imageSize == size) {
+        // There is no scale in effect.  If we had a scale in effect before, we can just delete this data.
+        if (data) {
+            gBoxModelObjects->remove(object);
+            delete data;
+        }
+        return false;
+    }
+
+    // There is no need to hash scaled images that always use low quality mode when the page demands it.  This is the iChat case.
+    if (object->document()->page()->inLowQualityImageInterpolationMode()) {
+        double totalPixels = static_cast<double>(image->width()) * static_cast<double>(image->height());
+        if (totalPixels > cInterpolationCutoff)
+            return true;
+    }
+
+    // If there is no data yet, we will paint the first scale at high quality and record the paint time in case a second scale happens
+    // very soon.
+    if (!data) {
+        data = new RenderBoxModelScaleData(object, size, currentTransform, currentTime(), false);
+        if (!gBoxModelObjects)
+            gBoxModelObjects = new HashMap<RenderBoxModelObject*, RenderBoxModelScaleData*>;
+        gBoxModelObjects->set(object, data);
+        return false;
+    }
+
+    // We are scaled, but we painted already at this size, so just keep using whatever mode we last painted with.
+    if ((!contextIsScaled || data->transform() == currentTransform) && data->size() == size)
+        return data->useLowQualityScale();
+
+    // We have data and our size just changed.  If this change happened quickly, go into low quality mode and then set a repaint
+    // timer to paint in high quality mode.  Otherwise it is ok to just paint in high quality mode.
+    double newTime = currentTime();
+    data->setUseLowQualityScale(newTime - data->lastPaintTime() < cLowQualityTimeThreshold);
+    data->setLastPaintTime(newTime);
+    data->setTransform(currentTransform);
+    data->setSize(size);
+    return data->useLowQualityScale();
+}
+
+HashMap<RenderBoxModelObject*, RenderBoxModelScaleData*>* RenderBoxModelScaleObserver::gBoxModelObjects = 0;
+
+void RenderBoxModelObject::highQualityRepaintTimerFired(Timer<RenderBoxModelObject>*)
+{
+    RenderBoxModelScaleObserver::highQualityRepaintTimerFired(this);
+}
+
 RenderBoxModelObject::RenderBoxModelObject(Node* node)
     : RenderObject(node)
     , m_layer(0)
@@ -55,6 +190,7 @@ RenderBoxModelObject::~RenderBoxModelObject()
     // Our layer should have been destroyed and cleared by now
     ASSERT(!hasLayer());
     ASSERT(!m_layer);
+    RenderBoxModelScaleObserver::boxModelObjectDestroyed(this);
 }
 
 void RenderBoxModelObject::destroyLayer()
@@ -307,6 +443,9 @@ int RenderBoxModelObject::paddingRight(bool) const
 void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& c, const FillLayer* bgLayer, int tx, int ty, int w, int h, InlineFlowBox* box, CompositeOperator op, RenderObject* backgroundObject)
 {
     GraphicsContext* context = paintInfo.context;
+    if (context->paintingDisabled())
+        return;
+
     bool includeLeftEdge = box ? box->includeLeftEdge() : true;
     bool includeRightEdge = box ? box->includeRightEdge() : true;
     int bLeft = includeLeftEdge ? borderLeft() : 0;
@@ -464,7 +603,9 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
             phase += destRect.location() - destOrigin;
             CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op;
             RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this;
-            context->drawTiledImage(bg->image(clientForBackgroundImage, tileSize), style()->colorSpace(), destRect, phase, tileSize, compositeOp);
+            Image* image = bg->image(clientForBackgroundImage, tileSize);
+            bool useLowQualityScaling = RenderBoxModelScaleObserver::shouldPaintBackgroundAtLowQuality(context, this, image, destRect.size());
+            context->drawTiledImage(image, style()->colorSpace(), destRect, phase, tileSize, compositeOp, useLowQualityScaling);
         }
     }
 
diff --git a/WebCore/rendering/RenderBoxModelObject.h b/WebCore/rendering/RenderBoxModelObject.h
index fae866c..db7538d 100644
--- a/WebCore/rendering/RenderBoxModelObject.h
+++ b/WebCore/rendering/RenderBoxModelObject.h
@@ -98,6 +98,8 @@ public:
     // Called by RenderObject::destroy() (and RenderWidget::destroy()) and is the only way layers should ever be destroyed
     void destroyLayer();
 
+    void highQualityRepaintTimerFired(Timer<RenderBoxModelObject>*);
+
 protected:
     void calculateBackgroundImageGeometry(const FillLayer*, int tx, int ty, int w, int h, IntRect& destRect, IntPoint& phase, IntSize& tileSize);
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list