[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.20-204-g221d8e8

eric at webkit.org eric at webkit.org
Wed Feb 10 22:13:42 UTC 2010


The following commit has been merged in the webkit-1.1 branch:
commit bb5cc8075da64938883a2eee95b189cfa88f058b
Author: eric at webkit.org <eric at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Feb 4 16:56:18 2010 +0000

    2010-02-04  No'am Rosenthal  <noam.rosenthal at nokia.com>
    
            Reviewed by Ariya Hidayat.
    
            [Qt] Tuning and optimizations to GraphicsLayerQt. Reduce unnecessary
            recaching, remove QTimer::singleShot and QPixmap::scaled, more
            accurate strategy of handling transform operation blends. Rotating a
            bordered-table, for example, now runs at 50FPS instead of 40FPS on Maemo5.
    
            https://bugs.webkit.org/show_bug.cgi?id=34062
    
            This is tested by https://bugs.webkit.org/show_bug.cgi?id=34450, fps measurements.
    
            * platform/graphics/qt/GraphicsLayerQt.cpp:
            (WebCore::GraphicsLayerQtImpl::flushChanges): Fine-tune caching
            (WebCore::TransformAnimationQt::TransformAnimationQt): transform bugs
            (WebCore::OpacityAnimationQt::updateState): style change
    2010-02-04  No'am Rosenthal  <noam.rosenthal at nokia.com>
    
            Reviewed by Ariya Hidayat.
    
            [Qt] Tuning and optimizations to GraphicsLayerQt. Mainly reduced usage
            of QTimer::singleShot, and moved syncLayers() from paint() to update()
            https://bugs.webkit.org/show_bug.cgi?id=34062
    
            * Api/qgraphicswebview.cpp:
            (QGraphicsWebViewPrivate::update): Moved the sync operation to update
            (QGraphicsWebView::paint): Moved the sync operation to update
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@54344 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index a43954c..f3015a0 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,21 @@
+2010-02-04  No'am Rosenthal  <noam.rosenthal at nokia.com>
+
+        Reviewed by Ariya Hidayat.
+
+        [Qt] Tuning and optimizations to GraphicsLayerQt. Reduce unnecessary
+        recaching, remove QTimer::singleShot and QPixmap::scaled, more
+        accurate strategy of handling transform operation blends. Rotating a
+        bordered-table, for example, now runs at 50FPS instead of 40FPS on Maemo5.
+
+        https://bugs.webkit.org/show_bug.cgi?id=34062
+
+        This is tested by https://bugs.webkit.org/show_bug.cgi?id=34450, fps measurements.
+
+        * platform/graphics/qt/GraphicsLayerQt.cpp:
+        (WebCore::GraphicsLayerQtImpl::flushChanges): Fine-tune caching
+        (WebCore::TransformAnimationQt::TransformAnimationQt): transform bugs
+        (WebCore::OpacityAnimationQt::updateState): style change
+
 2010-02-04  Pavel Feldman  <pfeldman at chromium.org>
 
         Reviewed by Timothy Hatcher.
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
index 5712eee..70743d8 100644
--- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
@@ -99,14 +99,26 @@ public:
     // or ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP)
     void flushChanges(bool recursive = true);
 
+    // optimization: when we have an animation running on an element with no contents, that has child-elements with contents,
+    // ALL of them have to have ItemCoordinateCache and not DeviceCoordinateCache
+    void adjustCachingRecursively(bool animationIsRunning);
+
+    // optimization: returns true if this or an ancestor has a transform animation running.
+    // this enables us to use ItemCoordinatesCache while the animation is running, otherwise we have to recache for every frame
+    bool isTransformAnimationRunning() const;
+
 public slots:
     // we need to notify the client (aka the layer compositor) when the animation actually starts
     void notifyAnimationStarted();
 
+signals:
+    // optimization: we don't want to use QTimer::singleShot
+    void notifyAnimationStartedAsync();
+
 public:
     GraphicsLayerQt* m_layer;
 
-    QTransform m_baseTransfom;
+    QTransform m_baseTransform;
     bool m_transformAnimationRunning;
     bool m_opacityAnimationRunning;
 
@@ -157,12 +169,14 @@ public:
         bool backfaceVisibility: 1;
         bool distributeOpacity: 1;
         bool align: 2;
-        State(): maskLayer(0), opacity(1), preserves3D(false), masksToBounds(false),
+        State(): maskLayer(0), opacity(1.f), preserves3D(false), masksToBounds(false),
                   drawsContent(false), contentsOpaque(false), backfaceVisibility(false),
                   distributeOpacity(false)
         {
         }
     } m_state;
