[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.19-706-ge5415e9
hausmann at webkit.org
hausmann at webkit.org
Thu Feb 4 21:23:06 UTC 2010
The following commit has been merged in the webkit-1.1 branch:
commit f4520084c272cbca8243d3aad789f50ff8bcdf7f
Author: hausmann at webkit.org <hausmann at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Thu Jan 21 09:49:02 2010 +0000
[Qt] Implement GraphicsLayer for accelerated layer compositing
https://bugs.webkit.org/show_bug.cgi?id=33514
Patch by No'am Rosenthal <noam.rosenthal at nokia.com> on 2010-01-21
Reviewed by Antti Koivisto.
.:
* WebKit.pri: Addded compile flags to enable accelerated compositing
on versions higher than 4.5
WebCore:
No new tests: tests in LayoutTests/compositing are now relevant for
QtWebkit!
* WebCore.pro: added accelerated-compositing related files
* platform/graphics/GraphicsLayer.h: define Qt-specific implementation of GraphicsLayer
* platform/graphics/qt/GraphicsLayerQt.cpp: Added.
(WebCore::GraphicsLayerQtImpl::): Implementation of GraphicsLayer with
a QGraphicsItem
(WebCore::GraphicsLayerQtImpl::ContentData::ContentData): save
pixmap/color info for directly composited content
(WebCore::GraphicsLayerQtImpl::State::State): save info for syncing
(WebCore::GraphicsLayerQtImpl::GraphicsLayerQtImpl): ctor
(WebCore::GraphicsLayerQtImpl::~GraphicsLayerQtImpl): dtor
(WebCore::GraphicsLayerQtImpl::setBaseTransform): set Qt
transformation in the way WebCore wants it
(WebCore::GraphicsLayerQtImpl::opaqueArea): calculate opaque area
based on info we have
(WebCore::GraphicsLayerQtImpl::boundingRect): reimp QGraphicsItem
(WebCore::GraphicsLayerQtImpl::paint): reimp QGraphicsItem
(WebCore::GraphicsLayerQtImpl::drawContents): draw HTML/Pixmap/Color
(WebCore::GraphicsLayerQtImpl::notifyChange): let WebCore know
something has changed
(WebCore::GraphicsLayerQtImpl::flushChanges): Make the changes appear
on screen by setting them to QGraphicsItems
(WebCore::GraphicsLayerQtImpl::notifyAnimationStarted): let WebCore
know the QAnimation started
(WebCore::GraphicsLayerQt::GraphicsLayerQt): ctor
(WebCore::GraphicsLayerQt::~GraphicsLayerQt): dtor
(WebCore::GraphicsLayer::create): hook for WebCore to know we're
implementing compositing
(WebCore::GraphicsLayer::compositingCoordinatesOrientation): hook for
WebCore to know we use a top-down system
(WebCore::GraphicsLayerQt::setNeedsDisplay): update the display
(WebCore::GraphicsLayerQt::setNeedsDisplayInRect): udpate part of the
display
(WebCore::GraphicsLayerQt::setName): reimp
(WebCore::GraphicsLayerQt::setParent): reimp
(WebCore::GraphicsLayerQt::setChildren): reimp
(WebCore::GraphicsLayerQt::addChild): reimp
(WebCore::GraphicsLayerQt::addChildAtIndex): reimp
(WebCore::GraphicsLayerQt::addChildAbove): reimp
(WebCore::GraphicsLayerQt::addChildBelow): reimp
(WebCore::GraphicsLayerQt::replaceChild): reimp
(WebCore::GraphicsLayerQt::removeFromParent): reimp
(WebCore::GraphicsLayerQt::setMaskLayer): reimp
(WebCore::GraphicsLayerQt::setPosition): reimp
(WebCore::GraphicsLayerQt::setAnchorPoint): reimp
(WebCore::GraphicsLayerQt::setSize): reimp
(WebCore::GraphicsLayerQt::setTransform): reimp
(WebCore::GraphicsLayerQt::setChildrenTransform): reimp
(WebCore::GraphicsLayerQt::setPreserves3D): reimp
(WebCore::GraphicsLayerQt::setMasksToBounds): reimp
(WebCore::GraphicsLayerQt::setDrawsContent): reimp
(WebCore::GraphicsLayerQt::setBackgroundColor): reimp
(WebCore::GraphicsLayerQt::clearBackgroundColor): reimp
(WebCore::GraphicsLayerQt::setContentsOpaque): reimp
(WebCore::GraphicsLayerQt::setBackfaceVisibility): reimp
(WebCore::GraphicsLayerQt::setOpacity): reimp
(WebCore::GraphicsLayerQt::setContentsRect): reimp
(WebCore::GraphicsLayerQt::setContentsToImage): reimp
(WebCore::GraphicsLayerQt::setContentsBackgroundColor): reimp
(WebCore::GraphicsLayerQt::setGeometryOrientation): reimp
(WebCore::GraphicsLayerQt::setContentsOrientation): reimp
(WebCore::GraphicsLayerQt::distributeOpacity): reimp
(WebCore::GraphicsLayerQt::accumulatedOpacity): reimp
(WebCore::GraphicsLayerQt::syncCompositingState): reimp
(WebCore::GraphicsLayerQt::nativeLayer): reimp (QGraphicsItem*)
(WebCore::GraphicsLayerQt::platformLayer): reimp (QGraphicsItem*)
(WebCore::solveEpsilon): copy from AnimationBase.cpp
(WebCore::solveCubicBezierFunction): copy from AniamtionBase.cpp
(WebCore::applyTimingFunction): use WebCore's timing and not Qt's
(WebCore::webkitAnimationToQtAnimationValue): safely figure out
animation values
(WebCore::AnimationQtBase::AnimationQtBase): base class for Qt-based
Webcore-initiated animations
(WebCore::AnimationQtBase::updateState): notify when an animation
starts
(WebCore::AnimationQtBase::duration): reimp QAbstractAnimation
(WebCore::AnimationQt:::AnimationQtBase):
(WebCore::AnimationQt::updateCurrentTime): realize keyframes from
progress
(WebCore::TransformAnimationQt::TransformAnimationQt): ctor
(WebCore::TransformAnimationQt::~TransformAnimationQt): dtor
(WebCore::TransformAnimationQt::applyFrame): set the actual QTransform
based on WebCore TransformOperations
(WebCore::TransformAnimationQt::updateState): change cache mode
(WebCore::OpacityAnimationQt::OpacityAnimationQt):
(WebCore::OpacityAnimationQt::applyFrame): change item's opacity
(WebCore::OpacityAnimationQt::updateState):
(WebCore::GraphicsLayerQt::addAnimation): convert WebCore Animation to
Qt Animation
(WebCore::GraphicsLayerQt::removeAnimationsForProperty):
(WebCore::GraphicsLayerQt::removeAnimationsForKeyframes):
(WebCore::GraphicsLayerQt::pauseAnimation):
(WebCore::GraphicsLayerQt::suspendAnimations):
(WebCore::GraphicsLayerQt::resumeAnimations):
* platform/graphics/qt/GraphicsLayerQt.h: Added.
* platform/qt/QWebPageClient.h: virtual functions for QGraphicsWebView
compositing
(QWebPageClient::setRootGraphicsLayer): let QGraphicsWebView know that
compositing has started/ended
(QWebPageClient::markForSync): let QGraphicsWebView know the
compositing layers need to sync, either soon or with the next update
WebKit/qt:
Here we have the QGraphicsWebView support for accelerated compositing
* Api/qgraphicswebview.cpp:
(QGraphicsWebViewOverlay::q): access to container object
(QGraphicsWebViewOverlay::boundingRect): overlay has same rect as the
webview
(QGraphicsWebViewOverlay::paint): paint everything but the contents
(QGraphicsWebViewPrivate::QGraphicsWebViewPrivate): some vars needed
for accelerated compositing
(QGraphicsWebViewPrivate::):
(QGraphicsWebViewPrivate::~QGraphicsWebViewPrivate):
(QGraphicsWebViewPrivate::setRootGraphicsLayer): make sure we have a
scrollbar overlay, and that the new graphics layer is parented by the
web-view
(QGraphicsWebViewPrivate::markForSync): flush changes at earliest
convenience or during the next draw
(QGraphicsWebViewPrivate::updateCompositingScrollPosition): sync the
position of the compositing layer with the scroll position
(QGraphicsWebViewPrivate::syncLayers): flush changes now
(QGraphicsWebViewPrivate::scroll): make sure we also move the
compositing layer
(QGraphicsWebViewPrivate::update): also update the overlay if needed
(QGraphicsWebView::QGraphicsWebView): initialize overlay with 0
(QGraphicsWebView::paint): paint only contents if we have an overlay,
sync the compositing layers now if needed
(QGraphicsWebView::setPage): also clean up the compositing
(QGraphicsWebView::updateGeometry): also update overlay geo
(QGraphicsWebView::setGeometry): also update overlay geo
* Api/qgraphicswebview.h: reimp compositing stuff from QWebPageClient
* Api/qwebsettings.cpp: init new settings flag for compositing as
false
(QWebSettingsPrivate::apply): apply new settings flag for compositing
(QWebSettings::QWebSettings):
* Api/qwebsettings.h: new settings flag for compositing
* Api/qwebview.cpp:
(QWebView::setPage): qwebview doesn't support compositing: always false
* QGVLauncher/main.cpp:
(WebView::WebView): some more cmdline arguments + compositing
(MainWindow::init): some more cmdline arguments
(main): ditto
* WebCoreSupport/ChromeClientQt.cpp:
(WebCore::ChromeClientQt::attachRootGraphicsLayer): reimp for
accel-compositing
(WebCore::ChromeClientQt::setNeedsOneShotDrawingSynchronization):
reimp for accel compositing
(WebCore::ChromeClientQt::scheduleCompositingLayerSync): reimp for
accel compositing
* WebCoreSupport/ChromeClientQt.h: reimps for accel compositing
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@53618 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/ChangeLog b/ChangeLog
index 6b0e084..fdefebe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2010-01-21 No'am Rosenthal <noam.rosenthal at nokia.com>
+
+ Reviewed by Antti Koivisto.
+
+ [Qt] Implement GraphicsLayer for accelerated layer compositing
+ https://bugs.webkit.org/show_bug.cgi?id=33514
+
+ * WebKit.pri: Addded compile flags to enable accelerated compositing
+ on versions higher than 4.5
+
2010-01-20 Tor Arne Vestbø <tor.arne.vestbo at nokia.com>
Reviewed by Simon Hausmann.
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 9e94f0f..2eca751 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -18,6 +18,117 @@
2010-01-21 No'am Rosenthal <noam.rosenthal at nokia.com>
+ Reviewed by Antti Koivisto.
+
+ [Qt] Implement GraphicsLayer for accelerated layer compositing
+ https://bugs.webkit.org/show_bug.cgi?id=33514
+
+ No new tests: tests in LayoutTests/compositing are now relevant for
+ QtWebkit!
+
+ * WebCore.pro: added accelerated-compositing related files
+ * platform/graphics/GraphicsLayer.h: define Qt-specific implementation of GraphicsLayer
+ * platform/graphics/qt/GraphicsLayerQt.cpp: Added.
+ (WebCore::GraphicsLayerQtImpl::): Implementation of GraphicsLayer with
+ a QGraphicsItem
+ (WebCore::GraphicsLayerQtImpl::ContentData::ContentData): save
+ pixmap/color info for directly composited content
+ (WebCore::GraphicsLayerQtImpl::State::State): save info for syncing
+ (WebCore::GraphicsLayerQtImpl::GraphicsLayerQtImpl): ctor
+ (WebCore::GraphicsLayerQtImpl::~GraphicsLayerQtImpl): dtor
+ (WebCore::GraphicsLayerQtImpl::setBaseTransform): set Qt
+ transformation in the way WebCore wants it
+ (WebCore::GraphicsLayerQtImpl::opaqueArea): calculate opaque area
+ based on info we have
+ (WebCore::GraphicsLayerQtImpl::boundingRect): reimp QGraphicsItem
+ (WebCore::GraphicsLayerQtImpl::paint): reimp QGraphicsItem
+ (WebCore::GraphicsLayerQtImpl::drawContents): draw HTML/Pixmap/Color
+ (WebCore::GraphicsLayerQtImpl::notifyChange): let WebCore know
+ something has changed
+ (WebCore::GraphicsLayerQtImpl::flushChanges): Make the changes appear
+ on screen by setting them to QGraphicsItems
+ (WebCore::GraphicsLayerQtImpl::notifyAnimationStarted): let WebCore
+ know the QAnimation started
+ (WebCore::GraphicsLayerQt::GraphicsLayerQt): ctor
+ (WebCore::GraphicsLayerQt::~GraphicsLayerQt): dtor
+ (WebCore::GraphicsLayer::create): hook for WebCore to know we're
+ implementing compositing
+ (WebCore::GraphicsLayer::compositingCoordinatesOrientation): hook for
+ WebCore to know we use a top-down system
+ (WebCore::GraphicsLayerQt::setNeedsDisplay): update the display
+ (WebCore::GraphicsLayerQt::setNeedsDisplayInRect): udpate part of the
+ display
+ (WebCore::GraphicsLayerQt::setName): reimp
+ (WebCore::GraphicsLayerQt::setParent): reimp
+ (WebCore::GraphicsLayerQt::setChildren): reimp
+ (WebCore::GraphicsLayerQt::addChild): reimp
+ (WebCore::GraphicsLayerQt::addChildAtIndex): reimp
+ (WebCore::GraphicsLayerQt::addChildAbove): reimp
+ (WebCore::GraphicsLayerQt::addChildBelow): reimp
+ (WebCore::GraphicsLayerQt::replaceChild): reimp
+ (WebCore::GraphicsLayerQt::removeFromParent): reimp
+ (WebCore::GraphicsLayerQt::setMaskLayer): reimp
+ (WebCore::GraphicsLayerQt::setPosition): reimp
+ (WebCore::GraphicsLayerQt::setAnchorPoint): reimp
+ (WebCore::GraphicsLayerQt::setSize): reimp
+ (WebCore::GraphicsLayerQt::setTransform): reimp
+ (WebCore::GraphicsLayerQt::setChildrenTransform): reimp
+ (WebCore::GraphicsLayerQt::setPreserves3D): reimp
+ (WebCore::GraphicsLayerQt::setMasksToBounds): reimp
+ (WebCore::GraphicsLayerQt::setDrawsContent): reimp
+ (WebCore::GraphicsLayerQt::setBackgroundColor): reimp
+ (WebCore::GraphicsLayerQt::clearBackgroundColor): reimp
+ (WebCore::GraphicsLayerQt::setContentsOpaque): reimp
+ (WebCore::GraphicsLayerQt::setBackfaceVisibility): reimp
+ (WebCore::GraphicsLayerQt::setOpacity): reimp
+ (WebCore::GraphicsLayerQt::setContentsRect): reimp
+ (WebCore::GraphicsLayerQt::setContentsToImage): reimp
+ (WebCore::GraphicsLayerQt::setContentsBackgroundColor): reimp
+ (WebCore::GraphicsLayerQt::setGeometryOrientation): reimp
+ (WebCore::GraphicsLayerQt::setContentsOrientation): reimp
+ (WebCore::GraphicsLayerQt::distributeOpacity): reimp
+ (WebCore::GraphicsLayerQt::accumulatedOpacity): reimp
+ (WebCore::GraphicsLayerQt::syncCompositingState): reimp
+ (WebCore::GraphicsLayerQt::nativeLayer): reimp (QGraphicsItem*)
+ (WebCore::GraphicsLayerQt::platformLayer): reimp (QGraphicsItem*)
+ (WebCore::solveEpsilon): copy from AnimationBase.cpp
+ (WebCore::solveCubicBezierFunction): copy from AniamtionBase.cpp
+ (WebCore::applyTimingFunction): use WebCore's timing and not Qt's
+ (WebCore::webkitAnimationToQtAnimationValue): safely figure out
+ animation values
+ (WebCore::AnimationQtBase::AnimationQtBase): base class for Qt-based
+ Webcore-initiated animations
+ (WebCore::AnimationQtBase::updateState): notify when an animation
+ starts
+ (WebCore::AnimationQtBase::duration): reimp QAbstractAnimation
+ (WebCore::AnimationQt:::AnimationQtBase):
+ (WebCore::AnimationQt::updateCurrentTime): realize keyframes from
+ progress
+ (WebCore::TransformAnimationQt::TransformAnimationQt): ctor
+ (WebCore::TransformAnimationQt::~TransformAnimationQt): dtor
+ (WebCore::TransformAnimationQt::applyFrame): set the actual QTransform
+ based on WebCore TransformOperations
+ (WebCore::TransformAnimationQt::updateState): change cache mode
+ (WebCore::OpacityAnimationQt::OpacityAnimationQt):
+ (WebCore::OpacityAnimationQt::applyFrame): change item's opacity
+ (WebCore::OpacityAnimationQt::updateState):
+ (WebCore::GraphicsLayerQt::addAnimation): convert WebCore Animation to
+ Qt Animation
+ (WebCore::GraphicsLayerQt::removeAnimationsForProperty):
+ (WebCore::GraphicsLayerQt::removeAnimationsForKeyframes):
+ (WebCore::GraphicsLayerQt::pauseAnimation):
+ (WebCore::GraphicsLayerQt::suspendAnimations):
+ (WebCore::GraphicsLayerQt::resumeAnimations):
+ * platform/graphics/qt/GraphicsLayerQt.h: Added.
+ * platform/qt/QWebPageClient.h: virtual functions for QGraphicsWebView
+ compositing
+ (QWebPageClient::setRootGraphicsLayer): let QGraphicsWebView know that
+ compositing has started/ended
+ (QWebPageClient::markForSync): let QGraphicsWebView know the
+ compositing layers need to sync, either soon or with the next update
+
+2010-01-21 No'am Rosenthal <noam.rosenthal at nokia.com>
+
Reviewed by Simon Hausmann.
[Qt] Adding QPixmap/QImage support for the Qt hybrid layer
diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro
index 15bacde..445059d 100644
--- a/WebCore/WebCore.pro
+++ b/WebCore/WebCore.pro
@@ -2722,6 +2722,19 @@ CONFIG(standalone_package):isEqual(QT_MAJOR_VERSION, 4):greaterThan(QT_MINOR_VER
plugins/win/PaintHooks.asm
}
}
+contains(DEFINES, WTF_USE_ACCELERATED_COMPOSITING) {
+HEADERS += \
+ rendering/RenderLayerBacking.h \
+ rendering/RenderLayerCompositor.h \
+ platform/graphics/GraphicsLayer.h \
+ platform/graphics/GraphicsLayerClient.h \
+ platform/graphics/qt/GraphicsLayerQt.h
+SOURCES += \
+ platform/graphics/GraphicsLayer.cpp \
+ platform/graphics/qt/GraphicsLayerQt.cpp \
+ rendering/RenderLayerBacking.cpp \
+ rendering/RenderLayerCompositor.cpp
+}
symbian {
shared {
diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h
index 80e9378..844301e 100644
--- a/WebCore/platform/graphics/GraphicsLayer.h
+++ b/WebCore/platform/graphics/GraphicsLayer.h
@@ -59,6 +59,10 @@ class WKCACFLayer;
typedef WKCACFLayer PlatformLayer;
typedef void* NativeLayer;
}
+#elif PLATFORM(QT)
+class QGraphicsItem;
+typedef QGraphicsItem PlatformLayer;
+typedef QGraphicsItem* NativeLayer;
#else
typedef void* PlatformLayer;
typedef void* NativeLayer;
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
new file mode 100644
index 0000000..5712eee
--- /dev/null
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
@@ -0,0 +1,1118 @@
+/*
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "GraphicsLayerQt.h"
+
+#include "CurrentTime.h"
+#include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "Image.h"
+#include "RefCounted.h"
+#include "TranslateTransformOperation.h"
+#include "UnitBezier.h"
+#include <QtCore/qabstractanimation.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qset.h>
+#include <QtCore/qtimer.h>
+#include <QtGui/qbitmap.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qgraphicseffect.h>
+#include <QtGui/qgraphicsitem.h>
+#include <QtGui/qgraphicsscene.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qstyleoption.h>
+
+namespace WebCore {
+
+class GraphicsLayerQtImpl : public QGraphicsObject {
+ Q_OBJECT
+
+public:
+ // this set of flags help us defer which properties of the layer have been
+ // modified by the compositor, so we can know what to look for in the next flush
+ enum ChangeMask {
+ NoChanges = 0,
+ ChildrenChange = (1L << 1),
+ MaskLayerChange = (1L << 2),
+ PositionChange = (1L << 3),
+ AnchorPointChange = (1L << 4),
+ SizeChange = (1L << 5),
+ TransformChange = (1L << 6),
+ ContentChange = (1L << 7),
+ GeometryOrientationChange = (1L << 8),
+ ContentsOrientationChange = (1L << 9),
+ OpacityChange = (1L << 10),
+ ContentsRectChange = (1L << 11),
+ Preserves3DChange = (1L << 12),
+ MasksToBoundsChange = (1L << 13),
+ DrawsContentChange = (1L << 14),
+ ContentsOpaqueChange = (1L << 15),
+ BackfaceVisibilityChange = (1L << 16),
+ ChildrenTransformChange = (1L << 17),
+ DisplayChange = (1L << 18),
+ BackgroundColorChange = (1L << 19),
+ ParentChange = (1L << 20),
+ DistributesOpacityChange = (1L << 21)
+ };
+
+ // the compositor lets us special-case images and colors, so we try to do so
+ enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType};
+
+ GraphicsLayerQtImpl(GraphicsLayerQt* newLayer);
+ virtual ~GraphicsLayerQtImpl();
+
+ // reimps from QGraphicsItem
+ virtual QPainterPath opaqueArea() const;
+ virtual QRectF boundingRect() const;
+ virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*);
+
+ // we manage transforms ourselves because transform-origin acts differently in webkit and in Qt
+ void setBaseTransform(const QTransform&);
+ void drawContents(QPainter*, const QRectF&, bool mask = false);
+
+ // let the compositor-API tell us which properties were changed
+ void notifyChange(ChangeMask);
+
+ // called when the compositor is ready for us to show the changes on screen
+ // this is called indirectly from ChromeClientQt::setNeedsOneShotDrawingSynchronization
+ // (meaning the sync would happen together with the next draw)
+ // or ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP)
+ void flushChanges(bool recursive = true);
+
+public slots:
+ // we need to notify the client (aka the layer compositor) when the animation actually starts
+ void notifyAnimationStarted();
+
+public:
+ GraphicsLayerQt* m_layer;
+
+ QTransform m_baseTransfom;
+ bool m_transformAnimationRunning;
+ bool m_opacityAnimationRunning;
+
+ struct ContentData {
+ QPixmap pixmap;
+ QRegion regionToUpdate;
+ bool updateAll;
+ QColor contentsBackgroundColor;
+ QColor backgroundColor;
+ StaticContentType contentType;
+ float opacity;
+ ContentData()
+ : updateAll(false)
+ , contentType(HTMLContentType)
+ , opacity(1.f)
+ {
+ }
+
+ };
+
+ ContentData m_pendingContent;
+ ContentData m_currentContent;
+
+ int m_changeMask;
+
+ QSizeF m_size;
+ QList<QWeakPointer<QAbstractAnimation> > m_animations;
+ QTimer m_suspendTimer;
+
+ struct State {
+ GraphicsLayer* maskLayer;
+ FloatPoint pos;
+ FloatPoint3D anchorPoint;
+ FloatSize size;
+ TransformationMatrix transform;
+ TransformationMatrix childrenTransform;
+ Color backgroundColor;
+ Color currentColor;
+ GraphicsLayer::CompositingCoordinatesOrientation geoOrientation;
+ GraphicsLayer::CompositingCoordinatesOrientation contentsOrientation;
+ float opacity;
+ QRect contentsRect;
+
+ bool preserves3D: 1;
+ bool masksToBounds: 1;
+ bool drawsContent: 1;
+ bool contentsOpaque: 1;
+ bool backfaceVisibility: 1;
+ bool distributeOpacity: 1;
+ bool align: 2;
+ State(): maskLayer(0), opacity(1), preserves3D(false), masksToBounds(false),
+ drawsContent(false), contentsOpaque(false), backfaceVisibility(false),
+ distributeOpacity(false)
+ {
+ }
+ } m_state;
+};
+
+GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer)
+ : QGraphicsObject(0)
+ , m_layer(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);
+}
+
+GraphicsLayerQtImpl::~GraphicsLayerQtImpl()
+{
+ // the compositor manages item lifecycle - we don't want the graphics-view
+ // system to automatically delete our items
+
+ const QList<QGraphicsItem*> children = childItems();
+ for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) {
+ if (QGraphicsItem* item = *it) {
+ if (scene())
+ scene()->removeItem(item);
+ item->setParentItem(0);
+ }
+ }
+
+ // we do, however, own the animations...
+ for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_animations.begin(); it != m_animations.end(); ++it)
+ if (QAbstractAnimation* anim = it->data())
+ delete anim;
+}
+
+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());
+ setTransform(transform, true);
+ translate(-originTranslate.x(), -originTranslate.y());
+ m_baseTransfom = transform;
+}
+
+QPainterPath GraphicsLayerQtImpl::opaqueArea() const
+{
+ QPainterPath painterPath;
+ // we try out best to return the opaque area, maybe it will help graphics-view render less items
+ if (m_currentContent.backgroundColor.isValid() && m_currentContent.backgroundColor.alpha() == 0xff)
+ painterPath.addRect(boundingRect());
+ else {
+ if (m_state.contentsOpaque
+ || (m_currentContent.contentType == ColorContentType && m_currentContent.contentsBackgroundColor.alpha() == 0xff)
+ || (m_currentContent.contentType == PixmapContentType && !m_currentContent.pixmap.hasAlpha())) {
+
+ painterPath.addRect(m_state.contentsRect);
+ }
+ }
+ return painterPath;
+}
+
+QRectF GraphicsLayerQtImpl::boundingRect() const
+{
+ return QRectF(QPointF(0, 0), QSizeF(m_size));
+}
+
+void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
+{
+ if (m_state.maskLayer && m_state.maskLayer->platformLayer()) {
+ // FIXME: see if this is better done somewhere else
+ GraphicsLayerQtImpl* otherMask = static_cast<GraphicsLayerQtImpl*>(m_state.maskLayer->platformLayer());
+ otherMask->flushChanges(true);
+
+ // CSS3 mask and QGraphicsOpacityEffect are the same thing! we just need to convert...
+ // The conversion is as fast as we can make it - we render the layer once and send it to the QGraphicsOpacityEffect
+ if (!graphicsEffect()) {
+ QPixmap mask(QSize(m_state.maskLayer->size().width(), m_state.maskLayer->size().height()));
+ mask.fill(Qt::transparent);
+ {
+ QPainter p(&mask);
+ p.setRenderHints(painter->renderHints(), true);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ static_cast<GraphicsLayerQtImpl*>(m_state.maskLayer->platformLayer())->drawContents(&p, option->exposedRect, true);
+ }
+ QGraphicsOpacityEffect* opacityEffect = new QGraphicsOpacityEffect(this);
+ opacityEffect->setOpacity(1);
+ opacityEffect->setOpacityMask(QBrush(mask));
+ setGraphicsEffect(opacityEffect);
+ }
+ }
+ drawContents(painter, option->exposedRect);
+}
+
+void GraphicsLayerQtImpl::drawContents(QPainter* painter, const QRectF& r, 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));
+
+ 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;
+ }
+ }
+}
+
+void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask)
+{
+ if (!this)
+ return;
+
+ m_changeMask |= changeMask;
+
+ if (m_layer->client())
+ m_layer->client()->notifySyncRequired(m_layer);
+}
+
+void GraphicsLayerQtImpl::flushChanges(bool recursive)
+{
+ // this is the bulk of the work. understanding what the compositor is trying to achieve,
+ // what graphics-view can do, and trying to find a sane common-grounds
+ if (!m_layer || m_changeMask == NoChanges)
+ goto afterLayerChanges;
+
+ if (m_currentContent.contentType == HTMLContentType && (m_changeMask & ParentChange)) {
+ // the WebCore compositor manages item ownership. We have to make sure
+ // graphics-view doesn't try to snatch that ownership...
+ if (!m_layer->parent() && !parentItem())
+ setParentItem(0);
+ else if (m_layer && m_layer->parent() && m_layer->parent()->nativeLayer() != parentItem())
+ setParentItem(m_layer->parent()->nativeLayer());
+ }
+
+ if (m_changeMask & ChildrenChange) {
+ // we basically do an XOR operation on the list of current children
+ // and the list of wanted children, and remove/add
+ QSet<QGraphicsItem*> newChildren;
+ const Vector<GraphicsLayer*> newChildrenVector = (m_layer->children());
+ newChildren.reserve(newChildrenVector.size());
+
+ for (size_t i = 0; i < newChildrenVector.size(); ++i)
+ newChildren.insert(newChildrenVector[i]->platformLayer());
+
+ 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) {
+ if (QGraphicsItem* w = *it)
+ w->setParentItem(this);
+ }
+ 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)
+ if (newChildrenVector[i]->platformLayer())
+ newChildrenVector[i]->platformLayer()->setZValue(i);
+ }
+
+ if (m_changeMask & MaskLayerChange) {
+ // we can't paint here, because we don't know if the mask layer
+ // itself is ready... we'll have to wait till this layer tries to paint
+ setGraphicsEffect(0);
+ if (m_layer->maskLayer())
+ setFlag(ItemClipsChildrenToShape, true);
+ else
+ setFlag(ItemClipsChildrenToShape, m_layer->masksToBounds());
+ update();
+ }
+
+ if ((m_changeMask & PositionChange) && (m_layer->position() != m_state.pos))
+ setPos(m_layer->position().x(), m_layer->position().y());
+
+ if (m_changeMask & SizeChange) {
+ if (m_layer->size() != m_state.size) {
+ prepareGeometryChange();
+ m_size = QSizeF(m_layer->size().width(), m_layer->size().height());
+ }
+ }
+
+ if (m_changeMask & (TransformChange | AnchorPointChange | SizeChange)) {
+ // since we convert a percentage-based origin-point to a pixel-based one,
+ // 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()));
+ }
+
+ 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);
+ break;
+
+ case ColorContentType:
+ // no point in caching a solid-color rectangle
+ setCacheMode(QGraphicsItem::NoCache);
+ if (m_pendingContent.contentType != m_currentContent.contentType || m_pendingContent.contentsBackgroundColor != m_currentContent.contentsBackgroundColor)
+ update();
+ m_state.drawsContent = false;
+ setFlag(ItemHasNoContents, false);
+ break;
+
+ case HTMLContentType:
+ if (m_pendingContent.contentType != m_currentContent.contentType)
+ update();
+ if (!m_state.drawsContent && m_layer->drawsContent())
+ update();
+ if (m_layer->drawsContent())
+ setCacheMode(m_transformAnimationRunning ? ItemCoordinateCache : DeviceCoordinateCache);
+ else
+ setCacheMode(NoCache);
+
+ setFlag(ItemHasNoContents, !m_layer->drawsContent());
+ break;
+ }
+ }
+
+ if ((m_changeMask & OpacityChange) && m_state.opacity != m_layer->opacity())
+ setOpacity(m_layer->opacity());
+
+ if (m_changeMask & ContentsRectChange) {
+ const QRect rect(m_layer->contentsRect());
+ if (m_state.contentsRect != rect) {
+ m_state.contentsRect = rect;
+ update();
+ }
+ }
+
+ if ((m_changeMask & MasksToBoundsChange)
+ && m_state.masksToBounds != m_layer->masksToBounds()) {
+
+ setFlag(QGraphicsItem::ItemClipsToShape, m_layer->masksToBounds());
+ setFlag(QGraphicsItem::ItemClipsChildrenToShape, m_layer->masksToBounds());
+ }
+
+ if ((m_changeMask & ContentsOpaqueChange) && m_state.contentsOpaque != m_layer->contentsOpaque())
+ prepareGeometryChange();
+
+ if (m_changeMask & DisplayChange)
+ update(m_pendingContent.regionToUpdate.boundingRect());
+
+ if ((m_changeMask & BackgroundColorChange) && (m_pendingContent.backgroundColor != m_currentContent.backgroundColor))
+ 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
+
+ m_state.maskLayer = m_layer->maskLayer();
+ m_state.pos = m_layer->position();
+ m_state.anchorPoint = m_layer->anchorPoint();
+ m_state.size = m_layer->size();
+ m_state.transform = m_layer->transform();
+ m_state.geoOrientation = m_layer->geometryOrientation();
+ m_state.contentsOrientation =m_layer->contentsOrientation();
+ m_state.opacity = m_layer->opacity();
+ m_state.contentsRect = m_layer->contentsRect();
+ m_state.preserves3D = m_layer->preserves3D();
+ m_state.masksToBounds = m_layer->masksToBounds();
+ m_state.drawsContent = m_layer->drawsContent();
+ m_state.contentsOpaque = m_layer->contentsOpaque();
+ m_state.backfaceVisibility = m_layer->backfaceVisibility();
+ m_currentContent.pixmap = m_pendingContent.pixmap;
+ m_currentContent.contentType = m_pendingContent.contentType;
+ m_currentContent.backgroundColor = m_pendingContent.backgroundColor;
+ m_currentContent.regionToUpdate |= m_pendingContent.regionToUpdate;
+ m_currentContent.contentsBackgroundColor = m_pendingContent.contentsBackgroundColor;
+ m_pendingContent.regionToUpdate = QRegion();
+ m_changeMask = NoChanges;
+
+
+afterLayerChanges:
+ if (!recursive)
+ return;
+
+ 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()))
+ layer->flushChanges(true);
+ }
+}
+
+void GraphicsLayerQtImpl::notifyAnimationStarted()
+{
+ // WebCore notifies javascript when the animation starts
+ // here we're letting it know
+ m_layer->client()->notifyAnimationStarted(m_layer, WTF::currentTime());
+}
+
+GraphicsLayerQt::GraphicsLayerQt(GraphicsLayerClient* client)
+ : GraphicsLayer(client)
+ , m_impl(PassOwnPtr<GraphicsLayerQtImpl>(new GraphicsLayerQtImpl(this)))
+{
+}
+
+GraphicsLayerQt::~GraphicsLayerQt()
+{
+}
+
+// this is the hook for WebCore compositor to know that Qt implements compositing with GraphicsLayerQt
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
+{
+ return new GraphicsLayerQt(client);
+}
+
+// reimp from GraphicsLayer.h: Qt is top-down
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
+{
+ return CompositingCoordinatesTopDown;
+}
+
+// reimp from GraphicsLayer.h: we'll need to update the whole display, and we can't count on the current size because it might change
+void GraphicsLayerQt::setNeedsDisplay()
+{
+ m_impl->m_pendingContent.regionToUpdate = QRegion(QRect(QPoint(0, 0), QSize(size().width(), size().height())));
+ m_impl->notifyChange(GraphicsLayerQtImpl::DisplayChange);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setNeedsDisplayInRect(const FloatRect& r)
+{
+ m_impl->m_pendingContent.regionToUpdate|= QRectF(r).toAlignedRect();
+ m_impl->notifyChange(GraphicsLayerQtImpl::DisplayChange);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setName(const String& name)
+{
+ m_impl->setObjectName(name);
+ GraphicsLayer::setName(name);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setParent(GraphicsLayer* layer)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::ParentChange);
+ GraphicsLayer::setParent(layer);
+}
+
+// reimp from GraphicsLayer.h
+bool GraphicsLayerQt::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange);
+ return GraphicsLayer::setChildren(children);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::addChild(GraphicsLayer* layer)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange);
+ GraphicsLayer::addChild(layer);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::addChildAtIndex(GraphicsLayer* layer, int index)
+{
+ GraphicsLayer::addChildAtIndex(layer, index);
+ m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildAbove(layer, sibling);
+ m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
+{
+
+ GraphicsLayer::addChildBelow(layer, sibling);
+ m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange);
+}
+
+// reimp from GraphicsLayer.h
+bool GraphicsLayerQt::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ if (GraphicsLayer::replaceChild(oldChild, newChild)) {
+ m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange);
+ return true;
+ }
+
+ return false;
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::removeFromParent()
+{
+ if (parent())
+ m_impl->notifyChange(GraphicsLayerQtImpl::ParentChange);
+ GraphicsLayer::removeFromParent();
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setMaskLayer(GraphicsLayer* layer)
+{
+ GraphicsLayer::setMaskLayer(layer);
+ m_impl->notifyChange(GraphicsLayerQtImpl::MaskLayerChange);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setPosition(const FloatPoint& p)
+{
+ if (position() != p)
+ m_impl->notifyChange(GraphicsLayerQtImpl::PositionChange);
+ GraphicsLayer::setPosition(p);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setAnchorPoint(const FloatPoint3D& p)
+{
+ if (anchorPoint() != p)
+ m_impl->notifyChange(GraphicsLayerQtImpl::AnchorPointChange);
+ GraphicsLayer::setAnchorPoint(p);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setSize(const FloatSize& size)
+{
+ if (this->size() != size)
+ m_impl->notifyChange(GraphicsLayerQtImpl::SizeChange);
+ GraphicsLayer::setSize(size);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setTransform(const TransformationMatrix& t)
+{
+ if (!m_impl->m_transformAnimationRunning && transform() != t)
+ m_impl->notifyChange(GraphicsLayerQtImpl::TransformChange);
+ GraphicsLayer::setTransform(t);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setChildrenTransform(const TransformationMatrix& t)
+{
+ GraphicsLayer::setChildrenTransform(t);
+ m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenTransformChange);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setPreserves3D(bool b)
+{
+ if (b != preserves3D());
+ m_impl->notifyChange(GraphicsLayerQtImpl::Preserves3DChange);
+ GraphicsLayer::setPreserves3D(b);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setMasksToBounds(bool b)
+{
+ GraphicsLayer::setMasksToBounds(b);
+ m_impl->notifyChange(GraphicsLayerQtImpl::MasksToBoundsChange);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setDrawsContent(bool b)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::DrawsContentChange);
+ GraphicsLayer::setDrawsContent(b);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setBackgroundColor(const Color& c)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange);
+ m_impl->m_pendingContent.backgroundColor = c;
+ GraphicsLayer::setBackgroundColor(c);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::clearBackgroundColor()
+{
+ m_impl->m_pendingContent.backgroundColor = QColor();
+ m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange);
+ GraphicsLayer::clearBackgroundColor();
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setContentsOpaque(bool b)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::ContentsOpaqueChange);
+ GraphicsLayer::setContentsOpaque(b);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setBackfaceVisibility(bool b)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::BackfaceVisibilityChange);
+ GraphicsLayer::setBackfaceVisibility(b);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setOpacity(float o)
+{
+ if (!m_impl->m_opacityAnimationRunning && opacity() != o)
+ m_impl->notifyChange(GraphicsLayerQtImpl::OpacityChange);
+ GraphicsLayer::setOpacity(o);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setContentsRect(const IntRect& r)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::ContentsRectChange);
+ GraphicsLayer::setContentsRect(r);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setContentsToImage(Image* image)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange);
+ m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::HTMLContentType;
+ GraphicsLayer::setContentsToImage(image);
+ if (image) {
+ QPixmap* pxm = image->nativeImageForCurrentFrame();
+ if (pxm) {
+ m_impl->m_pendingContent.pixmap = *pxm;
+ m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::PixmapContentType;
+ return;
+ }
+ }
+ m_impl->m_pendingContent.pixmap = QPixmap();
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setContentsBackgroundColor(const Color& color)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange);
+ m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::ColorContentType;
+ m_impl->m_pendingContent.contentsBackgroundColor = QColor(color);
+ GraphicsLayer::setContentsBackgroundColor(color);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setGeometryOrientation(CompositingCoordinatesOrientation orientation)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::GeometryOrientationChange);
+ GraphicsLayer::setGeometryOrientation(orientation);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::setContentsOrientation(CompositingCoordinatesOrientation orientation)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::ContentsOrientationChange);
+ GraphicsLayer::setContentsOrientation(orientation);
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::distributeOpacity(float o)
+{
+ m_impl->notifyChange(GraphicsLayerQtImpl::OpacityChange);
+ m_impl->m_state.distributeOpacity = true;
+}
+
+// reimp from GraphicsLayer.h
+float GraphicsLayerQt::accumulatedOpacity() const
+{
+ return m_impl->effectiveOpacity();
+}
+
+// reimp from GraphicsLayer.h
+void GraphicsLayerQt::syncCompositingState()
+{
+ m_impl->flushChanges();
+ GraphicsLayer::syncCompositingState();
+}
+
+// reimp from GraphicsLayer.h
+NativeLayer GraphicsLayerQt::nativeLayer() const
+{
+ return m_impl.get();
+}
+
+// reimp from GraphicsLayer.h
+PlatformLayer* GraphicsLayerQt::platformLayer() const
+{
+ return m_impl.get();
+}
+
+// now we start dealing with WebCore animations translated to Qt animations
+
+template <typename T>
+struct KeyframeValueQt {
+ TimingFunction timingFunction;
+ T value;
+};
+
+// we copy this from the AnimationBase.cpp
+static inline double solveEpsilon(double duration)
+{
+ return 1.0 / (200.0 * duration);
+}
+
+static inline double solveCubicBezierFunction(qreal p1x, qreal p1y, qreal p2x, qreal p2y, double t, double duration)
+{
+ UnitBezier bezier(p1x, p1y, p2x, p2y);
+ return bezier.solve(t, solveEpsilon(duration));
+}
+
+// we want the timing function to be as close as possible to what the web-developer intended, so we're using the same function used by WebCore when compositing is disabled
+// 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)
+ 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*
+static void webkitAnimationToQtAnimationValue(const AnimationValue* animationValue, TransformOperations& transformOperations)
+{
+ transformOperations = TransformOperations();
+ if (!animationValue)
+ return;
+
+ const TransformOperations* ops = static_cast<const TransformAnimationValue*>(animationValue)->value();
+
+ if (ops)
+ transformOperations = *ops;
+}
+
+static void webkitAnimationToQtAnimationValue(const AnimationValue* animationValue, qreal& realValue)
+{
+ realValue = animationValue ? static_cast<const FloatAnimationValue*>(animationValue)->value() : 0;
+}
+
+// we put a bit of the functionality in a base class to allow casting and to save some code size
+class AnimationQtBase : public QAbstractAnimation {
+public:
+ AnimationQtBase(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name)
+ : QAbstractAnimation(0)
+ , m_layer(layer)
+ , m_boxSize(boxSize)
+ , m_duration(anim->duration() * 1000)
+ , m_isAlternate(anim->direction() == Animation::AnimationDirectionAlternate)
+ , m_webkitPropertyID(values.property())
+ , m_keyframesName(name)
+ {
+ }
+
+ virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
+ {
+ 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()));
+ }
+
+ virtual int duration() const { return m_duration; }
+
+ QWeakPointer<GraphicsLayerQtImpl> m_layer;
+ IntSize m_boxSize;
+ int m_duration;
+ bool m_isAlternate;
+ AnimatedPropertyID m_webkitPropertyID;
+ QString m_keyframesName;
+};
+
+// we'd rather have a templatized QAbstractAnimation than QPropertyAnimation / QVariantAnimation;
+// Since we know the types that we're dealing with, the QObject/QProperty/QVariant abstraction
+// buys us very little in this case, for too much overhead
+template <typename T>
+class AnimationQt : public AnimationQtBase {
+
+public:
+ AnimationQt(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name)
+ :AnimationQtBase(layer, values, boxSize, anim, name)
+ {
+ // copying those WebCore structures is not trivial, we have to do it like this
+ for (size_t i = 0; i < values.size(); ++i) {
+ const AnimationValue* animationValue = values.at(i);
+ KeyframeValueQt<T> keyframeValue;
+ if (animationValue->timingFunction())
+ keyframeValue.timingFunction = *animationValue->timingFunction();
+ webkitAnimationToQtAnimationValue(animationValue, keyframeValue.value);
+ m_keyframeValues[animationValue->keyTime()] = keyframeValue;
+ }
+ }
+
+protected:
+
+ // this is the part that differs between animated properties
+ virtual void applyFrame(const T& fromValue, const T& toValue, qreal progress) = 0;
+
+ virtual void updateCurrentTime(int currentTime)
+ {
+ if (!m_layer)
+ return;
+
+ qreal progress = qreal(currentLoopTime()) / duration();
+
+ if (m_isAlternate && currentLoop()%2)
+ progress = 1-progress;
+
+ if (m_keyframeValues.isEmpty())
+ return;
+
+ // we find the current from-to keyframes in our little map
+ typename QMap<qreal, KeyframeValueQt<T> >::iterator it = m_keyframeValues.find(progress);
+
+ // we didn't find an exact match, we try the closest match (lower bound)
+ if (it == m_keyframeValues.end())
+ it = m_keyframeValues.lowerBound(progress)-1;
+
+ // we didn't find any match - we use the first keyframe
+ if (it == m_keyframeValues.end())
+ it = m_keyframeValues.begin();
+
+ typename QMap<qreal, KeyframeValueQt<T> >::iterator it2 = it+1;
+ if (it2 == m_keyframeValues.end())
+ it2 = m_keyframeValues.begin();
+ const KeyframeValueQt<T>& fromKeyframe = it.value();
+ const KeyframeValueQt<T>& toKeyframe = it2.value();
+
+ const TimingFunction& timingFunc = fromKeyframe.timingFunction;
+ const T& fromValue = fromKeyframe.value;
+ const T& toValue = toKeyframe.value;
+
+ // 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);
+ }
+
+ QMap<qreal, KeyframeValueQt<T> > m_keyframeValues;
+};
+
+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)
+ {
+ }
+
+ ~TransformAnimationQt()
+ {
+ // 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()));
+ }
+
+ // the idea is that we let WebCore manage the transform-operations
+ // and Qt just manages the animation heartbeat and the bottom-line QTransform
+ // we get the performance not by using QTransform instead of TransformationMatrix, but by proper caching of
+ // items that are expensive for WebCore to render. We want the rest to be as close to WebCore's idea as possible.
+ virtual void applyFrame(const TransformOperations& sourceOperations, const TransformOperations& targetOperations, qreal progress)
+ {
+ 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));
+ }
+
+ virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
+ {
+ AnimationQtBase::updateState(newState, oldState);
+ if (!m_layer)
+ return;
+ m_layer.data()->flushChanges(true);
+
+ // 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_layer.data()->m_transformAnimationRunning = true;
+ if (m_layer.data()->cacheMode() == QGraphicsItem::DeviceCoordinateCache)
+ m_layer.data()->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ } else {
+ m_layer.data()->m_transformAnimationRunning = false;
+ if (m_layer.data()->cacheMode() == QGraphicsItem::ItemCoordinateCache)
+ m_layer.data()->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ }
+ }
+};
+
+class OpacityAnimationQt : public AnimationQt<qreal> {
+public:
+ OpacityAnimationQt(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name)
+ : AnimationQt<qreal>(layer, values, boxSize, anim, name)
+ {
+ }
+
+ virtual void applyFrame(const qreal& fromValue, const qreal& toValue, qreal progress)
+ {
+ m_layer.data()->setOpacity(qMin<qreal>(qMax<qreal>(fromValue + (toValue-fromValue)*progress, 0), 1));
+ }
+
+ virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
+ {
+ QAbstractAnimation::updateState(newState, oldState);
+ if (m_layer)
+ m_layer.data()->m_opacityAnimationRunning = (newState == QAbstractAnimation::Running);
+ }
+};
+
+bool GraphicsLayerQt::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
+{
+ if (!anim->duration() || !anim->iterationCount())
+ return false;
+
+ QAbstractAnimation* newAnim;
+
+ switch (values.property()) {
+ case AnimatedPropertyOpacity:
+ newAnim = new OpacityAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName);
+ break;
+ case AnimatedPropertyWebkitTransform:
+ newAnim = new TransformAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName);
+ break;
+ default:
+ return false;
+ }
+
+ // we make sure WebCore::Animation and QAnimation are on the same terms
+ newAnim->setLoopCount(anim->iterationCount());
+ m_impl->m_animations.append(QWeakPointer<QAbstractAnimation>(newAnim));
+ QObject::connect(&m_impl->m_suspendTimer, SIGNAL(timeout()), newAnim, SLOT(resume()));
+ timeOffset += anim->delay();
+
+ // flush now or flicker...
+ m_impl->flushChanges(false);
+
+ if (timeOffset)
+ QTimer::singleShot(timeOffset * 1000, newAnim, SLOT(start()));
+ else
+ newAnim->start();
+
+ QObject::connect(newAnim, SIGNAL(finished()), newAnim, SLOT(deleteLater()));
+
+ return true;
+}
+
+void GraphicsLayerQt::removeAnimationsForProperty(AnimatedPropertyID id)
+{
+ 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_webkitPropertyID == id) {
+ delete anim;
+ it = m_impl->m_animations.erase(it);
+ --it;
+ }
+ }
+ }
+}
+
+void GraphicsLayerQt::removeAnimationsForKeyframes(const String& name)
+{
+ 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)) {
+ (*it).data()->deleteLater();
+ it = m_impl->m_animations.erase(it);
+ --it;
+ }
+ }
+ }
+}
+
+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()));
+ }
+ }
+}
+
+void GraphicsLayerQt::suspendAnimations(double time)
+{
+ if (m_impl->m_suspendTimer.isActive()) {
+ m_impl->m_suspendTimer.stop();
+ m_impl->m_suspendTimer.start(time * 1000);
+ } else {
+ for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) {
+ QAbstractAnimation* anim = it->data();
+ if (anim)
+ anim->pause();
+ }
+ }
+}
+
+void GraphicsLayerQt::resumeAnimations()
+{
+ if (m_impl->m_suspendTimer.isActive()) {
+ m_impl->m_suspendTimer.stop();
+ for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) {
+ QAbstractAnimation* anim = (*it).data();
+ if (anim)
+ anim->resume();
+ }
+ }
+}
+
+}
+
+#include <GraphicsLayerQt.moc>
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/WebCore/platform/graphics/qt/GraphicsLayerQt.h
new file mode 100644
index 0000000..3a53bd9
--- /dev/null
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.h
@@ -0,0 +1,85 @@
+/*
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef GraphicsLayerQt_h
+#define GraphicsLayerQt_h
+
+#include "GraphicsLayer.h"
+#include "GraphicsLayerClient.h"
+
+namespace WebCore {
+
+class GraphicsLayerQtImpl;
+
+class GraphicsLayerQt : public GraphicsLayer {
+ friend class GraphicsLayerQtImpl;
+
+public:
+ GraphicsLayerQt(GraphicsLayerClient*);
+ virtual ~GraphicsLayerQt();
+
+ // reimps from GraphicsLayer.h
+ virtual NativeLayer nativeLayer() const;
+ virtual PlatformLayer* platformLayer() const;
+ virtual void setNeedsDisplay();
+ virtual void setNeedsDisplayInRect(const FloatRect&);
+ virtual void setParent(GraphicsLayer* layer);
+ virtual void setName(const String& name);
+ virtual bool setChildren(const Vector<GraphicsLayer*>&);
+ virtual void addChild(GraphicsLayer*);
+ virtual void addChildAtIndex(GraphicsLayer*, int index);
+ virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling);
+ virtual void addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling);
+ virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild);
+ virtual void removeFromParent();
+ virtual void setMaskLayer(GraphicsLayer* layer);
+ virtual void setPosition(const FloatPoint& p);
+ virtual void setAnchorPoint(const FloatPoint3D& p);
+ virtual void setSize(const FloatSize& size);
+ virtual void setTransform(const TransformationMatrix& t);
+ virtual void setChildrenTransform(const TransformationMatrix& t);
+ virtual void setPreserves3D(bool b);
+ virtual void setMasksToBounds(bool b);
+ virtual void setDrawsContent(bool b);
+ virtual void setBackgroundColor(const Color&);
+ virtual void clearBackgroundColor();
+ virtual void setContentsOpaque(bool b);
+ virtual void setBackfaceVisibility(bool b);
+ virtual void setOpacity(float opacity);
+ virtual void setContentsRect(const IntRect& r);
+ virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, const String& keyframesName, double timeOffset);
+ virtual void removeAnimationsForProperty(AnimatedPropertyID);
+ virtual void removeAnimationsForKeyframes(const String& keyframesName);
+ virtual void pauseAnimation(const String& keyframesName, double timeOffset);
+ virtual void suspendAnimations(double time);
+ virtual void resumeAnimations();
+ virtual void setContentsToImage(Image*);
+ virtual void setContentsBackgroundColor(const Color&);
+ virtual void setGeometryOrientation(CompositingCoordinatesOrientation orientation);
+ virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation);
+ virtual void distributeOpacity(float);
+ virtual float accumulatedOpacity() const;
+ virtual void syncCompositingState();
+
+private:
+ OwnPtr<GraphicsLayerQtImpl> m_impl;
+};
+
+}
+#endif // GraphicsLayerQt_h
diff --git a/WebCore/platform/qt/QWebPageClient.h b/WebCore/platform/qt/QWebPageClient.h
index b510736..09fe768 100644
--- a/WebCore/platform/qt/QWebPageClient.h
+++ b/WebCore/platform/qt/QWebPageClient.h
@@ -29,7 +29,9 @@
#ifndef QT_NO_CURSOR
#include <QCursor>
#endif
+
#include <QRect>
+class QGraphicsItem;
class QWebPageClient {
public:
@@ -39,6 +41,16 @@ public:
virtual void update(const QRect&) = 0;
virtual void setInputMethodEnabled(bool enable) = 0;
virtual bool inputMethodEnabled() const = 0;
+#if USE(ACCELERATED_COMPOSITING)
+ // this gets called when we start/stop compositing.
+ virtual void setRootGraphicsLayer(QGraphicsItem* layer) {}
+
+ // this gets called when the compositor wants us to sync the layers
+ // if scheduleSync is true, we schedule a sync ourselves. otherwise,
+ // we wait for the next update and sync the layers then.
+ virtual void markForSync(bool scheduleSync = false) {}
+#endif
+
#if QT_VERSION >= 0x040600
virtual void setInputMethodHint(Qt::InputMethodHint hint, bool enable) = 0;
#endif
diff --git a/WebKit.pri b/WebKit.pri
index 211f6a4..7b68edb 100644
--- a/WebKit.pri
+++ b/WebKit.pri
@@ -45,6 +45,7 @@ building-libs {
}
DEPENDPATH += $$PWD/WebKit/qt/Api
}
+greaterThan(QT_MINOR_VERSION, 5):DEFINES += WTF_USE_ACCELERATED_COMPOSITING
!mac:!unix|symbian {
DEFINES += USE_SYSTEM_MALLOC
diff --git a/WebKit/qt/Api/qgraphicswebview.cpp b/WebKit/qt/Api/qgraphicswebview.cpp
index 82aede5..d9e8a74 100644
--- a/WebKit/qt/Api/qgraphicswebview.cpp
+++ b/WebKit/qt/Api/qgraphicswebview.cpp
@@ -22,24 +22,71 @@
#include "qgraphicswebview.h"
#include "qwebframe.h"
+#include "qwebframe_p.h"
#include "qwebpage.h"
#include "qwebpage_p.h"
#include "QWebPageClient.h"
-#include <QtGui/QGraphicsScene>
-#include <QtGui/QGraphicsView>
+#include <FrameView.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qtimer.h>
#include <QtGui/qapplication.h>
+#include <QtGui/qgraphicsscene.h>
#include <QtGui/qgraphicssceneevent.h>
+#include <QtGui/qgraphicsview.h>
+#include <QtGui/qpixmapcache.h>
#include <QtGui/qstyleoption.h>
#if defined(Q_WS_X11)
#include <QX11Info>
#endif
+#include <Settings.h>
+
+#if USE(ACCELERATED_COMPOSITING)
+
+// the overlay is here for one reason only: to have the scroll-bars and other
+// extra UI elements appear on top of any QGraphicsItems created by CSS compositing layers
+class QGraphicsWebViewOverlay : public QGraphicsItem {
+ public:
+ QGraphicsWebViewOverlay(QGraphicsWebView* view)
+ :QGraphicsItem(view)
+ , q(view)
+ {
+ setPos(0, 0);
+ setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ }
+
+ QRectF boundingRect() const
+ {
+ return q->boundingRect();
+ }
+
+ void paint(QPainter* painter, const QStyleOptionGraphicsItem* options, QWidget*)
+ {
+ q->page()->mainFrame()->render(painter, static_cast<QWebFrame::RenderLayer>(QWebFrame::AllLayers&(~QWebFrame::ContentsLayer)), options->exposedRect.toRect());
+ }
+
+ friend class QGraphicsWebView;
+ QGraphicsWebView* q;
+};
+
+#endif
class QGraphicsWebViewPrivate : public QWebPageClient {
public:
QGraphicsWebViewPrivate(QGraphicsWebView* parent)
: q(parent)
, page(0)
- {}
+#if USE(ACCELERATED_COMPOSITING)
+ , rootGraphicsLayer(0)
+ , shouldSync(true)
+#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);
+#endif
+ }
virtual ~QGraphicsWebViewPrivate();
virtual void scroll(int dx, int dy, const QRect&);
@@ -61,14 +108,95 @@ public:
virtual QObject* pluginParent() const;
+#if USE(ACCELERATED_COMPOSITING)
+ virtual void setRootGraphicsLayer(QGraphicsItem* layer);
+ virtual void markForSync(bool scheduleSync);
+ void updateCompositingScrollPosition();
+#endif
+
+ void syncLayers();
void _q_doLoadFinished(bool success);
QGraphicsWebView* q;
QWebPage* page;
+#if USE(ACCELERATED_COMPOSITING)
+ QGraphicsItem* rootGraphicsLayer;
+
+ // the overlay gets instantiated when the root layer is attached, and get deleted when it's detached
+ QSharedPointer<QGraphicsWebViewOverlay> overlay;
+
+ // we need to sync the layers if we get a special call from the WebCore
+ // compositor telling us to do so. We'll get that call from ChromeClientQt
+ bool shouldSync;
+
+ // we need to put the root graphics layer behind the overlay (which contains the scrollbar)
+ enum { RootGraphicsLayerZValue, OverlayZValue };
+#endif
};
QGraphicsWebViewPrivate::~QGraphicsWebViewPrivate()
{
+#if USE(ACCELERATED_COMPOSITING)
+ if (rootGraphicsLayer) {
+ // we don't need to delete the root graphics layer
+ // The lifecycle is managed in GraphicsLayerQt.cpp
+ rootGraphicsLayer->setParentItem(0);
+ q->scene()->removeItem(rootGraphicsLayer);
+ }
+#endif
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+void QGraphicsWebViewPrivate::setRootGraphicsLayer(QGraphicsItem* layer)
+{
+ if (rootGraphicsLayer) {
+ rootGraphicsLayer->setParentItem(0);
+ q->scene()->removeItem(rootGraphicsLayer);
+ QWebFramePrivate::core(q->page()->mainFrame())->view()->syncCompositingStateRecursive();
+ }
+
+ rootGraphicsLayer = layer;
+
+ if (layer) {
+ layer->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
+ layer->setParentItem(q);
+ layer->setZValue(RootGraphicsLayerZValue);
+ if (!overlay) {
+ overlay = QSharedPointer<QGraphicsWebViewOverlay>(new QGraphicsWebViewOverlay(q));
+ overlay->setZValue(OverlayZValue);
+ }
+ updateCompositingScrollPosition();
+ } else {
+ // we don't have compositing layers, we can render the scrollbars and content in one go
+ overlay.clear();
+ }
+}
+
+void QGraphicsWebViewPrivate::markForSync(bool scheduleSync)
+{
+ shouldSync = true;
+ if (scheduleSync)
+ QTimer::singleShot(0, q, SLOT(syncLayers()));
+}
+
+void QGraphicsWebViewPrivate::updateCompositingScrollPosition()
+{
+ if (rootGraphicsLayer && q->page() && q->page()->mainFrame()) {
+ const QPoint scrollPosition = q->page()->mainFrame()->scrollPosition();
+ rootGraphicsLayer->setPos(-scrollPosition);
+ }
+}
+
+#endif
+
+void QGraphicsWebViewPrivate::syncLayers()
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (shouldSync) {
+ QWebFramePrivate::core(q->page()->mainFrame())->view()->syncCompositingStateRecursive();
+ shouldSync = false;
+ }
+#endif
}
void QGraphicsWebViewPrivate::_q_doLoadFinished(bool success)
@@ -83,11 +211,18 @@ void QGraphicsWebViewPrivate::_q_doLoadFinished(bool success)
void QGraphicsWebViewPrivate::scroll(int dx, int dy, const QRect& rectToScroll)
{
q->scroll(qreal(dx), qreal(dy), QRectF(rectToScroll));
+#if USE(ACCELERATED_COMPOSITING)
+ updateCompositingScrollPosition();
+#endif
}
void QGraphicsWebViewPrivate::update(const QRect & dirtyRect)
{
q->update(QRectF(dirtyRect));
+#if USE(ACCELERATED_COMPOSITING)
+ if (overlay)
+ overlay->update(QRectF(dirtyRect));
+#endif
}
@@ -248,6 +383,7 @@ QGraphicsWebView::QGraphicsWebView(QGraphicsItem* parent)
setAcceptTouchEvents(true);
#endif
setFocusPolicy(Qt::StrongFocus);
+ setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
}
/*!
@@ -297,7 +433,12 @@ QWebPage* QGraphicsWebView::page() const
*/
void QGraphicsWebView::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*)
{
- page()->mainFrame()->render(painter, option->exposedRect.toRect());
+#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
}
/*! \reimp
@@ -425,6 +566,10 @@ void QGraphicsWebView::setPage(QWebPage* page)
d->page = page;
if (!d->page)
return;
+#if USE(ACCELERATED_COMPOSITING)
+ if (d->overlay)
+ d->overlay->prepareGeometryChange();
+#endif
d->page->d->client = d; // set the page client
QSize size = geometry().size().toSize();
@@ -528,6 +673,12 @@ qreal QGraphicsWebView::zoomFactor() const
*/
void QGraphicsWebView::updateGeometry()
{
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (d->overlay)
+ d->overlay->prepareGeometryChange();
+#endif
+
QGraphicsWidget::updateGeometry();
if (!d->page)
@@ -543,6 +694,11 @@ void QGraphicsWebView::setGeometry(const QRectF& rect)
{
QGraphicsWidget::setGeometry(rect);
+#if USE(ACCELERATED_COMPOSITING)
+ if (d->overlay)
+ d->overlay->prepareGeometryChange();
+#endif
+
if (!d->page)
return;
diff --git a/WebKit/qt/Api/qgraphicswebview.h b/WebKit/qt/Api/qgraphicswebview.h
index f3afb4c..3cf51b2 100644
--- a/WebKit/qt/Api/qgraphicswebview.h
+++ b/WebKit/qt/Api/qgraphicswebview.h
@@ -134,6 +134,9 @@ protected:
private:
Q_PRIVATE_SLOT(d, void _q_doLoadFinished(bool success))
+ // we don't want to change the moc based on USE() macro, so this function is here
+ // but will be empty if ACCLERATED_COMPOSITING is disabled
+ Q_PRIVATE_SLOT(d, void syncLayers())
QGraphicsWebViewPrivate* const d;
friend class QGraphicsWebViewPrivate;
diff --git a/WebKit/qt/Api/qwebsettings.cpp b/WebKit/qt/Api/qwebsettings.cpp
index d7d375b..a94a3aa 100644
--- a/WebKit/qt/Api/qwebsettings.cpp
+++ b/WebKit/qt/Api/qwebsettings.cpp
@@ -152,7 +152,12 @@ void QWebSettingsPrivate::apply()
value = attributes.value(QWebSettings::JavascriptEnabled,
global->attributes.value(QWebSettings::JavascriptEnabled));
settings->setJavaScriptEnabled(value);
+#if USE(ACCELERATED_COMPOSITING)
+ value = attributes.value(QWebSettings::AcceleratedCompositingEnabled,
+ global->attributes.value(QWebSettings::AcceleratedCompositingEnabled));
+ settings->setAcceleratedCompositingEnabled(value);
+#endif
value = attributes.value(QWebSettings::JavascriptCanOpenWindows,
global->attributes.value(QWebSettings::JavascriptCanOpenWindows));
settings->setJavaScriptCanOpenWindowsAutomatically(value);
@@ -389,6 +394,7 @@ QWebSettings::QWebSettings()
d->attributes.insert(QWebSettings::OfflineWebApplicationCacheEnabled, false);
d->attributes.insert(QWebSettings::LocalStorageEnabled, false);
d->attributes.insert(QWebSettings::LocalContentCanAccessRemoteUrls, false);
+ d->attributes.insert(QWebSettings::AcceleratedCompositingEnabled, false);
d->offlineStorageDefaultQuota = 5 * 1024 * 1024;
d->defaultTextEncoding = QLatin1String("iso-8859-1");
}
diff --git a/WebKit/qt/Api/qwebsettings.h b/WebKit/qt/Api/qwebsettings.h
index 32af448..77f2167 100644
--- a/WebKit/qt/Api/qwebsettings.h
+++ b/WebKit/qt/Api/qwebsettings.h
@@ -68,7 +68,8 @@ public:
#endif
LocalContentCanAccessRemoteUrls,
DnsPrefetchEnabled,
- XSSAuditorEnabled
+ XSSAuditorEnabled,
+ AcceleratedCompositingEnabled
};
enum WebGraphic {
MissingImageGraphic,
diff --git a/WebKit/qt/Api/qwebview.cpp b/WebKit/qt/Api/qwebview.cpp
index 275f208..9ef2e55 100644
--- a/WebKit/qt/Api/qwebview.cpp
+++ b/WebKit/qt/Api/qwebview.cpp
@@ -22,10 +22,11 @@
#include "config.h"
#include "qwebview.h"
+#include "Page.h"
#include "QWebPageClient.h"
+#include "Settings.h"
#include "qwebframe.h"
#include "qwebpage_p.h"
-
#include "qbitmap.h"
#include "qevent.h"
#include "qpainter.h"
@@ -247,6 +248,9 @@ void QWebView::setPage(QWebPage* page)
this, SLOT(_q_pageDestroyed()));
}
setAttribute(Qt::WA_OpaquePaintEvent, d->page);
+#if USE(ACCELERATED_COMPOSITING)
+ d->page->d->page->settings()->setAcceleratedCompositingEnabled(false);
+#endif
update();
}
diff --git a/WebKit/qt/ChangeLog b/WebKit/qt/ChangeLog
index a6b4124..3244aee 100644
--- a/WebKit/qt/ChangeLog
+++ b/WebKit/qt/ChangeLog
@@ -1,3 +1,60 @@
+2010-01-21 No'am Rosenthal <noam.rosenthal at nokia.com>
+
+ Reviewed by Antti Koivisto.
+
+ [Qt] Implement GraphicsLayer for accelerated layer compositing
+ https://bugs.webkit.org/show_bug.cgi?id=33514
+
+ Here we have the QGraphicsWebView support for accelerated compositing
+
+ * Api/qgraphicswebview.cpp:
+ (QGraphicsWebViewOverlay::q): access to container object
+ (QGraphicsWebViewOverlay::boundingRect): overlay has same rect as the
+ webview
+ (QGraphicsWebViewOverlay::paint): paint everything but the contents
+ (QGraphicsWebViewPrivate::QGraphicsWebViewPrivate): some vars needed
+ for accelerated compositing
+ (QGraphicsWebViewPrivate::):
+ (QGraphicsWebViewPrivate::~QGraphicsWebViewPrivate):
+ (QGraphicsWebViewPrivate::setRootGraphicsLayer): make sure we have a
+ scrollbar overlay, and that the new graphics layer is parented by the
+ web-view
+ (QGraphicsWebViewPrivate::markForSync): flush changes at earliest
+ convenience or during the next draw
+
+ (QGraphicsWebViewPrivate::updateCompositingScrollPosition): sync the
+ position of the compositing layer with the scroll position
+ (QGraphicsWebViewPrivate::syncLayers): flush changes now
+ (QGraphicsWebViewPrivate::scroll): make sure we also move the
+ compositing layer
+ (QGraphicsWebViewPrivate::update): also update the overlay if needed
+ (QGraphicsWebView::QGraphicsWebView): initialize overlay with 0
+ (QGraphicsWebView::paint): paint only contents if we have an overlay,
+ sync the compositing layers now if needed
+ (QGraphicsWebView::setPage): also clean up the compositing
+ (QGraphicsWebView::updateGeometry): also update overlay geo
+ (QGraphicsWebView::setGeometry): also update overlay geo
+ * Api/qgraphicswebview.h: reimp compositing stuff from QWebPageClient
+ * Api/qwebsettings.cpp: init new settings flag for compositing as
+ false
+ (QWebSettingsPrivate::apply): apply new settings flag for compositing
+ (QWebSettings::QWebSettings):
+ * Api/qwebsettings.h: new settings flag for compositing
+ * Api/qwebview.cpp:
+ (QWebView::setPage): qwebview doesn't support compositing: always false
+ * QGVLauncher/main.cpp:
+ (WebView::WebView): some more cmdline arguments + compositing
+ (MainWindow::init): some more cmdline arguments
+ (main): ditto
+ * WebCoreSupport/ChromeClientQt.cpp:
+ (WebCore::ChromeClientQt::attachRootGraphicsLayer): reimp for
+ accel-compositing
+ (WebCore::ChromeClientQt::setNeedsOneShotDrawingSynchronization):
+ reimp for accel compositing
+ (WebCore::ChromeClientQt::scheduleCompositingLayerSync): reimp for
+ accel compositing
+ * WebCoreSupport/ChromeClientQt.h: reimps for accel compositing
+
2010-01-21 Benjamin Poulain <benjamin.poulain at nokia.com>
Reviewed by Simon Hausmann.
diff --git a/WebKit/qt/QGVLauncher/main.cpp b/WebKit/qt/QGVLauncher/main.cpp
index b82347e..1b04c60 100644
--- a/WebKit/qt/QGVLauncher/main.cpp
+++ b/WebKit/qt/QGVLauncher/main.cpp
@@ -72,6 +72,8 @@ public:
WebView(QGraphicsItem* parent = 0)
: QGraphicsWebView(parent)
{
+ if (QApplication::instance()->arguments().contains("--cacheWebView"))
+ setCacheMode(QGraphicsItem::DeviceCoordinateCache);
}
void setYRotation(qreal angle)
{
@@ -253,6 +255,12 @@ public:
setAttribute(Qt::WA_DeleteOnClose);
view->setScene(scene->scene());
+ const QStringList arguments = QApplication::instance()->arguments();
+ const int indexOfViewportUpdateMode = arguments.indexOf("--updateMode");
+ if (indexOfViewportUpdateMode > 1 && indexOfViewportUpdateMode < arguments.count() - 1) {
+ const QString updateMode = arguments[indexOfViewportUpdateMode+1] + "ViewportUpdate";
+ view->setViewportUpdateMode(static_cast<QGraphicsView::ViewportUpdateMode>(QGraphicsView::staticMetaObject.enumerator(QGraphicsView::staticMetaObject.indexOfEnumerator("ViewportUpdateMode")).keysToValue(updateMode.toAscii())));
+ }
setCentralWidget(view);
@@ -447,6 +455,10 @@ QWebPage* WebPage::createWindow(QWebPage::WebWindowType)
int main(int argc, char** argv)
{
QApplication app(argc, argv);
+ if (app.arguments().contains("--help")) {
+ qDebug() << "Usage: QGVLauncher [--url url] [--compositing] [--updateMode Full|Minimal|Smart|No|BoundingRect] [--cacheWebView]\n";
+ return 0;
+ }
QString url = QString("file://%1/%2").arg(QDir::homePath()).arg(QLatin1String("index.html"));
app.setApplicationName("GQVLauncher");
@@ -458,14 +470,20 @@ int main(int argc, char** argv)
QWebSettings::enablePersistentStorage();
const QStringList args = app.arguments();
- if (args.count() > 1)
+ const int indexOfUrl = args.indexOf("--url");
+ if (indexOfUrl > 0 && indexOfUrl < args.count() - 1)
+ url = args.at(indexOfUrl+1);
+ else if (args.count() > 1)
url = args.at(1);
+ if (args.contains("--compositing"))
+ QWebSettings::globalSettings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, true);
MainWindow* window = new MainWindow;
window->load(url);
- for (int i = 2; i < args.count(); i++)
- window->newWindow(args.at(i));
+ for (int i = 2; i < args.count(); ++i)
+ if (!args.at(i).startsWith("-") && !args.at(i - 1).startsWith("-"))
+ window->newWindow(args.at(i));
window->show();
return app.exec();
diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp
index 6345539..5a269dd 100644
--- a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp
+++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp
@@ -25,6 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
#include "config.h"
#include "ChromeClientQt.h"
@@ -42,6 +43,10 @@
#include "QWebPageClient.h"
#include "SecurityOrigin.h"
+#include <qdebug.h>
+#include <qtextdocument.h>
+#include <qtooltip.h>
+
#include "qwebpage.h"
#include "qwebpage_p.h"
#include "qwebframe_p.h"
@@ -49,12 +54,11 @@
#include "qwebsecurityorigin_p.h"
#include "qwebview.h"
-#include <qtooltip.h>
-#include <qtextdocument.h>
-
-namespace WebCore
-{
+#if USE(ACCELERATED_COMPOSITING)
+#include "GraphicsLayerQt.h"
+#endif
+namespace WebCore {
ChromeClientQt::ChromeClientQt(QWebPage* webPage)
: m_webPage(webPage)
@@ -466,6 +470,28 @@ void ChromeClientQt::requestGeolocationPermissionForFrame(Frame*, Geolocation*)
notImplemented();
}
+#if USE(ACCELERATED_COMPOSITING)
+void ChromeClientQt::attachRootGraphicsLayer(Frame* frame, GraphicsLayer* graphicsLayer)
+{
+ if (platformPageClient())
+ platformPageClient()->setRootGraphicsLayer(graphicsLayer ? graphicsLayer->nativeLayer() : 0);
+}
+
+void ChromeClientQt::setNeedsOneShotDrawingSynchronization()
+{
+ // we want the layers to synchronize next time we update the screen anyway
+ if (platformPageClient())
+ platformPageClient()->markForSync(false);
+}
+
+void ChromeClientQt::scheduleCompositingLayerSync()
+{
+ // we want the layers to synchronize ASAP
+ if (platformPageClient())
+ platformPageClient()->markForSync(true);
+}
+#endif
+
QtAbstractWebPopup* ChromeClientQt::createSelectPopup()
{
return new QtFallbackWebPopup;
diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.h b/WebKit/qt/WebCoreSupport/ChromeClientQt.h
index 7077501..d60ec06 100644
--- a/WebKit/qt/WebCoreSupport/ChromeClientQt.h
+++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.h
@@ -123,6 +123,15 @@ namespace WebCore {
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
virtual void reachedMaxAppCacheSize(int64_t spaceNeeded);
#endif
+
+#if USE(ACCELERATED_COMPOSITING)
+ // see ChromeClient.h
+ // this is a hook for WebCore to tell us what we need to do with the GraphicsLayers
+ virtual void attachRootGraphicsLayer(Frame*, GraphicsLayer*);
+ virtual void setNeedsOneShotDrawingSynchronization();
+ virtual void scheduleCompositingLayerSync();
+#endif
+
virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>);
virtual void formStateDidChange(const Node*) { }
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list