+
+    friend class AnimationQtBase;
 };
 
 GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer)
@@ -171,16 +185,14 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer)
     , m_transformAnimationRunning(false)
     , m_changeMask(NoChanges)
 {
-    // better to calculate the exposed rect in QGraphicsView than over-render in WebCore
-    // FIXME: test different approaches
-    setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
-
     // we use graphics-view for compositing, not for interactivity
     setAcceptedMouseButtons(Qt::NoButton);
     setEnabled(false);
 
     // we'll set the cache when we know what's going on
     setCacheMode(NoCache);
+
+    connect(this, SIGNAL(notifyAnimationStartedAsync()), this, SLOT(notifyAnimationStarted()), Qt::QueuedConnection);
 }
 
 GraphicsLayerQtImpl::~GraphicsLayerQtImpl()
@@ -203,22 +215,42 @@ GraphicsLayerQtImpl::~GraphicsLayerQtImpl()
             delete anim;
 }
 
+void GraphicsLayerQtImpl::adjustCachingRecursively(bool animationIsRunning)
+{
+    // optimization: we make sure all our children have ItemCoordinateCache -
+    // otherwise we end up re-rendering them during the animation
+    const QList<QGraphicsItem*> children = childItems();
+
+    for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) {
+        if (QGraphicsItem* item = *it)
+            if (GraphicsLayerQtImpl* layer = qobject_cast<GraphicsLayerQtImpl*>(item->toGraphicsObject())) {
+                if (layer->m_layer->drawsContent() && layer->m_currentContent.contentType == HTMLContentType)
+                    layer->setCacheMode(animationIsRunning ? QGraphicsItem::ItemCoordinateCache : QGraphicsItem::DeviceCoordinateCache);
+            }
+    }    
+}
+
 void GraphicsLayerQtImpl::setBaseTransform(const QTransform& transform)
 {
     if (!m_layer)
         return;
-    // webkit has relative-to-size originPoint, graphics-view has a pixel originPoint
-    // here we convert
-    QPointF originTranslate(
-            m_layer->anchorPoint().x() * m_layer->size().width(), m_layer->anchorPoint().y() * m_layer->size().height());
-
-    resetTransform();
-
-    // we have to manage this ourselves because QGraphicsView's transformOrigin is incomplete
-    translate(originTranslate.x(), originTranslate.y());
+    // webkit has relative-to-size originPoint, graphics-view has a pixel originPoint, here we convert
+    // we have to manage this ourselves because QGraphicsView's transformOrigin is incompatible
+    const qreal x = m_layer->anchorPoint().x() * m_layer->size().width();
+    const qreal y = m_layer->anchorPoint().y() * m_layer->size().height();
+    setTransform(QTransform::fromTranslate(x, y));
     setTransform(transform, true);
-    translate(-originTranslate.x(), -originTranslate.y());
-    m_baseTransfom = transform;
+    translate(-x, -y);
+    m_baseTransform = transform;
+}
+
+bool GraphicsLayerQtImpl::isTransformAnimationRunning() const
+{
+    if (m_transformAnimationRunning)
+        return true;
+    if (GraphicsLayerQtImpl* parent = qobject_cast<GraphicsLayerQtImpl*>(parentObject()))
+        return parent->isTransformAnimationRunning();
+    return false;
 }
 
 QPainterPath GraphicsLayerQtImpl::opaqueArea() const
@@ -270,42 +302,31 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte
     drawContents(painter, option->exposedRect);
 }
 
-void GraphicsLayerQtImpl::drawContents(QPainter* painter, const QRectF& r, bool mask)
+void GraphicsLayerQtImpl::drawContents(QPainter* painter, const QRectF& exposedRect, bool mask)
 {
-    QRect rect = r.toAlignedRect();
-    
-    if (m_currentContent.contentType != HTMLContentType && !m_state.contentsRect.isEmpty())
-        rect = rect.intersected(m_state.contentsRect);
-
     if (m_currentContent.backgroundColor.isValid())
-        painter->fillRect(r, QColor(m_currentContent.backgroundColor));
+        painter->fillRect(exposedRect, QColor(m_currentContent.backgroundColor));
 
-    if (!rect.isEmpty()) {
-        switch (m_currentContent.contentType) {
-        case PixmapContentType:
-            // we have to scale the image to the contentsRect
-            // FIXME: a better way would probably be drawPixmap with a src/target rect
-            painter->drawPixmap(rect.topLeft(), m_currentContent.pixmap.scaled(m_state.contentsRect.size()), r);
-            break;
-        case ColorContentType:
-            painter->fillRect(rect, m_currentContent.contentsBackgroundColor);
-            break;
-        default:
-            if (m_state.drawsContent) {
-                // this is the "expensive" bit. we try to minimize calls to this
-                // neck of the woods by proper caching
-                GraphicsContext gc(painter);
-                m_layer->paintGraphicsLayerContents(gc, rect);
-            }
-            break;
+    switch (m_currentContent.contentType) {
+    case PixmapContentType:
+        painter->drawPixmap(m_state.contentsRect, m_currentContent.pixmap);
+        break;
+    case ColorContentType:
+        painter->fillRect(m_state.contentsRect, m_currentContent.contentsBackgroundColor);
+        break;
+    default:
+        if (m_state.drawsContent) {
+            // this is the "expensive" bit. we try to minimize calls to this neck of the woods by proper caching
+            GraphicsContext gc(painter);
+            m_layer->paintGraphicsLayerContents(gc, exposedRect.toAlignedRect());
         }
+        break;
     }
 }
 
 void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask)
 {
-    if (!this)
-        return;
+    Q_ASSERT(this);
 
     m_changeMask |= changeMask;
 
@@ -342,14 +363,14 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive)
         const QSet<QGraphicsItem*> currentChildren = childItems().toSet();
         const QSet<QGraphicsItem*> childrenToAdd = newChildren - currentChildren;
         const QSet<QGraphicsItem*> childrenToRemove = currentChildren - newChildren;
-        for (QSet<QGraphicsItem*>::const_iterator it = childrenToAdd.begin(); it != childrenToAdd.end(); ++it) {
+
+        for (QSet<QGraphicsItem*>::const_iterator it = childrenToAdd.begin(); it != childrenToAdd.end(); ++it)
              if (QGraphicsItem* w = *it)
                 w->setParentItem(this);
-        }
-        for (QSet<QGraphicsItem*>::const_iterator it = childrenToRemove.begin(); it != childrenToRemove.end(); ++it) {
+
+        for (QSet<QGraphicsItem*>::const_iterator it = childrenToRemove.begin(); it != childrenToRemove.end(); ++it)
              if (QGraphicsItem* w = *it)
                 w->setParentItem(0);
-        }
 
         // children are ordered by z-value, let graphics-view know.
         for (size_t i = 0; i < newChildrenVector.size(); ++i)
@@ -383,17 +404,17 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive)
         // the anchor-point, transform and size from WebCore all affect the one
         // that we give Qt
         if (m_state.transform != m_layer->transform() || m_state.anchorPoint != m_layer->anchorPoint() || m_state.size != m_layer->size())
-            setBaseTransform(QTransform(m_layer->transform()));
+            setBaseTransform(m_layer->transform());
     }
 
     if (m_changeMask & (ContentChange | DrawsContentChange)) {
         switch (m_pendingContent.contentType) {
         case PixmapContentType:
-            // we need cache even for images, because they need to be resized
-            // to the contents rect. maybe this can be optimized though
-            setCacheMode(m_transformAnimationRunning ? ItemCoordinateCache : DeviceCoordinateCache);
             update();
             setFlag(ItemHasNoContents, false);
+
+            // we only use ItemUsesExtendedStyleOption for HTML content - pixmap can be handled better with regular clipping
+            setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
             break;
 
         case ColorContentType:
@@ -403,6 +424,9 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive)
                 update();
             m_state.drawsContent = false;
             setFlag(ItemHasNoContents, false);
+
+            // we only use ItemUsesExtendedStyleOption for HTML content - colors don't gain much from that anyway
+            setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
             break;
 
         case HTMLContentType:
@@ -410,8 +434,16 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive)
                 update();
             if (!m_state.drawsContent && m_layer->drawsContent())
                 update();
-            if (m_layer->drawsContent())
-                setCacheMode(m_transformAnimationRunning ? ItemCoordinateCache : DeviceCoordinateCache);
+                if (m_layer->drawsContent()) {
+                    const QGraphicsItem::CacheMode mewCacheMode = isTransformAnimationRunning() ? ItemCoordinateCache : DeviceCoordinateCache;
+
+                    // optimization: QGraphicsItem doesn't always perform this test
+                    if (mewCacheMode != cacheMode())
+                        setCacheMode(mewCacheMode);
+
+                    // HTML content: we want to use exposedRect so we don't use WebCore rendering if we don't have to
+                    setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+                }
             else
                 setCacheMode(NoCache);
 
@@ -448,7 +480,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive)
         update();
 
     // FIXME: the following flags are currently not handled, as they don't have a clear test or are in low priority
-    // GeometryOrientationChange, ContentsOrientationChange, BackfaceVisibilityChange, ChildrenTransformChange
+    // GeometryOrientationChange, ContentsOrientationChange, BackfaceVisibilityChange, ChildrenTransformChange, Preserves3DChange
 
     m_state.maskLayer = m_layer->maskLayer();
     m_state.pos = m_layer->position();
@@ -523,9 +555,9 @@ void GraphicsLayerQt::setNeedsDisplay()
 }
 
 // reimp from GraphicsLayer.h
-void GraphicsLayerQt::setNeedsDisplayInRect(const FloatRect& r)
+void GraphicsLayerQt::setNeedsDisplayInRect(const FloatRect& rect)
 {
-    m_impl->m_pendingContent.regionToUpdate|= QRectF(r).toAlignedRect();
+    m_impl->m_pendingContent.regionToUpdate|= QRectF(rect).toAlignedRect();
     m_impl->notifyChange(GraphicsLayerQtImpl::DisplayChange);
 }
 
@@ -807,16 +839,16 @@ static inline double solveCubicBezierFunction(qreal p1x, qreal p1y, qreal p2x, q
 // Using easing-curves would probably work for some of the cases, but wouldn't really buy us anything as we'd have to convert the bezier function back to an easing curve
 static inline qreal applyTimingFunction(const TimingFunction& timingFunction, qreal progress, int duration)
 {
-    if (timingFunction.type() == LinearTimingFunction)
+        if (timingFunction.type() == LinearTimingFunction)
+            return progress;
+        if (timingFunction.type() == CubicBezierTimingFunction) {
+            return solveCubicBezierFunction(timingFunction.x1(),
+                                            timingFunction.y1(),
+                                            timingFunction.x2(),
+                                            timingFunction.y2(),
+                                            double(progress), double(duration) / 1000);
+        }
         return progress;
-    if (timingFunction.type() == CubicBezierTimingFunction) {
-        return solveCubicBezierFunction(timingFunction.x1(),
-                                        timingFunction.y1(),
-                                        timingFunction.x2(),
-                                        timingFunction.y2(),
-                                        double(progress), double(duration) / 1000);
-    }
-    return progress;
 }
 
 // helper functions to safely get a value out of WebCore's AnimationValue*
@@ -826,9 +858,7 @@ static void webkitAnimationToQtAnimationValue(const AnimationValue* animationVal
     if (!animationValue)
         return;
 
-    const TransformOperations* ops = static_cast<const TransformAnimationValue*>(animationValue)->value();
-
-    if (ops)
+    if (const TransformOperations* ops = static_cast<const TransformAnimationValue*>(animationValue)->value())
         transformOperations = *ops;
 }
 
@@ -856,8 +886,8 @@ public:
         QAbstractAnimation::updateState(newState, oldState);
 
         // for some reason I have do this asynchronously - or the animation won't work
-        if (newState == Running && oldState == Stopped)
-            QTimer::singleShot(0, m_layer.data(), SLOT(notifyAnimationStarted()));
+        if (newState == Running && oldState == Stopped && m_layer.data())
+            m_layer.data()->notifyAnimationStartedAsync();
     }
 
     virtual int duration() const { return m_duration; }
@@ -932,9 +962,10 @@ protected:
 
         // now we have a source keyframe, origin keyframe and a timing function
         // we can now process the progress and apply the frame
-        qreal normalizedProgress = (it.key() == it2.key()) ? 0 : (progress - it.key()) / (it2.key() - it.key());
-        normalizedProgress = applyTimingFunction(timingFunc, normalizedProgress, duration() / 1000);
-        applyFrame(fromValue, toValue, normalizedProgress);
+        progress = (!progress || progress == 1 || it.key() == it2.key())
+                                         ? progress
+                                         : applyTimingFunction(timingFunc, (progress - it.key()) / (it2.key() - it.key()), duration() / 1000);
+        applyFrame(fromValue, toValue, progress);
     }
 
     QMap<qreal, KeyframeValueQt<T> > m_keyframeValues;
@@ -943,7 +974,7 @@ protected:
 class TransformAnimationQt : public AnimationQt<TransformOperations> {
 public:
     TransformAnimationQt(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name)
-                : AnimationQt<TransformOperations>(layer, values, boxSize, anim, name)
+        : AnimationQt<TransformOperations>(layer, values, boxSize, anim, name)
     {
     }
 
@@ -952,7 +983,7 @@ public:
         // this came up during the compositing/animation LayoutTests
         // when the animation dies, the transform has to go back to default
         if (m_layer)
-            m_layer.data()->setBaseTransform(QTransform(m_layer.data()->m_layer->transform()));
+            m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform());
     }
 
     // the idea is that we let WebCore manage the transform-operations
@@ -963,11 +994,22 @@ public:
     {
         TransformationMatrix transformMatrix;
 
-        // this looks simple but is really tricky to get right. Use caution.
-        for (size_t i = 0; i < targetOperations.size(); ++i)
-            targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize);
-
-        m_layer.data()->setBaseTransform(QTransform(transformMatrix));
+        // sometimes the animation values from WebCore are misleading and we have to use the actual matrix as source
+        // The Mac implementation simply doesn't try to accelerate those (e.g. 360deg rotation), but we do.
+        if (progress == 1 || !targetOperations.size() || sourceOperations == targetOperations) {
+            TransformationMatrix sourceMatrix;
+            sourceOperations.apply(m_boxSize, sourceMatrix);
+            transformMatrix = m_sourceMatrix;
+            transformMatrix.blend(sourceMatrix, 1 - progress);
+        } else if (targetOperations.size() != sourceOperations.size()) {
+            transformMatrix = m_sourceMatrix;
+            targetOperations.apply(m_boxSize, transformMatrix);
+            transformMatrix.blend(m_sourceMatrix, progress);
+        } else {
+            for (size_t i = 0; i < targetOperations.size(); ++i)
+                targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize);
+        }
+        m_layer.data()->setBaseTransform(transformMatrix);
     }
 
     virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
@@ -980,15 +1022,16 @@ public:
         // to increase FPS, we use a less accurate caching mechanism while animation is going on
         // this is a UX choice that should probably be customizable
         if (newState == QAbstractAnimation::Running) {
+            m_sourceMatrix = m_layer.data()->m_layer->transform();
             m_layer.data()->m_transformAnimationRunning = true;
-            if (m_layer.data()->cacheMode() == QGraphicsItem::DeviceCoordinateCache)
-                m_layer.data()->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+            m_layer.data()->adjustCachingRecursively(true);
         } else {
             m_layer.data()->m_transformAnimationRunning = false;
-            if (m_layer.data()->cacheMode() == QGraphicsItem::ItemCoordinateCache)
-                m_layer.data()->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+            m_layer.data()->adjustCachingRecursively(false);
         }
     }
+
+    TransformationMatrix m_sourceMatrix;
 };
 
 class OpacityAnimationQt : public AnimationQt<qreal> {
@@ -1006,6 +1049,7 @@ public:
     virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
     {
         QAbstractAnimation::updateState(newState, oldState);
+
         if (m_layer)
             m_layer.data()->m_opacityAnimationRunning = (newState == QAbstractAnimation::Running);
     }
@@ -1079,11 +1123,12 @@ void GraphicsLayerQt::removeAnimationsForKeyframes(const String& name)
 void GraphicsLayerQt::pauseAnimation(const String& name, double timeOffset)
 {
     for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) {
-        if (*it) {
-            AnimationQtBase* anim = static_cast<AnimationQtBase*>((*it).data());
-            if (anim && anim->m_keyframesName == QString(name))
-                QTimer::singleShot(timeOffset * 1000, anim, SLOT(pause()));
-        }
+        if (!(*it))
+            continue;
+
+        AnimationQtBase* anim = static_cast<AnimationQtBase*>((*it).data());
+        if (anim && anim->m_keyframesName == QString(name))
+            QTimer::singleShot(timeOffset * 1000, anim, SLOT(pause()));
     }
 }
 
diff --git a/WebKit/qt/Api/qgraphicswebview.cpp b/WebKit/qt/Api/qgraphicswebview.cpp
index 8d4f3ba..b323598 100644
--- a/WebKit/qt/Api/qgraphicswebview.cpp
+++ b/WebKit/qt/Api/qgraphicswebview.cpp
@@ -27,6 +27,7 @@
 #include "qwebpage_p.h"
 #include "QWebPageClient.h"
 #include <FrameView.h>
+#include <QtCore/qmetaobject.h>
 #include <QtCore/qsharedpointer.h>
 #include <QtCore/qtimer.h>
 #include <QtGui/qapplication.h>
@@ -78,13 +79,14 @@ public:
         , page(0)
 #if USE(ACCELERATED_COMPOSITING)
         , rootGraphicsLayer(0)
-        , shouldSync(true)
+        , shouldSync(false)
 #endif
     {
 #if USE(ACCELERATED_COMPOSITING)
         // the overlay and stays alive for the lifetime of
         // this QGraphicsWebView as the scrollbars are needed when there's no compositing
         q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
+        syncMetaMethod = q->metaObject()->method(q->metaObject()->indexOfMethod("syncLayers()"));
 #endif
     }
 
@@ -131,6 +133,9 @@ public:
     // compositor telling us to do so. We'll get that call from ChromeClientQt
     bool shouldSync;
 
+    // we have to flush quite often, so we use a meta-method instead of QTimer::singleShot for putting the event in the queue
+    QMetaMethod syncMetaMethod;
+
     // we need to put the root graphics layer behind the overlay (which contains the scrollbar)
     enum { RootGraphicsLayerZValue, OverlayZValue };
 #endif
@@ -178,7 +183,7 @@ void QGraphicsWebViewPrivate::markForSync(bool scheduleSync)
 {
     shouldSync = true;
     if (scheduleSync)
-        QTimer::singleShot(0, q, SLOT(syncLayers()));
+        syncMetaMethod.invoke(q, Qt::QueuedConnection);
 }
 
 void QGraphicsWebViewPrivate::updateCompositingScrollPosition()
@@ -224,6 +229,7 @@ void QGraphicsWebViewPrivate::update(const QRect & dirtyRect)
 #if USE(ACCELERATED_COMPOSITING)
     if (overlay)
         overlay->update(QRectF(dirtyRect));
+    syncLayers();
 #endif
 }
 
@@ -442,7 +448,6 @@ void QGraphicsWebView::paint(QPainter* painter, const QStyleOptionGraphicsItem*
 {
 #if USE(ACCELERATED_COMPOSITING)
     page()->mainFrame()->render(painter, d->overlay ? QWebFrame::ContentsLayer : QWebFrame::AllLayers, option->exposedRect.toAlignedRect());
-    d->syncLayers();
 #else
     page()->mainFrame()->render(painter, QWebFrame::AllLayers, option->exposedRect.toRect());
 #endif
diff --git a/WebKit/qt/ChangeLog b/WebKit/qt/ChangeLog
index e63ee86..dbc841e 100644
--- a/WebKit/qt/ChangeLog
+++ b/WebKit/qt/ChangeLog
@@ -1,3 +1,15 @@
+2010-02-04  No'am Rosenthal  <noam.rosenthal at nokia.com>
+
+        Reviewed by Ariya Hidayat.
+
+        [Qt] Tuning and optimizations to GraphicsLayerQt. Mainly reduced usage
+        of QTimer::singleShot, and moved syncLayers() from paint() to update()
+        https://bugs.webkit.org/show_bug.cgi?id=34062
+
+        * Api/qgraphicswebview.cpp:
+        (QGraphicsWebViewPrivate::update): Moved the sync operation to update
+        (QGraphicsWebView::paint): Moved the sync operation to update
+
 2010-02-03  Andras Becsi  <abecsi at webkit.org>
 
         Unreviewed build fix.

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list