aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick
diff options
context:
space:
mode:
authorSergio Ahumada <sergio.ahumada@digia.com>2013-11-27 10:58:56 +0100
committerSergio Ahumada <sergio.ahumada@digia.com>2013-11-27 10:58:56 +0100
commit9df70b0304fa44d2f1b1504d7e58d718eab4343a (patch)
tree95a7b207a39c2b44bd4e80bcc1ea3d36bedd9a99 /src/quick
parent648d4ae6a3591e916f175e32c12a2ea4f8edb6a9 (diff)
parent900e3d4ad5f2bc4994ddf164c15c641f85630b81 (diff)
Merge branch 'stable' into dev
Conflicts: .qmake.conf Change-Id: I10d4f9e993d23750a6e8ddc1291b79e47fc83c64
Diffstat (limited to 'src/quick')
-rw-r--r--src/quick/designer/designerwindowmanager.cpp9
-rw-r--r--src/quick/designer/designerwindowmanager_p.h4
-rw-r--r--src/quick/doc/images/qml-xmllistmodel-example.pngbin0 -> 5252 bytes
-rw-r--r--src/quick/doc/qtquick.qdocconf2
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc2
-rw-r--r--src/quick/doc/src/concepts/positioning/layouts.qdoc2
-rw-r--r--src/quick/doc/src/concepts/positioning/righttoleft.qdoc2
-rw-r--r--src/quick/doc/src/concepts/statesanimations/animations.qdoc16
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc5
-rw-r--r--src/quick/doc/src/cppextensionpoints.qdoc6
-rw-r--r--src/quick/doc/src/qmltypereference.qdoc33
-rw-r--r--src/quick/doc/src/qtquick.qdoc61
-rw-r--r--src/quick/doc/src/tutorial.qdoc1
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp2
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp374
-rw-r--r--src/quick/items/items.pri17
-rw-r--r--src/quick/items/items.qrc16
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp55
-rw-r--r--src/quick/items/qquickborderimage.cpp10
-rw-r--r--src/quick/items/qquickflickable.cpp6
-rw-r--r--src/quick/items/qquickgridview.cpp2
-rw-r--r--src/quick/items/qquickimage.cpp16
-rw-r--r--src/quick/items/qquickitem.cpp11
-rw-r--r--src/quick/items/qquickitem_p.h7
-rw-r--r--src/quick/items/qquickitemanimation.cpp2
-rw-r--r--src/quick/items/qquickitemsmodule.cpp11
-rw-r--r--src/quick/items/qquickitemview.cpp2
-rw-r--r--src/quick/items/qquicklistview.cpp5
-rw-r--r--src/quick/items/qquickmousearea.cpp2
-rw-r--r--src/quick/items/qquickpainteditem.cpp2
-rw-r--r--src/quick/items/qquickpathview.cpp4
-rw-r--r--src/quick/items/qquickscreen.cpp51
-rw-r--r--src/quick/items/qquickscreen_p.h3
-rw-r--r--src/quick/items/qquickshadereffect.cpp34
-rw-r--r--src/quick/items/qquickshadereffectnode.cpp22
-rw-r--r--src/quick/items/qquickshadereffectsource.cpp50
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h7
-rw-r--r--src/quick/items/qquicksprite.cpp2
-rw-r--r--src/quick/items/qquickspritesequence.cpp55
-rw-r--r--src/quick/items/qquicktext.cpp32
-rw-r--r--src/quick/items/qquicktextedit.cpp5
-rw-r--r--src/quick/items/qquicktextinput.cpp19
-rw-r--r--src/quick/items/qquicktextinput_p.h1
-rw-r--r--src/quick/items/qquicktextnode.cpp21
-rw-r--r--src/quick/items/qquicktextnode_p.h3
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp4
-rw-r--r--src/quick/items/qquicktranslate.cpp2
-rw-r--r--src/quick/items/qquickwindow.cpp128
-rw-r--r--src/quick/items/qquickwindow.h6
-rw-r--r--src/quick/items/qquickwindow_p.h3
-rw-r--r--src/quick/items/shaders/shadereffect.frag9
-rw-r--r--src/quick/items/shaders/shadereffect.vert12
-rw-r--r--src/quick/items/shaders/shadereffect_core.frag13
-rw-r--r--src/quick/items/shaders/shadereffect_core.vert14
-rw-r--r--src/quick/items/shaders/shadereffectfallback.frag4
-rw-r--r--src/quick/items/shaders/shadereffectfallback.vert8
-rw-r--r--src/quick/items/shaders/shadereffectfallback_core.frag8
-rw-r--r--src/quick/items/shaders/shadereffectfallback_core.vert10
-rw-r--r--src/quick/items/shaders/sprite.frag12
-rw-r--r--src/quick/items/shaders/sprite.vert23
-rw-r--r--src/quick/items/shaders/sprite_core.frag16
-rw-r--r--src/quick/items/shaders/sprite_core.vert24
-rw-r--r--src/quick/qtquick2.cpp7
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp175
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h31
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp63
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.h15
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterialshader_p.h (renamed from src/quick/scenegraph/qsgflashnode_p.h)22
-rw-r--r--src/quick/scenegraph/coreapi/qsgnodeupdater.cpp9
-rw-r--r--src/quick/scenegraph/coreapi/qsgnodeupdater_p.h5
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp32
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h8
-rw-r--r--src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp29
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp5
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer_p.h4
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp591
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h107
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp142
-rw-r--r--src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h10
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.cpp168
-rw-r--r--src/quick/scenegraph/qsgdefaultimagenode.cpp76
-rw-r--r--src/quick/scenegraph/qsgdefaultrectanglenode.cpp66
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode.cpp9
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp250
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p.h6
-rw-r--r--src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h1
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp32
-rw-r--r--src/quick/scenegraph/qsgrenderloop_p.h3
-rw-r--r--src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp1
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp681
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop_p.h30
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp29
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop_p.h7
-rw-r--r--src/quick/scenegraph/scenegraph.pri85
-rw-r--r--src/quick/scenegraph/scenegraph.qrc68
-rw-r--r--src/quick/scenegraph/shaders/24bittextmask.frag10
-rw-r--r--src/quick/scenegraph/shaders/24bittextmask_core.frag14
-rw-r--r--src/quick/scenegraph/shaders/8bittextmask.frag9
-rw-r--r--src/quick/scenegraph/shaders/8bittextmask_core.frag13
-rw-r--r--src/quick/scenegraph/shaders/distancefieldoutlinetext.frag16
-rw-r--r--src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag20
-rw-r--r--src/quick/scenegraph/shaders/distancefieldshiftedtext.frag17
-rw-r--r--src/quick/scenegraph/shaders/distancefieldshiftedtext.vert17
-rw-r--r--src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag20
-rw-r--r--src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert18
-rw-r--r--src/quick/scenegraph/shaders/distancefieldtext.frag13
-rw-r--r--src/quick/scenegraph/shaders/distancefieldtext.vert13
-rw-r--r--src/quick/scenegraph/shaders/distancefieldtext_core.frag16
-rw-r--r--src/quick/scenegraph/shaders/distancefieldtext_core.vert15
-rw-r--r--src/quick/scenegraph/shaders/flatcolor.frag6
-rw-r--r--src/quick/scenegraph/shaders/flatcolor.vert7
-rw-r--r--src/quick/scenegraph/shaders/flatcolor_core.frag10
-rw-r--r--src/quick/scenegraph/shaders/flatcolor_core.vert10
-rw-r--r--src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag58
-rw-r--r--src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert34
-rw-r--r--src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag32
-rw-r--r--src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert36
-rw-r--r--src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext.frag17
-rw-r--r--src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext.vert27
-rw-r--r--src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag21
-rw-r--r--src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert29
-rw-r--r--src/quick/scenegraph/shaders/opaquetexture.frag8
-rw-r--r--src/quick/scenegraph/shaders/opaquetexture.vert12
-rw-r--r--src/quick/scenegraph/shaders/opaquetexture_core.frag12
-rw-r--r--src/quick/scenegraph/shaders/opaquetexture_core.vert14
-rw-r--r--src/quick/scenegraph/shaders/outlinedtext.frag21
-rw-r--r--src/quick/scenegraph/shaders/outlinedtext.vert22
-rw-r--r--src/quick/scenegraph/shaders/outlinedtext_core.frag25
-rw-r--r--src/quick/scenegraph/shaders/outlinedtext_core.vert24
-rw-r--r--src/quick/scenegraph/shaders/rendernode.frag8
-rw-r--r--src/quick/scenegraph/shaders/rendernode.vert10
-rw-r--r--src/quick/scenegraph/shaders/rendernode_core.frag12
-rw-r--r--src/quick/scenegraph/shaders/rendernode_core.vert12
-rw-r--r--src/quick/scenegraph/shaders/smoothcolor.frag6
-rw-r--r--src/quick/scenegraph/shaders/smoothcolor.vert45
-rw-r--r--src/quick/scenegraph/shaders/smoothcolor_core.frag10
-rw-r--r--src/quick/scenegraph/shaders/smoothcolor_core.vert47
-rw-r--r--src/quick/scenegraph/shaders/smoothtexture.frag9
-rw-r--r--src/quick/scenegraph/shaders/smoothtexture.vert52
-rw-r--r--src/quick/scenegraph/shaders/smoothtexture_core.frag13
-rw-r--r--src/quick/scenegraph/shaders/smoothtexture_core.vert54
-rw-r--r--src/quick/scenegraph/shaders/stencilclip.frag4
-rw-r--r--src/quick/scenegraph/shaders/stencilclip.vert8
-rw-r--r--src/quick/scenegraph/shaders/stencilclip_core.frag8
-rw-r--r--src/quick/scenegraph/shaders/stencilclip_core.vert10
-rw-r--r--src/quick/scenegraph/shaders/styledtext.frag14
-rw-r--r--src/quick/scenegraph/shaders/styledtext.vert16
-rw-r--r--src/quick/scenegraph/shaders/styledtext_core.frag18
-rw-r--r--src/quick/scenegraph/shaders/styledtext_core.vert18
-rw-r--r--src/quick/scenegraph/shaders/textmask.frag10
-rw-r--r--src/quick/scenegraph/shaders/textmask.vert13
-rw-r--r--src/quick/scenegraph/shaders/textmask_core.frag14
-rw-r--r--src/quick/scenegraph/shaders/textmask_core.vert15
-rw-r--r--src/quick/scenegraph/shaders/texture.frag9
-rw-r--r--src/quick/scenegraph/shaders/texture_core.frag13
-rw-r--r--src/quick/scenegraph/shaders/vertexcolor.frag6
-rw-r--r--src/quick/scenegraph/shaders/vertexcolor.vert13
-rw-r--r--src/quick/scenegraph/shaders/vertexcolor_core.frag10
-rw-r--r--src/quick/scenegraph/shaders/vertexcolor_core.vert15
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp51
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture_p.h10
-rw-r--r--src/quick/scenegraph/util/qsgflatcolormaterial.cpp29
-rw-r--r--src/quick/scenegraph/util/qsgpainternode.cpp6
-rw-r--r--src/quick/scenegraph/util/qsgpainternode_p.h2
-rw-r--r--src/quick/scenegraph/util/qsgshadersourcebuilder.cpp403
-rw-r--r--src/quick/scenegraph/util/qsgshadersourcebuilder_p.h (renamed from src/quick/scenegraph/qsgflashnode.cpp)50
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp16
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial.cpp50
-rw-r--r--src/quick/scenegraph/util/qsgtexturematerial_p.h8
-rw-r--r--src/quick/scenegraph/util/qsgvertexcolormaterial.cpp33
-rw-r--r--src/quick/util/qquickanimation.cpp19
-rw-r--r--src/quick/util/qquickanimatorcontroller.cpp187
-rw-r--r--src/quick/util/qquickanimatorcontroller_p.h63
-rw-r--r--src/quick/util/qquickanimatorjob.cpp108
-rw-r--r--src/quick/util/qquickanimatorjob_p.h12
-rw-r--r--src/quick/util/qquicksmoothedanimation.cpp5
-rw-r--r--src/quick/util/qquickspringanimation.cpp5
177 files changed, 4095 insertions, 2145 deletions
diff --git a/src/quick/designer/designerwindowmanager.cpp b/src/quick/designer/designerwindowmanager.cpp
index 76789cd3a8..25ea5e7f93 100644
--- a/src/quick/designer/designerwindowmanager.cpp
+++ b/src/quick/designer/designerwindowmanager.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include "designerwindowmanager_p.h"
-
+#include "private/qquickwindow_p.h"
#include <QtGui/QOpenGLContext>
#include <QtQuick/QQuickWindow>
@@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE
DesignerWindowManager::DesignerWindowManager()
: m_sgContext(QSGContext::createDefaultContext())
{
+ m_renderContext.reset(new QSGRenderContext(m_sgContext.data()));
}
void DesignerWindowManager::show(QQuickWindow *window)
@@ -74,7 +75,7 @@ void DesignerWindowManager::makeOpenGLContext(QQuickWindow *window)
m_openGlContext->create();
if (!m_openGlContext->makeCurrent(window))
qWarning("QQuickWindow: makeCurrent() failed...");
- m_sgContext->initialize(m_openGlContext.data());
+ m_renderContext->initialize(m_openGlContext.data());
} else {
m_openGlContext->makeCurrent(window);
}
@@ -89,10 +90,6 @@ QImage DesignerWindowManager::grab(QQuickWindow *)
return QImage();
}
-void DesignerWindowManager::resize(QQuickWindow *, const QSize &)
-{
-}
-
void DesignerWindowManager::maybeUpdate(QQuickWindow *)
{
}
diff --git a/src/quick/designer/designerwindowmanager_p.h b/src/quick/designer/designerwindowmanager_p.h
index a822ead64e..7414f4e3ba 100644
--- a/src/quick/designer/designerwindowmanager_p.h
+++ b/src/quick/designer/designerwindowmanager_p.h
@@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
class QQuickWindow;
class QSGContext;
+class QSGRenderContext;
class QAnimationDriver;
class QOpenGLContext;
@@ -81,7 +82,6 @@ public:
void makeOpenGLContext(QQuickWindow *window);
void exposureChanged(QQuickWindow *window);
QImage grab(QQuickWindow *window);
- void resize(QQuickWindow *window, const QSize &size);
void maybeUpdate(QQuickWindow *window);
void update(QQuickWindow *window); // identical for this implementation.
@@ -91,12 +91,14 @@ public:
QAnimationDriver *animationDriver() const { return 0; }
QSGContext *sceneGraphContext() const;
+ QSGRenderContext *createRenderContext(QSGContext *) const { return m_renderContext.data(); }
static void createOpenGLContext(QQuickWindow *window);
private:
QScopedPointer<QOpenGLContext> m_openGlContext;
QScopedPointer<QSGContext> m_sgContext;
+ QScopedPointer<QSGRenderContext> m_renderContext;
};
QT_END_NAMESPACE
diff --git a/src/quick/doc/images/qml-xmllistmodel-example.png b/src/quick/doc/images/qml-xmllistmodel-example.png
new file mode 100644
index 0000000000..be2d15d342
--- /dev/null
+++ b/src/quick/doc/images/qml-xmllistmodel-example.png
Binary files differ
diff --git a/src/quick/doc/qtquick.qdocconf b/src/quick/doc/qtquick.qdocconf
index 8f769871a5..22880c4086 100644
--- a/src/quick/doc/qtquick.qdocconf
+++ b/src/quick/doc/qtquick.qdocconf
@@ -2,7 +2,7 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
project = QtQuick
description = Qt Quick Reference Documentation
-url = http://qt-project.org/doc/qt-$QT_VER/qtquick-index.html
+url = http://qt-project.org/doc/qt-$QT_VER
version = $QT_VERSION
examplesinstallpath = quick
diff --git a/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc b/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc
index ba9ec9229e..b5dd961ea9 100644
--- a/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc
+++ b/src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc
@@ -245,7 +245,7 @@ To visualize data, bind the view's \c model property to a model and the
}
\endqml
- The \l{declarative/rssnews}{RSS News demo} shows how XmlListModel can
+ The \l{Qt Quick Demo - RSS News}{RSS News demo} shows how XmlListModel can
be used to display an RSS feed.
diff --git a/src/quick/doc/src/concepts/positioning/layouts.qdoc b/src/quick/doc/src/concepts/positioning/layouts.qdoc
index 35be2f6235..fef55582dc 100644
--- a/src/quick/doc/src/concepts/positioning/layouts.qdoc
+++ b/src/quick/doc/src/concepts/positioning/layouts.qdoc
@@ -32,7 +32,7 @@
Positioner items are container items that manage the positions of
items in a declarative user interface. Positioners behave in a similar way to
-the \l{Widgets and Layouts}{layout managers} used with standard Qt widgets,
+the \l{Qt Widgets}{layout managers} used with standard Qt widgets,
except that they are also containers in their own right.
Positioners make it easier to work with many items when they need
diff --git a/src/quick/doc/src/concepts/positioning/righttoleft.qdoc b/src/quick/doc/src/concepts/positioning/righttoleft.qdoc
index 1c48058510..ad8b2f3b63 100644
--- a/src/quick/doc/src/concepts/positioning/righttoleft.qdoc
+++ b/src/quick/doc/src/concepts/positioning/righttoleft.qdoc
@@ -185,7 +185,7 @@ command-line parameter "-reverse":
qmlviewer myapp.qml -reverse
\endcode
-The layout direction can also be set from C++ by calling the static function \l QApplication::setLayoutDirection():
+The layout direction can also be set from C++ by calling the static function \l QGuiApplication::setLayoutDirection():
\code
QApplication app(argc, argv);
diff --git a/src/quick/doc/src/concepts/statesanimations/animations.qdoc b/src/quick/doc/src/concepts/statesanimations/animations.qdoc
index dcf1d49a72..07f1048bf2 100644
--- a/src/quick/doc/src/concepts/statesanimations/animations.qdoc
+++ b/src/quick/doc/src/concepts/statesanimations/animations.qdoc
@@ -32,7 +32,7 @@
\brief the animation system in Qt Quick
\section1 Animation and Transitions Types
-\generatelist{related}
+
\list
\li \l {Transition} - Animates transitions during state changes
\li \l {SequentialAnimation} - Runs animations sequentially
@@ -47,15 +47,6 @@
Types that animate properties based on data types
\annotatedlist qtquick-animation-properties
-\list
-\li \l {PropertyAnimation} - Animates property changes
-\li \l {NumberAnimation} - Animates properties of type qreal
-\li \l {Vector3dAnimation} - Animates properties of type QVector3d
-\li \l {ColorAnimation} - Animates color changes
-\li \l {RotationAnimation} - Animates rotations
-\li \l {ParentAnimation} - Animates parent changes
-\li \l {AnchorAnimation} - Animates anchor changes
-\endlist
Animations are created by applying animation types to property
values. Animation types will interpolate property values to create smooth
@@ -65,6 +56,8 @@ To create an animation, use an appropriate animation type for the type of
the property that is to be animated, and apply the animation depending on the
type of behavior that is required.
+\sa {Qt Quick Examples - Animation}
+
\section1 Triggering Animations
There are several ways of setting animation to an object.
@@ -218,9 +211,6 @@ The \l SequentialAnimation type is also useful for playing
\l{qml-transition-animations}{transition animations} because animations are
played in parallel inside transitions.
-See the \l {declarative/animation/basics}{Animation basics example} for a
-demonstration of creating and combining multiple animations in QML.
-
\keyword qml-controlling-animations
\section1 Controlling Animations
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 384e8209c1..16075f0db3 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -724,6 +724,11 @@ with multiple windows.
\li Some material flags prevent batching, the most limiting one
being QSGMaterial::RequiresFullMatrix which prevents all batching.
+ \li Applications with a monochrome background should set it using
+ QQuickWindow::setColor() rather than using a top-level Rectangle item.
+ QQuickWindow::setColor() will be used in a call to \c glClear(),
+ which is potentially faster.
+
\endlist
If an application performs poorly, make sure that rendering is
diff --git a/src/quick/doc/src/cppextensionpoints.qdoc b/src/quick/doc/src/cppextensionpoints.qdoc
index 7fa7ee7aca..db003b2427 100644
--- a/src/quick/doc/src/cppextensionpoints.qdoc
+++ b/src/quick/doc/src/cppextensionpoints.qdoc
@@ -41,7 +41,7 @@ QQuickItem-derived types which can be rendered by Qt Quick. It also provides
several scene graph-related classes which allow developers to define their own
rendering primitives.
-
+\target user-defined-qquickitem-derived-types
\section1 User-Defined QQuickItem-Derived Types
While the Qt Quick module already provides a rich library of visual item types
@@ -51,7 +51,7 @@ way to do this is to subclass QQuickItem, which is the base type
for all visual types in the Qt Quick module. See the QQuickItem documentation
for more details.
-
+\target scene-graph-related-classes
\section1 Scene Graph-Related Classes
Qt Quick 2 makes use of a dedicated scene graph based on OpenGL ES 2.0 or OpenGL 2.0
@@ -66,7 +66,7 @@ enable custom nodes to be created in C++.
See the \l {Qt Quick Scene Graph} documentation for details.
-
+\target pixmap-and-threaded-image-support
\section1 Pixmap and Threaded Image Support
While the QML engine allows QML application to load images from filesystem or
diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc
index fce7c05e00..cf40fbe37c 100644
--- a/src/quick/doc/src/qmltypereference.qdoc
+++ b/src/quick/doc/src/qmltypereference.qdoc
@@ -36,6 +36,7 @@ interfaces and applications with QML. This page lists every QML type provided
by this module, organized according to category and purpose.
+\target importing-qtquick
\section1 Importing Qt Quick
The types provided by the \l {Qt Quick} module are only available in a QML document
@@ -71,7 +72,7 @@ information about the concepts which are central to \c QtQuick.
\li \l{Qt Quick Layouts QML Types}{Layouts} - contains types that are used
to arrange items in the user interface
\endlist
-
+\target basic-types
\section1 Basic Types
There are a number of basic types that are
@@ -80,7 +81,7 @@ There are a number of basic types that are
In addition, the \c QtQuick module provides the following basic types:
\annotatedlist qtquickbasictypes
-
+\target object-types
\section1 Object Types
All of the object types provided by \c QtQuick are based on the \l{Item} type,
@@ -88,7 +89,7 @@ which itself derives from \l{QtQml::QtObject}{QtObject}. \l{qtqml-typereference
{QML object types} provided by the Qt QML module
(such as \l{QtQml::QtObject}{QtObject} and \l{QtQml::Component}{Component}) are also available when
you import \c QtQuick.
-
+\target visual-types
\section2 Visual Types
\list
@@ -129,7 +130,7 @@ Visual Item Transformations
\li \l {Translate} - Assigns item translation behaviors
\endlist
-
+\target user-input
\section2 User Input
\list
@@ -163,7 +164,7 @@ User Input Events
\li \l {KeyEvent} - Provides information about a key press event
\li \l {DragEvent} -Provides information about a drag event
\endlist
-
+\target positioning
\section2 Positioning
\list
@@ -174,7 +175,7 @@ User Input Events
\li \l {Flow} - Positions its children with wrapping support
\li \l {LayoutMirroring} - Attached property used to mirror layout behavior
\endlist
-
+\target states-transitions-and-animations
\section2 States, Transitions and Animations
States
@@ -211,6 +212,12 @@ Type-specific Animations
\li \l {ParentAnimation} - Animates parent changes
\li \l {AnchorAnimation} - Animates anchor changes
\li \l {PathAnimation} - Animates position along a path
+\li \l {XAnimator} - Animates x position asynchronously
+\li \l {YAnimator} - Animates y position asynchronously
+\li \l {ScaleAnimator} - Animates scale asynchronously
+\li \l {RotationAnimator} - Animates rotation asynchronously
+\li \l {OpacityAnimator} - Animates opacity asynchronously
+\li \l {UniformAnimator} - Animates a \l ShaderEffect uniform asynchronously
\endlist
Lower-level Animation Types
@@ -231,7 +238,7 @@ Animation paths
\li \l {PathAttribute} - Allows the setting of attributes along a \l {Path}
\li \l {PathPercent} - Modifies the item distribution along a \l {Path}
\endlist
-
+\target model-view-types-and-data-storage-and-access
\section2 Model/View Types And Data Storage And Access
QML Lists and Models
@@ -268,9 +275,10 @@ Views
Data Storage
\list
-\li \l {QtQuick.LocalStorage 2} - Singleton type providing simplified SQL access
+\li \l {Qt Quick Local Storage QML Types}{QtQuick.LocalStorage 2} - Singleton
+type providing simplified SQL access
\endlist
-
+\target graphical-effects
\section2 Graphical Effects
\list
@@ -278,9 +286,10 @@ Data Storage
\li \l {ShaderEffect} - Allows GLSL shaders to be used as graphical effects
\li \l {ShaderEffectSource} - Usable as a texture in ShaderEffect
\li \l {GridMesh} - Generates a grid mesh of vertices for use by ShaderEffect
-\li The \l{QtQuick.Particles 2} module provides a set of Particle System types for Qt Quick 2
+\li The \l{Qt Quick Particles QML Types}{QtQuick.Particles 2} module provides a
+set of Particle System types for Qt Quick 2
\endlist
-
+\target convenience-types
\section2 Convenience Types
\list
@@ -289,7 +298,7 @@ Data Storage
\li \l {Timer} - Provides timed triggers
\li \l {WorkerScript} - Enables the use of threads in a Qt Quick application
\endlist
-
+\target canvas-similar-to-html5-canvas
\section2 Canvas (similar to HTML5 canvas)
\list
diff --git a/src/quick/doc/src/qtquick.qdoc b/src/quick/doc/src/qtquick.qdoc
index 088e62d81a..392ae0af92 100644
--- a/src/quick/doc/src/qtquick.qdoc
+++ b/src/quick/doc/src/qtquick.qdoc
@@ -61,20 +61,18 @@ and visual effects can be supplemented through specialised components for
particle and shader effects.
\list
-\li \l{qtquick-visualcanvas-topic.html}{The Visual Canvas}
-\li \l{qtquick-input-topic.html}{User Input}
-\li \l{qtquick-positioning-topic.html}{Positioning}
-\li \l{qtquick-statesanimations-topic.html}{States, Transitions And Animations}
-\li \l{qtquick-modelviewsdata-topic.html}{Data - Models, Views and Data Storage}
-\li \l{qtquick-effects-topic.html}{Particles And Graphical Effects}
-\li \l{qtquick-convenience-topic.html}{Convenience Types}
+\li \l{Important Concepts In Qt Quick - The Visual Canvas}{The Visual Canvas}
+\li \l{Important Concepts In Qt Quick - User Input}{User Input}
+\li \l{Important Concepts In Qt Quick - Positioning}{Positioning}
+\li \l{Important Concepts in Qt Quick - States, Transitions and Animations}{States, Transitions And Animations}
+\li \l{Important Concepts In Qt Quick - Data - Models, Views and Data Storage}{Data - Models, Views and Data Storage}
+\li \l{Important Concepts In Qt Quick - Graphical Effects}{Particles And Graphical Effects}
+\li \l{Important Concepts In Qt Quick - Convenience Types}{Convenience Types}
\endlist
When using the \c QtQuick module, you will need to know how to write QML
-applications using the QML language. In particular, you should have a grasp
-of the \l{qtquick-quickstart-basics.html}{QML Basics} and
-\l{qtquick-quickstart-essentials.html}{QML Essentials} from the
-\l{QML Applications}.
+applications using the QML language. In particular, QML Basics and QML
+Essentials from the \l{QML Applications} page.
To find out more about using the QML language, see the \l{Qt QML} module documentation.
@@ -82,28 +80,28 @@ To find out more about using the QML language, see the \l{Qt QML} module documen
\section1 Qt Quick Module Documentation
\list
- \li \l{qtquick-qmltypereference.html}{Qt Quick QML Types}
+ \li \l{Qt Quick QML Types}
\list
- \li \l{qtquick-qmltypereference.html#importing-qtquick}{Importing QtQuick}
- \li \l{qtquick-qmltypereference.html#basic-types}{Basic Types}
- \li \l{qtquick-qmltypereference.html#object-types}{Object Types}
+ \li \l{importing-qtquick}{Importing QtQuick}
+ \li \l{basic-types}{Basic Types}
+ \li \l{object-types}{Object Types}
\list
- \li \l{qtquick-qmltypereference.html#visual-types}{Visual Types}
- \li \l{qtquick-qmltypereference.html#user-input}{User Input}
- \li \l{qtquick-qmltypereference.html#positioning}{Positioning}
- \li \l{qtquick-qmltypereference.html#states-transitions-and-animations}{States, Transitions And Animations}
- \li \l{qtquick-qmltypereference.html#model-view-types-and-data-storage-and-access}{Model/View Types And Data Storage And Access}
- \li \l{qtquick-qmltypereference.html#graphical-effects}{Graphical Effects}
- \li \l{qtquick-qmltypereference.html#convenience-types}{Convenience Types}
- \li \l{qtquick-qmltypereference.html#canvas-similar-to-html5-canvas}{Canvas (similar to HTML5 Canvas)}
+ \li \l{visual-types}{Visual Types}
+ \li \l{user-input}{User Input}
+ \li \l{positioning}{Positioning}
+ \li \l{states-transitions-and-animations}{States, Transitions And Animations}
+ \li \l{model-view-types-and-data-storage-and-access}{Model/View Types And Data Storage And Access}
+ \li \l{graphical-effects}{Graphical Effects}
+ \li \l{convenience-types}{Convenience Types}
+ \li \l{canvas-similar-to-html5-canvas}{Canvas (similar to HTML5 Canvas)}
\endlist
\endlist
- \li \l{qtquick-cppextensionpoints.html}{C++ Extension Points}
+ \li \l{C++ Extension Points Provided By Qt Quick}{C++ Extension Points}
\list
- \li \l{qtquick-cppextensionpoints.html#user-defined-qquickitem-derived-types}{Creating User-Defined QQuickItem-Derived Types}
- \li \l{qtquick-cppextensionpoints.html#scene-graph-related-classes}{Scene Graph-Related Classes}
- \li \l{qtquick-cppextensionpoints.html#pixmap-and-threaded-image-support}{Pixmap and Threaded Image Support}
+ \li \l{user-defined-qquickitem-derived-types}{Creating User-Defined QQuickItem-Derived Types}
+ \li \l{scene-graph-related-classes}{Scene Graph-Related Classes}
+ \li \l{pixmap-and-threaded-image-support}{Pixmap and Threaded Image Support}
\endlist
\endlist
@@ -117,20 +115,19 @@ Additional Qt Quick information:
\li \l{Qt Quick QML Types} - a list of QML types provided by the
\c{QtQuick} import
\list
- \li \l{QtQuick.XmlListModel 2}{XML List Model} - contains types
+ \li \l{Qt Quick XmlListModel QML Types}{XML List Model} - contains types
for creating models from XML data
- \li \l{QtQuick.LocalStorage 2}{Local Storage} - a submodule
+ \li \l{Qt Quick Local Storage QML Types}{Local Storage} - a submodule
containing a JavaScript interface for an SQLite database
- \li \l{QtQuick.Particles 2}{Particles} - provides a particle
+ \li \l{Qt Quick Particles QML Types}{Particles} - provides a particle
system for Qt Quick
- \li \l{QtQuick.Window 2}{Window} - contains types for creating
+ \li \l{Qt Quick Window QML Types}{Window} - contains types for creating
top-level windows and accessing screen information
\li \l{Qt Quick Dialogs}{Dialogs} - contains types for creating and
interacting with system dialogs
\endlist
\li \l{Qt Quick Release Notes} - list of changes and additions in the Qt Quick
\li \l{Qt Quick Code Samples} - list of all Qt Quick examples
-module
\endlist
Further information for writing QML applications:
diff --git a/src/quick/doc/src/tutorial.qdoc b/src/quick/doc/src/tutorial.qdoc
index bd07c9a98d..a4428c5818 100644
--- a/src/quick/doc/src/tutorial.qdoc
+++ b/src/quick/doc/src/tutorial.qdoc
@@ -29,7 +29,6 @@
\page qml-tutorial.html
\title QML Tutorial
\brief An introduction to the basic concepts and features of QML.
-\previouspage Introduction to the QML Language
\nextpage QML Tutorial 1 - Basic Types
This tutorial gives an introduction to QML, the declarative language for Qt Quick. It doesn't cover everything;
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index d9feb8d8eb..ba3592986c 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -112,7 +112,7 @@ QSGTexture *QQuickCanvasPixmap::texture()
Q_ASSERT(m_pixmap->textureFactory());
m_texture = m_pixmap->textureFactory()->createTexture(m_window);
} else {
- m_texture = QQuickWindowPrivate::get(m_window)->context->createTexture(m_image);
+ m_texture = m_window->createTextureFromImage(m_image, QQuickWindow::TextureCanUseAtlas);
}
}
return m_texture;
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 2fb6cb9f63..2a9e0f2ac2 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -488,45 +488,45 @@ public:
}
QQuickContext2D* context;
- static QV4::ReturnedValue method_get_globalAlpha(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_globalAlpha(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_globalCompositeOperation(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_globalCompositeOperation(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_fillStyle(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_fillStyle(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_fillRule(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_fillRule(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_strokeStyle(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_strokeStyle(QV4::SimpleCallContext *ctx);
-
- static QV4::ReturnedValue method_get_lineCap(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_lineCap(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_lineJoin(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_lineJoin(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_lineWidth(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_lineWidth(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_miterLimit(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_miterLimit(QV4::SimpleCallContext *ctx);
-
- static QV4::ReturnedValue method_get_shadowBlur(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_shadowBlur(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_shadowColor(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_shadowColor(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_shadowOffsetX(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_shadowOffsetX(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_shadowOffsetY(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_shadowOffsetY(QV4::SimpleCallContext *ctx);
+ static QV4::ReturnedValue method_get_globalAlpha(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_globalAlpha(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_globalCompositeOperation(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_globalCompositeOperation(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_fillStyle(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_fillStyle(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_fillRule(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_fillRule(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_strokeStyle(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_strokeStyle(QV4::CallContext *ctx);
+
+ static QV4::ReturnedValue method_get_lineCap(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_lineCap(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_lineJoin(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_lineJoin(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_lineWidth(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_lineWidth(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_miterLimit(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_miterLimit(QV4::CallContext *ctx);
+
+ static QV4::ReturnedValue method_get_shadowBlur(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_shadowBlur(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_shadowColor(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_shadowColor(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_shadowOffsetX(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_shadowOffsetX(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_shadowOffsetY(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_shadowOffsetY(QV4::CallContext *ctx);
// should these two be on the proto?
- static QV4::ReturnedValue method_get_path(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_path(QV4::SimpleCallContext *ctx);
+ static QV4::ReturnedValue method_get_path(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_path(QV4::CallContext *ctx);
- static QV4::ReturnedValue method_get_font(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_font(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_textAlign(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_textAlign(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_textBaseline(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_set_textBaseline(QV4::SimpleCallContext *ctx);
+ static QV4::ReturnedValue method_get_font(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_font(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_textAlign(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_textAlign(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_textBaseline(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_set_textBaseline(QV4::CallContext *ctx);
protected:
static void destroy(Managed *that)
@@ -594,50 +594,50 @@ public:
defineAccessorProperty(QStringLiteral("canvas"), QQuickJSContext2DPrototype::method_get_canvas, 0);
}
- static QV4::ReturnedValue method_get_canvas(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_restore(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_reset(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_save(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_rotate(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_scale(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_translate(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_setTransform(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_transform(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_resetTransform(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_shear(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_createLinearGradient(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_createRadialGradient(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_createConicalGradient(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_createPattern(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_clearRect(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_fillRect(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_strokeRect(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_arc(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_arcTo(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_beginPath(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_bezierCurveTo(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_clip(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_closePath(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_fill(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_lineTo(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_moveTo(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_quadraticCurveTo(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_rect(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_roundedRect(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_ellipse(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_text(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_stroke(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_isPointInPath(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_drawFocusRing(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_setCaretSelectionRect(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_caretBlinkRate(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_fillText(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_strokeText(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_measureText(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_drawImage(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_createImageData(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_getImageData(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_putImageData(QV4::SimpleCallContext *ctx);
+ static QV4::ReturnedValue method_get_canvas(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_restore(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_reset(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_save(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_rotate(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_scale(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_translate(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_setTransform(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_transform(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_resetTransform(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_shear(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_createLinearGradient(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_createRadialGradient(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_createConicalGradient(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_createPattern(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_clearRect(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_fillRect(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_strokeRect(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_arc(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_arcTo(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_beginPath(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_bezierCurveTo(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_clip(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_closePath(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_fill(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_lineTo(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_moveTo(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_quadraticCurveTo(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_rect(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_roundedRect(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_ellipse(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_text(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_stroke(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_isPointInPath(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_drawFocusRing(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_setCaretSelectionRect(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_caretBlinkRate(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_fillText(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_strokeText(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_measureText(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_drawImage(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_createImageData(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_getImageData(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_putImageData(QV4::CallContext *ctx);
};
@@ -659,7 +659,7 @@ public:
bool patternRepeatX:1;
bool patternRepeatY:1;
- static QV4::ReturnedValue gradient_proto_addColorStop(QV4::SimpleCallContext *ctx);
+ static QV4::ReturnedValue gradient_proto_addColorStop(QV4::CallContext *ctx);
protected:
static void destroy(Managed *that)
{
@@ -880,7 +880,7 @@ struct QQuickJSContext2DPixelData : public QV4::Object
static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty);
static void putIndexed(QV4::Managed *m, uint index, const QV4::ValueRef value);
- static QV4::ReturnedValue proto_get_length(QV4::SimpleCallContext *ctx);
+ static QV4::ReturnedValue proto_get_length(QV4::CallContext *ctx);
QImage image;
};
@@ -904,12 +904,13 @@ struct QQuickJSContext2DImageData : public QV4::Object
defineAccessorProperty(QStringLiteral("data"), method_get_data, 0);
}
- static QV4::ReturnedValue method_get_width(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_height(QV4::SimpleCallContext *ctx);
- static QV4::ReturnedValue method_get_data(QV4::SimpleCallContext *ctx);
+ static QV4::ReturnedValue method_get_width(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_height(QV4::CallContext *ctx);
+ static QV4::ReturnedValue method_get_data(QV4::CallContext *ctx);
- static void markObjects(Managed *that) {
- static_cast<QQuickJSContext2DImageData *>(that)->pixelData.mark();
+ static void markObjects(Managed *that, QV4::ExecutionEngine *engine) {
+ static_cast<QQuickJSContext2DImageData *>(that)->pixelData.mark(engine);
+ QV4::Object::markObjects(that, engine);
}
@@ -949,7 +950,7 @@ static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV8Engine* engi
This property is read only.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_get_canvas(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_get_canvas(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -965,7 +966,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_get_canvas(QV4::SimpleCall
\sa save()
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_restore(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_restore(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -980,7 +981,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_restore(QV4::SimpleCallCon
\qmlmethod object QtQuick::Context2D::reset()
Resets the context state and properties to the default values.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_reset(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_reset(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1022,7 +1023,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_reset(QV4::SimpleCallConte
The current path is NOT part of the drawing state. The path can be reset by
invoking the beginPath() method.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_save(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_save(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1052,7 +1053,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_save(QV4::SimpleCallContex
where the \a angle of rotation is in radians.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_rotate(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_rotate(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1081,7 +1082,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_rotate(QV4::SimpleCallCont
\image qml-item-canvas-scale.png
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_scale(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_scale(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1127,7 +1128,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_scale(QV4::SimpleCallConte
\sa transform()
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_setTransform(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_setTransform(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1157,7 +1158,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_setTransform(QV4::SimpleCa
\sa setTransform()
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_transform(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_transform(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1184,7 +1185,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_transform(QV4::SimpleCallC
Translating the origin enables you to draw patterns of different objects on the canvas
without having to measure the coordinates manually for each shape.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_translate(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_translate(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1205,7 +1206,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_translate(QV4::SimpleCallC
\sa transform(), setTransform(), reset()
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_resetTransform(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_resetTransform(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1224,7 +1225,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_resetTransform(QV4::Simple
Shears the transformation matrix by \a sh in the horizontal direction and
\a sv in the vertical direction.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_shear(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_shear(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1245,7 +1246,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_shear(QV4::SimpleCallConte
The value must be in the range from \c 0.0 (fully transparent) to \c 1.0 (fully opaque).
The default value is \c 1.0.
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_globalAlpha(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_globalAlpha(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1255,7 +1256,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_globalAlpha(QV4::SimpleCallCont
return QV4::Encode(r->context->state.globalAlpha);
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_globalAlpha(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_globalAlpha(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1300,7 +1301,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalAlpha(QV4::SimpleCallCont
extension composition modes are provided as "vendorName-operationName" syntax, for example: QPainter::CompositionMode_Exclusion is provided as
"qt-exclusion".
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_globalCompositeOperation(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_globalCompositeOperation(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1310,7 +1311,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_globalCompositeOperation(QV4::S
return QV4::Encode(ctx->engine->newString(qt_composite_mode_to_string(r->context->state.globalCompositeOperation)));
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_globalCompositeOperation(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_globalCompositeOperation(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1318,7 +1319,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalCompositeOperation(QV4::S
CHECK_CONTEXT_SETTER(r)
if (!ctx->callData->argc)
- ctx->throwTypeError();
+ return ctx->throwTypeError();
QString mode = ctx->callData->args[0].toQString();
QPainter::CompositionMode cm = qt_composite_mode_from_string(mode);
@@ -1355,7 +1356,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalCompositeOperation(QV4::S
\sa createPattern()
\sa strokeStyle
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_fillStyle(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_fillStyle(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1377,7 +1378,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_fillStyle(QV4::SimpleCallContex
return r->context->m_fillStyle.value();
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1425,7 +1426,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::SimpleCallContex
\sa fillStyle
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_fillRule(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_fillRule(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1436,7 +1437,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_fillRule(QV4::SimpleCallContext
return engine->fromVariant(r->context->state.fillRule);
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_fillRule(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_fillRule(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1470,7 +1471,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillRule(QV4::SimpleCallContext
\sa createPattern()
\sa fillStyle
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_strokeStyle(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_strokeStyle(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1492,7 +1493,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_strokeStyle(QV4::SimpleCallCont
return r->context->m_strokeStyle.value();
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1547,7 +1548,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::SimpleCallCont
\sa strokeStyle
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1594,7 +1595,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::
\sa strokeStyle
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1649,7 +1650,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::
\sa strokeStyle
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1659,7 +1660,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4:
QV8Engine *engine = ctx->engine->v8Engine;
- if (ctx->callData->argc == 6) {
+ if (ctx->callData->argc == 3) {
qreal x = ctx->callData->args[0].toNumber();
qreal y = ctx->callData->args[1].toNumber();
qreal angle = DEGREES(ctx->callData->args[2].toNumber());
@@ -1725,7 +1726,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4:
\sa strokeStyle
\sa fillStyle
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1797,7 +1798,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::SimpleC
\endlist
Other values are ignored.
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_lineCap(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_lineCap(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1816,7 +1817,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_lineCap(QV4::SimpleCallContext
return QV4::Encode(ctx->engine->newString(QStringLiteral("butt")));
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_lineCap(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_lineCap(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1855,7 +1856,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineCap(QV4::SimpleCallContext
\endlist
Other values are ignored.
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_lineJoin(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_lineJoin(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1874,7 +1875,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_lineJoin(QV4::SimpleCallContext
return QV4::Encode(ctx->engine->newString(QStringLiteral("miter")));
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_lineJoin(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_lineJoin(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1882,7 +1883,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineJoin(QV4::SimpleCallContext
CHECK_CONTEXT_SETTER(r)
if (!ctx->callData->argc)
- ctx->throwTypeError();
+ return ctx->throwTypeError();
QString lineJoin = ctx->callData->args[0].toQString();
Qt::PenJoinStyle join;
@@ -1906,7 +1907,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineJoin(QV4::SimpleCallContext
\qmlproperty real QtQuick::Context2D::lineWidth
Holds the current line width. Values that are not finite values greater than zero are ignored.
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_lineWidth(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_lineWidth(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1916,7 +1917,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_lineWidth(QV4::SimpleCallContex
return QV4::Encode(r->context->state.lineWidth);
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_lineWidth(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_lineWidth(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1937,7 +1938,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineWidth(QV4::SimpleCallContex
Holds the current miter limit ratio.
The default miter limit value is 10.0.
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_miterLimit(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_miterLimit(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1947,7 +1948,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_miterLimit(QV4::SimpleCallConte
return QV4::Encode(r->context->state.miterLimit);
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1968,7 +1969,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_miterLimit(QV4::SimpleCallConte
\qmlproperty real QtQuick::Context2D::shadowBlur
Holds the current level of blur applied to shadows
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_shadowBlur(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_shadowBlur(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1978,7 +1979,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowBlur(QV4::SimpleCallConte
return QV4::Encode(r->context->state.shadowBlur);
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_shadowBlur(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_shadowBlur(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -1998,7 +1999,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowBlur(QV4::SimpleCallConte
\qmlproperty string QtQuick::Context2D::shadowColor
Holds the current shadow color.
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_shadowColor(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_shadowColor(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2008,7 +2009,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowColor(QV4::SimpleCallCont
return QV4::Encode(ctx->engine->newString(r->context->state.shadowColor.name()));
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_shadowColor(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_shadowColor(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2033,7 +2034,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowColor(QV4::SimpleCallCont
\sa shadowOffsetY
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetX(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetX(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2043,7 +2044,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetX(QV4::SimpleCallCo
return QV4::Encode(r->context->state.shadowOffsetX);
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetX(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetX(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2063,7 +2064,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetX(QV4::SimpleCallCo
\sa shadowOffsetX
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetY(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetY(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2073,7 +2074,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_shadowOffsetY(QV4::SimpleCallCo
return QV4::Encode(r->context->state.shadowOffsetY);
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetY(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetY(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2088,7 +2089,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_shadowOffsetY(QV4::SimpleCallCo
return QV4::Encode::undefined();
}
-QV4::ReturnedValue QQuickJSContext2D::method_get_path(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_path(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2098,7 +2099,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_path(QV4::SimpleCallContext *ct
return r->context->m_v4path.value();
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2123,7 +2124,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::SimpleCallContext *ct
\qmlmethod object QtQuick::Context2D::clearRect(real x, real y, real w, real h)
Clears all pixels on the canvas in the given rectangle to transparent black.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_clearRect(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_clearRect(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2145,7 +2146,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_clearRect(QV4::SimpleCallC
\sa fillStyle
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillRect(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillRect(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2167,7 +2168,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillRect(QV4::SimpleCallCo
\sa lineJoin
\sa miterLimit
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeRect(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeRect(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2201,7 +2202,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeRect(QV4::SimpleCall
\sa arcTo, {http://www.w3.org/TR/2dcontext/#dom-context-2d-arc}{W3C's 2D
Context Standard for arc()}
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_arc(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_arc(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2253,7 +2254,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arc(QV4::SimpleCallContext
\sa arc, {http://www.w3.org/TR/2dcontext/#dom-context-2d-arcto}{W3C's 2D
Context Standard for arcTo()}
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_arcTo(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_arcTo(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2281,7 +2282,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_arcTo(QV4::SimpleCallConte
Resets the current path to a new path.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_beginPath(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_beginPath(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2312,7 +2313,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_beginPath(QV4::SimpleCallC
\sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-beziercurveto}{W3C 2d context standard for bezierCurveTo}
\sa {http://www.openrise.com/lab/FlowerPower/}{The beautiful flower demo by using bezierCurveTo}
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_bezierCurveTo(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_bezierCurveTo(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2361,7 +2362,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_bezierCurveTo(QV4::SimpleC
\sa fill()
\sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-clip}{W3C 2d context standard for clip}
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_clip(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_clip(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2379,7 +2380,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_clip(QV4::SimpleCallContex
\sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-closepath}{W3C 2d context standard for closePath}
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_closePath(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_closePath(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2401,7 +2402,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_closePath(QV4::SimpleCallC
\sa fillStyle
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_fill(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_fill(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2416,7 +2417,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fill(QV4::SimpleCallContex
Draws a line from the current position to the point (x, y).
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_lineTo(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_lineTo(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2441,7 +2442,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_lineTo(QV4::SimpleCallCont
Creates a new subpath with the given point.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_moveTo(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_moveTo(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2465,7 +2466,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_moveTo(QV4::SimpleCallCont
See \l{http://www.w3.org/TR/2dcontext/#dom-context-2d-quadraticcurveto}{W3C 2d context standard for for quadraticCurveTo}
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_quadraticCurveTo(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_quadraticCurveTo(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2491,7 +2492,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_quadraticCurveTo(QV4::Simp
Adds a rectangle at position (\c x, \c y), with the given width \c w and height \c h, as a closed subpath.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_rect(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_rect(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2508,7 +2509,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_rect(QV4::SimpleCallContex
Adds the given rectangle rect with rounded corners to the path. The \c xRadius and \c yRadius arguments specify the radius of the
ellipses defining the corners of the rounded rectangle.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_roundedRect(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_roundedRect(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2532,7 +2533,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_roundedRect(QV4::SimpleCal
The ellipse is composed of a clockwise curve, starting and finishing at zero degrees (the 3 o'clock position).
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_ellipse(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_ellipse(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2551,7 +2552,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_ellipse(QV4::SimpleCallCon
Adds the given \c text to the path as a set of closed subpaths created from the current context font supplied.
The subpaths are positioned so that the left end of the text's baseline lies at the point specified by (\c x, \c y).
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_text(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_text(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2577,7 +2578,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_text(QV4::SimpleCallContex
\sa strokeStyle
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_stroke(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_stroke(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2594,7 +2595,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_stroke(QV4::SimpleCallCont
\sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath}{W3C 2d context standard for isPointInPath}
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_isPointInPath(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_isPointInPath(QV4::CallContext *ctx)
{
QV4::ExecutionEngine *v4 = ctx->engine;
QV4::Scope scope(v4);
@@ -2607,21 +2608,21 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_isPointInPath(QV4::SimpleC
return QV4::Primitive::fromBoolean(pointInPath).asReturnedValue();
}
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawFocusRing(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawFocusRing(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::drawFocusRing is not supported");
}
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_setCaretSelectionRect(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_setCaretSelectionRect(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Context2D::setCaretSelectionRect is not supported");
}
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_caretBlinkRate(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_caretBlinkRate(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
@@ -2651,7 +2652,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_caretBlinkRate(QV4::Simple
The default font value is "10px sans-serif".
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_font(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_font(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2660,13 +2661,15 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_font(QV4::SimpleCallContext *ct
return QV4::Encode(ctx->engine->newString(r->context->state.font.toString()));
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_font(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_font(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
CHECK_CONTEXT_SETTER(r)
QV4::Scoped<QV4::String> s(scope, ctx->argument(0), QV4::Scoped<QV4::String>::Convert);
+ if (scope.engine->hasException)
+ return QV4::Encode::undefined();
QFont font = qt_font_from_string(s->toQString(), r->context->state.font);
if (font != r->context->state.font) {
r->context->state.font = font;
@@ -2688,7 +2691,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_font(QV4::SimpleCallContext *ct
\endlist
Other values are ignored. The default value is "start".
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_textAlign(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_textAlign(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2710,13 +2713,15 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_textAlign(QV4::SimpleCallContex
return QV4::Encode(ctx->engine->newString(QStringLiteral("start")));
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_textAlign(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_textAlign(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
CHECK_CONTEXT_SETTER(r)
QV4::Scoped<QV4::String> s(scope, ctx->argument(0), QV4::Scoped<QV4::String>::Convert);
+ if (scope.engine->hasException)
+ return QV4::Encode::undefined();
QString textAlign = s->toQString();
QQuickContext2D::TextAlignType ta;
@@ -2754,7 +2759,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textAlign(QV4::SimpleCallContex
\endlist
Other values are ignored. The default value is "alphabetic".
*/
-QV4::ReturnedValue QQuickJSContext2D::method_get_textBaseline(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_get_textBaseline(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2776,12 +2781,14 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_textBaseline(QV4::SimpleCallCon
return QV4::Encode(ctx->engine->newString(QStringLiteral("alphabetic")));
}
-QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
CHECK_CONTEXT_SETTER(r)
QV4::Scoped<QV4::String> s(scope, ctx->argument(0), QV4::Scoped<QV4::String>::Convert);
+ if (scope.engine->hasException)
+ return QV4::Encode::undefined();
QString textBaseline = s->toQString();
QQuickContext2D::TextBaseLineType tb;
@@ -2812,7 +2819,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(QV4::SimpleCallCon
\sa textBaseline
\sa strokeText
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillText(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillText(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2836,7 +2843,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_fillText(QV4::SimpleCallCo
\sa textBaseline
\sa fillText
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeText(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeText(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2871,7 +2878,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeText(QV4::SimpleCall
\qmlmethod variant QtQuick::Context2D::measureText(text)
Returns a TextMetrics object with the metrics of the given text in the current font.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_measureText(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_measureText(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2947,7 +2954,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_measureText(QV4::SimpleCal
\sa {http://www.w3.org/TR/2dcontext/#dom-context-2d-drawimage}{W3C 2d context standard for drawImage}
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject);
@@ -2974,7 +2981,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallC
} else if (arg->isObject()) {
if (QV4::Referenced<QV4::QObjectWrapper> qobjectWrapper = arg->asRef<QV4::QObjectWrapper>()) {
if (QQuickImage *imageItem = qobject_cast<QQuickImage*>(qobjectWrapper->object())) {
- pixmap.take(r->context->createPixmap(imageItem->source()));
+ pixmap = r->context->createPixmap(imageItem->source());
} else if (QQuickCanvasItem *canvas = qobject_cast<QQuickCanvasItem*>(qobjectWrapper->object())) {
QImage img = canvas->toImage();
if (!img.isNull())
@@ -3083,12 +3090,12 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::SimpleCallC
\qmlproperty int QtQuick::CanvasImageData::width
Holds the actual width dimension of the data in the ImageData object, in device pixels.
*/
-QV4::ReturnedValue QQuickJSContext2DImageData::method_get_width(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DImageData::method_get_width(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, ctx->callData->thisObject);
if (!imageData)
- ctx->throwTypeError();
+ return ctx->throwTypeError();
QV4::Scoped<QQuickJSContext2DPixelData> r(scope, imageData->pixelData.as<QQuickJSContext2DPixelData>());
if (!r)
return QV4::Encode(0);
@@ -3099,12 +3106,12 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_width(QV4::SimpleCallC
\qmlproperty int QtQuick::CanvasImageData::height
Holds the actual height dimension of the data in the ImageData object, in device pixels.
*/
-QV4::ReturnedValue QQuickJSContext2DImageData::method_get_height(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DImageData::method_get_height(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, ctx->callData->thisObject);
if (!imageData)
- ctx->throwTypeError();
+ return ctx->throwTypeError();
QV4::Scoped<QQuickJSContext2DPixelData> r(scope, imageData->pixelData.as<QQuickJSContext2DPixelData>());
if (!r)
return QV4::Encode(0);
@@ -3115,12 +3122,12 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_height(QV4::SimpleCall
\qmlproperty object QtQuick::CanvasImageData::data
Holds the one-dimensional array containing the data in RGBA order, as integers in the range 0 to 255.
*/
-QV4::ReturnedValue QQuickJSContext2DImageData::method_get_data(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DImageData::method_get_data(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, ctx->callData->thisObject);
if (!imageData)
- ctx->throwTypeError();
+ return ctx->throwTypeError();
return imageData->pixelData.asReturnedValue();
}
@@ -3142,7 +3149,7 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_data(QV4::SimpleCallCo
The length attribute of a CanvasPixelArray object must return this h×w×4 number value.
This property is read only.
*/
-QV4::ReturnedValue QQuickJSContext2DPixelData::proto_get_length(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPixelData::proto_get_length(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2DPixelData> r(scope, ctx->callData->thisObject.as<QQuickJSContext2DPixelData>());
@@ -3158,7 +3165,7 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(QV4::Managed *m, uint
QV4::Scope scope(v4);
QV4::Scoped<QQuickJSContext2DPixelData> r(scope, m->as<QQuickJSContext2DPixelData>());
if (!m)
- m->engine()->current->throwTypeError();
+ return m->engine()->current->throwTypeError();
if (r && index < static_cast<quint32>(r->image.width() * r->image.height() * 4)) {
if (hasProperty)
@@ -3188,9 +3195,14 @@ void QQuickJSContext2DPixelData::putIndexed(QV4::Managed *m, uint index, const Q
{
QV4::ExecutionEngine *v4 = m->engine();
QV4::Scope scope(v4);
+ if (scope.hasException())
+ return;
+
QV4::Scoped<QQuickJSContext2DPixelData> r(scope, m->as<QQuickJSContext2DPixelData>());
- if (!r)
- m->engine()->current->throwTypeError();
+ if (!r) {
+ v4->current->throwTypeError();
+ return;
+ }
const int v = value->toInt32();
if (r && index < static_cast<quint32>(r->image.width() * r->image.height() * 4) && v >= 0 && v <= 255) {
@@ -3237,7 +3249,7 @@ void QQuickJSContext2DPixelData::putIndexed(QV4::Managed *m, uint index, const Q
\sa Canvas::loadImage(), QtQuick::Canvas::unloadImage(),
QtQuick::Canvas::isImageLoaded
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject.as<QQuickJSContext2D>());
@@ -3277,7 +3289,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::Simpl
\qmlmethod CanvasImageData QtQuick::Context2D::getImageData(real sx, real sy, real sw, real sh)
Returns an CanvasImageData object containing the image data for the given rectangle of the canvas.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject.as<QQuickJSContext2D>());
@@ -3305,7 +3317,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(QV4::SimpleCa
\qmlmethod object QtQuick::Context2D::putImageData(CanvasImageData imageData, real dx, real dy, real dirtyX, real dirtyY, real dirtyWidth, real dirtyHeight)
Paints the data from the given ImageData object onto the canvas. If a dirty rectangle (\a dirtyX, \a dirtyY, \a dirtyWidth, \a dirtyHeight) is provided, only the pixels from that rectangle are painted.
*/
-QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->callData->thisObject.as<QQuickJSContext2D>());
@@ -3406,7 +3418,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_putImageData(QV4::SimpleCa
gradient.addColorStop(0.7, 'rgba(0, 255, 255, 1');
\endcode
*/
-QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::SimpleCallContext *ctx)
+QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQuickContext2DStyle> style(scope, ctx->callData->thisObject.as<QQuickContext2DStyle>());
@@ -4101,7 +4113,7 @@ void QQuickContext2D::init(QQuickCanvasItem *canvasItem, const QVariantMap &args
m_texture->moveToThread(renderThread);
if (m_renderTarget == QQuickCanvasItem::FramebufferObject && renderThread != sceneGraphThread) {
- QOpenGLContext *cc = QQuickWindowPrivate::get(window)->context->glContext();
+ QOpenGLContext *cc = QQuickWindowPrivate::get(window)->context->openglContext();
m_surface = window;
m_glContext = new QOpenGLContext;
m_glContext->setFormat(cc->format());
diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri
index cbdc5fd80f..3996512f9d 100644
--- a/src/quick/items/items.pri
+++ b/src/quick/items/items.pri
@@ -139,6 +139,21 @@ HEADERS += \
$$PWD/qquickshadereffectnode_p.h \
$$PWD/qquickshadereffectsource_p.h \
-include(context2d/context2d.pri)
+OTHER_FILES += \
+ $$PWD/shaders/sprite.vert \
+ $$PWD/shaders/sprite.frag \
+ $$PWD/shaders/shadereffect.vert \
+ $$PWD/shaders/shadereffect.frag \
+ $$PWD/shaders/shadereffectfallback.vert \
+ $$PWD/shaders/shadereffectfallback.frag \
+ $$PWD/shaders/sprite_core.vert \
+ $$PWD/shaders/sprite_core.frag \
+ $$PWD/shaders/shadereffect_core.vert \
+ $$PWD/shaders/shadereffect_core.frag \
+ $$PWD/shaders/shadereffectfallback_core.vert \
+ $$PWD/shaders/shadereffectfallback_core.frag
+RESOURCES += \
+ $$PWD/items.qrc
+include(context2d/context2d.pri)
diff --git a/src/quick/items/items.qrc b/src/quick/items/items.qrc
new file mode 100644
index 0000000000..671d8acdbb
--- /dev/null
+++ b/src/quick/items/items.qrc
@@ -0,0 +1,16 @@
+<RCC>
+ <qresource prefix="/items">
+ <file>shaders/sprite.frag</file>
+ <file>shaders/sprite.vert</file>
+ <file>shaders/shadereffect.vert</file>
+ <file>shaders/shadereffect.frag</file>
+ <file>shaders/shadereffectfallback.frag</file>
+ <file>shaders/shadereffectfallback.vert</file>
+ <file>shaders/shadereffect_core.frag</file>
+ <file>shaders/shadereffect_core.vert</file>
+ <file>shaders/shadereffectfallback_core.frag</file>
+ <file>shaders/shadereffectfallback_core.vert</file>
+ <file>shaders/sprite_core.frag</file>
+ <file>shaders/sprite_core.vert</file>
+ </qresource>
+</RCC>
diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp
index 846de15581..64b8f257dc 100644
--- a/src/quick/items/qquickanimatedsprite.cpp
+++ b/src/quick/items/qquickanimatedsprite.cpp
@@ -57,39 +57,6 @@
QT_BEGIN_NAMESPACE
-static const char vertexShaderCode[] =
- "attribute highp vec2 vPos;\n"
- "attribute highp vec2 vTex;\n"
- "uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress\n"
- "uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation)\n"
- "\n"
- "uniform highp mat4 qt_Matrix;\n"
- "\n"
- "varying highp vec4 fTexS;\n"
- "varying lowp float progress;\n"
- "\n"
- "\n"
- "void main() {\n"
- " progress = animData.z;\n"
- " //Calculate frame location in texture\n"
- " fTexS.xy = animPos.xy + vTex.xy * animData.xy;\n"
- " //Next frame is also passed, for interpolation\n"
- " fTexS.zw = animPos.zw + vTex.xy * animData.xy;\n"
- "\n"
- " gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1);\n"
- "}\n";
-
-static const char fragmentShaderCode[] =
- "uniform sampler2D _qt_texture;\n"
- "uniform lowp float qt_Opacity;\n"
- "\n"
- "varying highp vec4 fTexS;\n"
- "varying lowp float progress;\n"
- "\n"
- "void main() {\n"
- " gl_FragColor = mix(texture2D(_qt_texture, fTexS.xy), texture2D(_qt_texture, fTexS.zw), progress) * qt_Opacity;\n"
- "}\n";
-
class QQuickAnimatedSpriteMaterial : public QSGMaterial
{
public:
@@ -134,16 +101,11 @@ QQuickAnimatedSpriteMaterial::~QQuickAnimatedSpriteMaterial()
class AnimatedSpriteMaterialData : public QSGMaterialShader
{
public:
- AnimatedSpriteMaterialData(const char * /* vertexFile */ = 0, const char * /* fragmentFile */ = 0)
+ AnimatedSpriteMaterialData()
+ : QSGMaterialShader()
{
- }
-
- void deactivate() {
- QSGMaterialShader::deactivate();
-
- for (int i=0; i<8; ++i) {
- program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
- }
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/items/shaders/sprite.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/items/shaders/sprite.frag"));
}
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
@@ -166,9 +128,6 @@ public:
m_animPos_id = program()->uniformLocation("animPos");
}
- virtual const char *vertexShader() const { return vertexShaderCode; }
- virtual const char *fragmentShader() const { return fragmentShaderCode; }
-
virtual char const *const *attributeNames() const {
static const char *attr[] = {
"vPos",
@@ -182,12 +141,8 @@ public:
int m_opacity_id;
int m_animData_id;
int m_animPos_id;
-
- static float chunkOfBytes[1024];
};
-float AnimatedSpriteMaterialData::chunkOfBytes[1024];
-
QSGMaterialShader *QQuickAnimatedSpriteMaterial::createShader() const
{
return new AnimatedSpriteMaterialData;
@@ -219,7 +174,7 @@ struct AnimatedSpriteVertices {
as multiple frames in the same image file. You can play it at a fixed speed, at the
frame rate of your display, or manually advance and control the progress.
- For details of how a sprite animation is defined see the \l{Sprite Animation} overview.
+ For details of how a sprite animation is defined see the \l{Sprite Animations} overview.
Note that the AnimatedSprite type does not use Sprite types to define multiple animations,
but instead encapsulates a single animation itself.
*/
diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp
index 9fc9752707..0bed5e96a2 100644
--- a/src/quick/items/qquickborderimage.cpp
+++ b/src/quick/items/qquickborderimage.cpp
@@ -301,7 +301,7 @@ void QQuickBorderImage::load()
d->oldSourceSize = sourceSize();
emit sourceSizeChanged();
}
- update();
+ pixmapChange();
return;
} else {
if (d->url.path().endsWith(QLatin1String("sci"))) {
@@ -509,7 +509,7 @@ void QQuickBorderImage::requestFinished()
emit sourceSizeChanged();
}
- update();
+ pixmapChange();
}
#define BORDERIMAGE_MAX_REDIRECT 16
@@ -551,7 +551,7 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
{
Q_D(QQuickBorderImage);
- QSGTexture *texture = d->sceneGraphContext()->textureForFactory(d->pix.textureFactory(), window());
+ QSGTexture *texture = d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window());
if (!texture || width() <= 0 || height() <= 0) {
delete oldNode;
@@ -561,6 +561,7 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
QSGImageNode *node = static_cast<QSGImageNode *>(oldNode);
bool updatePixmap = d->pixmapChanged;
+ d->pixmapChanged = false;
if (!node) {
node = d->sceneGraphContext()->createImageNode();
updatePixmap = true;
@@ -634,10 +635,7 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
void QQuickBorderImage::pixmapChange()
{
Q_D(QQuickBorderImage);
-
d->pixmapChanged = true;
-
- // When the pixmap changes, such as being deleted, we need to update the textures
update();
}
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index f0a68b184a..ae174d86e0 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1116,10 +1116,10 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event)
hData.velocity = 0;
}
- if ((hMoved && !prevHMoved) || (vMoved && !prevVMoved)) {
- draggingStarting();
+ draggingStarting();
+
+ if ((hMoved && !prevHMoved) || (vMoved && !prevVMoved))
q->movementStarting();
- }
qint64 currentTimestamp = computeCurrentTime(event);
qreal elapsed = qreal(currentTimestamp - (lastPos.isNull() ? lastPressTime : lastPosTime)) / 1000.;
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index 1c6168fbc5..c9e6d4d7e2 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -1248,7 +1248,7 @@ bool QQuickGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
\image gridview-layout-toptobottom-rtl-btt.png
\endtable
- \sa {quick/modelviews/gridview}{GridView example}
+ \sa {QML Data Models}, ListView, PathView, {Qt Quick Examples - Views}
*/
QQuickGridView::QQuickGridView(QQuickItem *parent)
diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp
index d6be13f3c0..0708304051 100644
--- a/src/quick/items/qquickimage.cpp
+++ b/src/quick/items/qquickimage.cpp
@@ -532,17 +532,17 @@ QRectF QQuickImage::boundingRect() const
QSGTextureProvider *QQuickImage::textureProvider() const
{
Q_D(const QQuickImage);
+
+ if (!d->window || !d->sceneGraphRenderContext() || QThread::currentThread() != d->sceneGraphRenderContext()->thread()) {
+ qWarning("QQuickImage::textureProvider: can only be queried on the rendering thread of an exposed window");
+ return 0;
+ }
+
if (!d->provider) {
- // Make sure it gets thread affinity on the rendering thread so deletion works properly..
- Q_ASSERT_X(d->window
- && d->sceneGraphContext()
- && QThread::currentThread() == d->sceneGraphContext()->thread(),
- "QQuickImage::textureProvider",
- "Cannot be used outside the GUI thread");
QQuickImagePrivate *dd = const_cast<QQuickImagePrivate *>(d);
dd->provider = new QQuickImageTextureProvider;
dd->provider->m_smooth = d->smooth;
- dd->provider->m_texture = d->sceneGraphContext()->textureForFactory(d->pix.textureFactory(), window());
+ dd->provider->m_texture = d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window());
}
return d->provider;
@@ -552,7 +552,7 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
Q_D(QQuickImage);
- QSGTexture *texture = d->sceneGraphContext()->textureForFactory(d->pix.textureFactory(), window());
+ QSGTexture *texture = d->sceneGraphRenderContext()->textureForFactory(d->pix.textureFactory(), window());
// Copy over the current texture state into the texture provider...
if (d->provider) {
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index c3b221b2c8..c11bf904be 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -732,7 +732,7 @@ void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, co
do {
isNextItem = false;
if (currentItem->isVisible() && currentItem->isEnabled()) {
- currentItem->setFocus(true);
+ currentItem->forceActiveFocus(Qt::OtherFocusReason);
} else {
QObject *attached =
qmlAttachedPropertiesObject<QQuickKeyNavigationAttached>(currentItem, false);
@@ -3827,7 +3827,12 @@ void QQuickItem::setBaselineOffset(qreal offset)
void QQuickItem::update()
{
Q_D(QQuickItem);
- Q_ASSERT(flags() & ItemHasContents);
+ if (!(flags() & ItemHasContents)) {
+#ifndef QT_NO_DEBUG
+ qWarning() << metaObject()->className() << ": Update called for a item without content";
+#endif
+ return;
+ }
d->dirty(QQuickItemPrivate::Content);
}
@@ -4125,7 +4130,7 @@ QQmlListProperty<QQuickItem> QQuickItemPrivate::children()
}
/*!
- \qmlproperty real QtQuick::Item::visibleChildren
+ \qmlproperty list<Item> QtQuick::Item::visibleChildren
This read-only property lists all of the item's children that are currently visible.
Note that a child's visibility may have changed explicitly, or because the visibility
of this (it's parent) item or another grandparent changed.
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index f731acabbb..7faf39f8e5 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -468,6 +468,7 @@ public:
QQuickWindow *window;
int windowRefCount;
inline QSGContext *sceneGraphContext() const;
+ inline QSGRenderContext *sceneGraphRenderContext() const;
QQuickItem *parentItem;
QQmlNotifier parentNotifier;
@@ -840,6 +841,12 @@ Qt::MouseButtons QQuickItemPrivate::acceptedMouseButtons() const
QSGContext *QQuickItemPrivate::sceneGraphContext() const
{
Q_ASSERT(window);
+ return static_cast<QQuickWindowPrivate *>(QObjectPrivate::get(window))->context->sceneGraphContext();
+}
+
+QSGRenderContext *QQuickItemPrivate::sceneGraphRenderContext() const
+{
+ Q_ASSERT(window);
return static_cast<QQuickWindowPrivate *>(QObjectPrivate::get(window))->context;
}
diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp
index 534ad0e2f4..b840ee421c 100644
--- a/src/quick/items/qquickitemanimation.cpp
+++ b/src/quick/items/qquickitemanimation.cpp
@@ -86,7 +86,7 @@ QT_BEGIN_NAMESPACE
ParentChange that has occurred during the state change. This can be
overridden by setting a specific target item using the \l target property.
- \sa {Animation and Transitions in Qt Quick}, {declarative/animation/basics}{Animation basics example}
+ \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
QQuickParentAnimation::QQuickParentAnimation(QObject *parent)
: QQuickAnimationGroup(*(new QQuickParentAnimationPrivate), parent)
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index daf76c377e..a5b78b28e1 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -188,6 +188,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickTextEdit>(uri,major,minor,"TextEdit");
qmlRegisterType<QQuickTextEdit,1>(uri,2,1,"TextEdit");
qmlRegisterType<QQuickTextInput>(uri,major,minor,"TextInput");
+ qmlRegisterType<QQuickTextInput,2>(uri,2,2,"TextInput");
qmlRegisterType<QQuickViewSection>(uri,major,minor,"ViewSection");
qmlRegisterType<QQuickItemLayer>();
@@ -268,8 +269,17 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickTextEdit, 2>(uri, 2, 2, "TextEdit");
}
+static void initResources()
+{
+ Q_INIT_RESOURCE(items);
+}
+
+QT_BEGIN_NAMESPACE
+
void QQuickItemsModule::defineModule()
{
+ initResources();
+
QByteArray name = "QtQuick";
int majorVersion = 2;
int minorVersion = 0;
@@ -277,3 +287,4 @@ void QQuickItemsModule::defineModule()
qt_quickitems_defineModule(name, majorVersion, minorVersion);
}
+QT_END_NAMESPACE
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 513f8f3857..d9ff024d9f 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1118,11 +1118,13 @@ void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &
if (header && header->item == item) {
updateHeader();
markExtentsDirty();
+ updateViewport();
if (!q->isMoving() && !q->isFlicking())
fixupPosition();
} else if (footer && footer->item == item) {
updateFooter();
markExtentsDirty();
+ updateViewport();
if (!q->isMoving() && !q->isFlicking())
fixupPosition();
}
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 22d8176086..c55f9ef696 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -1744,7 +1744,7 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
\image listview-layout-righttoleft.png
\endtable
- \sa {QML Data Models}, GridView, {quick/modelviews/listview}{ListView examples}
+ \sa {QML Data Models}, GridView, PathView, {Qt Quick Examples - Views}
*/
QQuickListView::QQuickListView(QQuickItem *parent)
: QQuickItemView(*(new QQuickListViewPrivate), parent)
@@ -1907,7 +1907,8 @@ QQuickListView::~QQuickListView()
so as to stay with the current item, unless the highlightFollowsCurrentItem
property is false.
- \sa highlightItem, highlightFollowsCurrentItem, {quick/modelviews/listview}{ListView examples}
+ \sa highlightItem, highlightFollowsCurrentItem,
+ {Qt Quick Examples - Views#Highlight demonstrates adding a custom highlight to a ListView.}{ListView highlight example}
*/
/*!
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index b9e6efaa10..ca64ebb6e3 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -156,7 +156,7 @@ bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *i
}
QQuickMouseArea* ma = qobject_cast<QQuickMouseArea*>(item);
- if (ma && ma != q && itemPrivate->acceptedMouseButtons() & ev->button()) {
+ if (ma && ma != q && ma->isEnabled() && itemPrivate->acceptedMouseButtons() & ev->button()) {
switch (sig) {
case Click:
if (!ma->d_func()->isClickConnected())
diff --git a/src/quick/items/qquickpainteditem.cpp b/src/quick/items/qquickpainteditem.cpp
index e0ac974022..3bf5d82e4d 100644
--- a/src/quick/items/qquickpainteditem.cpp
+++ b/src/quick/items/qquickpainteditem.cpp
@@ -276,7 +276,7 @@ void QQuickPaintedItem::setMipmap(bool enable)
/*!
Returns the performance hints.
- By default, no performance hint is enabled/
+ By default, no performance hint is enabled.
\sa setPerformanceHint(), setPerformanceHints()
*/
diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp
index d8132bdd12..1f41fe04e5 100644
--- a/src/quick/items/qquickpathview.cpp
+++ b/src/quick/items/qquickpathview.cpp
@@ -553,7 +553,7 @@ void QQuickPathViewPrivate::setDragging(bool d)
to set \e {clip: true} in order to have the out of view items clipped
nicely.
- \sa Path, {quick/modelviews/pathview}{PathView example}
+ \sa Path, {QML Data Models}, ListView, GridView, {Qt Quick Examples - Views}
*/
QQuickPathView::QQuickPathView(QQuickItem *parent)
@@ -2031,7 +2031,7 @@ void QQuickPathView::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
const int modelCount = d->modelCount;
int moveId = -1;
- int moveOffset;
+ int moveOffset = 0;
bool currentChanged = false;
bool changedOffset = false;
foreach (const QQmlChangeSet::Remove &r, changeSet.removes()) {
diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp
index 75eccf6c59..48c0f8e084 100644
--- a/src/quick/items/qquickscreen.cpp
+++ b/src/quick/items/qquickscreen.cpp
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
/*!
\qmltype Screen
\instantiates QQuickScreenAttached
- \inqmlmodule QtQuick.Window 2
+ \inqmlmodule QtQuick.Window
\ingroup qtquick-visual-utility
\brief The Screen attached object provides information about the Screen an Item or Window is displayed on.
@@ -80,26 +80,26 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \qmlattachedproperty String QtQuick.Window::Screen::name
+ \qmlattachedproperty string Screen::name
\readonly
\since 5.1
The name of the screen.
*/
/*!
- \qmlattachedproperty int QtQuick.Window::Screen::width
+ \qmlattachedproperty int Screen::width
\readonly
This contains the width of the screen in pixels.
*/
/*!
- \qmlattachedproperty int QtQuick.Window::Screen::height
+ \qmlattachedproperty int Screen::height
\readonly
This contains the height of the screen in pixels.
*/
/*!
- \qmlattachedproperty int QtQuick.Window::Screen::desktopAvailableWidth
+ \qmlattachedproperty int Screen::desktopAvailableWidth
\readonly
\since 5.1
@@ -113,7 +113,7 @@ QT_BEGIN_NAMESPACE
\endqml
*/
/*!
- \qmlattachedproperty int QtQuick.Window::Screen::desktopAvailableHeight
+ \qmlattachedproperty int Screen::desktopAvailableHeight
\readonly
\since 5.1
@@ -127,16 +127,30 @@ QT_BEGIN_NAMESPACE
\endqml
*/
/*!
- \qmlattachedproperty real QtQuick.Window::Screen::logicalPixelDensity
+ \qmlattachedproperty real Screen::logicalPixelDensity
\readonly
\since 5.1
+ \deprecated
- The number of logical pixels per millimeter. Logical pixels are the
- usual units in QML; on some systems they may be different than physical
- pixels.
+ The number of logical pixels per millimeter. This is the effective pixel
+ density provided by the platform to use in image scaling calculations.
+
+ Due to inconsistencies in how logical pixel density is handled across
+ the various platforms Qt supports, it is recommended to
+ use physical pixels instead (via the \c pixelDensity property) for
+ portability.
+
+ \sa pixelDensity
+*/
+/*!
+ \qmlattachedproperty real Screen::pixelDensity
+ \readonly
+ \since 5.2
+
+ The number of physical pixels per millimeter.
*/
/*!
- \qmlattachedproperty Qt::ScreenOrientation QtQuick.Window::Screen::primaryOrientation
+ \qmlattachedproperty Qt::ScreenOrientation Screen::primaryOrientation
\readonly
This contains the primary orientation of the screen. If the
@@ -153,7 +167,7 @@ QT_BEGIN_NAMESPACE
automatically, so again you will see the primaryOrientation change.
*/
/*!
- \qmlattachedproperty Qt::ScreenOrientation QtQuick.Window::Screen::orientation
+ \qmlattachedproperty Qt::ScreenOrientation Screen::orientation
\readonly
This contains the current orientation of the screen, from the accelerometer
@@ -167,7 +181,7 @@ QT_BEGIN_NAMESPACE
\l Item.transform to rotate your content.
*/
/*!
- \qmlattachedmethod int QtQuick.Window::Screen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b)
+ \qmlattachedmethod int Screen::angleBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b)
Returns the rotation angle, in degrees, between the two specified angles.
*/
@@ -233,6 +247,13 @@ qreal QQuickScreenAttached::logicalPixelDensity() const
return m_screen->logicalDotsPerInch() / 25.4;
}
+qreal QQuickScreenAttached::pixelDensity() const
+{
+ if (!m_screen)
+ return 0.0;
+ return m_screen->physicalDotsPerInch() / 25.4;
+}
+
Qt::ScreenOrientation QQuickScreenAttached::primaryOrientation() const
{
if (!m_screen)
@@ -291,6 +312,8 @@ void QQuickScreenAttached::screenChanged(QScreen *screen)
emit desktopGeometryChanged();
if (!oldScreen || screen->logicalDotsPerInch() != oldScreen->logicalDotsPerInch())
emit logicalPixelDensityChanged();
+ if (!oldScreen || screen->physicalDotsPerInch() != oldScreen->physicalDotsPerInch())
+ emit pixelDensityChanged();
connect(screen, SIGNAL(geometryChanged(QRect)),
this, SIGNAL(widthChanged()));
@@ -304,6 +327,8 @@ void QQuickScreenAttached::screenChanged(QScreen *screen)
this, SIGNAL(desktopGeometryChanged()));
connect(screen, SIGNAL(logicalDotsPerInchChanged(qreal)),
this, SIGNAL(logicalPixelDensityChanged()));
+ connect(screen, SIGNAL(physicalDotsPerInchChanged(qreal)),
+ this, SIGNAL(pixelDensityChanged()));
}
}
diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h
index 0f1e79b1a2..a155ff1843 100644
--- a/src/quick/items/qquickscreen_p.h
+++ b/src/quick/items/qquickscreen_p.h
@@ -64,6 +64,7 @@ class Q_AUTOTEST_EXPORT QQuickScreenAttached : public QObject
Q_PROPERTY(int desktopAvailableWidth READ desktopAvailableWidth NOTIFY desktopGeometryChanged REVISION 1)
Q_PROPERTY(int desktopAvailableHeight READ desktopAvailableHeight NOTIFY desktopGeometryChanged REVISION 1)
Q_PROPERTY(qreal logicalPixelDensity READ logicalPixelDensity NOTIFY logicalPixelDensityChanged REVISION 1)
+ Q_PROPERTY(qreal pixelDensity READ pixelDensity NOTIFY pixelDensityChanged REVISION 2)
Q_PROPERTY(Qt::ScreenOrientation primaryOrientation READ primaryOrientation NOTIFY primaryOrientationChanged)
Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged)
@@ -76,6 +77,7 @@ public:
int desktopAvailableWidth() const;
int desktopAvailableHeight() const;
qreal logicalPixelDensity() const;
+ qreal pixelDensity() const;
Qt::ScreenOrientation primaryOrientation() const;
Qt::ScreenOrientation orientation() const;
@@ -90,6 +92,7 @@ Q_SIGNALS:
void heightChanged();
Q_REVISION(1) void desktopGeometryChanged();
Q_REVISION(1) void logicalPixelDensityChanged();
+ Q_REVISION(2) void pixelDensityChanged();
void primaryOrientationChanged();
void orientationChanged();
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index 354b9f751b..9a20703f18 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -43,6 +43,7 @@
#include <private/qquickshadereffectnode_p.h>
#include <QtQuick/qsgmaterial.h>
+#include <QtQuick/private/qsgshadersourcebuilder_p.h>
#include "qquickitem_p.h"
#include <QtQuick/private/qsgcontext_p.h>
@@ -57,24 +58,6 @@
QT_BEGIN_NAMESPACE
-static const char qt_default_vertex_code[] =
- "uniform highp mat4 qt_Matrix; \n"
- "attribute highp vec4 qt_Vertex; \n"
- "attribute highp vec2 qt_MultiTexCoord0; \n"
- "varying highp vec2 qt_TexCoord0; \n"
- "void main() { \n"
- " qt_TexCoord0 = qt_MultiTexCoord0; \n"
- " gl_Position = qt_Matrix * qt_Vertex; \n"
- "}";
-
-static const char qt_default_fragment_code[] =
- "varying highp vec2 qt_TexCoord0; \n"
- "uniform sampler2D source; \n"
- "uniform lowp float qt_Opacity; \n"
- "void main() { \n"
- " gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity; \n"
- "}";
-
static const char qt_position_attribute_name[] = "qt_Vertex";
static const char qt_texcoord_attribute_name[] = "qt_MultiTexCoord0";
@@ -576,6 +559,7 @@ void QQuickShaderEffectCommon::propertyChanged(QQuickItem *item, int mappedId,
\li QVector4D -> vec4
\li QTransform -> mat3
\li QMatrix4x4 -> mat4
+ \li QQuaternion -> vec4, scalar value is \c w.
\li \l Image, \l ShaderEffectSource -> sampler2D - Origin is in the top-left
corner, and the color values are premultiplied.
\endlist
@@ -979,10 +963,16 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
if (m_dirtyProgram) {
Key s = m_common.source;
- if (s.sourceCode[Key::FragmentShader].isEmpty())
- s.sourceCode[Key::FragmentShader] = qt_default_fragment_code;
- if (s.sourceCode[Key::VertexShader].isEmpty())
- s.sourceCode[Key::VertexShader] = qt_default_vertex_code;
+ QSGShaderSourceBuilder builder;
+ if (s.sourceCode[Key::FragmentShader].isEmpty()) {
+ builder.appendSourceFile(QStringLiteral(":/items/shaders/shadereffect.frag"));
+ s.sourceCode[Key::FragmentShader] = builder.source();
+ builder.clear();
+ }
+ if (s.sourceCode[Key::VertexShader].isEmpty()) {
+ builder.appendSourceFile(QStringLiteral(":/items/shaders/shadereffect.vert"));
+ s.sourceCode[Key::VertexShader] = builder.source();
+ }
s.className = metaObject()->className();
material->setProgramSource(s);
diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp
index b84d251de5..3ab13dbbc7 100644
--- a/src/quick/items/qquickshadereffectnode.cpp
+++ b/src/quick/items/qquickshadereffectnode.cpp
@@ -45,6 +45,7 @@
#include "qquickshadereffect_p.h"
#include <QtQuick/qsgtextureprovider.h>
#include <QtQuick/private/qsgrenderer_p.h>
+#include <QtQuick/private/qsgshadersourcebuilder_p.h>
QT_BEGIN_NAMESPACE
@@ -196,6 +197,12 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
case QMetaType::QVector4D:
program()->setUniformValue(loc, qvariant_cast<QVector4D>(d.value));
break;
+ case QMetaType::QQuaternion:
+ {
+ QQuaternion q = qvariant_cast<QQuaternion>(d.value);
+ program()->setUniformValue(loc, q.x(), q.y(), q.z(), q.scalar());
+ }
+ break;
case QMetaType::QMatrix4x4:
program()->setUniformValue(loc, qvariant_cast<QMatrix4x4>(d.value));
break;
@@ -276,20 +283,15 @@ void QQuickCustomMaterialShader::compile()
m_log += program()->log();
}
- static const char fallbackVertexShader[] =
- "uniform highp mat4 qt_Matrix;"
- "attribute highp vec4 v;"
- "void main() { gl_Position = qt_Matrix * v; }";
- static const char fallbackFragmentShader[] =
- "void main() { gl_FragColor = vec4(1., 0., 1., 1.); }";
-
if (!m_compiled) {
qWarning("QQuickCustomMaterialShader: Shader compilation failed:");
qWarning() << program()->log();
- program()->removeAllShaders();
- program()->addShaderFromSourceCode(QOpenGLShader::Vertex, fallbackVertexShader);
- program()->addShaderFromSourceCode(QOpenGLShader::Fragment, fallbackFragmentShader);
+ QSGShaderSourceBuilder::initializeProgramFromFiles(
+ program(),
+ QStringLiteral(":/items/shaders/shadereffectfallback.vert"),
+ QStringLiteral(":/items/shaders/shadereffectfallback.frag"));
+
#ifndef QT_NO_DEBUG
for (int i = 0; i < attrCount; ++i) {
#else
diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp
index e86550d731..e076a342df 100644
--- a/src/quick/items/qquickshadereffectsource.cpp
+++ b/src/quick/items/qquickshadereffectsource.cpp
@@ -45,6 +45,7 @@
#include "qquickwindow_p.h"
#include <private/qsgadaptationlayer_p.h>
#include <QtQuick/private/qsgrenderer_p.h>
+#include <qsgsimplerectnode.h>
#include "qopenglframebufferobject.h"
#include "qmath.h"
@@ -140,10 +141,11 @@ QQuickShaderEffectTexture::QQuickShaderEffectTexture(QQuickItem *shaderSource)
, m_renderer(0)
, m_fbo(0)
, m_secondaryFbo(0)
+ , m_transparentTexture(0)
#ifdef QSG_DEBUG_FBO_OVERLAY
, m_debugOverlay(0)
#endif
- , m_context(QQuickItemPrivate::get(shaderSource)->sceneGraphContext())
+ , m_context(QQuickItemPrivate::get(shaderSource)->sceneGraphRenderContext())
, m_mipmap(false)
, m_live(true)
, m_recursive(false)
@@ -164,6 +166,8 @@ QQuickShaderEffectTexture::~QQuickShaderEffectTexture()
#ifdef QSG_DEBUG_FBO_OVERLAY
delete m_debugOverlay;
#endif
+ if (m_transparentTexture)
+ glDeleteTextures(1, &m_transparentTexture);
}
int QQuickShaderEffectTexture::textureId() const
@@ -188,8 +192,20 @@ void QQuickShaderEffectTexture::bind()
if (!m_recursive && m_fbo && ((m_multisampling && m_secondaryFbo->isBound()) || m_fbo->isBound()))
qWarning("ShaderEffectSource: \'recursive\' must be set to true when rendering recursively.");
#endif
- glBindTexture(GL_TEXTURE_2D, m_fbo ? m_fbo->texture() : 0);
- updateBindOptions();
+
+ if (!m_fbo && m_format == GL_RGBA) {
+ if (m_transparentTexture == 0) {
+ glGenTextures(1, &m_transparentTexture);
+ glBindTexture(GL_TEXTURE_2D, m_transparentTexture);
+ const uint zero = 0;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &zero);
+ } else {
+ glBindTexture(GL_TEXTURE_2D, m_transparentTexture);
+ }
+ } else {
+ glBindTexture(GL_TEXTURE_2D, m_fbo ? m_fbo->texture() : 0);
+ updateBindOptions();
+ }
}
bool QQuickShaderEffectTexture::updateTexture()
@@ -326,7 +342,7 @@ void QQuickShaderEffectTexture::grab()
|| (!m_fbo->format().mipmap() && m_mipmap))
{
if (!m_multisamplingChecked) {
- if (m_context->glContext()->format().samples() <= 1) {
+ if (m_context->openglContext()->format().samples() <= 1) {
m_multisampling = false;
} else {
QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
@@ -342,7 +358,7 @@ void QQuickShaderEffectTexture::grab()
QOpenGLFramebufferObjectFormat format;
format.setInternalTextureFormat(m_format);
- format.setSamples(m_context->glContext()->format().samples());
+ format.setSamples(m_context->openglContext()->format().samples());
m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
} else {
@@ -385,20 +401,16 @@ void QQuickShaderEffectTexture::grab()
#ifdef QSG_DEBUG_FBO_OVERLAY
if (qmlFboOverlay()) {
if (!m_debugOverlay)
- m_debugOverlay = m_context->createRectangleNode();
+ m_debugOverlay = new QSGSimpleRectNode();
m_debugOverlay->setRect(QRectF(0, 0, m_size.width(), m_size.height()));
m_debugOverlay->setColor(QColor(0xff, 0x00, 0x80, 0x40));
- m_debugOverlay->setPenColor(QColor());
- m_debugOverlay->setPenWidth(0);
- m_debugOverlay->setRadius(0);
- m_debugOverlay->update();
root->appendChildNode(m_debugOverlay);
}
#endif
m_dirtyTexture = false;
- QOpenGLContext *ctx = m_context->glContext();
+ QOpenGLContext *ctx = m_context->openglContext();
m_renderer->setDeviceRect(m_size);
m_renderer->setViewportRect(m_size);
QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
@@ -591,8 +603,8 @@ void QQuickShaderEffectSource::ensureTexture()
return;
Q_ASSERT_X(QQuickItemPrivate::get(this)->window
- && QQuickItemPrivate::get(this)->sceneGraphContext()
- && QThread::currentThread() == QQuickItemPrivate::get(this)->sceneGraphContext()->thread(),
+ && QQuickItemPrivate::get(this)->sceneGraphRenderContext()
+ && QThread::currentThread() == QQuickItemPrivate::get(this)->sceneGraphRenderContext()->thread(),
"QQuickShaderEffectSource::ensureTexture",
"Cannot be used outside the rendering thread");
@@ -603,13 +615,13 @@ void QQuickShaderEffectSource::ensureTexture()
QSGTextureProvider *QQuickShaderEffectSource::textureProvider() const
{
+ const QQuickItemPrivate *d = QQuickItemPrivate::get(this);
+ if (!d->window || !d->sceneGraphRenderContext() || QThread::currentThread() != d->sceneGraphRenderContext()->thread()) {
+ qWarning("QQuickShaderEffectSource::textureProvider: can only be queried on the rendering thread of an exposed window");
+ return 0;
+ }
+
if (!m_provider) {
- // Make sure it gets thread affinity on the rendering thread so deletion works properly..
- Q_ASSERT_X(QQuickItemPrivate::get(this)->window
- && QQuickItemPrivate::get(this)->sceneGraphContext()
- && QThread::currentThread() == QQuickItemPrivate::get(this)->sceneGraphContext()->thread(),
- "QQuickShaderEffectSource::textureProvider",
- "Cannot be used outside the rendering thread");
const_cast<QQuickShaderEffectSource *>(this)->m_provider = new QQuickShaderEffectSourceTextureProvider();
const_cast<QQuickShaderEffectSource *>(this)->ensureTexture();
connect(m_texture, SIGNAL(updateRequested()), m_provider, SIGNAL(textureChanged()));
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 7d1a9b7304..6218775700 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -60,6 +60,7 @@ QT_BEGIN_NAMESPACE
class QSGNode;
class UpdatePaintNodeData;
class QOpenGLFramebufferObject;
+class QSGSimpleRectNode;
class QQuickShaderEffectSourceTextureProvider;
@@ -138,11 +139,13 @@ private:
QOpenGLFramebufferObject *m_secondaryFbo;
QSharedPointer<QSGDepthStencilBuffer> m_depthStencilBuffer;
+ GLuint m_transparentTexture;
+
#ifdef QSG_DEBUG_FBO_OVERLAY
- QSGRectangleNode *m_debugOverlay;
+ QSGSimpleRectNode *m_debugOverlay;
#endif
- QSGContext *m_context;
+ QSGRenderContext *m_context;
uint m_mipmap : 1;
uint m_live : 1;
diff --git a/src/quick/items/qquicksprite.cpp b/src/quick/items/qquicksprite.cpp
index b2bfb69bab..00a265c814 100644
--- a/src/quick/items/qquicksprite.cpp
+++ b/src/quick/items/qquicksprite.cpp
@@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE
can be in the middle of an image file, or split along multiple rows, as long as they form
a contiguous line wrapping to the next row of the file from the left edge of the file.
- For full details, see the \l{Sprite Animation} overview.
+ For full details, see the \l{Sprite Animations} overview.
*/
/*!
\qmlproperty int QtQuick::Sprite::duration
diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp
index 3c1492e0b3..a90aa9ace2 100644
--- a/src/quick/items/qquickspritesequence.cpp
+++ b/src/quick/items/qquickspritesequence.cpp
@@ -56,39 +56,6 @@
QT_BEGIN_NAMESPACE
-static const char vertexShaderCode[] =
- "attribute highp vec2 vPos;\n"
- "attribute highp vec2 vTex;\n"
- "uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress\n"
- "uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation)\n"
- "\n"
- "uniform highp mat4 qt_Matrix;\n"
- "\n"
- "varying highp vec4 fTexS;\n"
- "varying lowp float progress;\n"
- "\n"
- "\n"
- "void main() {\n"
- " progress = animData.z;\n"
- " //Calculate frame location in texture\n"
- " fTexS.xy = animPos.xy + vTex.xy * animData.xy;\n"
- " //Next frame is also passed, for interpolation\n"
- " fTexS.zw = animPos.zw + vTex.xy * animData.xy;\n"
- "\n"
- " gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1);\n"
- "}\n";
-
-static const char fragmentShaderCode[] =
- "uniform sampler2D _qt_texture;\n"
- "uniform lowp float qt_Opacity;\n"
- "\n"
- "varying highp vec4 fTexS;\n"
- "varying lowp float progress;\n"
- "\n"
- "void main() {\n"
- " gl_FragColor = mix(texture2D(_qt_texture, fTexS.xy), texture2D(_qt_texture, fTexS.zw), progress) * qt_Opacity;\n"
- "}\n";
-
class QQuickSpriteSequenceMaterial : public QSGMaterial
{
public:
@@ -133,16 +100,11 @@ QQuickSpriteSequenceMaterial::~QQuickSpriteSequenceMaterial()
class SpriteSequenceMaterialData : public QSGMaterialShader
{
public:
- SpriteSequenceMaterialData(const char * /* vertexFile */ = 0, const char * /* fragmentFile */ = 0)
+ SpriteSequenceMaterialData()
+ : QSGMaterialShader()
{
- }
-
- void deactivate() {
- QSGMaterialShader::deactivate();
-
- for (int i=0; i<8; ++i) {
- program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0);
- }
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/items/shaders/sprite.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/items/shaders/sprite.frag"));
}
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
@@ -165,9 +127,6 @@ public:
m_animPos_id = program()->uniformLocation("animPos");
}
- virtual const char *vertexShader() const { return vertexShaderCode; }
- virtual const char *fragmentShader() const { return fragmentShaderCode; }
-
virtual char const *const *attributeNames() const {
static const char *attr[] = {
"vPos",
@@ -181,12 +140,8 @@ public:
int m_opacity_id;
int m_animData_id;
int m_animPos_id;
-
- static float chunkOfBytes[1024];
};
-float SpriteSequenceMaterialData::chunkOfBytes[1024];
-
QSGMaterialShader *QQuickSpriteSequenceMaterial::createShader() const
{
return new SpriteSequenceMaterialData;
@@ -217,7 +172,7 @@ struct SpriteVertices {
SpriteSequence renders and controls a list of animations defined
by \l Sprite types.
- For full details, see the \l{Sprite Animation} overview.
+ For full details, see the \l{Sprite Animations} overview.
*/
/*!
\qmlproperty bool QtQuick::SpriteSequence::running
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index fbda2df2dc..d62bf8efa1 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -107,7 +107,6 @@ void QQuickTextPrivate::init()
Q_Q(QQuickText);
q->setAcceptedMouseButtons(Qt::LeftButton);
q->setFlag(QQuickItem::ItemHasContents);
- q->setAcceptHoverEvents(true);
}
QQuickTextDocumentWithImageResources::QQuickTextDocumentWithImageResources(QQuickItem *parent)
@@ -1523,6 +1522,7 @@ void QQuickText::setText(const QString &n)
qDeleteAll(d->imgTags);
d->imgTags.clear();
d->updateLayout();
+ setAcceptHoverEvents(d->richText || d->styledText);
emit textChanged(d->text);
}
@@ -2002,6 +2002,7 @@ void QQuickText::setTextFormat(TextFormat format)
d->determineHorizontalAlignment();
}
d->updateLayout();
+ setAcceptHoverEvents(d->richText || d->styledText);
emit textFormatChanged(d->format);
}
@@ -2241,11 +2242,10 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data
const qreal dy = QQuickTextUtil::alignedY(d->layedOutTextRect.height(), height(), d->vAlign);
QQuickTextNode *node = 0;
- if (!oldNode) {
- node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext(), this);
- } else {
+ if (!oldNode)
+ node = new QQuickTextNode(this);
+ else
node = static_cast<QQuickTextNode *>(oldNode);
- }
node->setUseNativeRenderer(d->renderType == NativeRendering && d->window->devicePixelRatio() <= 1);
node->deleteContent();
@@ -2635,34 +2635,34 @@ void QQuickTextPrivate::processHoverEvent(QHoverEvent *event)
{
Q_Q(QQuickText);
QString link;
- if (event->type() != QEvent::HoverLeave)
- link = anchorAt(event->posF());
+ if (isLinkHoveredConnected()) {
+ if (event->type() != QEvent::HoverLeave)
+ link = anchorAt(event->posF());
- if ((!extra.isAllocated() && !link.isEmpty()) || (extra.isAllocated() && extra->hoveredLink != link)) {
- extra.value().hoveredLink = link;
- emit q->linkHovered(extra->hoveredLink);
+ if ((!extra.isAllocated() && !link.isEmpty()) || (extra.isAllocated() && extra->hoveredLink != link)) {
+ extra.value().hoveredLink = link;
+ emit q->linkHovered(extra->hoveredLink);
+ }
}
+ event->setAccepted(!link.isEmpty());
}
void QQuickText::hoverEnterEvent(QHoverEvent *event)
{
Q_D(QQuickText);
- if (d->isLinkHoveredConnected())
- d->processHoverEvent(event);
+ d->processHoverEvent(event);
}
void QQuickText::hoverMoveEvent(QHoverEvent *event)
{
Q_D(QQuickText);
- if (d->isLinkHoveredConnected())
- d->processHoverEvent(event);
+ d->processHoverEvent(event);
}
void QQuickText::hoverLeaveEvent(QHoverEvent *event)
{
Q_D(QQuickText);
- if (d->isLinkHoveredConnected())
- d->processHoverEvent(event);
+ d->processHoverEvent(event);
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 48518f1ba3..ffc732621d 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1769,6 +1769,9 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
d->updateType = QQuickTextEditPrivate::UpdateNone;
+ if (!oldNode) // If we had any text node references, they were deleted along with the root node
+ d->textNodeMap.clear();
+
RootNode *rootNode = static_cast<RootNode *>(oldNode);
TextNodeIterator nodeIterator = d->textNodeMap.begin();
while (nodeIterator != d->textNodeMap.end() && !(*nodeIterator)->dirty())
@@ -2367,7 +2370,7 @@ void QQuickTextEditPrivate::addCurrentTextNodeToRoot(QSGTransformNode *root, QQu
QQuickTextNode *QQuickTextEditPrivate::createTextNode()
{
Q_Q(QQuickTextEdit);
- QQuickTextNode* node = new QQuickTextNode(QQuickItemPrivate::get(q)->sceneGraphContext(), q);
+ QQuickTextNode* node = new QQuickTextNode(q);
node->setUseNativeRenderer(renderType == QQuickTextEdit::NativeRendering && window->devicePixelRatio() <= 1);
node->initEngine(color, selectedTextColor, selectionColor);
return node;
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index 1848fbb80b..c56f3648e6 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -1212,6 +1212,17 @@ bool QQuickTextInput::hasAcceptableInput() const
state.
*/
+/*!
+ \qmlsignal QtQuick::TextInput::onEditingFinished()
+ \since 5.2
+
+ This handler is called when the Return or Enter key is pressed or
+ the text input loses focus. Note that if there is a validator or
+ inputMask set on the text input and enter/return is pressed, this
+ handler will only be called if the input follows
+ the inputMask and the validator returns an acceptable state.
+*/
+
#ifndef QT_NO_IM
Qt::InputMethodHints QQuickTextInputPrivate::effectiveInputMethodHints() const
{
@@ -1834,7 +1845,7 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
QQuickTextNode *node = static_cast<QQuickTextNode *>(oldNode);
if (node == 0)
- node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext(), this);
+ node = new QQuickTextNode(this);
d->textNode = node;
if (!d->textLayoutDirty && oldNode != 0) {
@@ -2522,6 +2533,9 @@ void QQuickTextInputPrivate::handleFocusEvent(QFocusEvent *event)
&& !persistentSelection)
deselect();
+ if (hasAcceptableInput(m_text) || fixup())
+ emit q->editingFinished();
+
#ifndef QT_NO_IM
q->disconnect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
q, SLOT(q_updateAlignment()));
@@ -3378,7 +3392,6 @@ bool QQuickTextInputPrivate::finishChange(int validateFromState, bool update, bo
*/
void QQuickTextInputPrivate::internalSetText(const QString &txt, int pos, bool edited)
{
- Q_Q(QQuickTextInput);
internalDeselect();
QString oldText = m_text;
if (m_maskData) {
@@ -3396,6 +3409,7 @@ void QQuickTextInputPrivate::internalSetText(const QString &txt, int pos, bool e
#ifdef QT_NO_ACCESSIBILITY
Q_UNUSED(changed)
#else
+ Q_Q(QQuickTextInput);
if (changed && QAccessible::isActive()) {
if (QObject *acc = QQuickAccessibleAttached::findAccessible(q, QAccessible::EditableText)) {
QAccessibleTextUpdateEvent ev(acc, 0, oldText, m_text);
@@ -4105,6 +4119,7 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
if (hasAcceptableInput(m_text) || fixup()) {
emit q->accepted();
+ emit q->editingFinished();
}
event->ignore();
return;
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 2b72afb9dc..5f0250aaf1 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -284,6 +284,7 @@ Q_SIGNALS:
void selectedTextChanged();
void accepted();
void acceptableInputChanged();
+ Q_REVISION(2) void editingFinished();
void colorChanged();
void selectionColorChanged();
void selectedTextColorChanged();
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
index 1f4ca34b13..18ee1a479d 100644
--- a/src/quick/items/qquicktextnode.cpp
+++ b/src/quick/items/qquicktextnode.cpp
@@ -47,6 +47,7 @@
#include <private/qsgadaptationlayer_p.h>
#include <private/qsgdistancefieldglyphnode_p.h>
#include <private/qquickclipnode_p.h>
+#include <private/qquickitem_p.h>
#include <QtQuick/private/qsgcontext_p.h>
#include <QtCore/qpoint.h>
@@ -80,8 +81,8 @@ namespace {
/*!
Creates an empty QQuickTextNode
*/
-QQuickTextNode::QQuickTextNode(QSGContext *context, QQuickItem *ownerElement)
- : m_context(context), m_cursorNode(0), m_ownerElement(ownerElement), m_useNativeRenderer(false)
+QQuickTextNode::QQuickTextNode(QQuickItem *ownerElement)
+ : m_cursorNode(0), m_ownerElement(ownerElement), m_useNativeRenderer(false)
{
#ifdef QSG_RUNTIME_DESCRIPTION
qsgnode_set_description(this, QLatin1String("text"));
@@ -141,9 +142,14 @@ QSGGlyphNode *QQuickTextNode::addGlyphs(const QPointF &position, const QGlyphRun
QQuickText::TextStyle style, const QColor &styleColor,
QSGNode *parentNode)
{
- QSGGlyphNode *node = m_useNativeRenderer
- ? m_context->createNativeGlyphNode()
- : m_context->createGlyphNode();
+ QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext();
+ QRawFont font = glyphs.rawFont();
+ bool smoothScalable = QFontDatabase().isSmoothlyScalable(font.familyName(),
+ font.styleName());
+ QSGGlyphNode *node = m_useNativeRenderer || !smoothScalable
+ ? sg->sceneGraphContext()->createNativeGlyphNode(sg)
+ : sg->sceneGraphContext()->createGlyphNode(sg);
+
node->setOwnerElement(m_ownerElement);
node->setGlyphs(position + QPointF(0, glyphs.rawFont().ascent()), glyphs);
node->setStyle(style);
@@ -189,8 +195,9 @@ void QQuickTextNode::initEngine(const QColor& textColor, const QColor& selectedT
void QQuickTextNode::addImage(const QRectF &rect, const QImage &image)
{
- QSGImageNode *node = m_context->createImageNode();
- QSGTexture *texture = m_context->createTexture(image);
+ QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext();
+ QSGImageNode *node = sg->sceneGraphContext()->createImageNode();
+ QSGTexture *texture = sg->createTexture(image);
m_textures.append(texture);
node->setTargetRect(rect);
node->setInnerTargetRect(rect);
diff --git a/src/quick/items/qquicktextnode_p.h b/src/quick/items/qquicktextnode_p.h
index 64f396eb10..0bff0d5cff 100644
--- a/src/quick/items/qquicktextnode_p.h
+++ b/src/quick/items/qquicktextnode_p.h
@@ -77,7 +77,7 @@ public:
};
Q_DECLARE_FLAGS(Decorations, Decoration)
- QQuickTextNode(QSGContext *, QQuickItem *ownerElement);
+ QQuickTextNode(QQuickItem *ownerElement);
~QQuickTextNode();
static bool isComplexRichText(QTextDocument *);
@@ -110,7 +110,6 @@ private:
void initEngine(const QColor &textColor, const QColor &selectedTextColor, const QColor &selectionColor, const QColor& anchorColor = QColor()
, const QPointF &position = QPointF());
- QSGContext *m_context;
QSGSimpleRectNode *m_cursorNode;
QList<QSGTexture *> m_textures;
QQuickItem *m_ownerElement;
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index fe7effa4f1..e9ff70e00b 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -898,8 +898,8 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText
int fragmentEnd = textPos + fragment.length();
#ifndef QT_NO_IM
if (preeditPosition >= 0
- && preeditPosition >= textPos
- && preeditPosition <= fragmentEnd) {
+ && (preeditPosition + block.position()) >= textPos
+ && (preeditPosition + block.position()) <= fragmentEnd) {
fragmentEnd += preeditLength;
}
#endif
diff --git a/src/quick/items/qquicktranslate.cpp b/src/quick/items/qquicktranslate.cpp
index 1ea5a6f7d6..93104ffa7a 100644
--- a/src/quick/items/qquicktranslate.cpp
+++ b/src/quick/items/qquicktranslate.cpp
@@ -335,7 +335,7 @@ public:
\image axisrotation.png
- \sa {declarative/ui-components/dialcontrol}{Dial Control example}, {declarative/toys/clocks}{Clocks example}
+ \sa {declarative/ui-components/dialcontrol}{Dial Control example}, {Qt Quick Demo - Clocks}
*/
QQuickRotation::QQuickRotation(QObject *parent)
: QQuickTransform(*new QQuickRotationPrivate, parent)
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 894059e193..a993889c45 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -50,8 +50,6 @@
#include <QtQuick/private/qsgrenderer_p.h>
#include <QtQuick/private/qsgtexture_p.h>
-#include <QtQuick/private/qsgflashnode_p.h>
-
#include <private/qsgrenderloop_p.h>
#include <private/qquickanimatorcontroller_p.h>
@@ -218,6 +216,7 @@ void QQuickWindow::exposeEvent(QExposeEvent *)
/*! \reimp */
void QQuickWindow::resizeEvent(QResizeEvent *)
{
+ d_func()->windowManager->resize(this);
}
/*! \reimp */
@@ -416,12 +415,13 @@ void QQuickWindowPrivate::init(QQuickWindow *c)
contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope;
windowManager = QSGRenderLoop::instance();
- context = windowManager->sceneGraphContext();
+ QSGContext *sg = windowManager->sceneGraphContext();
+ context = windowManager->createRenderContext(sg);
q->setSurfaceType(QWindow::OpenGLSurface);
- q->setFormat(context->defaultSurfaceFormat());
+ q->setFormat(sg->defaultSurfaceFormat());
animationController = new QQuickAnimatorController();
- animationController->window = q;
+ animationController->m_window = q;
QObject::connect(context, SIGNAL(initialized()), q, SIGNAL(sceneGraphInitialized()), Qt::DirectConnection);
QObject::connect(context, SIGNAL(invalidated()), q, SIGNAL(sceneGraphInvalidated()), Qt::DirectConnection);
@@ -666,14 +666,18 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q
QVarLengthArray<QQuickItem *, 20> changed;
// Does this change the active focus?
- if (item == contentItem || (scopePrivate->activeFocus && item->isEnabled())) {
+ if (item == contentItem || scopePrivate->activeFocus) {
QQuickItem *oldActiveFocusItem = 0;
oldActiveFocusItem = activeFocusItem;
- newActiveFocusItem = item;
- while (newActiveFocusItem->isFocusScope()
- && newActiveFocusItem->scopedFocusItem()
- && newActiveFocusItem->scopedFocusItem()->isEnabled()) {
- newActiveFocusItem = newActiveFocusItem->scopedFocusItem();
+ if (item->isEnabled()) {
+ newActiveFocusItem = item;
+ while (newActiveFocusItem->isFocusScope()
+ && newActiveFocusItem->scopedFocusItem()
+ && newActiveFocusItem->scopedFocusItem()->isEnabled()) {
+ newActiveFocusItem = newActiveFocusItem->scopedFocusItem();
+ }
+ } else {
+ newActiveFocusItem = scope;
}
if (oldActiveFocusItem) {
@@ -772,23 +776,24 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
oldActiveFocusItem = activeFocusItem;
newActiveFocusItem = scope;
- Q_ASSERT(oldActiveFocusItem);
-
#ifndef QT_NO_IM
qApp->inputMethod()->commit();
#endif
activeFocusItem = 0;
- QFocusEvent event(QEvent::FocusOut, reason);
- q->sendEvent(oldActiveFocusItem, &event);
- QQuickItem *afi = oldActiveFocusItem;
- while (afi && afi != scope) {
- if (QQuickItemPrivate::get(afi)->activeFocus) {
- QQuickItemPrivate::get(afi)->activeFocus = false;
- changed << afi;
+ if (oldActiveFocusItem) {
+ QFocusEvent event(QEvent::FocusOut, reason);
+ q->sendEvent(oldActiveFocusItem, &event);
+
+ QQuickItem *afi = oldActiveFocusItem;
+ while (afi && afi != scope) {
+ if (QQuickItemPrivate::get(afi)->activeFocus) {
+ QQuickItemPrivate::get(afi)->activeFocus = false;
+ changed << afi;
+ }
+ afi = afi->parentItem();
}
- afi = afi->parentItem();
}
}
@@ -821,6 +826,11 @@ void QQuickWindowPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
notifyFocusChangesRecur(changed.data(), changed.count() - 1);
}
+void QQuickWindowPrivate::clearFocusObject()
+{
+ contentItem->setFocus(false, Qt::OtherFocusReason);
+}
+
void QQuickWindowPrivate::notifyFocusChangesRecur(QQuickItem **items, int remaining)
{
QPointer<QQuickItem> item(*items);
@@ -862,7 +872,7 @@ void QQuickWindowPrivate::cleanup(QSGNode *n)
/*!
\qmltype Window
\instantiates QQuickWindow
- \inqmlmodule QtQuick.Window 2
+ \inqmlmodule QtQuick.Window
\ingroup qtquick-visual
\brief Creates a new top-level window
@@ -2136,7 +2146,7 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent
}
/*!
- \qmlproperty list<Object> QtQuick.Window::Window::data
+ \qmlproperty list<Object> Window::data
\default
The data property allows you to freely mix visual children, resources
@@ -2345,10 +2355,6 @@ void QQuickWindowPrivate::updateDirtyNodes()
void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
{
-#ifdef QML_RUNTIME_TESTING
- bool didFlash = false;
-#endif
-
QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
quint32 dirty = itemPriv->dirtyAttributes;
itemPriv->dirtyAttributes = 0;
@@ -2572,19 +2578,6 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
}
#endif
-#ifdef QML_RUNTIME_TESTING
- if (itemPriv->sceneGraphContext()->isFlashModeEnabled()) {
- QSGFlashNode *flash = new QSGFlashNode();
- flash->setRect(item->boundingRect());
- itemPriv->childContainerNode()->appendChildNode(flash);
- didFlash = true;
- }
- Q_Q(QQuickWindow);
- if (didFlash) {
- q->maybeUpdate();
- }
-#endif
-
}
void QQuickWindow::maybeUpdate()
@@ -2624,9 +2617,7 @@ void QQuickWindow::setTransientParent_helper(QQuickWindow *window)
QOpenGLContext *QQuickWindow::openglContext() const
{
Q_D(const QQuickWindow);
- if (d->context->isReady())
- return d->context->glContext();
- return 0;
+ return d->context->openglContext();
}
/*!
@@ -2672,7 +2663,7 @@ QOpenGLContext *QQuickWindow::openglContext() const
/*!
\qmltype CloseEvent
\instantiates QQuickCloseEvent
- \inqmlmodule QtQuick.Window 2
+ \inqmlmodule QtQuick.Window
\ingroup qtquick-visual
\brief Notification that a \l Window is about to be closed
\since 5.1
@@ -2685,7 +2676,7 @@ QOpenGLContext *QQuickWindow::openglContext() const
*/
/*!
- \qmlproperty bool QtQuick.Window::CloseEvent::accepted
+ \qmlproperty bool CloseEvent::accepted
This property indicates whether the application will allow the user to
close the window. It is true by default.
@@ -2700,7 +2691,7 @@ QOpenGLContext *QQuickWindow::openglContext() const
*/
/*!
- \qmlsignal QtQuick.Window::closing(CloseEvent close)
+ \qmlsignal closing(CloseEvent close)
\since 5.1
This signal is emitted when the user tries to close the window.
@@ -2809,7 +2800,7 @@ QOpenGLFramebufferObject *QQuickWindow::renderTarget() const
Grabs the contents of the window and returns it as an image.
It is possible to call the grabWindow() function when the window is not
- visible. This requires that the window is \l{QWindow::create} {created}
+ visible. This requires that the window is \l{QWindow::create()} {created}
and has a valid size and that no other QQuickWindow instances are rendering
in the same process.
@@ -2822,7 +2813,7 @@ QImage QQuickWindow::grabWindow()
Q_D(QQuickWindow);
if (!isVisible()) {
- if (d->context->isReady()) {
+ if (d->context->openglContext()) {
qWarning("QQuickWindow::grabWindow: scene graph already in use");
return QImage();
}
@@ -2834,6 +2825,7 @@ QImage QQuickWindow::grabWindow()
QOpenGLContext context;
context.setFormat(requestedFormat());
+ context.setShareContext(QSGContext::sharedOpenGLContext());
context.create();
context.makeCurrent(this);
d->context->initialize(&context);
@@ -3019,7 +3011,7 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image) const
QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateTextureOptions options) const
{
Q_D(const QQuickWindow);
- if (d->context && d->context->isReady()) {
+ if (d->context && d->context->openglContext()) {
if (options & TextureCanUseAtlas)
return d->context->createTexture(image);
else
@@ -3047,7 +3039,7 @@ QSGTexture *QQuickWindow::createTextureFromImage(const QImage &image, CreateText
QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, CreateTextureOptions options) const
{
Q_D(const QQuickWindow);
- if (d->context && d->context->isReady()) {
+ if (d->context && d->context->openglContext()) {
QSGPlainTexture *texture = new QSGPlainTexture();
texture->setTextureId(id);
texture->setHasAlphaChannel(options & TextureHasAlphaChannel);
@@ -3060,7 +3052,7 @@ QSGTexture *QQuickWindow::createTextureFromId(uint id, const QSize &size, Create
}
/*!
- \qmlproperty color QtQuick.Window::Window::color
+ \qmlproperty color Window::color
The background color for the window.
@@ -3189,7 +3181,7 @@ void QQuickWindow::resetOpenGLState()
}
/*!
- \qmlproperty string QtQuick.Window::Window::title
+ \qmlproperty string Window::title
The window's title in the windowing system.
@@ -3200,7 +3192,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty Qt::WindowModality QtQuick.Window::Window::modality
+ \qmlproperty Qt::WindowModality Window::modality
The modality of the window.
@@ -3210,7 +3202,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty Qt::WindowFlags QtQuick.Window::Window::flags
+ \qmlproperty Qt::WindowFlags Window::flags
The window flags of the window.
@@ -3223,10 +3215,10 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty int QtQuick.Window::Window::x
- \qmlproperty int QtQuick.Window::Window::y
- \qmlproperty int QtQuick.Window::Window::width
- \qmlproperty int QtQuick.Window::Window::height
+ \qmlproperty int Window::x
+ \qmlproperty int Window::y
+ \qmlproperty int Window::width
+ \qmlproperty int Window::height
Defines the window's position and size.
@@ -3241,8 +3233,8 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty int QtQuick.Window::Window::minimumWidth
- \qmlproperty int QtQuick.Window::Window::minimumHeight
+ \qmlproperty int Window::minimumWidth
+ \qmlproperty int Window::minimumHeight
\since 5.1
Defines the window's minimum size.
@@ -3252,8 +3244,8 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty int QtQuick.Window::Window::maximumWidth
- \qmlproperty int QtQuick.Window::Window::maximumHeight
+ \qmlproperty int Window::maximumWidth
+ \qmlproperty int Window::maximumHeight
\since 5.1
Defines the window's maximum size.
@@ -3263,7 +3255,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty bool QtQuick.Window::Window::visible
+ \qmlproperty bool Window::visible
Whether the window is visible on the screen.
@@ -3273,7 +3265,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty QWindow::Visibility QtQuick.Window::Window::visibility
+ \qmlproperty QWindow::Visibility Window::visibility
The screen-occupation state of the window.
@@ -3293,7 +3285,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty Qt::ScreenOrientation QtQuick.Window::Window::contentOrientation
+ \qmlproperty Qt::ScreenOrientation Window::contentOrientation
This is a hint to the window manager in case it needs to display
additional content like popups, dialogs, status bars, or similar
@@ -3314,7 +3306,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty real QtQuick.Window::Window::opacity
+ \qmlproperty real Window::opacity
The opacity of the window.
@@ -3331,7 +3323,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty Item QtQuick.Window::Window::activeFocusItem
+ \qmlproperty Item Window::activeFocusItem
\since 5.1
The item which currently has active focus or \c null if there is
@@ -3339,7 +3331,7 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
- \qmlproperty QtQuick.Window::Window::active
+ \qmlproperty Window::active
\since 5.1
The active status of the window.
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 420b13eeff..5063b3b5db 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -64,7 +64,7 @@ class Q_QUICK_EXPORT QQuickWindow : public QWindow
Q_OBJECT
Q_PRIVATE_PROPERTY(QQuickWindow::d_func(), QQmlListProperty<QObject> data READ data DESIGNABLE false)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
- Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT FINAL)
+ Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT)
Q_PROPERTY(QQuickItem* activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged REVISION 1)
Q_CLASSINFO("DefaultProperty", "data")
Q_DECLARE_PRIVATE(QQuickWindow)
@@ -143,7 +143,6 @@ Q_SIGNALS:
public Q_SLOTS:
void update();
- void forcePolish();
void releaseResources();
protected:
@@ -173,11 +172,12 @@ protected:
private Q_SLOTS:
void maybeUpdate();
void cleanupSceneGraph();
+ void forcePolish();
void setTransientParent_helper(QQuickWindow *window);
private:
friend class QQuickItem;
- friend class QQuickWindowRenderLoop;
+ friend class QQuickAnimatorController;
Q_DISABLE_COPY(QQuickWindow)
};
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index c02f7107d4..c23745b5f1 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -166,6 +166,7 @@ public:
void setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = 0);
void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = 0);
static void notifyFocusChangesRecur(QQuickItem **item, int remaining);
+ void clearFocusObject();
void updateFocusItemTransform();
@@ -194,7 +195,7 @@ public:
void fireFrameSwapped() { Q_EMIT q_func()->frameSwapped(); }
- QSGContext *context;
+ QSGRenderContext *context;
QSGRenderer *renderer;
QSGRenderLoop *windowManager;
diff --git a/src/quick/items/shaders/shadereffect.frag b/src/quick/items/shaders/shadereffect.frag
new file mode 100644
index 0000000000..c1c15ecb0c
--- /dev/null
+++ b/src/quick/items/shaders/shadereffect.frag
@@ -0,0 +1,9 @@
+varying highp vec2 qt_TexCoord0;
+
+uniform sampler2D source;
+uniform lowp float qt_Opacity;
+
+void main()
+{
+ gl_FragColor = texture2D(source, qt_TexCoord0) * qt_Opacity;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffect.vert b/src/quick/items/shaders/shadereffect.vert
new file mode 100644
index 0000000000..ae1e84a50c
--- /dev/null
+++ b/src/quick/items/shaders/shadereffect.vert
@@ -0,0 +1,12 @@
+uniform highp mat4 qt_Matrix;
+
+attribute highp vec4 qt_Vertex;
+attribute highp vec2 qt_MultiTexCoord0;
+
+varying highp vec2 qt_TexCoord0;
+
+void main()
+{
+ qt_TexCoord0 = qt_MultiTexCoord0;
+ gl_Position = qt_Matrix * qt_Vertex;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffect_core.frag b/src/quick/items/shaders/shadereffect_core.frag
new file mode 100644
index 0000000000..2163753edc
--- /dev/null
+++ b/src/quick/items/shaders/shadereffect_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 qt_TexCoord0;
+
+out vec4 fragColor;
+
+uniform sampler2D source;
+uniform float qt_Opacity;
+
+void main()
+{
+ fragColor = texture(source, qt_TexCoord0) * qt_Opacity;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffect_core.vert b/src/quick/items/shaders/shadereffect_core.vert
new file mode 100644
index 0000000000..2ed2d47b5f
--- /dev/null
+++ b/src/quick/items/shaders/shadereffect_core.vert
@@ -0,0 +1,14 @@
+#version 150 core
+
+in vec4 qt_Vertex;
+in vec2 qt_MultiTexCoord0;
+
+out vec2 qt_TexCoord0;
+
+uniform mat4 qt_Matrix;
+
+void main()
+{
+ qt_TexCoord0 = qt_MultiTexCoord0;
+ gl_Position = qt_Matrix * qt_Vertex;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffectfallback.frag b/src/quick/items/shaders/shadereffectfallback.frag
new file mode 100644
index 0000000000..d279e54083
--- /dev/null
+++ b/src/quick/items/shaders/shadereffectfallback.frag
@@ -0,0 +1,4 @@
+void main()
+{
+ gl_FragColor = vec4(1., 0., 1., 1.);
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffectfallback.vert b/src/quick/items/shaders/shadereffectfallback.vert
new file mode 100644
index 0000000000..0a11a1d340
--- /dev/null
+++ b/src/quick/items/shaders/shadereffectfallback.vert
@@ -0,0 +1,8 @@
+uniform highp mat4 qt_Matrix;
+
+attribute highp vec4 v;
+
+void main()
+{
+ gl_Position = qt_Matrix * v;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffectfallback_core.frag b/src/quick/items/shaders/shadereffectfallback_core.frag
new file mode 100644
index 0000000000..4abf124737
--- /dev/null
+++ b/src/quick/items/shaders/shadereffectfallback_core.frag
@@ -0,0 +1,8 @@
+#version 150 core
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(1., 0., 1., 1.);
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/shadereffectfallback_core.vert b/src/quick/items/shaders/shadereffectfallback_core.vert
new file mode 100644
index 0000000000..b1ca84cc6d
--- /dev/null
+++ b/src/quick/items/shaders/shadereffectfallback_core.vert
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 v;
+
+uniform mat4 qt_Matrix;
+
+void main()
+{
+ gl_Position = qt_Matrix * v;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/sprite.frag b/src/quick/items/shaders/sprite.frag
new file mode 100644
index 0000000000..e1fcb0f006
--- /dev/null
+++ b/src/quick/items/shaders/sprite.frag
@@ -0,0 +1,12 @@
+uniform sampler2D _qt_texture;
+uniform lowp float qt_Opacity;
+
+varying highp vec4 fTexS;
+varying lowp float progress;
+
+void main()
+{
+ gl_FragColor = mix(texture2D(_qt_texture, fTexS.xy),
+ texture2D(_qt_texture, fTexS.zw),
+ progress) * qt_Opacity;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/sprite.vert b/src/quick/items/shaders/sprite.vert
new file mode 100644
index 0000000000..fc826f60b4
--- /dev/null
+++ b/src/quick/items/shaders/sprite.vert
@@ -0,0 +1,23 @@
+attribute highp vec2 vPos;
+attribute highp vec2 vTex;
+
+uniform highp vec3 animData;// w,h(premultiplied of anim), interpolation progress
+uniform highp vec4 animPos;//x,y, x,y (two frames for interpolation)
+
+uniform highp mat4 qt_Matrix;
+
+varying highp vec4 fTexS;
+varying lowp float progress;
+
+void main()
+{
+ progress = animData.z;
+
+ // Calculate frame location in texture
+ fTexS.xy = animPos.xy + vTex.xy * animData.xy;
+
+ // Next frame is also passed, for interpolation
+ fTexS.zw = animPos.zw + vTex.xy * animData.xy;
+
+ gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1);
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/sprite_core.frag b/src/quick/items/shaders/sprite_core.frag
new file mode 100644
index 0000000000..c1087a8754
--- /dev/null
+++ b/src/quick/items/shaders/sprite_core.frag
@@ -0,0 +1,16 @@
+#version 150 core
+
+in vec4 fTexS;
+in float progress;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform float qt_Opacity;
+
+void main()
+{
+ fragColor = mix(texture(_qt_texture, fTexS.xy),
+ texture(_qt_texture, fTexS.zw),
+ progress) * qt_Opacity;
+} \ No newline at end of file
diff --git a/src/quick/items/shaders/sprite_core.vert b/src/quick/items/shaders/sprite_core.vert
new file mode 100644
index 0000000000..5027bf03fc
--- /dev/null
+++ b/src/quick/items/shaders/sprite_core.vert
@@ -0,0 +1,24 @@
+#version 150 core
+
+in vec2 vPos;
+in vec2 vTex;
+
+out vec4 fTexS;
+out float progress;
+
+uniform vec3 animData; // w,h(premultiplied of anim), interpolation progress
+uniform vec4 animPos; // x,y, x,y (two frames for interpolation)
+uniform mat4 qt_Matrix;
+
+void main()
+{
+ progress = animData.z;
+
+ // Calculate frame location in texture
+ fTexS.xy = animPos.xy + vTex.xy * animData.xy;
+
+ // Next frame is also passed, for interpolation
+ fTexS.zw = animPos.zw + vTex.xy * animData.xy;
+
+ gl_Position = qt_Matrix * vec4(vPos.x, vPos.y, 0, 1);
+} \ No newline at end of file
diff --git a/src/quick/qtquick2.cpp b/src/quick/qtquick2.cpp
index 5216fca355..ee5034c108 100644
--- a/src/quick/qtquick2.cpp
+++ b/src/quick/qtquick2.cpp
@@ -55,6 +55,11 @@
#include <qqmlproperty.h>
#include <QtCore/QPointer>
+static void initResources()
+{
+ Q_INIT_RESOURCE(scenegraph);
+}
+
QT_BEGIN_NAMESPACE
class QQmlQtQuick2DebugStatesDelegate : public QQmlDebugStatesDelegate
@@ -172,6 +177,8 @@ void QQmlQtQuick2DebugStatesDelegate::resetBindingForInvalidProperty(QObject *ob
void QQmlQtQuick2Module::defineModule()
{
+ initResources();
+
QQuick_initializeProviders();
QQuickUtilModule::defineModule();
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index f25e144674..79b5de72c0 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -40,11 +40,13 @@
****************************************************************************/
#include "qsgbatchrenderer_p.h"
+#include <private/qsgshadersourcebuilder_p.h>
#include <QtCore/QElapsedTimer>
#include <QtGui/QGuiApplication>
#include <QtGui/QOpenGLFramebufferObject>
+#include <QtGui/QOpenGLVertexArrayObject>
#include <private/qqmlprofilerservice_p.h>
@@ -56,7 +58,7 @@
QT_BEGIN_NAMESPACE
-extern QByteArray qsgShaderRewriter_insertZAttributes(const char *input);
+extern QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat::OpenGLContextProfile profile);
namespace QSGBatchRenderer
{
@@ -112,6 +114,7 @@ struct QMatrix4x4_Accessor
int flagBits;
static bool isTranslate(const QMatrix4x4 &m) { return ((const QMatrix4x4_Accessor &) m).flagBits <= 0x1; }
+ static bool isScale(const QMatrix4x4 &m) { return ((const QMatrix4x4_Accessor &) m).flagBits <= 0x2; }
static bool is2DSafe(const QMatrix4x4 &m) { return ((const QMatrix4x4_Accessor &) m).flagBits < 0x8; }
};
@@ -130,10 +133,12 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
#endif
QSGMaterialShader *s = material->createShader();
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QSurfaceFormat::OpenGLContextProfile profile = ctx->format().profile();
QOpenGLShaderProgram *p = s->program();
p->addShaderFromSourceCode(QOpenGLShader::Vertex,
- qsgShaderRewriter_insertZAttributes(s->vertexShader()));
+ qsgShaderRewriter_insertZAttributes(s->vertexShader(), profile));
p->addShaderFromSourceCode(QOpenGLShader::Fragment,
s->fragmentShader());
@@ -283,7 +288,6 @@ Updater::Updater(Renderer *r)
void Updater::updateStates(QSGNode *n)
{
- m_toplevel_alpha = 1;
m_current_clip = 0;
m_added = 0;
@@ -389,6 +393,9 @@ void Updater::visitOpacityNode(Node *n)
if (was != is) {
renderer->m_rebuild = Renderer::FullRebuild;
n->isOpaque = is;
+ } else if (!is) {
+ renderer->invalidateAlphaBatchesForRoot(m_roots.last());
+ renderer->m_rebuild |= Renderer::BuildBatches;
}
++m_force_update;
SHADOWNODE_TRAVERSE(n) visitNode(*child);
@@ -530,6 +537,38 @@ int qsg_positionAttribute(QSGGeometry *g) {
return -1;
}
+
+void Rect::map(const QMatrix4x4 &matrix)
+{
+ const float *m = matrix.constData();
+ if (QMatrix4x4_Accessor::isScale(matrix)) {
+ tl.x = tl.x * m[0] + m[12];
+ tl.y = tl.y * m[5] + m[13];
+ br.x = br.x * m[0] + m[12];
+ br.y = br.y * m[5] + m[13];
+ if (tl.x > br.x)
+ qSwap(tl.x, br.x);
+ if (tl.y > br.y)
+ qSwap(tl.y, br.y);
+ } else {
+ Pt mtl = tl;
+ Pt mtr = { br.x, tl.y };
+ Pt mbl = { tl.x, br.y };
+ Pt mbr = br;
+
+ mtl.map(matrix);
+ mtr.map(matrix);
+ mbl.map(matrix);
+ mbr.map(matrix);
+
+ set(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
+ (*this) |= mtl;
+ (*this) |= mtr;
+ (*this) |= mbl;
+ (*this) |= mbr;
+ }
+}
+
void Element::computeBounds()
{
Q_ASSERT(!boundsComputed);
@@ -550,6 +589,17 @@ void Element::computeBounds()
vd += g->sizeOfVertex();
}
bounds.map(*node->matrix());
+
+ if (!qIsFinite(bounds.tl.x))
+ bounds.tl.x = -FLT_MAX;
+ if (!qIsFinite(bounds.tl.y))
+ bounds.tl.y = -FLT_MAX;
+ if (!qIsFinite(bounds.br.x))
+ bounds.br.x = FLT_MAX;
+ if (!qIsFinite(bounds.br.y))
+ bounds.br.y = FLT_MAX;
+
+ boundsOutsideFloatRange = bounds.isOutsideFloatRange();
}
RenderNodeElement::~RenderNodeElement()
@@ -650,12 +700,26 @@ bool Batch::isTranslateOnlyToRoot() const {
/*
* Iterates through all the nodes in the batch and returns true if the
- * nodes are all "2D safe" meaning that they can be merged and that
- * the value in the z coordinate is of no consequence.
+ * nodes are all safe to batch. There are two separate criteria:
+ *
+ * - The matrix is such that the z component of the result is of no
+ * consequence.
+ *
+ * - The bounds are inside the stable floating point range. This applies
+ * to desktop only where we in this case can trigger a fallback to
+ * unmerged in which case we pass the geometry straight through and
+ * just apply the matrix.
+ *
+ * NOTE: This also means a slight performance impact for geometries which
+ * are defined to be outside the stable floating point range and still
+ * use single precision float, but given that this implicitly fixes
+ * huge lists and tables, it is worth it.
*/
-bool Batch::allMatricesAre2DSafe() const {
+bool Batch::isSafeToBatch() const {
Element *e = first;
while (e) {
+ if (e->boundsOutsideFloatRange)
+ return false;
if (!QMatrix4x4_Accessor::is2DSafe(*e->node->matrix()))
return false;
e = e->nextInBatch;
@@ -683,7 +747,7 @@ static int qsg_countNodesInBatches(const QDataBuffer<Batch *> &batches)
return sum;
}
-Renderer::Renderer(QSGContext *ctx)
+Renderer::Renderer(QSGRenderContext *ctx)
: QSGRenderer(ctx)
, m_opaqueRenderList(64)
, m_alphaRenderList(64)
@@ -700,6 +764,7 @@ Renderer::Renderer(QSGContext *ctx)
, m_zRange(0)
, m_currentMaterial(0)
, m_currentShader(0)
+ , m_vao(0)
{
setNodeUpdater(new Updater(this));
@@ -740,6 +805,13 @@ Renderer::Renderer(QSGContext *ctx)
qDebug() << "Batch thresholds: nodes:" << m_batchNodeThreshold << " vertices:" << m_batchVertexThreshold;
qDebug() << "Using buffer strategy:" << (m_bufferStrategy == GL_STATIC_DRAW ? "static" : (m_bufferStrategy == GL_DYNAMIC_DRAW ? "dynamic" : "stream"));
}
+
+ // If rendering with an OpenGL Core profile context, we need to create a VAO
+ // to hold our vertex specification state.
+ if (context()->openglContext()->format().profile() == QSurfaceFormat::CoreProfile) {
+ m_vao = new QOpenGLVertexArrayObject(this);
+ m_vao->create();
+ }
}
static void qsg_wipeBuffer(Buffer *buffer, QOpenGLFunctions *funcs)
@@ -1344,6 +1416,15 @@ void Renderer::buildRenderListsFromScratch()
buildRenderLists(rootNode());
}
+void Renderer::invalidateAlphaBatchesForRoot(Node *root)
+{
+ for (int i=0; i<m_alphaBatches.size(); ++i) {
+ Batch *b = m_alphaBatches.at(i);
+ if (b->root == root || root == 0)
+ b->invalidate();
+ }
+}
+
/* Clean up batches by making it a consecutive list of "valid"
* batches and moving all invalidated batches to the batches pool.
*/
@@ -1491,6 +1572,13 @@ void Renderer::prepareAlphaBatches()
ej->batch = batch;
next->nextInBatch = ej;
next = ej;
+ } else {
+ /* When we come across a compatible element which hits an overlap, we
+ * need to stop the batch right away. We cannot add more elements
+ * to the current batch as they will be rendered before the batch that the
+ * current 'ej' will be added to.
+ */
+ break;
}
} else {
overlapBounds |= ej->bounds;
@@ -1616,7 +1704,7 @@ void Renderer::uploadBatch(Batch *b)
&& (((gn->activeMaterial()->flags() & QSGMaterial::RequiresDeterminant) == 0)
|| (((gn->activeMaterial()->flags() & QSGMaterial_RequiresFullMatrixBit) == 0) && b->isTranslateOnlyToRoot())
)
- && b->allMatricesAre2DSafe();
+ && b->isSafeToBatch();
b->merged = canMerge;
@@ -1890,7 +1978,14 @@ void Renderer::renderMergedBatch(const Batch *batch)
updateClip(gn->clipList(), batch);
glBindBuffer(GL_ARRAY_BUFFER, batch->vbo.id);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vbo.id);
+
+ char *indexBase = 0;
+ if (m_context->hasBrokenIndexBufferObjects()) {
+ indexBase = batch->vbo.data;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ } else {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vbo.id);
+ }
QSGMaterial *material = gn->activeMaterial();
@@ -1925,7 +2020,7 @@ void Renderer::renderMergedBatch(const Batch *batch)
}
glVertexAttribPointer(sms->pos_order, 1, GL_FLOAT, false, 0, (void *) (qintptr) (draw.zorders));
- glDrawElements(g->drawingMode(), draw.indexCount, GL_UNSIGNED_SHORT, (void *) (qintptr) (draw.indices));
+ glDrawElements(g->drawingMode(), draw.indexCount, GL_UNSIGNED_SHORT, (void *) (qintptr) (indexBase + draw.indices));
}
}
@@ -1958,8 +2053,15 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
updateClip(gn->clipList(), batch);
glBindBuffer(GL_ARRAY_BUFFER, batch->vbo.id);
- if (batch->indexCount)
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vbo.id);
+ char *indexBase = 0;
+ if (batch->indexCount) {
+ if (m_context->hasBrokenIndexBufferObjects()) {
+ indexBase = batch->vbo.data;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ } else {
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->vbo.id);
+ }
+ }
// We always have dirty matrix as all batches are at a unique z range.
QSGMaterialShader::RenderState::DirtyStates dirty = QSGMaterialShader::RenderState::DirtyMatrix;
@@ -1978,7 +2080,7 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
}
int vOffset = 0;
- int iOffset = batch->vertexCount * gn->geometry()->sizeOfVertex();
+ char *iOffset = indexBase + batch->vertexCount * gn->geometry()->sizeOfVertex();
QMatrix4x4 rootMatrix = batch->root ? matrixForRoot(batch->root) : QMatrix4x4();
@@ -1994,7 +2096,9 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
program->updateState(state(dirty), material, m_currentMaterial);
- m_currentMaterial = gn->activeMaterial();
+ // We don't need to bother with asking each node for its material as they
+ // are all identical (compare==0) since they are in the same batch.
+ m_currentMaterial = material;
QSGGeometry* g = gn->geometry();
char const *const *attrNames = program->attributeNames();
@@ -2009,7 +2113,7 @@ void Renderer::renderUnmergedBatch(const Batch *batch)
}
if (g->indexCount())
- glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), (void *) (qintptr) iOffset);
+ glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), iOffset);
else
glDrawArrays(g->drawingMode(), 0, g->vertexCount());
@@ -2031,14 +2135,13 @@ void Renderer::renderBatches()
<< " -> Alpha: " << qsg_countNodesInBatches(m_alphaBatches) << " nodes in " << m_alphaBatches.size() << " batches...";
}
- QRect r = viewportRect();
- glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height());
-
for (QHash<QSGRenderNode *, RenderNodeElement *>::const_iterator it = m_renderNodeElements.constBegin();
it != m_renderNodeElements.constEnd(); ++it) {
prepareRenderNode(it.value());
}
+ QRect r = viewportRect();
+ glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height());
glClearColor(clearColor().redF(), clearColor().greenF(), clearColor().blueF(), clearColor().alphaF());
#if defined(QT_OPENGL_ES)
glClearDepthf(1);
@@ -2126,6 +2229,17 @@ void Renderer::deleteRemovedElements()
m_elementsToDelete.reset();
}
+void Renderer::preprocess()
+{
+ // Bind our VAO. It's important that we do this here as the
+ // QSGRenderer::preprocess() call may well do work that requires
+ // a bound VAO.
+ if (m_vao)
+ m_vao->bind();
+
+ QSGRenderer::preprocess();
+}
+
void Renderer::render()
{
if (Q_UNLIKELY(debug_dump)) {
@@ -2233,6 +2347,9 @@ void Renderer::render()
renderBatches();
m_rebuild = 0;
+
+ if (m_vao)
+ m_vao->release();
}
void Renderer::prepareRenderNode(RenderNodeElement *e)
@@ -2310,23 +2427,11 @@ void Renderer::renderRenderNode(Batch *batch)
if (!m_shaderManager->blitProgram) {
m_shaderManager->blitProgram = new QOpenGLShaderProgram();
- const char *vs =
- "attribute highp vec4 av; "
- "attribute highp vec2 at; "
- "varying highp vec2 t; "
- "void main() { "
- " gl_Position = av; "
- " t = at; "
- "} ";
- const char *fs =
- "uniform lowp sampler2D tex; "
- "varying highp vec2 t; "
- "void main() { "
- " gl_FragColor = texture2D(tex, t); "
- "} ";
-
- m_shaderManager->blitProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, vs);
- m_shaderManager->blitProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, fs);
+
+ QSGShaderSourceBuilder::initializeProgramFromFiles(
+ m_shaderManager->blitProgram,
+ QStringLiteral(":/scenegraph/shaders/rendernode.vert"),
+ QStringLiteral(":/scenegraph/shaders/rendernode.frag"));
m_shaderManager->blitProgram->bindAttributeLocation("av", 0);
m_shaderManager->blitProgram->bindAttributeLocation("at", 1);
m_shaderManager->blitProgram->link();
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 94e8ba5d96..95e111552d 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -50,9 +50,13 @@
QT_BEGIN_NAMESPACE
+class QOpenGLVertexArrayObject;
+
namespace QSGBatchRenderer
{
+#define QSG_RENDERER_COORD_LIMIT 1000000.0f
+
struct Vec;
struct Rect;
struct Buffer;
@@ -117,14 +121,7 @@ struct Rect {
Q_ASSERT(tl.y <= br.y);
}
- void map(const QMatrix4x4 &m) {
- tl.map(m);
- br.map(m);
- if (br.x < tl.x)
- qSwap(br.x, tl.x);
- if (br.y < tl.y)
- qSwap(br.y, tl.y);
- }
+ void map(const QMatrix4x4 &m);
void set(float left, float top, float right, float bottom) {
tl.set(left, top);
@@ -136,6 +133,13 @@ struct Rect {
bool yOverlap = r.tl.y < br.y && r.br.y > tl.y;
return xOverlap && yOverlap;
}
+
+ bool isOutsideFloatRange() const {
+ return tl.x < -QSG_RENDERER_COORD_LIMIT
+ || tl.y < -QSG_RENDERER_COORD_LIMIT
+ || br.x > QSG_RENDERER_COORD_LIMIT
+ || br.y > QSG_RENDERER_COORD_LIMIT;
+ }
};
inline QDebug operator << (QDebug d, const Rect &r) {
@@ -158,6 +162,7 @@ struct Element {
, root(0)
, order(0)
, boundsComputed(false)
+ , boundsOutsideFloatRange(false)
, translateOnlyToRoot(false)
, removed(false)
, orphaned(false)
@@ -181,6 +186,7 @@ struct Element {
int order;
uint boundsComputed : 1;
+ uint boundsOutsideFloatRange : 1;
uint translateOnlyToRoot : 1;
uint removed : 1;
uint orphaned : 1;
@@ -242,7 +248,7 @@ struct Batch
void cleanupRemovedElements();
bool isTranslateOnlyToRoot() const;
- bool allMatricesAre2DSafe() const;
+ bool isSafeToBatch() const;
// pseudo-constructor...
void init() {
@@ -389,11 +395,12 @@ public:
class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer
{
public:
- Renderer(QSGContext *);
+ Renderer(QSGRenderContext *);
~Renderer();
protected:
void nodeChanged(QSGNode *node, QSGNode::DirtyState state);
+ void preprocess() Q_DECL_OVERRIDE;
void render();
private:
@@ -420,6 +427,7 @@ private:
void prepareOpaqueBatches();
bool checkOverlap(int first, int last, const Rect &bounds);
void prepareAlphaBatches();
+ void invalidateAlphaBatchesForRoot(Node *root);
void uploadBatch(Batch *b);
void uploadMergedElement(Element *e, int vaOffset, char **vertexData, char **zData, char **indexData, quint16 *iBase, int *indexCount);
@@ -476,6 +484,9 @@ private:
QSGMaterialShader *m_currentProgram;
ShaderManager::Shader *m_currentShader;
const QSGClipNode *m_currentClip;
+
+ // For minimal OpenGL core profile support
+ QOpenGLVertexArrayObject *m_vao;
};
Batch *Renderer::newBatch()
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
index 25d256158e..686d1438b4 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp
@@ -41,9 +41,21 @@
#include "qsgmaterial.h"
#include "qsgrenderer_p.h"
+#include "qsgmaterialshader_p.h"
+#include <private/qsgshadersourcebuilder_p.h>
QT_BEGIN_NAMESPACE
+const char *QSGMaterialShaderPrivate::loadShaderSource(QOpenGLShader::ShaderType type) const
+{
+ QStringList files = m_sourceFiles[type];
+ QSGShaderSourceBuilder builder;
+ Q_FOREACH (const QString &file, files)
+ builder.appendSourceFile(file);
+ m_sources[type] = builder.source();
+ return m_sources[type].constData();
+}
+
#ifndef QT_NO_DEBUG
static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty();
#endif
@@ -165,14 +177,21 @@ static bool qsg_leak_check = !qgetenv("QML_LEAK_CHECK").isEmpty();
Creates a new QSGMaterialShader.
*/
QSGMaterialShader::QSGMaterialShader()
+ : d_ptr(new QSGMaterialShaderPrivate)
+{
+}
+
+QSGMaterialShader::QSGMaterialShader(QSGMaterialShaderPrivate &dd)
+ : d_ptr(&dd)
{
- Q_UNUSED(m_reserved);
}
/*!
- \fn QSGMaterialShader::~QSGMaterialShader()
\internal
*/
+QSGMaterialShader::~QSGMaterialShader()
+{
+}
/*!
\fn char const *const *QSGMaterialShader::attributeNames() const
@@ -194,6 +213,11 @@ QSGMaterialShader::QSGMaterialShader()
The contents returned from this function should never change.
*/
+const char *QSGMaterialShader::vertexShader() const
+{
+ Q_D(const QSGMaterialShader);
+ return d->loadShaderSource(QOpenGLShader::Vertex);
+}
/*!
@@ -204,6 +228,11 @@ QSGMaterialShader::QSGMaterialShader()
The contents returned from this function should never change.
*/
+const char *QSGMaterialShader::fragmentShader() const
+{
+ Q_D(const QSGMaterialShader);
+ return d->loadShaderSource(QOpenGLShader::Fragment);
+}
/*!
@@ -274,7 +303,35 @@ void QSGMaterialShader::updateState(const RenderState & /* state */, QSGMaterial
{
}
+/*!
+ Sets the GLSL source file for the shader stage \a type to \a sourceFile. The
+ default implementation of the vertexShader() and fragmentShader() functions
+ will load the source files set by this function.
+
+ This function is useful when you have a single source file for a given shader
+ stage. If your shader consists of multiple source files then use
+ setShaderSourceFiles()
+
+ \sa setShaderSourceFiles(), vertexShader(), fragmentShader()
+ */
+void QSGMaterialShader::setShaderSourceFile(QOpenGLShader::ShaderType type, const QString &sourceFile)
+{
+ Q_D(QSGMaterialShader);
+ d->m_sourceFiles[type] = (QStringList() << sourceFile);
+}
+
+/*!
+ Sets the GLSL source files for the shader stage \a type to \a sourceFiles. The
+ default implementation of the vertexShader() and fragmentShader() functions
+ will load the source files set by this function in the order given.
+ \sa setShaderSourceFile(), vertexShader(), fragmentShader()
+ */
+void QSGMaterialShader::setShaderSourceFiles(QOpenGLShader::ShaderType type, const QStringList &sourceFiles)
+{
+ Q_D(QSGMaterialShader);
+ d->m_sourceFiles[type] = sourceFiles;
+}
/*!
This function is called when the shader is initialized to compile the
@@ -478,7 +535,7 @@ QRect QSGMaterialShader::RenderState::deviceRect() const
QOpenGLContext *QSGMaterialShader::RenderState::context() const
{
- return static_cast<const QSGRenderer *>(m_data)->glContext();
+ return static_cast<const QSGRenderer *>(m_data)->context()->openglContext();
}
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.h b/src/quick/scenegraph/coreapi/qsgmaterial.h
index f3ef62d3e5..bfe570ca02 100644
--- a/src/quick/scenegraph/coreapi/qsgmaterial.h
+++ b/src/quick/scenegraph/coreapi/qsgmaterial.h
@@ -48,6 +48,7 @@
QT_BEGIN_NAMESPACE
class QSGMaterial;
+class QSGMaterialShaderPrivate;
namespace QSGBatchRenderer {
class ShaderManager;
@@ -88,7 +89,7 @@ public:
};
QSGMaterialShader();
- virtual ~QSGMaterialShader() {};
+ virtual ~QSGMaterialShader();
virtual void activate();
virtual void deactivate();
@@ -99,18 +100,24 @@ public:
inline QOpenGLShaderProgram *program() { return &m_program; }
protected:
+ Q_DECLARE_PRIVATE(QSGMaterialShader)
+ QSGMaterialShader(QSGMaterialShaderPrivate &dd);
+
friend class QSGContext;
friend class QSGBatchRenderer::ShaderManager;
+ void setShaderSourceFile(QOpenGLShader::ShaderType type, const QString &sourceFile);
+ void setShaderSourceFiles(QOpenGLShader::ShaderType type, const QStringList &sourceFiles);
+
virtual void compile();
virtual void initialize() { }
- virtual const char *vertexShader() const = 0;
- virtual const char *fragmentShader() const = 0;
+ virtual const char *vertexShader() const;
+ virtual const char *fragmentShader() const;
private:
QOpenGLShaderProgram m_program;
- void *m_reserved;
+ QScopedPointer<QSGMaterialShaderPrivate> d_ptr;
};
struct QSGMaterialType { };
diff --git a/src/quick/scenegraph/qsgflashnode_p.h b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
index 96496158ae..fc8a35c41d 100644
--- a/src/quick/scenegraph/qsgflashnode_p.h
+++ b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -39,25 +39,23 @@
**
****************************************************************************/
-#ifndef QSGFLASHNODE_H
-#define QSGFLASHNODE_H
+#ifndef QSGMATERIALSHADER_P_H
+#define QSGMATERIALSHADER_P_H
-#include <QtQuick/QSGSimpleRectNode>
+#include <private/qtquickglobal_p.h>
+#include <QOpenGLShader>
QT_BEGIN_NAMESPACE
-class QSGFlashNode : public QSGSimpleRectNode
+class Q_QUICK_PRIVATE_EXPORT QSGMaterialShaderPrivate
{
public:
- QSGFlashNode();
+ const char *loadShaderSource(QOpenGLShader::ShaderType type) const;
- void preprocess();
-
-private:
- int m_counter;
+ QHash<QOpenGLShader::ShaderType, QStringList> m_sourceFiles;
+ mutable QHash<QOpenGLShader::ShaderType, QByteArray> m_sources;
};
QT_END_NAMESPACE
-#endif // QSGFLASHNODE_H
-
+#endif // QSGMATERIALSHADER_P_H
diff --git a/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
index d5e83bb452..51cc844612 100644
--- a/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp
@@ -102,16 +102,11 @@ void QSGNodeUpdater::updateStates(QSGNode *n)
bool QSGNodeUpdater::isNodeBlocked(QSGNode *node, QSGNode *root) const
{
- qreal opacity = 1;
while (node != root && node != 0) {
- if (node->type() == QSGNode::OpacityNodeType) {
- opacity *= static_cast<QSGOpacityNode *>(node)->opacity();
- if (opacity < 0.001)
- return true;
- }
+ if (node->isSubtreeBlocked())
+ return true;
node = node->parent();
}
-
return false;
}
diff --git a/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h b/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
index d0adbc5dd2..4c3be61a76 100644
--- a/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
+++ b/src/quick/scenegraph/coreapi/qsgnodeupdater_p.h
@@ -64,9 +64,6 @@ public:
virtual void updateStates(QSGNode *n);
virtual bool isNodeBlocked(QSGNode *n, QSGNode *root) const;
- void setToplevelOpacity(qreal alpha) { m_opacity_stack.last() = alpha; }
- qreal toplevelOpacity() const { return m_opacity_stack.last(); }
-
protected:
virtual void enterTransformNode(QSGTransformNode *);
virtual void leaveTransformNode(QSGTransformNode *);
@@ -88,8 +85,6 @@ protected:
const QSGClipNode *m_current_clip;
int m_force_update;
-
- qreal m_toplevel_alpha;
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index 216c32f027..3c9c353bd8 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -46,6 +46,7 @@
#include "qsggeometry_p.h"
#include <private/qsgadaptationlayer_p.h>
+#include <private/qsgshadersourcebuilder_p.h>
#include <QOpenGLShaderProgram>
#include <qopenglframebufferobject.h>
@@ -133,7 +134,7 @@ void QSGBindableFboId::bind() const
*/
-QSGRenderer::QSGRenderer(QSGContext *context)
+QSGRenderer::QSGRenderer(QSGRenderContext *context)
: QObject()
, m_clear_color(Qt::transparent)
, m_clear_mode(ClearColorBuffer | ClearDepthBuffer)
@@ -162,20 +163,6 @@ QSGRenderer::~QSGRenderer()
}
/*!
- Returns the scene graph context for this renderer.
-
- \internal
- */
-
-QSGContext *QSGRenderer::context()
-{
- return m_context;
-}
-
-
-
-
-/*!
Returns the node updater that this renderer uses to update states in the
scene graph.
@@ -398,7 +385,6 @@ void QSGRenderer::preprocess()
preprocessTime = frameTimer.nsecsElapsed();
#endif
- nodeUpdater()->setToplevelOpacity(context()->renderAlpha());
nodeUpdater()->updateStates(m_root_node);
#ifndef QSG_NO_RENDER_TIMING
@@ -496,16 +482,10 @@ QSGRenderer::ClipType QSGRenderer::updateStencilClip(const QSGClipNode *clip)
} else {
if (!(clipType & StencilClip)) {
if (!m_clip_program.isLinked()) {
- m_clip_program.addShaderFromSourceCode(QOpenGLShader::Vertex,
- "attribute highp vec4 vCoord; \n"
- "uniform highp mat4 matrix; \n"
- "void main() { \n"
- " gl_Position = matrix * vCoord; \n"
- "}");
- m_clip_program.addShaderFromSourceCode(QOpenGLShader::Fragment,
- "void main() { \n"
- " gl_FragColor = vec4(0.81, 0.83, 0.12, 1.0); \n" // Trolltech green ftw!
- "}");
+ QSGShaderSourceBuilder::initializeProgramFromFiles(
+ &m_clip_program,
+ QStringLiteral(":/scenegraph/shaders/stencilclip.vert"),
+ QStringLiteral(":/scenegraph/shaders/stencilclip.frag"));
m_clip_program.bindAttributeLocation("vCoord", 0);
m_clip_program.link();
m_clip_matrix_id = m_clip_program.uniformLocation("matrix");
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
index a1ebfa0946..43811e6d5e 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -84,7 +84,7 @@ public:
};
Q_DECLARE_FLAGS(ClearMode, ClearModeBit)
- QSGRenderer(QSGContext *context);
+ QSGRenderer(QSGRenderContext *context);
virtual ~QSGRenderer();
void setRootNode(QSGRootNode *node);
@@ -117,9 +117,7 @@ public:
void setClearColor(const QColor &color);
QColor clearColor() const { return m_clear_color; }
- QOpenGLContext *glContext() const { Q_ASSERT(m_context); return m_context->glContext(); }
-
- QSGContext *context();
+ QSGRenderContext *context() const { return m_context; }
void renderScene();
void renderScene(const QSGBindable &bindable);
@@ -161,7 +159,7 @@ protected:
QRect m_current_scissor_rect;
int m_current_stencil_value;
- QSGContext *m_context;
+ QSGRenderContext *m_context;
private:
QSGRootNode *m_root_node;
diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
index eade198cd0..2849eff304 100644
--- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
+++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include <QtCore>
+#include <QtGui/QSurfaceFormat>
// Duct Tape tokenizer for the purpose of parsing and rewriting
// shader source code
@@ -173,7 +174,7 @@ Tokenizer::Token Tokenizer::next()
using namespace QSGShaderRewriter;
-QByteArray qsgShaderRewriter_insertZAttributes(const char *input)
+QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat::OpenGLContextProfile profile)
{
Tokenizer tok;
tok.initialize(input);
@@ -182,15 +183,33 @@ QByteArray qsgShaderRewriter_insertZAttributes(const char *input)
Tokenizer::Token t = tok.next();
// First find "void main() { ... "
+ const char* voidPos = input;
while (t != Tokenizer::Token_EOF) {
if (lt == Tokenizer::Token_Void && t == Tokenizer::Token_Identifier) {
if (qstrncmp("main", tok.identifier, 4) == 0)
break;
}
+ voidPos = tok.pos - 4;
lt = t;
t = tok.next();
}
+ QByteArray result;
+ result.reserve(1024);
+ result += QByteArray::fromRawData(input, voidPos - input);
+ switch (profile) {
+ case QSurfaceFormat::NoProfile:
+ case QSurfaceFormat::CompatibilityProfile:
+ result += QByteArrayLiteral("attribute highp float _qt_order;\n");
+ result += QByteArrayLiteral("uniform highp float _qt_zRange;\n");
+ break;
+
+ case QSurfaceFormat::CoreProfile:
+ result += QByteArrayLiteral("in float _qt_order;\n");
+ result += QByteArrayLiteral("uniform float _qt_zRange;\n");
+ break;
+ }
+
// Find first brace '{'
while (t != Tokenizer::Token_EOF && t != Tokenizer::Token_OpenBrace) t = tok.next();
int braceDepth = 1;
@@ -202,12 +221,8 @@ QByteArray qsgShaderRewriter_insertZAttributes(const char *input)
case Tokenizer::Token_CloseBrace:
braceDepth--;
if (braceDepth == 0) {
- QByteArray result;
- result.reserve(1024);
- result += "attribute highp float _qt_order;\n";
- result += "uniform highp float _qt_zRange;\n";
- result += QByteArray::fromRawData(input, tok.pos - 1 - input);
- result += " gl_Position.z = gl_Position.z * _qt_zRange + _qt_order;\n";
+ result += QByteArray::fromRawData(voidPos, tok.pos - 1 - voidPos);
+ result += QByteArrayLiteral(" gl_Position.z = (gl_Position.z * _qt_zRange + _qt_order) * gl_Position.w;\n");
result += QByteArray(tok.pos - 1);
return result;
}
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index cdf63be5f2..58c843a286 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -61,8 +61,7 @@ static QElapsedTimer qsg_render_timer;
QSGDistanceFieldGlyphCache::Texture QSGDistanceFieldGlyphCache::s_emptyTexture;
QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font)
- : ctx(c)
- , m_manager(man)
+ : m_manager(man)
, m_pendingGlyphs(64)
{
Q_ASSERT(font.isValid());
@@ -75,6 +74,8 @@ QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCach
m_referenceFont = font;
m_referenceFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(m_doubleGlyphResolution));
Q_ASSERT(m_referenceFont.isValid());
+
+ m_coreProfile = (c->format().profile() == QSurfaceFormat::CoreProfile);
}
QSGDistanceFieldGlyphCache::~QSGDistanceFieldGlyphCache()
diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h
index ebeb449be5..f2d7dc07ca 100644
--- a/src/quick/scenegraph/qsgadaptationlayer_p.h
+++ b/src/quick/scenegraph/qsgadaptationlayer_p.h
@@ -66,6 +66,7 @@ class QImage;
class TextureReference;
class QSGDistanceFieldGlyphCacheManager;
class QSGDistanceFieldGlyphNode;
+class QOpenGLContext;
class Q_QUICK_PRIVATE_EXPORT QSGRectangleNode : public QSGGeometryNode
{
@@ -246,7 +247,7 @@ protected:
GlyphData &glyphData(glyph_t glyph);
- QOpenGLContext *ctx;
+ inline bool isCoreProfile() const { return m_coreProfile; }
private:
QSGDistanceFieldGlyphCacheManager *m_manager;
@@ -255,6 +256,7 @@ private:
int m_glyphCount;
bool m_doubleGlyphResolution;
+ bool m_coreProfile;
QList<Texture> m_textures;
QHash<glyph_t, GlyphData> m_glyphsData;
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index bb8e3c4b36..afde7939f2 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -72,11 +72,8 @@
#include <private/qqmlprofilerservice_p.h>
-DEFINE_BOOL_CONFIG_OPTION(qmlFlashMode, QML_FLASH_MODE)
-DEFINE_BOOL_CONFIG_OPTION(qmlTranslucentMode, QML_TRANSLUCENT_MODE)
DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
-
/*
Comments about this class from Gunnar:
@@ -94,51 +91,38 @@ DEFINE_BOOL_CONFIG_OPTION(qmlDisableDistanceField, QML_DISABLE_DISTANCEFIELD)
to defining plugin interfaces..
*/
-
QT_BEGIN_NAMESPACE
class QSGContextPrivate : public QObjectPrivate
{
public:
QSGContextPrivate()
- : gl(0)
- , depthStencilBufferManager(0)
- , distanceFieldCacheManager(0)
- #if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2_ANGLE)
- , distanceFieldAntialiasing(QSGGlyphNode::HighQualitySubPixelAntialiasing)
- #else
- , distanceFieldAntialiasing(QSGGlyphNode::GrayAntialiasing)
- #endif
- , atlasManager(0)
- , flashMode(qmlFlashMode())
+ : antialiasingMethod(QSGContext::UndecidedAntialiasing)
, distanceFieldDisabled(qmlDisableDistanceField())
- , msaa(false)
+ , distanceFieldAntialiasing(
+#if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2_ANGLE)
+ QSGGlyphNode::HighQualitySubPixelAntialiasing
+#else
+ QSGGlyphNode::GrayAntialiasing
+#endif
+ )
{
- renderAlpha = qmlTranslucentMode() ? 0.5 : 1;
}
~QSGContextPrivate()
{
}
- QOpenGLContext *gl;
-
- QMutex textureMutex;
- QHash<QQuickTextureFactory *, QSGTexture *> textures;
- QSGDepthStencilBufferManager *depthStencilBufferManager;
- QSGDistanceFieldGlyphCacheManager *distanceFieldCacheManager;
-
- QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing;
-
- QSGAtlasTexture::Manager *atlasManager;
-
- bool flashMode;
- float renderAlpha;
+ QMutex mutex;
+ QSGContext::AntialiasingMethod antialiasingMethod;
bool distanceFieldDisabled;
+ QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing;
- bool msaa;
+ static QOpenGLContext *sharedOpenGLContext;
};
+QOpenGLContext *QSGContextPrivate::sharedOpenGLContext = 0;
+
class QSGTextureCleanupEvent : public QEvent
{
public:
@@ -188,144 +172,190 @@ QSGContext::QSGContext(QObject *parent) :
QSGContext::~QSGContext()
{
- invalidate();
}
+/*!
+ * This function is used by the Qt WebEngine to set up context sharing
+ * across multiple windows. Do not use it for any other purpose.
+ */
+void QSGContext::setSharedOpenGLContext(QOpenGLContext *context)
+{
+ QSGContextPrivate::sharedOpenGLContext = context;
+}
+QOpenGLContext *QSGContext::sharedOpenGLContext()
+{
+ return QSGContextPrivate::sharedOpenGLContext;
+}
-void QSGContext::invalidate()
+void QSGContext::renderContextInitialized(QSGRenderContext *renderContext)
{
Q_D(QSGContext);
- d->textureMutex.lock();
- qDeleteAll(d->textures.values());
- d->textures.clear();
- d->textureMutex.unlock();
- delete d->depthStencilBufferManager;
- d->depthStencilBufferManager = 0;
- delete d->distanceFieldCacheManager;
- d->distanceFieldCacheManager = 0;
- d->gl = 0;
-
- emit invalidated();
-
- /* The cleanup of the atlas textures is a bit intruiging.
- As part of the cleanup in the threaded render loop, we
- do:
- 1. call this function
- 2. call QCoreApp::sendPostedEvents() to immediately process
- any pending deferred deletes.
- 3. delete the GL context.
- As textures need the atlas manager while cleaning up, the
- manager needs to be cleaned up after the textures, so
- we post a deleteLater here at the very bottom so it gets
- deferred deleted last.
-
- Another alternative would be to use a QPointer in
- QSGAtlasTexture::Texture, but this seemed simpler.
- */
+ d->mutex.lock();
+ if (d->antialiasingMethod == UndecidedAntialiasing) {
+ QByteArray aaType = qgetenv("QSG_ANTIALIASING_METHOD");
+ if (aaType == "msaa") {
+ d->antialiasingMethod = MsaaAntialiasing;
+ } else if (aaType == "vertex") {
+ d->antialiasingMethod = VertexAntialiasing;
+ } else {
+ if (renderContext->openglContext()->format().samples() > 0)
+ d->antialiasingMethod = MsaaAntialiasing;
+ else
+ d->antialiasingMethod = VertexAntialiasing;
+ }
+ }
- if (d->atlasManager) {
- d->atlasManager->deleteLater();
- d->atlasManager = 0;
+ static bool dumped = false;
+ if (!dumped && qEnvironmentVariableIsSet("QSG_INFO")) {
+ dumped = true;
+ qDebug() << "GL_VENDOR: " << (const char *) glGetString(GL_VENDOR);
+ qDebug() << "GL_RENDERER: " << (const char *) glGetString(GL_RENDERER);
+ qDebug() << "GL_VERSION: " << (const char *) glGetString(GL_VERSION);
+ qDebug() << "GL_EXTENSIONS:\n " << QByteArray((const char *) glGetString(GL_EXTENSIONS)).replace(" ", "\n ").constData();
}
+
+ d->mutex.unlock();
}
+void QSGContext::renderContextInvalidated(QSGRenderContext *)
+{
+}
-QSGTexture *QSGContext::textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window)
+/*!
+ Factory function for scene graph backends of the Rectangle element.
+ */
+QSGRectangleNode *QSGContext::createRectangleNode()
{
Q_D(QSGContext);
- if (!factory)
- return 0;
-
- d->textureMutex.lock();
- QSGTexture *texture = d->textures.value(factory);
- if (!texture) {
- if (QQuickDefaultTextureFactory *dtf = qobject_cast<QQuickDefaultTextureFactory *>(factory))
- texture = createTexture(dtf->image());
- else
- texture = factory->createTexture(window);
- d->textures.insert(factory, texture);
- connect(factory, SIGNAL(destroyed(QObject *)), this, SLOT(textureFactoryDestroyed(QObject *)), Qt::DirectConnection);
- }
- d->textureMutex.unlock();
- return texture;
+ return d->antialiasingMethod == MsaaAntialiasing
+ ? new QSGMultisampleAntialiasing::RectangleNode
+ : new QSGDefaultRectangleNode;
}
+/*!
+ Factory function for scene graph backends of the Image element.
+ */
+QSGImageNode *QSGContext::createImageNode()
+{
+ Q_D(QSGContext);
+ return d->antialiasingMethod == MsaaAntialiasing
+ ? new QSGMultisampleAntialiasing::ImageNode
+ : new QSGDefaultImageNode;
+}
-void QSGContext::textureFactoryDestroyed(QObject *o)
+/*!
+ Factory function for scene graph backends of the Text elements which supports native
+ text rendering. Used in special cases where native look and feel is a main objective.
+*/
+QSGGlyphNode *QSGContext::createNativeGlyphNode(QSGRenderContext *rc)
{
+#if defined(QT_OPENGL_ES) && !defined(QT_OPENGL_ES_2_ANGLE)
Q_D(QSGContext);
- QQuickTextureFactory *f = static_cast<QQuickTextureFactory *>(o);
+ if (d->distanceFieldDisabled)
+ return new QSGDefaultGlyphNode;
+ else
+ return createGlyphNode(rc);
+#else
+ Q_UNUSED(rc);
+ return new QSGDefaultGlyphNode;
+#endif
+}
- d->textureMutex.lock();
- QSGTexture *t = d->textures.take(f);
- d->textureMutex.unlock();
+/*!
+ Factory function for scene graph backends of the Text elements;
+ */
+QSGGlyphNode *QSGContext::createGlyphNode(QSGRenderContext *rc)
+{
+ Q_D(QSGContext);
- if (t) {
- if (t->thread() == thread())
- t->deleteLater();
- else
- QCoreApplication::postEvent(this, new QSGTextureCleanupEvent(t));
+ if (d->distanceFieldDisabled) {
+ return createNativeGlyphNode(rc);
+ } else {
+ QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(rc);
+ node->setPreferredAntialiasingMode(d->distanceFieldAntialiasing);
+ return node;
}
}
-
-QOpenGLContext *QSGContext::glContext() const
+QSurfaceFormat QSGContext::defaultSurfaceFormat() const
{
- Q_D(const QSGContext);
- return d->gl;
+ QSurfaceFormat format;
+ format.setDepthBufferSize(24);
+ format.setStencilBufferSize(8);
+ if (QQuickWindow::hasDefaultAlphaBuffer())
+ format.setAlphaBufferSize(8);
+ format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
+ return format;
}
/*!
- Initializes the scene graph context with the GL context \a context. This also
- emits the ready() signal so that the QML graph can start building scene graph nodes.
+ Returns the minimum supported framebuffer object size.
*/
-void QSGContext::initialize(QOpenGLContext *context)
+
+QSize QSGContext::minimumFBOSize() const
{
- Q_D(QSGContext);
+#ifdef Q_OS_MAC
+ return QSize(33, 33);
+#else
+ return QSize(1, 1);
+#endif
+}
- QByteArray aaType = qgetenv("QSG_ANTIALIASING_METHOD");
- if (aaType == "msaa") {
- d->msaa = true;
- } else if (aaType == "vertex") {
- d->msaa = false;
- } else {
- if (context->format().samples() > 0)
- d->msaa = true;
- else
- d->msaa = false;
- }
- // Sanity check the surface format, in case it was overridden by the application
- QSurfaceFormat requested = defaultSurfaceFormat();
- QSurfaceFormat actual = context->format();
- if (requested.depthBufferSize() > 0 && actual.depthBufferSize() <= 0)
- qWarning("QSGContext::initialize: depth buffer support missing, expect rendering errors");
- if (requested.stencilBufferSize() > 0 && actual.stencilBufferSize() <= 0)
- qWarning("QSGContext::initialize: stencil buffer support missing, expect rendering errors");
- d->atlasManager = new QSGAtlasTexture::Manager();
+/*!
+ Sets whether or not the scene graph should use the distance field technique to render text
+ */
+void QSGContext::setDistanceFieldEnabled(bool enabled)
+{
+ d_func()->distanceFieldDisabled = !enabled;
+}
- Q_ASSERT(!d->gl);
- d->gl = context;
- emit initialized();
+/*!
+ Returns true if the scene graph uses the distance field technique to render text
+ */
+bool QSGContext::isDistanceFieldEnabled() const
+{
+ return !d_func()->distanceFieldDisabled;
}
+
+
/*!
- Returns if the scene graph context is ready or not, meaning that it has a valid
- GL context.
+ Creates a new animation driver.
*/
-bool QSGContext::isReady() const
+
+QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
{
- Q_D(const QSGContext);
- return d->gl;
+ return new QAnimationDriver(parent);
}
+QSGRenderContext::QSGRenderContext(QSGContext *context)
+ : m_gl(0)
+ , m_sg(context)
+ , m_atlasManager(0)
+ , m_depthStencilManager(0)
+ , m_distanceFieldCacheManager(0)
+ , m_brokenIBOs(false)
+ , m_serializedRender(false)
+{
+}
-void QSGContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId)
+QSGRenderContext::~QSGRenderContext()
{
+ invalidate();
+}
+
+static QBasicMutex qsg_framerender_mutex;
+
+void QSGRenderContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId)
+{
+ if (m_serializedRender)
+ qsg_framerender_mutex.lock();
+
if (fboId) {
QSGBindableFboId bindable(fboId);
renderer->renderScene(bindable);
@@ -333,39 +363,20 @@ void QSGContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId)
renderer->renderScene();
}
-}
+ if (m_serializedRender)
+ qsg_framerender_mutex.unlock();
-/*!
- Factory function for scene graph backends of the Rectangle element.
- */
-QSGRectangleNode *QSGContext::createRectangleNode()
-{
- Q_D(QSGContext);
- return d->msaa ? new QSGMultisampleAntialiasing::RectangleNode
- : new QSGDefaultRectangleNode;
-}
-
-/*!
- Factory function for scene graph backends of the Image element.
- */
-QSGImageNode *QSGContext::createImageNode()
-{
- Q_D(QSGContext);
- return d->msaa ? new QSGMultisampleAntialiasing::ImageNode
- : new QSGDefaultImageNode;
}
/*!
Factory function for scene graph backends of the distance-field glyph cache.
*/
-QSGDistanceFieldGlyphCache *QSGContext::distanceFieldGlyphCache(const QRawFont &font)
+QSGDistanceFieldGlyphCache *QSGRenderContext::distanceFieldGlyphCache(const QRawFont &font)
{
- Q_D(QSGContext);
-
- if (!d->distanceFieldCacheManager)
- d->distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager;
+ if (!m_distanceFieldCacheManager)
+ m_distanceFieldCacheManager = new QSGDistanceFieldGlyphCacheManager;
- QSGDistanceFieldGlyphCache *cache = d->distanceFieldCacheManager->cache(font);
+ QSGDistanceFieldGlyphCache *cache = m_distanceFieldCacheManager->cache(font);
if (!cache) {
QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
if (platformIntegration != 0
@@ -387,125 +398,125 @@ QSGDistanceFieldGlyphCache *QSGContext::distanceFieldGlyphCache(const QRawFont &
QPlatformSharedGraphicsCache::Alpha8);
cache = new QSGSharedDistanceFieldGlyphCache(keyName,
- sharedGraphicsCache,
- d->distanceFieldCacheManager,
- glContext(),
- font);
+ sharedGraphicsCache,
+ m_distanceFieldCacheManager,
+ openglContext(),
+ font);
}
}
}
if (!cache)
- cache = new QSGDefaultDistanceFieldGlyphCache(d->distanceFieldCacheManager, glContext(), font);
- d->distanceFieldCacheManager->insertCache(font, cache);
+ cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, openglContext(), font);
+ m_distanceFieldCacheManager->insertCache(font, cache);
}
+
return cache;
}
-/*!
- Factory function for scene graph backends of the Text elements which supports native
- text rendering. Used in special cases where native look and feel is a main objective.
-*/
-QSGGlyphNode *QSGContext::createNativeGlyphNode()
+#define QSG_RENDERCONTEXT_PROPERTY "_q_sgrendercontext"
+
+QSGRenderContext *QSGRenderContext::from(QOpenGLContext *context)
{
-#if defined(QT_OPENGL_ES) && !defined(QT_OPENGL_ES_2_ANGLE)
- Q_D(QSGContext);
- if (d->distanceFieldDisabled)
- return new QSGDefaultGlyphNode;
- else
- return createGlyphNode();
-#else
- return new QSGDefaultGlyphNode;
-#endif
+ return qobject_cast<QSGRenderContext *>(context->property(QSG_RENDERCONTEXT_PROPERTY).value<QObject *>());
}
-/*!
- Factory function for scene graph backends of the Text elements;
- */
-QSGGlyphNode *QSGContext::createGlyphNode()
+void QSGRenderContext::registerFontengineForCleanup(QFontEngine *engine)
{
- Q_D(QSGContext);
-
- if (d->distanceFieldDisabled) {
- return createNativeGlyphNode();
- } else {
- QSGDistanceFieldGlyphNode *node = new QSGDistanceFieldGlyphNode(this);
- node->setPreferredAntialiasingMode(d->distanceFieldAntialiasing);
- return node;
- }
+ m_fontEnginesToClean << engine;
}
/*!
- Factory function for the scene graph renderers.
-
- The renderers are used for the toplevel renderer and once for every
- QQuickShaderEffectSource used in the QML scene.
+ Initializes the scene graph render context with the GL context \a context. This also
+ emits the ready() signal so that the QML graph can start building scene graph nodes.
*/
-QSGRenderer *QSGContext::createRenderer()
+void QSGRenderContext::initialize(QOpenGLContext *context)
{
- return new QSGBatchRenderer::Renderer(this);
-}
-
-
+ // Sanity check the surface format, in case it was overridden by the application
+ QSurfaceFormat requested = m_sg->defaultSurfaceFormat();
+ QSurfaceFormat actual = context->format();
+ if (requested.depthBufferSize() > 0 && actual.depthBufferSize() <= 0)
+ qWarning("QSGContext::initialize: depth buffer support missing, expect rendering errors");
+ if (requested.stencilBufferSize() > 0 && actual.stencilBufferSize() <= 0)
+ qWarning("QSGContext::initialize: stencil buffer support missing, expect rendering errors");
+ if (!m_atlasManager)
+ m_atlasManager = new QSGAtlasTexture::Manager();
+
+ Q_ASSERT_X(!m_gl, "QSGRenderContext::initialize", "already initialized!");
+ m_gl = context;
+ m_gl->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant::fromValue(this));
+ m_sg->renderContextInitialized(this);
+
+#ifdef Q_OS_LINUX
+ const char *vendor = (const char *) glGetString(GL_VENDOR);
+ if (strstr(vendor, "nouveau"))
+ m_brokenIBOs = true;
+ const char *renderer = (const char *) glGetString(GL_RENDERER);
+ if (strstr(renderer, "llvmpipe"))
+ m_serializedRender = true;
+#endif
-QSurfaceFormat QSGContext::defaultSurfaceFormat() const
-{
- QSurfaceFormat format;
- format.setDepthBufferSize(24);
- format.setStencilBufferSize(8);
- if (QQuickWindow::hasDefaultAlphaBuffer())
- format.setAlphaBufferSize(8);
- format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
- return format;
+ emit initialized();
}
-
-/*!
- Factory function for texture objects.
-
- If \a image is a valid image, the QSGTexture::setImage function
- will be called with \a image as argument.
- */
-
-QSGTexture *QSGContext::createTexture(const QImage &image) const
+void QSGRenderContext::invalidate()
{
- Q_D(const QSGContext);
- QSGTexture *at = d->atlasManager->create(image);
- if (at)
- return at;
- return createTextureNoAtlas(image);
-}
+ if (!m_gl)
+ return;
+
+ qDeleteAll(m_textures.values());
+ m_textures.clear();
+
+ /* The cleanup of the atlas textures is a bit intriguing.
+ As part of the cleanup in the threaded render loop, we
+ do:
+ 1. call this function
+ 2. call QCoreApp::sendPostedEvents() to immediately process
+ any pending deferred deletes.
+ 3. delete the GL context.
+
+ As textures need the atlas manager while cleaning up, the
+ manager needs to be cleaned up after the textures, so
+ we post a deleteLater here at the very bottom so it gets
+ deferred deleted last.
+
+ Another alternative would be to use a QPointer in
+ QSGAtlasTexture::Texture, but this seemed simpler.
+ */
+ m_atlasManager->invalidate();
+ m_atlasManager->deleteLater();
+ m_atlasManager = 0;
+
+ // The following piece of code will read/write to the font engine's caches,
+ // potentially from different threads. However, this is safe because this
+ // code is only called from QQuickWindow's shutdown which is called
+ // only when the GUI is blocked, and multiple threads will call it in
+ // sequence. (see qsgdefaultglyphnode_p.cpp's init())
+ for (QSet<QFontEngine *>::const_iterator it = m_fontEnginesToClean.constBegin(),
+ end = m_fontEnginesToClean.constEnd(); it != end; ++it) {
+ (*it)->clearGlyphCache(m_gl);
+ }
+ m_fontEnginesToClean.clear();
-QSGTexture *QSGContext::createTextureNoAtlas(const QImage &image) const
-{
- QSGPlainTexture *t = new QSGPlainTexture();
- if (!image.isNull())
- t->setImage(image);
- return t;
-}
+ delete m_depthStencilManager;
+ m_depthStencilManager = 0;
-/*!
- Returns the minimum supported framebuffer object size.
- */
-
-QSize QSGContext::minimumFBOSize() const
-{
-#ifdef Q_OS_MAC
- return QSize(33, 33);
-#else
- return QSize(1, 1);
-#endif
-}
+ delete m_distanceFieldCacheManager;
+ m_distanceFieldCacheManager = 0;
+ m_gl->setProperty(QSG_RENDERCONTEXT_PROPERTY, QVariant());
+ m_gl = 0;
+ m_sg->renderContextInvalidated(this);
+ emit invalidated();
+}
/*!
Returns a shared pointer to a depth stencil buffer that can be used with \a fbo.
*/
-QSharedPointer<QSGDepthStencilBuffer> QSGContext::depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo)
+QSharedPointer<QSGDepthStencilBuffer> QSGRenderContext::depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo)
{
- Q_D(QSGContext);
- if (!d->gl)
+ if (!m_gl)
return QSharedPointer<QSGDepthStencilBuffer>();
QSGDepthStencilBufferManager *manager = depthStencilBufferManager();
QSGDepthStencilBuffer::Format format;
@@ -514,7 +525,7 @@ QSharedPointer<QSGDepthStencilBuffer> QSGContext::depthStencilBufferForFbo(QOpen
format.attachments = QSGDepthStencilBuffer::DepthAttachment | QSGDepthStencilBuffer::StencilAttachment;
QSharedPointer<QSGDepthStencilBuffer> buffer = manager->bufferForFormat(format);
if (buffer.isNull()) {
- buffer = QSharedPointer<QSGDepthStencilBuffer>(new QSGDefaultDepthStencilBuffer(d->gl, format));
+ buffer = QSharedPointer<QSGDepthStencilBuffer>(new QSGDefaultDepthStencilBuffer(m_gl, format));
manager->insertBuffer(buffer);
}
return buffer;
@@ -524,89 +535,81 @@ QSharedPointer<QSGDepthStencilBuffer> QSGContext::depthStencilBufferForFbo(QOpen
Returns a pointer to the context's depth/stencil buffer manager. This is useful for custom
implementations of \l depthStencilBufferForFbo().
*/
-QSGDepthStencilBufferManager *QSGContext::depthStencilBufferManager()
+QSGDepthStencilBufferManager *QSGRenderContext::depthStencilBufferManager()
{
- Q_D(QSGContext);
- if (!d->gl)
+ if (!m_gl)
return 0;
- if (!d->depthStencilBufferManager)
- d->depthStencilBufferManager = new QSGDepthStencilBufferManager(d->gl);
- return d->depthStencilBufferManager;
+ if (!m_depthStencilManager)
+ m_depthStencilManager = new QSGDepthStencilBufferManager(m_gl);
+ return m_depthStencilManager;
}
/*!
- Sets whether the scene graph should render with flashing update rectangles or not
- */
-
-void QSGContext::setFlashModeEnabled(bool enabled)
-{
- d_func()->flashMode = enabled;
-}
-
+ Factory function for texture objects.
-/*!
- Returns true if the scene graph should be rendered with flashing update rectangles
+ If \a image is a valid image, the QSGTexture::setImage function
+ will be called with \a image as argument.
*/
-bool QSGContext::isFlashModeEnabled() const
+
+QSGTexture *QSGRenderContext::createTexture(const QImage &image) const
{
- return d_func()->flashMode;
+ QSGTexture *t = m_atlasManager->create(image);
+ if (t)
+ return t;
+ return createTextureNoAtlas(image);
}
-
-/*!
- Sets the toplevel opacity for rendering. This value will be multiplied into all
- drawing calls where possible.
-
- The default value is 1. Any other value will cause artifacts and is primarily
- useful for debugging.
- */
-void QSGContext::setRenderAlpha(qreal renderAlpha)
+QSGTexture *QSGRenderContext::createTextureNoAtlas(const QImage &image) const
{
- d_func()->renderAlpha = renderAlpha;
+ QSGPlainTexture *t = new QSGPlainTexture();
+ if (!image.isNull())
+ t->setImage(image);
+ return t;
}
-
/*!
- Returns the toplevel opacity used for rendering.
-
- The default value is 1.
+ Factory function for the scene graph renderers.
- \sa setRenderAlpha()
+ The renderers are used for the toplevel renderer and once for every
+ QQuickShaderEffectSource used in the QML scene.
*/
-qreal QSGContext::renderAlpha() const
+QSGRenderer *QSGRenderContext::createRenderer()
{
- return d_func()->renderAlpha;
+ return new QSGBatchRenderer::Renderer(this);
}
-
-/*!
- Sets whether or not the scene graph should use the distance field technique to render text
- */
-void QSGContext::setDistanceFieldEnabled(bool enabled)
+QSGTexture *QSGRenderContext::textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window)
{
- d_func()->distanceFieldDisabled = !enabled;
-}
+ if (!factory)
+ return 0;
+ m_mutex.lock();
+ QSGTexture *texture = m_textures.value(factory);
+ m_mutex.unlock();
-/*!
- Returns true if the scene graph uses the distance field technique to render text
- */
-bool QSGContext::isDistanceFieldEnabled() const
-{
- return !d_func()->distanceFieldDisabled;
-}
-
+ if (!texture) {
+ if (QQuickDefaultTextureFactory *dtf = qobject_cast<QQuickDefaultTextureFactory *>(factory))
+ texture = createTexture(dtf->image());
+ else
+ texture = factory->createTexture(window);
+ m_mutex.lock();
+ m_textures.insert(factory, texture);
+ m_mutex.unlock();
-/*!
- Creates a new animation driver.
- */
+ connect(factory, SIGNAL(destroyed(QObject *)), this, SLOT(textureFactoryDestroyed(QObject *)), Qt::DirectConnection);
+ }
+ return texture;
+}
-QAnimationDriver *QSGContext::createAnimationDriver(QObject *parent)
+void QSGRenderContext::textureFactoryDestroyed(QObject *o)
{
- return new QAnimationDriver(parent);
+ m_mutex.lock();
+ QSGTexture *t = m_textures.take(static_cast<QQuickTextureFactory *>(o));
+ m_mutex.unlock();
+ if (t)
+ t->deleteLater();
}
-
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index 2057c0031d..c562a909c5 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -56,6 +56,9 @@
QT_BEGIN_NAMESPACE
+namespace QSGAtlasTexture {
+ class Manager;
+}
class QSGContextPrivate;
class QSGRectangleNode;
@@ -73,66 +76,102 @@ class QOpenGLContext;
class QOpenGLFramebufferObject;
class QQuickTextureFactory;
+class QSGDistanceFieldGlyphCacheManager;
+class QSGContext;
-class Q_QUICK_PRIVATE_EXPORT QSGContext : public QObject
+
+class Q_QUICK_PRIVATE_EXPORT QSGRenderContext : public QObject
{
Q_OBJECT
- Q_DECLARE_PRIVATE(QSGContext)
-
public:
- explicit QSGContext(QObject *parent = 0);
- ~QSGContext();
+ QSGRenderContext(QSGContext *context);
+ ~QSGRenderContext();
+
+ QOpenGLContext *openglContext() const { return m_gl; }
+ QSGContext *sceneGraphContext() const { return m_sg; }
virtual void initialize(QOpenGLContext *context);
virtual void invalidate();
- QOpenGLContext *glContext() const;
-
- bool isReady() const;
-
virtual void renderNextFrame(QSGRenderer *renderer, GLuint fboId);
- virtual QSGDistanceFieldGlyphCache *distanceFieldGlyphCache(const QRawFont &font);
+ virtual QSharedPointer<QSGDepthStencilBuffer> depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo);
+ QSGDepthStencilBufferManager *depthStencilBufferManager();
- virtual QSGRectangleNode *createRectangleNode();
- virtual QSGImageNode *createImageNode();
- virtual QSGGlyphNode *createGlyphNode();
- virtual QSGGlyphNode *createNativeGlyphNode();
- virtual QSGRenderer *createRenderer();
+ virtual QSGDistanceFieldGlyphCache *distanceFieldGlyphCache(const QRawFont &font);
+ QSGTexture *textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window);
virtual QSGTexture *createTexture(const QImage &image) const;
virtual QSGTexture *createTextureNoAtlas(const QImage &image) const;
- virtual QSize minimumFBOSize() const;
- virtual QSharedPointer<QSGDepthStencilBuffer> depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo);
- QSGDepthStencilBufferManager *depthStencilBufferManager();
+ virtual QSGRenderer *createRenderer();
- virtual QSurfaceFormat defaultSurfaceFormat() const;
+ void registerFontengineForCleanup(QFontEngine *engine);
- QSGTexture *textureForFactory(QQuickTextureFactory *factory, QQuickWindow *window);
+ static QSGRenderContext *from(QOpenGLContext *context);
- static QSGContext *createDefaultContext();
+ bool hasBrokenIndexBufferObjects() const { return m_brokenIBOs; }
- void setFlashModeEnabled(bool enabled);
- bool isFlashModeEnabled() const;
+Q_SIGNALS:
+ void initialized();
+ void invalidated();
+
+public Q_SLOTS:
+ void textureFactoryDestroyed(QObject *o);
- void setRenderAlpha(qreal renderAlpha);
- qreal renderAlpha() const;
+protected:
+ QOpenGLContext *m_gl;
+ QSGContext *m_sg;
- void setDistanceFieldEnabled(bool enabled);
- bool isDistanceFieldEnabled() const;
+ QMutex m_mutex;
+ QHash<QQuickTextureFactory *, QSGTexture *> m_textures;
+ QSGAtlasTexture::Manager *m_atlasManager;
+ QSGDepthStencilBufferManager *m_depthStencilManager;
+ QSGDistanceFieldGlyphCacheManager *m_distanceFieldCacheManager;
+
+ QSet<QFontEngine *> m_fontEnginesToClean;
+
+ bool m_brokenIBOs;
+ bool m_serializedRender;
+};
+
+
+class Q_QUICK_PRIVATE_EXPORT QSGContext : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSGContext)
+
+public:
+ enum AntialiasingMethod {
+ UndecidedAntialiasing,
+ VertexAntialiasing,
+ MsaaAntialiasing
+ };
+
+ explicit QSGContext(QObject *parent = 0);
+ ~QSGContext();
+
+ virtual void renderContextInitialized(QSGRenderContext *renderContext);
+ virtual void renderContextInvalidated(QSGRenderContext *renderContext);
+
+ virtual QSGRectangleNode *createRectangleNode();
+ virtual QSGImageNode *createImageNode();
+ virtual QSGGlyphNode *createGlyphNode(QSGRenderContext *rc);
+ virtual QSGGlyphNode *createNativeGlyphNode(QSGRenderContext *rc);
virtual QAnimationDriver *createAnimationDriver(QObject *parent);
- static QQuickTextureFactory *createTextureFactoryFromImage(const QImage &image);
- static QSGRenderLoop *createWindowManager();
+ virtual QSize minimumFBOSize() const;
+ virtual QSurfaceFormat defaultSurfaceFormat() const;
+ static void setSharedOpenGLContext(QOpenGLContext *context);
+ static QOpenGLContext *sharedOpenGLContext();
-public Q_SLOTS:
- void textureFactoryDestroyed(QObject *o);
+ void setDistanceFieldEnabled(bool enabled);
+ bool isDistanceFieldEnabled() const;
-Q_SIGNALS:
- void initialized();
- void invalidated();
+ static QSGContext *createDefaultContext();
+ static QQuickTextureFactory *createTextureFactoryFromImage(const QImage &image);
+ static QSGRenderLoop *createWindowManager();
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
index 8a1a87cdc0..c5c4e18e37 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp
@@ -48,6 +48,10 @@
#include <qopenglfunctions.h>
#include <qmath.h>
+#if !defined(QT_OPENGL_ES_2)
+#include <QtGui/qopenglfunctions_3_2_core.h>
+#endif
+
QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlUseGlyphCacheWorkaround, QML_USE_GLYPHCACHE_WORKAROUND)
@@ -58,6 +62,9 @@ QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistance
, m_maxTextureCount(3)
, m_blitProgram(0)
, m_fboGuard(0)
+#if !defined(QT_OPENGL_ES_2)
+ , m_funcs(0)
+#endif
{
m_blitVertexCoordinateArray[0] = -1.0f;
m_blitVertexCoordinateArray[1] = -1.0f;
@@ -167,7 +174,7 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField>
if (glyph.width() != expectedWidth)
glyph = glyph.copy(0, 0, expectedWidth, glyph.height());
- if (useWorkaround()) {
+ if (useTextureResizeWorkaround()) {
uchar *inBits = glyph.scanLine(0);
uchar *outBits = texInfo->image.scanLine(int(c.y)) + int(c.x);
for (int y = 0; y < glyph.height(); ++y) {
@@ -177,7 +184,24 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField>
}
}
- glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits());
+#if !defined(QT_OPENGL_ES_2)
+ const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+ const GLenum format = GL_ALPHA;
+#endif
+ if (useTextureUploadWorkaround()) {
+ for (int i = 0; i < glyph.height(); ++i) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ c.x, c.y + i, glyph.width(),1,
+ format, GL_UNSIGNED_BYTE,
+ glyph.scanLine(i));
+ }
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ c.x, c.y, glyph.width(), glyph.height(),
+ format, GL_UNSIGNED_BYTE,
+ glyph.constBits());
+ }
}
// restore to previous alignment
@@ -204,7 +228,7 @@ void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &glyph
void QSGDefaultDistanceFieldGlyphCache::createTexture(TextureInfo *texInfo, int width, int height)
{
- if (useWorkaround() && texInfo->image.isNull())
+ if (useTextureResizeWorkaround() && texInfo->image.isNull())
texInfo->image = QDistanceField(width, height);
while (glGetError() != GL_NO_ERROR) { }
@@ -212,11 +236,20 @@ void QSGDefaultDistanceFieldGlyphCache::createTexture(TextureInfo *texInfo, int
glGenTextures(1, &texInfo->texture);
glBindTexture(GL_TEXTURE_2D, texInfo->texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#if !defined(QT_OPENGL_ES_2)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ const GLint internalFormat = isCoreProfile() ? GL_R8 : GL_ALPHA;
+ const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+ const GLint internalFormat = GL_ALPHA;
+ const GLenum format = GL_ALPHA;
+#endif
+
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, 0);
texInfo->size = QSize(width, height);
@@ -236,6 +269,9 @@ static void freeFramebufferFunc(QOpenGLFunctions *funcs, GLuint id)
void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int width, int height)
{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ Q_ASSERT(ctx);
+
int oldWidth = texInfo->size.width();
int oldHeight = texInfo->size.height();
if (width == oldWidth && height == oldHeight)
@@ -249,12 +285,76 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int
updateTexture(oldTexture, texInfo->texture, texInfo->size);
- if (useWorkaround()) {
+#if !defined(QT_OPENGL_ES_2)
+ if (isCoreProfile() && !useTextureResizeWorkaround()) {
+ // For an OpenGL Core Profile we can use http://www.opengl.org/wiki/Framebuffer#Blitting
+ // to efficiently copy the contents of the old texture to the new texture
+ // TODO: Use ARB_copy_image if available of if we have >=4.3 context
+ if (!m_funcs) {
+ m_funcs = ctx->versionFunctions<QOpenGLFunctions_3_2_Core>();
+ Q_ASSERT(m_funcs);
+ m_funcs->initializeOpenGLFunctions();
+ }
+
+ // Create a framebuffer object to which we can attach our old and new textures (to
+ // the first two color buffer attachment points)
+ if (!m_fboGuard) {
+ GLuint fbo;
+ m_funcs->glGenFramebuffers(1, &fbo);
+ m_fboGuard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
+ }
+
+ // Bind the FBO to both the GL_READ_FRAMEBUFFER? and GL_DRAW_FRAMEBUFFER targets
+ m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_fboGuard->id());
+
+ // Bind the old texture to GL_COLOR_ATTACHMENT0
+ m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, oldTexture, 0);
+
+ // Bind the new texture to GL_COLOR_ATTACHMENT1
+ m_funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
+ GL_TEXTURE_2D, texInfo->texture, 0);
+
+ // Set the source and destination buffers
+ m_funcs->glReadBuffer(GL_COLOR_ATTACHMENT0);
+ m_funcs->glDrawBuffer(GL_COLOR_ATTACHMENT1);
+
+ // Do the blit
+ m_funcs->glBlitFramebuffer(0, 0, oldWidth, oldHeight,
+ 0, 0, oldWidth, oldHeight,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ // Reset the default framebuffer
+ m_funcs->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ return;
+ } else if (useTextureResizeWorkaround()) {
+#else
+ if (useTextureResizeWorkaround()) {
+#endif
GLint alignment = 4; // default value
glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, texInfo->image.constBits());
+#if !defined(QT_OPENGL_ES_2)
+ const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+ const GLenum format = GL_ALPHA;
+#endif
+
+ if (useTextureUploadWorkaround()) {
+ for (int i = 0; i < texInfo->image.height(); ++i) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, i, oldWidth, 1,
+ format, GL_UNSIGNED_BYTE,
+ texInfo->image.scanLine(i));
+ }
+ } else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0,
+ 0, 0, oldWidth, oldHeight,
+ format, GL_UNSIGNED_BYTE,
+ texInfo->image.constBits());
+ }
glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); // restore to previous value
@@ -278,12 +378,15 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int
GLuint tmp_texture;
glGenTextures(1, &tmp_texture);
glBindTexture(GL_TEXTURE_2D, tmp_texture);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#if !defined(QT_OPENGL_ES_2)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+#endif
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
ctx->functions()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, tmp_texture, 0);
@@ -325,7 +428,12 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int
glBindTexture(GL_TEXTURE_2D, texInfo->texture);
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
+ if (useTextureUploadWorkaround()) {
+ for (int i = 0; i < oldHeight; ++i)
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, i, 0, i, oldWidth, 1);
+ } else {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
+ }
ctx->functions()->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, 0);
@@ -350,12 +458,12 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int
m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
}
-bool QSGDefaultDistanceFieldGlyphCache::useWorkaround() const
+bool QSGDefaultDistanceFieldGlyphCache::useTextureResizeWorkaround() const
{
static bool set = false;
static bool useWorkaround = false;
if (!set) {
- QOpenGLContextPrivate *ctx_p = static_cast<QOpenGLContextPrivate *>(QOpenGLContextPrivate::get(ctx));
+ QOpenGLContextPrivate *ctx_p = static_cast<QOpenGLContextPrivate *>(QOpenGLContextPrivate::get(QOpenGLContext::currentContext()));
useWorkaround = ctx_p->workaround_brokenFBOReadBack
|| qmlUseGlyphCacheWorkaround(); // on some hardware the workaround is faster (see QTBUG-29264)
set = true;
@@ -363,6 +471,18 @@ bool QSGDefaultDistanceFieldGlyphCache::useWorkaround() const
return useWorkaround;
}
+bool QSGDefaultDistanceFieldGlyphCache::useTextureUploadWorkaround() const
+{
+ static bool set = false;
+ static bool useWorkaround = false;
+ if (!set) {
+ useWorkaround = qstrcmp(reinterpret_cast<const char*>(glGetString(GL_RENDERER)),
+ "Mali-400 MP") == 0;
+ set = true;
+ }
+ return useWorkaround;
+}
+
int QSGDefaultDistanceFieldGlyphCache::maxTextureSize() const
{
if (!m_maxTextureSize)
diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
index cd6fa00852..a5833af5fb 100644
--- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
+++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h
@@ -51,6 +51,10 @@
QT_BEGIN_NAMESPACE
class QOpenGLSharedResourceGuard;
+#if !defined(QT_OPENGL_ES_2)
+class QOpenGLFunctions_3_2_Core;
+#endif
+
class Q_QUICK_PRIVATE_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceFieldGlyphCache
{
public:
@@ -62,7 +66,8 @@ public:
void referenceGlyphs(const QSet<glyph_t> &glyphs);
void releaseGlyphs(const QSet<glyph_t> &glyphs);
- bool useWorkaround() const;
+ bool useTextureResizeWorkaround() const;
+ bool useTextureUploadWorkaround() const;
int maxTextureSize() const;
void setMaxTextureCount(int max) { m_maxTextureCount = max; }
@@ -132,6 +137,9 @@ private:
GLfloat m_blitTextureCoordinateArray[8];
QOpenGLSharedResourceGuard *m_fboGuard;
+#if !defined(QT_OPENGL_ES_2)
+ QOpenGLFunctions_3_2_Core *m_funcs;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
index 39d9832f58..35c4d1c506 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qsgdefaultglyphnode_p_p.h"
+#include <private/qsgmaterialshader_p.h>
#include <qopenglshaderprogram.h>
@@ -75,8 +76,6 @@ public:
protected:
virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
int m_matrix_id;
int m_color_id;
@@ -85,30 +84,6 @@ protected:
QFontEngineGlyphCache::Type m_cacheType;
};
-const char *QSGTextMaskShader::vertexShader() const {
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "varying highp vec2 sampleCoord; \n"
- "void main() { \n"
- " sampleCoord = tCoord * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- "}";
-}
-
-const char *QSGTextMaskShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "uniform sampler2D _qt_texture; \n"
- "uniform lowp vec4 color; \n"
- "void main() { \n"
- " lowp vec4 glyph = texture2D(_qt_texture, sampleCoord); \n"
- " gl_FragColor = vec4(glyph.rgb * color.a, glyph.a); \n"
- "}";
-}
-
char const *const *QSGTextMaskShader::attributeNames() const
{
static char const *const attr[] = { "vCoord", "tCoord", 0 };
@@ -116,8 +91,11 @@ char const *const *QSGTextMaskShader::attributeNames() const
}
QSGTextMaskShader::QSGTextMaskShader(QFontEngineGlyphCache::Type cacheType)
- : m_cacheType(cacheType)
+ : QSGMaterialShader(*new QSGMaterialShaderPrivate),
+ m_cacheType(cacheType)
{
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/textmask.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/textmask.frag"));
}
static inline qreal fontSmoothingGamma()
@@ -186,22 +164,13 @@ class QSG8BitTextMaskShader : public QSGTextMaskShader
public:
QSG8BitTextMaskShader(QFontEngineGlyphCache::Type cacheType)
: QSGTextMaskShader(cacheType)
- {}
+ {
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/8bittextmask.frag"));
+ }
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual const char *fragmentShader() const;
};
-const char *QSG8BitTextMaskShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "uniform lowp sampler2D texture; \n"
- "uniform lowp vec4 color; \n"
- "void main() { \n"
- " gl_FragColor = color * texture2D(texture, sampleCoord).a; \n"
- "}";
-}
-
void QSG8BitTextMaskShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
{
QSGTextMaskShader::updateState(state, newEffect, oldEffect);
@@ -220,28 +189,18 @@ public:
QSG24BitTextMaskShader(QFontEngineGlyphCache::Type cacheType)
: QSGTextMaskShader(cacheType)
, m_useSRGB(false)
- {}
+ {
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/24bittextmask.frag"));
+ }
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
virtual void initialize();
void activate();
void deactivate();
- virtual const char *fragmentShader() const;
uint m_useSRGB : 1;
};
-const char *QSG24BitTextMaskShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "uniform lowp sampler2D texture; \n"
- "uniform lowp float color; // just the alpha, really... \n"
- "void main() { \n"
- " lowp vec4 glyph = texture2D(texture, sampleCoord); \n"
- " gl_FragColor = vec4(glyph.rgb * color, glyph.a); \n"
- "}";
-}
-
void QSG24BitTextMaskShader::initialize()
{
QSGTextMaskShader::initialize();
@@ -302,14 +261,15 @@ class QSGStyledTextShader : public QSG8BitTextMaskShader
public:
QSGStyledTextShader(QFontEngineGlyphCache::Type cacheType)
: QSG8BitTextMaskShader(cacheType)
- { }
+ {
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/styledtext.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/styledtext.frag"));
+ }
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
private:
virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
int m_shift_id;
int m_styleColor_id;
@@ -367,98 +327,17 @@ void QSGStyledTextShader::updateState(const RenderState &state,
program()->setUniformValue(m_matrix_id, state.combinedMatrix());
}
-const char *QSGStyledTextShader::vertexShader() const
-{
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "uniform highp vec2 shift; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec2 shiftedSampleCoord; \n"
- "void main() { \n"
- " sampleCoord = tCoord * textureScale; \n"
- " shiftedSampleCoord = (tCoord - shift) * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- "}";
-}
-
-const char *QSGStyledTextShader::fragmentShader() const
-{
- return
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec2 shiftedSampleCoord; \n"
- "uniform sampler2D _qt_texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform lowp vec4 styleColor; \n"
- "void main() { \n"
- " lowp float glyph = texture2D(_qt_texture, sampleCoord).a; \n"
- " lowp float style = clamp(texture2D(_qt_texture, shiftedSampleCoord).a - glyph, \n"
- " 0.0, 1.0); \n"
- " gl_FragColor = style * styleColor + glyph * color; \n"
- "}";
-}
-
-
class QSGOutlinedTextShader : public QSGStyledTextShader
{
public:
QSGOutlinedTextShader(QFontEngineGlyphCache::Type cacheType)
: QSGStyledTextShader(cacheType)
- { }
-
-private:
- const char *vertexShader() const;
- const char *fragmentShader() const;
+ {
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/outlinedtext.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/outlinedtext.frag"));
+ }
};
-const char *QSGOutlinedTextShader::vertexShader() const
-{
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "uniform highp vec2 shift; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec2 sCoordUp; \n"
- "varying highp vec2 sCoordDown; \n"
- "varying highp vec2 sCoordLeft; \n"
- "varying highp vec2 sCoordRight; \n"
- "void main() { \n"
- " sampleCoord = tCoord * textureScale; \n"
- " sCoordUp = (tCoord - vec2(0.0, -1.0)) * textureScale; \n"
- " sCoordDown = (tCoord - vec2(0.0, 1.0)) * textureScale; \n"
- " sCoordLeft = (tCoord - vec2(-1.0, 0.0)) * textureScale; \n"
- " sCoordRight = (tCoord - vec2(1.0, 0.0)) * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- "}";
-}
-
-const char *QSGOutlinedTextShader::fragmentShader() const
-{
- return
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec2 sCoordUp; \n"
- "varying highp vec2 sCoordDown; \n"
- "varying highp vec2 sCoordLeft; \n"
- "varying highp vec2 sCoordRight; \n"
- "uniform sampler2D _qt_texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform lowp vec4 styleColor; \n"
- "void main() { \n"
- "lowp float glyph = texture2D(_qt_texture, sampleCoord).a; \n"
- " lowp float outline = clamp(clamp(texture2D(_qt_texture, sCoordUp).a + \n"
- " texture2D(_qt_texture, sCoordDown).a + \n"
- " texture2D(_qt_texture, sCoordLeft).a + \n"
- " texture2D(_qt_texture, sCoordRight).a, \n"
- " 0.0, 1.0) - glyph, \n"
- " 0.0, 1.0); \n"
- " gl_FragColor = outline * styleColor + glyph * color; \n"
- "}";
-}
-
QSGTextMaskMaterial::QSGTextMaskMaterial(const QRawFont &font, int cacheType)
: m_texture(0)
, m_glyphCache(0)
@@ -480,6 +359,12 @@ void QSGTextMaskMaterial::init(int cacheType)
QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
Q_ASSERT(ctx != 0);
+ // The following piece of code will read/write to the font engine's caches,
+ // potentially from different threads. However, this is safe because this
+ // code is only called from QQuickItem::updatePaintNode() which is called
+ // only when the GUI is blocked, and multiple threads will call it in
+ // sequence. See also QSGRenderContext::invalidate
+
QRawFontPrivate *fontD = QRawFontPrivate::get(m_font);
if (fontD->fontEngine != 0) {
if (cacheType < 0) {
@@ -494,6 +379,9 @@ void QSGTextMaskMaterial::init(int cacheType)
m_glyphCache = new QOpenGLTextureGlyphCache(QFontEngineGlyphCache::Type(cacheType),
QTransform());
fontD->fontEngine->setGlyphCache(ctx, m_glyphCache.data());
+ QSGRenderContext *sg = QSGRenderContext::from(ctx);
+ Q_ASSERT(sg);
+ sg->registerFontengineForCleanup(fontD->fontEngine);
}
}
}
diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp
index 11d0e5dbeb..926c0c1f4a 100644
--- a/src/quick/scenegraph/qsgdefaultimagenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qsgdefaultimagenode_p.h"
+#include <private/qsgmaterialshader_p.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qmath.h>
@@ -75,13 +76,13 @@ namespace
class SmoothTextureMaterialShader : public QSGTextureMaterialShader
{
public:
+ SmoothTextureMaterialShader();
+
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
virtual char const *const *attributeNames() const;
protected:
virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
int m_pixelSizeLoc;
};
@@ -109,6 +110,13 @@ QSGMaterialShader *QSGSmoothTextureMaterial::createShader() const
return new SmoothTextureMaterialShader;
}
+SmoothTextureMaterialShader::SmoothTextureMaterialShader()
+ : QSGTextureMaterialShader()
+{
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/smoothtexture.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/smoothtexture.frag"));
+}
+
void SmoothTextureMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
{
if (oldEffect == 0) {
@@ -137,70 +145,6 @@ void SmoothTextureMaterialShader::initialize()
QSGTextureMaterialShader::initialize();
}
-const char *SmoothTextureMaterialShader::vertexShader() const
-{
- return
- "uniform highp vec2 pixelSize; \n"
- "uniform highp mat4 qt_Matrix; \n"
- "uniform lowp float opacity; \n"
- "attribute highp vec4 vertex; \n"
- "attribute highp vec2 multiTexCoord; \n"
- "attribute highp vec2 vertexOffset; \n"
- "attribute highp vec2 texCoordOffset; \n"
- "varying highp vec2 texCoord; \n"
- "varying lowp float vertexOpacity; \n"
- "void main() { \n"
- " highp vec4 pos = qt_Matrix * vertex; \n"
- " gl_Position = pos; \n"
- " texCoord = multiTexCoord; \n"
-
- " if (vertexOffset.x != 0.) { \n"
- " highp vec4 delta = qt_Matrix[0] * vertexOffset.x; \n"
- " highp vec2 dir = delta.xy * pos.w - pos.xy * delta.w; \n"
- " highp vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize); \n"
- " dir -= ndir * delta.w * pos.w; \n"
- " highp float numerator = dot(dir, ndir * pos.w * pos.w); \n"
- " highp float scale = 0.0; \n"
- " if (numerator < 0.0) \n"
- " scale = 1.0; \n"
- " else \n"
- " scale = min(1.0, numerator / dot(dir, dir)); \n"
- " gl_Position += scale * delta; \n"
- " texCoord.x += scale * texCoordOffset.x; \n"
- " } \n"
-
- " if (vertexOffset.y != 0.) { \n"
- " highp vec4 delta = qt_Matrix[1] * vertexOffset.y; \n"
- " highp vec2 dir = delta.xy * pos.w - pos.xy * delta.w; \n"
- " highp vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize); \n"
- " dir -= ndir * delta.w * pos.w; \n"
- " highp float numerator = dot(dir, ndir * pos.w * pos.w); \n"
- " highp float scale = 0.0; \n"
- " if (numerator < 0.0) \n"
- " scale = 1.0; \n"
- " else \n"
- " scale = min(1.0, numerator / dot(dir, dir)); \n"
- " gl_Position += scale * delta; \n"
- " texCoord.y += scale * texCoordOffset.y; \n"
- " } \n"
-
- " bool onEdge = any(notEqual(vertexOffset, vec2(0.))); \n"
- " bool outerEdge = all(equal(texCoordOffset, vec2(0.))); \n"
- " vertexOpacity = onEdge && outerEdge ? 0. : opacity; \n"
- "}";
-}
-
-const char *SmoothTextureMaterialShader::fragmentShader() const
-{
- return
- "uniform sampler2D qt_Texture; \n"
- "varying highp vec2 texCoord; \n"
- "varying lowp float vertexOpacity; \n"
- "void main() { \n"
- " gl_FragColor = texture2D(qt_Texture, texCoord) * vertexOpacity; \n"
- "}";
-}
-
QSGDefaultImageNode::QSGDefaultImageNode()
: m_innerSourceRect(0, 0, 1, 1)
, m_subSourceRect(0, 0, 1, 1)
diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp
index 14c61bae79..fb989fd6fb 100644
--- a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp
+++ b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp
@@ -110,19 +110,26 @@ namespace
class SmoothColorMaterialShader : public QSGMaterialShader
{
public:
+ SmoothColorMaterialShader();
+
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
virtual char const *const *attributeNames() const;
private:
virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
int m_matrixLoc;
int m_opacityLoc;
int m_pixelSizeLoc;
};
+SmoothColorMaterialShader::SmoothColorMaterialShader()
+ : QSGMaterialShader()
+{
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/smoothcolor.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/smoothcolor.frag"));
+}
+
void SmoothColorMaterialShader::updateState(const RenderState &state, QSGMaterial *, QSGMaterial *oldEffect)
{
if (state.isOpacityDirty())
@@ -156,61 +163,6 @@ void SmoothColorMaterialShader::initialize()
m_pixelSizeLoc = program()->uniformLocation("pixelSize");
}
-const char *SmoothColorMaterialShader::vertexShader() const
-{
- return
- "uniform highp vec2 pixelSize; \n"
- "uniform highp mat4 matrix; \n"
- "uniform lowp float opacity; \n"
- "attribute highp vec4 vertex; \n"
- "attribute lowp vec4 vertexColor; \n"
- "attribute highp vec2 vertexOffset; \n"
- "varying lowp vec4 color; \n"
- "void main() { \n"
- " highp vec4 pos = matrix * vertex; \n"
- " gl_Position = pos; \n"
-
- " if (vertexOffset.x != 0.) { \n"
- " highp vec4 delta = matrix[0] * vertexOffset.x; \n"
- " highp vec2 dir = delta.xy * pos.w - pos.xy * delta.w; \n"
- " highp vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize); \n"
- " dir -= ndir * delta.w * pos.w; \n"
- " highp float numerator = dot(dir, ndir * pos.w * pos.w); \n"
- " highp float scale = 0.0; \n"
- " if (numerator < 0.0) \n"
- " scale = 1.0; \n"
- " else \n"
- " scale = min(1.0, numerator / dot(dir, dir)); \n"
- " gl_Position += scale * delta; \n"
- " } \n"
-
- " if (vertexOffset.y != 0.) { \n"
- " highp vec4 delta = matrix[1] * vertexOffset.y; \n"
- " highp vec2 dir = delta.xy * pos.w - pos.xy * delta.w; \n"
- " highp vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize); \n"
- " dir -= ndir * delta.w * pos.w; \n"
- " highp float numerator = dot(dir, ndir * pos.w * pos.w); \n"
- " highp float scale = 0.0; \n"
- " if (numerator < 0.0) \n"
- " scale = 1.0; \n"
- " else \n"
- " scale = min(1.0, numerator / dot(dir, dir)); \n"
- " gl_Position += scale * delta; \n"
- " } \n"
-
- " color = vertexColor * opacity; \n"
- "}";
-}
-
-const char *SmoothColorMaterialShader::fragmentShader() const
-{
- return
- "varying lowp vec4 color; \n"
- "void main() { \n"
- " gl_FragColor = color; \n"
- "}";
-}
-
QSGSmoothColorMaterial::QSGSmoothColorMaterial()
{
setFlag(RequiresFullMatrixExceptTranslate, true);
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
index 876a9ea9ad..a9faf12096 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp
@@ -46,7 +46,7 @@
QT_BEGIN_NAMESPACE
-QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGContext *context)
+QSGDistanceFieldGlyphNode::QSGDistanceFieldGlyphNode(QSGRenderContext *context)
: m_glyphNodeType(RootGlyphNode)
, m_context(context)
, m_material(0)
@@ -235,7 +235,12 @@ void QSGDistanceFieldGlyphNode::updateGeometry()
if (texture->textureId && !m_texture)
m_texture = texture;
- if (m_texture != texture) {
+ // As we use UNSIGNED_SHORT indexing in the geometry, we overload the
+ // "glyphsInOtherTextures" concept as overflow for if there are more than
+ // 65536 vertices to render which would otherwise exceed the maximum index
+ // size. This will cause sub-nodes to be recursively created to handle any
+ // number of glyphs.
+ if (m_texture != texture || vp.size() >= 65536) {
if (texture->textureId) {
GlyphInfo &glyphInfo = glyphsInOtherTextures[texture];
glyphInfo.indexes.append(glyphIndex);
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
index 125243847a..12a431246c 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp
@@ -59,8 +59,6 @@ public:
protected:
virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
void updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc);
void updateColor(const QVector4D &c);
@@ -81,44 +79,20 @@ protected:
float m_lastAlphaMax;
};
-const char *QSGDistanceFieldTextMaterialShader::vertexShader() const {
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "varying highp vec2 sampleCoord; \n"
- "void main() { \n"
- " sampleCoord = tCoord * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- "}";
-}
-
-const char *QSGDistanceFieldTextMaterialShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "uniform mediump sampler2D _qt_texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform mediump float alphaMin; \n"
- "uniform mediump float alphaMax; \n"
- "void main() { \n"
- " gl_FragColor = color * smoothstep(alphaMin, \n"
- " alphaMax, \n"
- " texture2D(_qt_texture, sampleCoord).a); \n"
- "}";
-}
-
char const *const *QSGDistanceFieldTextMaterialShader::attributeNames() const {
static char const *const attr[] = { "vCoord", "tCoord", 0 };
return attr;
}
QSGDistanceFieldTextMaterialShader::QSGDistanceFieldTextMaterialShader()
- : m_fontScale(1.0)
+ : QSGMaterialShader(),
+ m_fontScale(1.0)
, m_matrixScale(1.0)
, m_lastAlphaMin(-1)
, m_lastAlphaMax(-1)
{
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/distancefieldtext.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/distancefieldtext.frag"));
}
void QSGDistanceFieldTextMaterialShader::updateAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc)
@@ -287,7 +261,6 @@ public:
protected:
virtual void initialize();
- virtual const char *fragmentShader() const = 0;
int m_styleColor_id;
};
@@ -355,7 +328,6 @@ public:
protected:
virtual void initialize();
- virtual const char *fragmentShader() const;
void updateOutlineAlphaRange(ThresholdFunc thresholdFunc, AntialiasingSpreadFunc spreadFunc, int dfRadius);
@@ -363,26 +335,10 @@ protected:
int m_outlineAlphaMax1_id;
};
-const char *DistanceFieldOutlineTextMaterialShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "uniform sampler2D _qt_texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform lowp vec4 styleColor; \n"
- "uniform mediump float alphaMin; \n"
- "uniform mediump float alphaMax; \n"
- "uniform mediump float outlineAlphaMax0; \n"
- "uniform mediump float outlineAlphaMax1; \n"
- "void main() { \n"
- " mediump float d = texture2D(_qt_texture, sampleCoord).a; \n"
- " gl_FragColor = mix(styleColor, color, smoothstep(alphaMin, alphaMax, d)) \n"
- " * smoothstep(outlineAlphaMax0, outlineAlphaMax1, d); \n"
- "}";
-}
-
DistanceFieldOutlineTextMaterialShader::DistanceFieldOutlineTextMaterialShader()
: DistanceFieldStyledTextMaterialShader()
{
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/distancefieldoutlinetext.frag"));
}
void DistanceFieldOutlineTextMaterialShader::initialize()
@@ -454,8 +410,6 @@ public:
protected:
virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
void updateShift(qreal fontScale, const QPointF& shift);
@@ -465,6 +419,8 @@ protected:
DistanceFieldShiftedStyleTextMaterialShader::DistanceFieldShiftedStyleTextMaterialShader()
: DistanceFieldStyledTextMaterialShader()
{
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/distancefieldshiftedtext.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/distancefieldshiftedtext.frag"));
}
void DistanceFieldShiftedStyleTextMaterialShader::initialize()
@@ -495,41 +451,6 @@ void DistanceFieldShiftedStyleTextMaterialShader::updateShift(qreal fontScale, c
program()->setUniformValue(m_shift_id, texel);
}
-const char *DistanceFieldShiftedStyleTextMaterialShader::vertexShader() const
-{
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "uniform highp vec2 shift; \n"
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec2 shiftedSampleCoord; \n"
- "void main() { \n"
- " sampleCoord = tCoord * textureScale; \n"
- " shiftedSampleCoord = (tCoord - shift) * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- "}";
-}
-
-const char *DistanceFieldShiftedStyleTextMaterialShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec2 shiftedSampleCoord; \n"
- "uniform sampler2D _qt_texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform lowp vec4 styleColor; \n"
- "uniform mediump float alphaMin; \n"
- "uniform mediump float alphaMax; \n"
- "void main() { \n"
- " highp float a = smoothstep(alphaMin, alphaMax, texture2D(_qt_texture, sampleCoord).a); \n"
- " highp vec4 shifted = styleColor * smoothstep(alphaMin, \n"
- " alphaMax, \n"
- " texture2D(_qt_texture, shiftedSampleCoord).a); \n"
- " gl_FragColor = mix(shifted, color, a); \n"
- "}";
-}
-
QSGDistanceFieldShiftedStyleTextMaterial::QSGDistanceFieldShiftedStyleTextMaterial()
: QSGDistanceFieldStyledTextMaterial()
{
@@ -550,111 +471,35 @@ QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader() cons
return new DistanceFieldShiftedStyleTextMaterialShader;
}
+int QSGDistanceFieldShiftedStyleTextMaterial::compare(const QSGMaterial *o) const
+{
+ const QSGDistanceFieldShiftedStyleTextMaterial *other = static_cast<const QSGDistanceFieldShiftedStyleTextMaterial *>(o);
+ if (m_shift != other->m_shift)
+ return &m_shift < &other->m_shift ? -1 : 1;
+ return QSGDistanceFieldStyledTextMaterial::compare(o);
+}
class QSGHiQSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTextMaterialShader
{
public:
+ QSGHiQSubPixelDistanceFieldTextMaterialShader();
+
virtual void initialize();
virtual void activate();
virtual void deactivate();
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
-protected:
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
-
private:
int m_fontScale_id;
int m_vecDelta_id;
};
-const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "uniform highp float fontScale; \n"
- "uniform highp vec4 vecDelta; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec3 sampleFarLeft; \n"
- "varying highp vec3 sampleNearLeft; \n"
- "varying highp vec3 sampleNearRight; \n"
- "varying highp vec3 sampleFarRight; \n"
- "void main() { \n"
- " sampleCoord = tCoord * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- // Calculate neighbour pixel position in item space.
- " highp vec3 wDelta = gl_Position.w * vecDelta.xyw; \n"
- " highp vec3 farLeft = vCoord.xyw - 0.667 * wDelta; \n"
- " highp vec3 nearLeft = vCoord.xyw - 0.333 * wDelta; \n"
- " highp vec3 nearRight = vCoord.xyw + 0.333 * wDelta; \n"
- " highp vec3 farRight = vCoord.xyw + 0.667 * wDelta; \n"
- // Calculate neighbour texture coordinate.
- " highp vec2 scale = textureScale / fontScale; \n"
- " highp vec2 base = sampleCoord - scale * vCoord.xy; \n"
- " sampleFarLeft = vec3(base * farLeft.z + scale * farLeft.xy, farLeft.z); \n"
- " sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z); \n"
- " sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z); \n"
- " sampleFarRight = vec3(base * farRight.z + scale * farRight.xy, farRight.z); \n"
- "}";
-}
-
-const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
- return
- "varying highp vec2 sampleCoord; \n"
- "varying highp vec3 sampleFarLeft; \n"
- "varying highp vec3 sampleNearLeft; \n"
- "varying highp vec3 sampleNearRight; \n"
- "varying highp vec3 sampleFarRight; \n"
- "uniform sampler2D _qt_texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform mediump float alphaMin; \n"
- "uniform mediump float alphaMax; \n"
- "void main() { \n"
- " highp vec4 n; \n"
- " n.x = texture2DProj(_qt_texture, sampleFarLeft).a; \n"
- " n.y = texture2DProj(_qt_texture, sampleNearLeft).a; \n"
- " highp float c = texture2D(_qt_texture, sampleCoord).a; \n"
- " n.z = texture2DProj(_qt_texture, sampleNearRight).a; \n"
- " n.w = texture2DProj(_qt_texture, sampleFarRight).a; \n"
-#if 0
- // Blurrier, faster.
- " n = smoothstep(alphaMin, alphaMax, n); \n"
- " c = smoothstep(alphaMin, alphaMax, c); \n"
-#else
- // Sharper, slower.
- " highp vec2 d = min(abs(n.yw - n.xz) * 2., 0.67); \n"
- " highp vec2 lo = mix(vec2(alphaMin), vec2(0.5), d); \n"
- " highp vec2 hi = mix(vec2(alphaMax), vec2(0.5), d); \n"
- " n = smoothstep(lo.xxyy, hi.xxyy, n); \n"
- " c = smoothstep(lo.x + lo.y, hi.x + hi.y, 2. * c); \n"
-#endif
- " gl_FragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w; \n"
- "}";
-}
-
-//const char *QSGHiQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
-// return
-// "#extension GL_OES_standard_derivatives: enable \n"
-// "varying highp vec2 sampleCoord; \n"
-// "uniform sampler2D _qt_texture; \n"
-// "uniform lowp vec4 color; \n"
-// "uniform highp float alphaMin; \n"
-// "uniform highp float alphaMax; \n"
-// "void main() { \n"
-// " highp vec2 delta = dFdx(sampleCoord); \n"
-// " highp vec4 n; \n"
-// " n.x = texture2D(_qt_texture, sampleCoord - 0.667 * delta).a; \n"
-// " n.y = texture2D(_qt_texture, sampleCoord - 0.333 * delta).a; \n"
-// " highp float c = texture2D(_qt_texture, sampleCoord).a; \n"
-// " n.z = texture2D(_qt_texture, sampleCoord + 0.333 * delta).a; \n"
-// " n.w = texture2D(_qt_texture, sampleCoord + 0.667 * delta).a; \n"
-// " n = smoothstep(alphaMin, alphaMax, n); \n"
-// " c = smoothstep(alphaMin, alphaMax, c); \n"
-// " gl_FragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w; \n"
-// "}";
-//}
+QSGHiQSubPixelDistanceFieldTextMaterialShader::QSGHiQSubPixelDistanceFieldTextMaterialShader()
+ : QSGDistanceFieldTextMaterialShader()
+{
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag"));
+}
void QSGHiQSubPixelDistanceFieldTextMaterialShader::initialize()
{
@@ -712,52 +557,15 @@ QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader() const
class QSGLoQSubPixelDistanceFieldTextMaterialShader : public QSGHiQSubPixelDistanceFieldTextMaterialShader
{
-protected:
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
+public:
+ QSGLoQSubPixelDistanceFieldTextMaterialShader();
};
-const char *QSGLoQSubPixelDistanceFieldTextMaterialShader::vertexShader() const {
- return
- "uniform highp mat4 matrix; \n"
- "uniform highp vec2 textureScale; \n"
- "uniform highp float fontScale; \n"
- "uniform highp vec4 vecDelta; \n"
- "attribute highp vec4 vCoord; \n"
- "attribute highp vec2 tCoord; \n"
- "varying highp vec3 sampleNearLeft; \n"
- "varying highp vec3 sampleNearRight; \n"
- "void main() { \n"
- " highp vec2 sampleCoord = tCoord * textureScale; \n"
- " gl_Position = matrix * vCoord; \n"
- // Calculate neighbour pixel position in item space.
- " highp vec3 wDelta = gl_Position.w * vecDelta.xyw; \n"
- " highp vec3 nearLeft = vCoord.xyw - 0.25 * wDelta; \n"
- " highp vec3 nearRight = vCoord.xyw + 0.25 * wDelta; \n"
- // Calculate neighbour texture coordinate.
- " highp vec2 scale = textureScale / fontScale; \n"
- " highp vec2 base = sampleCoord - scale * vCoord.xy; \n"
- " sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z); \n"
- " sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z); \n"
- "}";
-}
-
-const char *QSGLoQSubPixelDistanceFieldTextMaterialShader::fragmentShader() const {
- return
- "varying highp vec3 sampleNearLeft; \n"
- "varying highp vec3 sampleNearRight; \n"
- "uniform sampler2D _qt_texture; \n"
- "uniform lowp vec4 color; \n"
- "uniform mediump float alphaMin; \n"
- "uniform mediump float alphaMax; \n"
- "void main() { \n"
- " highp vec2 n; \n"
- " n.x = texture2DProj(_qt_texture, sampleNearLeft).a; \n"
- " n.y = texture2DProj(_qt_texture, sampleNearRight).a; \n"
- " n = smoothstep(alphaMin, alphaMax, n); \n"
- " highp float c = 0.5 * (n.x + n.y); \n"
- " gl_FragColor = vec4(n.x, c, n.y, c) * color.w; \n"
- "}";
+QSGLoQSubPixelDistanceFieldTextMaterialShader::QSGLoQSubPixelDistanceFieldTextMaterialShader()
+ : QSGHiQSubPixelDistanceFieldTextMaterialShader()
+{
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/loqsubpixeldistancefieldtext.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/loqsubpixeldistancefieldtext.frag"));
}
QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
index 2558413675..98a65d7347 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.h
@@ -49,13 +49,13 @@
QT_BEGIN_NAMESPACE
-class QSGContext;
+class QSGRenderContext;
class QSGDistanceFieldGlyphCacheManager;
class QSGDistanceFieldTextMaterial;
class QSGDistanceFieldGlyphNode: public QSGGlyphNode, public QSGDistanceFieldGlyphConsumer
{
public:
- QSGDistanceFieldGlyphNode(QSGContext *context);
+ QSGDistanceFieldGlyphNode(QSGRenderContext *context);
~QSGDistanceFieldGlyphNode();
virtual QPointF baseLine() const { return m_baseLine; }
@@ -86,7 +86,7 @@ private:
DistanceFieldGlyphNodeType m_glyphNodeType;
QColor m_color;
QPointF m_baseLine;
- QSGContext *m_context;
+ QSGRenderContext *m_context;
QSGDistanceFieldTextMaterial *m_material;
QPointF m_originalPosition;
QPointF m_position;
diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
index cf0d2d525e..d56fd01d3e 100644
--- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
+++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h
@@ -117,6 +117,7 @@ public:
virtual QSGMaterialType *type() const;
virtual QSGMaterialShader *createShader() const;
+ virtual int compare(const QSGMaterial *other) const;
void setShift(const QPointF &shift) { m_shift = shift; }
const QPointF &shift() const { return m_shift; }
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index 163d1d35c5..aa0d7b5a6c 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -87,13 +87,13 @@ class QSGGuiThreadRenderLoop : public QSGRenderLoop
Q_OBJECT
public:
QSGGuiThreadRenderLoop();
+ ~QSGGuiThreadRenderLoop();
void show(QQuickWindow *window);
void hide(QQuickWindow *window);
void windowDestroyed(QQuickWindow *window);
- void initializeGL();
void renderWindow(QQuickWindow *window);
void exposureChanged(QQuickWindow *window);
QImage grab(QQuickWindow *window);
@@ -106,6 +106,7 @@ public:
QAnimationDriver *animationDriver() const { return 0; }
QSGContext *sceneGraphContext() const;
+ QSGRenderContext *createRenderContext(QSGContext *) const { return rc; }
bool event(QEvent *);
@@ -118,6 +119,7 @@ public:
QOpenGLContext *gl;
QSGContext *sg;
+ QSGRenderContext *rc;
QImage grabContent;
@@ -140,11 +142,15 @@ bool QSGRenderLoop::useConsistentTiming()
QSGRenderLoop *QSGRenderLoop::instance()
{
if (!s_instance) {
-
s_instance = QSGContext::createWindowManager();
- if (useConsistentTiming())
+ bool info = qEnvironmentVariableIsSet("QSG_INFO");
+
+ if (useConsistentTiming()) {
QUnifiedTimer::instance(true)->setConsistentTiming(true);
+ if (info)
+ qDebug() << "QSG: using fixed animation steps";
+ }
if (!s_instance) {
@@ -177,12 +183,15 @@ QSGRenderLoop *QSGRenderLoop::instance()
switch (loopType) {
case ThreadedRenderLoop:
+ if (info) qDebug() << "QSG: threaded render loop";
s_instance = new QSGThreadedRenderLoop();
break;
case WindowsRenderLoop:
+ if (info) qDebug() << "QSG: windows render loop";
s_instance = new QSGWindowsRenderLoop();
break;
default:
+ if (info) qDebug() << "QSG: basic render loop";
s_instance = new QSGGuiThreadRenderLoop();
break;
}
@@ -202,8 +211,14 @@ QSGGuiThreadRenderLoop::QSGGuiThreadRenderLoop()
, eventPending(false)
{
sg = QSGContext::createDefaultContext();
+ rc = new QSGRenderContext(sg);
}
+QSGGuiThreadRenderLoop::~QSGGuiThreadRenderLoop()
+{
+ delete rc;
+ delete sg;
+}
void QSGGuiThreadRenderLoop::show(QQuickWindow *window)
{
@@ -226,7 +241,8 @@ void QSGGuiThreadRenderLoop::hide(QQuickWindow *window)
if (m_windows.size() == 0) {
if (!cd->persistentSceneGraph) {
- sg->invalidate();
+ rc->invalidate();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
if (!cd->persistentGLContext) {
delete gl;
gl = 0;
@@ -239,7 +255,8 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window)
{
hide(window);
if (m_windows.size() == 0) {
- sg->invalidate();
+ rc->invalidate();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete gl;
gl = 0;
}
@@ -257,14 +274,17 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
if (!gl) {
gl = new QOpenGLContext();
gl->setFormat(window->requestedFormat());
+ if (QSGContext::sharedOpenGLContext())
+ gl->setShareContext(QSGContext::sharedOpenGLContext());
if (!gl->create()) {
+ qWarning("QtQuick: failed to create OpenGL context");
delete gl;
gl = 0;
} else {
current = gl->makeCurrent(window);
}
if (current)
- sg->initialize(gl);
+ QQuickWindowPrivate::get(window)->context->initialize(gl);
} else {
current = gl->makeCurrent(window);
}
diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h
index 933a8428f1..72bad16c63 100644
--- a/src/quick/scenegraph/qsgrenderloop_p.h
+++ b/src/quick/scenegraph/qsgrenderloop_p.h
@@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE
class QQuickWindow;
class QSGContext;
+class QSGRenderContext;
class QAnimationDriver;
class Q_QUICK_PRIVATE_EXPORT QSGRenderLoop : public QObject
@@ -60,6 +61,7 @@ public:
virtual void show(QQuickWindow *window) = 0;
virtual void hide(QQuickWindow *window) = 0;
+ virtual void resize(QQuickWindow *) {};
virtual void windowDestroyed(QQuickWindow *window) = 0;
@@ -72,6 +74,7 @@ public:
virtual QAnimationDriver *animationDriver() const = 0;
virtual QSGContext *sceneGraphContext() const = 0;
+ virtual QSGRenderContext *createRenderContext(QSGContext *) const = 0;
virtual void releaseResources(QQuickWindow *window) = 0;
diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
index 34a884348d..cc0218aefd 100644
--- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
+++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp
@@ -228,6 +228,7 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr
this, SLOT(reportItemsInvalidated(QByteArray,QVector<quint32>)),
Qt::DirectConnection);
+ Q_ASSERT(c);
QQuickWindow *window = static_cast<QQuickWindow *>(c->surface());
Q_ASSERT(window != 0);
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 7421db1db1..850a463c3e 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -84,6 +84,17 @@
---
+ There is one thread per window and one opengl context per thread.
+
+ ---
+
+ The render thread has affinity to the GUI thread until a window
+ is shown. From that moment and until the window is destroyed, it
+ will have affinity to the render thread. (moved back at the end
+ of run for cleanup).
+
+ ---
+
The render loop is active while any window is exposed. All visible
windows are tracked, but only exposed windows are actually added to
the render thread and rendered. That means that if all windows are
@@ -97,26 +108,14 @@ QT_BEGIN_NAMESPACE
// #define QSG_RENDER_LOOP_DEBUG
-// #define QSG_RENDER_LOOP_DEBUG_FULL
-#ifdef QSG_RENDER_LOOP_DEBUG
-#define QSG_RENDER_LOOP_DEBUG_BASIC
-#endif
-
-#ifdef QSG_RENDER_LOOP_DEBUG_FULL
-#define QSG_RENDER_LOOP_DEBUG_BASIC
-#endif
-#if defined (QSG_RENDER_LOOP_DEBUG_FULL)
+#if defined (QSG_RENDER_LOOP_DEBUG)
QElapsedTimer qsgrl_timer;
-# define RLDEBUG1(x) qDebug("(%6d) %s : %4d - %s", (int) qsgrl_timer.elapsed(), __FILE__, __LINE__, x);
-# define RLDEBUG(x) qDebug("(%6d) %s : %4d - %s", (int) qsgrl_timer.elapsed(), __FILE__, __LINE__, x);
-#elif defined (QSG_RENDER_LOOP_DEBUG_BASIC)
-QElapsedTimer qsgrl_timer;
-# define RLDEBUG1(x) qDebug("(%6d) %s : %4d - %s", (int) qsgrl_timer.elapsed(), __FILE__, __LINE__, x);
-# define RLDEBUG(x)
+# define QSG_RT_DEBUG(MSG) qDebug("(%6d) line=%4d - win=%10p): Render: %s", (int) qsgrl_timer.elapsed(), __LINE__, window, MSG);
+# define QSG_GUI_DEBUG(WIN, MSG) qDebug("(%6d) line=%4d - win=%10p): Gui: %s", (int) qsgrl_timer.elapsed(), __LINE__, WIN, MSG);
#else
-# define RLDEBUG1(x)
-# define RLDEBUG(x)
+# define QSG_RT_DEBUG(MSG)
+# define QSG_GUI_DEBUG(WIN,MSG)
#endif
@@ -276,23 +275,25 @@ class QSGRenderThread : public QThread
{
Q_OBJECT
public:
-
- QSGRenderThread(QSGThreadedRenderLoop *w)
+ QSGRenderThread(QSGThreadedRenderLoop *w, QSGRenderContext *renderContext)
: wm(w)
, gl(0)
- , sg(QSGContext::createDefaultContext())
+ , sgrc(renderContext)
, animatorDriver(0)
, pendingUpdate(0)
, sleeping(false)
, syncResultedInChanges(false)
- , guiIsLocked(false)
- , shouldExit(false)
+ , active(false)
+ , window(0)
, stopEventProcessing(false)
{
- sg->moveToThread(this);
vsyncDelta = qsgrl_animation_interval();
}
+ ~QSGRenderThread()
+ {
+ delete sgrc;
+ }
void invalidateOpenGL(QQuickWindow *window, bool inDestructor);
void initializeOpenGL();
@@ -307,7 +308,7 @@ public:
{
if (sleeping)
stopEventProcessing = true;
- if (m_windows.size() > 0)
+ if (window)
pendingUpdate |= RepaintRequest;
}
@@ -317,7 +318,7 @@ public:
public slots:
void sceneGraphChanged() {
- RLDEBUG(" Render: sceneGraphChanged()");
+ QSG_RT_DEBUG("sceneGraphChanged()");
syncResultedInChanges = true;
}
@@ -329,16 +330,15 @@ public:
QSGThreadedRenderLoop *wm;
QOpenGLContext *gl;
- QSGContext *sg;
+ QSGRenderContext *sgrc;
QAnimationDriver *animatorDriver;
uint pendingUpdate;
- uint sleeping;
- uint syncResultedInChanges;
+ bool sleeping;
+ bool syncResultedInChanges;
- volatile bool guiIsLocked;
- volatile bool shouldExit;
+ volatile bool active;
float vsyncDelta;
@@ -347,11 +347,8 @@ public:
QElapsedTimer m_timer;
- struct Window {
- QQuickWindow *window;
- QSize size;
- };
- QList<Window> m_windows;
+ QQuickWindow *window; // Will be 0 when window is not exposed
+ QSize windowSize;
// Local event queue stuff...
bool stopEventProcessing;
@@ -363,64 +360,57 @@ bool QSGRenderThread::event(QEvent *e)
switch ((int) e->type()) {
case WM_Expose: {
- RLDEBUG1(" Render: WM_Expose");
+ QSG_RT_DEBUG("WM_Expose");
WMExposeEvent *se = static_cast<WMExposeEvent *>(e);
pendingUpdate |= RepaintRequest;
- if (Window *w = windowFor(m_windows, se->window)) {
- w->size = se->size;
- RLDEBUG1(" Render: - window already added...");
+ Q_ASSERT(!window || window == se->window);
+
+ windowSize = se->size;
+ if (window) {
+ QSG_RT_DEBUG(" - window already added...");
return true;
}
- Window window;
- window.window = se->window;
- window.size = se->size;
- m_windows << window;
- connect(animatorDriver, SIGNAL(started()), QQuickWindowPrivate::get(se->window)->animationController, SLOT(animationsStarted()));
+ window = se->window;
return true; }
case WM_Obscure: {
- RLDEBUG1(" Render: WM_Obscure");
- WMWindowEvent *ce = static_cast<WMWindowEvent *>(e);
- for (int i=0; i<m_windows.size(); ++i) {
- if (m_windows.at(i).window == ce->window) {
- RLDEBUG1(" Render: - removed one...");
- m_windows.removeAt(i);
- disconnect(animatorDriver, SIGNAL(started()), QQuickWindowPrivate::get(ce->window)->animationController, SLOT(animationsStarted()));
- break;
- }
- }
+ QSG_RT_DEBUG("WM_Obscure");
- if (sleeping && m_windows.size())
- stopEventProcessing = true;
+ Q_ASSERT(!window || window == static_cast<WMWindowEvent *>(e)->window);
+
+ mutex.lock();
+ if (window) {
+ QSG_RT_DEBUG(" - removed one...");
+ window = 0;
+ }
+ waitCondition.wakeOne();
+ mutex.unlock();
return true; }
case WM_RequestSync:
- RLDEBUG(" Render: WM_RequestSync");
+ QSG_RT_DEBUG("WM_RequestSync");
if (sleeping)
stopEventProcessing = true;
- if (m_windows.size() > 0)
+ if (window)
pendingUpdate |= SyncRequest;
return true;
case WM_TryRelease: {
- RLDEBUG1(" Render: WM_TryRelease");
+ QSG_RT_DEBUG("WM_TryRelease");
mutex.lock();
WMTryReleaseEvent *wme = static_cast<WMTryReleaseEvent *>(e);
- if (m_windows.size() == 0) {
- RLDEBUG1(" Render: - setting exit flag and invalidating GL");
+ if (!window || wme->inDestructor) {
+ QSG_RT_DEBUG(" - setting exit flag and invalidating GL");
invalidateOpenGL(wme->window, wme->inDestructor);
- shouldExit = !gl;
+ active = gl;
if (sleeping)
stopEventProcessing = true;
- } else if (wme->window == gl->surface()) {
- RLDEBUG1(" Render: - destroying the current window. Calling doneCurrent()...");
- gl->doneCurrent();
} else {
- RLDEBUG1(" Render: - not releasing anything because we have active windows...");
+ QSG_RT_DEBUG(" - not releasing anything because we have active windows...");
}
waitCondition.wakeOne();
mutex.unlock();
@@ -428,24 +418,24 @@ bool QSGRenderThread::event(QEvent *e)
}
case WM_Grab: {
- RLDEBUG1(" Render: WM_Grab");
+ QSG_RT_DEBUG("WM_Grab");
WMGrabEvent *ce = static_cast<WMGrabEvent *>(e);
- Window *w = windowFor(m_windows, ce->window);
+ Q_ASSERT(ce->window == window);
mutex.lock();
- if (w) {
- gl->makeCurrent(ce->window);
+ if (window) {
+ gl->makeCurrent(window);
- RLDEBUG1(" Render: - syncing scene graph");
- QQuickWindowPrivate *d = QQuickWindowPrivate::get(w->window);
+ QSG_RT_DEBUG(" - syncing scene graph");
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
d->syncSceneGraph();
- RLDEBUG1(" Render: - rendering scene graph");
- QQuickWindowPrivate::get(ce->window)->renderSceneGraph(w->size);
+ QSG_RT_DEBUG(" - rendering scene graph");
+ QQuickWindowPrivate::get(window)->renderSceneGraph(windowSize);
- RLDEBUG1(" Render: - grabbing result...");
- *ce->image = qt_gl_read_framebuffer(w->size, false, false);
+ QSG_RT_DEBUG(" - grabbing result...");
+ *ce->image = qt_gl_read_framebuffer(windowSize, false, false);
}
- RLDEBUG1(" Render: - waking gui to handle grab result");
+ QSG_RT_DEBUG(" - waking gui to handle grab result");
waitCondition.wakeOne();
mutex.unlock();
return true;
@@ -465,7 +455,7 @@ bool QSGRenderThread::event(QEvent *e)
void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor)
{
- RLDEBUG1(" Render: invalidateOpenGL()");
+ QSG_RT_DEBUG("invalidateOpenGL()");
if (!gl)
return;
@@ -476,43 +466,32 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor)
}
- bool persistentGL = false;
- bool persistentSG = false;
-
- // GUI is locked so accessing the wm and window here is safe
- for (int i=0; i<wm->m_windows.size(); ++i) {
- const QSGThreadedRenderLoop::Window &w = wm->m_windows.at(i);
- if (!inDestructor || w.window != window) {
- persistentSG |= w.window->isPersistentSceneGraph();
- persistentGL |= w.window->isPersistentOpenGLContext();
- }
- }
+ bool wipeSG = inDestructor || !window->isPersistentSceneGraph();
+ bool wipeGL = inDestructor || (wipeSG && !window->isPersistentOpenGLContext());
gl->makeCurrent(window);
- // The canvas nodes must be cleanded up regardless if we are in the destructor..
- if (!persistentSG || inDestructor) {
+ // The canvas nodes must be cleaned up regardless if we are in the destructor..
+ if (wipeSG) {
QQuickWindowPrivate *dd = QQuickWindowPrivate::get(window);
dd->cleanupNodesOnShutdown();
- }
-
- // We're not doing any cleanup in this case...
- if (persistentSG) {
- RLDEBUG1(" Render: - persistent SG, avoiding cleanup");
+ } else {
+ QSG_RT_DEBUG(" - persistent SG, avoiding cleanup");
return;
}
- sg->invalidate();
+ sgrc->invalidate();
+ QCoreApplication::processEvents();
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
gl->doneCurrent();
- RLDEBUG1(" Render: - invalidated scenegraph..");
+ QSG_RT_DEBUG(" - invalidated scenegraph..");
- if (!persistentGL) {
+ if (wipeGL) {
delete gl;
gl = 0;
- RLDEBUG1(" Render: - invalidated OpenGL");
+ QSG_RT_DEBUG(" - invalidated OpenGL");
} else {
- RLDEBUG1(" Render: - persistent GL, avoiding cleanup");
+ QSG_RT_DEBUG(" - persistent GL, avoiding cleanup");
}
}
@@ -522,32 +501,34 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor)
*/
void QSGRenderThread::sync()
{
- RLDEBUG(" Render: sync()");
+ QSG_RT_DEBUG("sync()");
mutex.lock();
- Q_ASSERT_X(guiIsLocked, "QSGRenderThread::sync()", "sync triggered on bad terms as gui is not already locked...");
+ Q_ASSERT_X(wm->m_locked, "QSGRenderThread::sync()", "sync triggered on bad terms as gui is not already locked...");
- for (int i=0; i<m_windows.size(); ++i) {
- Window &w = const_cast<Window &>(m_windows.at(i));
- if (w.size.width() == 0 || w.size.height() == 0) {
- RLDEBUG(" Render: - window has bad size, waiting...");
- continue;
- }
- gl->makeCurrent(w.window);
- QQuickWindowPrivate *d = QQuickWindowPrivate::get(w.window);
+ bool current = false;
+ if (windowSize.width() > 0 && windowSize.height() > 0)
+ current = gl->makeCurrent(window);
+ if (current) {
+ gl->makeCurrent(window);
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
bool hadRenderer = d->renderer != 0;
d->syncSceneGraph();
if (!hadRenderer && d->renderer) {
- RLDEBUG(" Render: - renderer was created, hooking up changed signal");
+ QSG_RT_DEBUG(" - renderer was created, hooking up changed signal");
syncResultedInChanges = true;
connect(d->renderer, SIGNAL(sceneGraphChanged()), this, SLOT(sceneGraphChanged()), Qt::DirectConnection);
}
- }
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
-
- RLDEBUG(" Render: - unlocking after sync");
+ // Process deferred deletes now, directly after the sync as
+ // deleteLater on the GUI must now also have resulted in SG changes
+ // and the delete is a safe operation.
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ } else {
+ QSG_RT_DEBUG(" - window has bad size, waiting...");
+ }
+ QSG_RT_DEBUG(" - window has bad size, waiting...");
waitCondition.wakeOne();
mutex.unlock();
}
@@ -565,7 +546,7 @@ void QSGRenderThread::syncAndRender()
QElapsedTimer waitTimer;
waitTimer.start();
- RLDEBUG(" Render: syncAndRender()");
+ QSG_RT_DEBUG("syncAndRender()");
syncResultedInChanges = false;
@@ -574,16 +555,15 @@ void QSGRenderThread::syncAndRender()
pendingUpdate = 0;
if (syncRequested) {
- RLDEBUG(" Render: - update pending, doing sync");
+ QSG_RT_DEBUG(" - update pending, doing sync");
sync();
}
if (!syncResultedInChanges && !(repaintRequested)) {
- RLDEBUG(" Render: - no changes, rendering aborted");
+ QSG_RT_DEBUG(" - no changes, rendering aborted");
int waitTime = vsyncDelta - (int) waitTimer.elapsed();
if (waitTime > 0)
msleep(waitTime);
- emit wm->timeToIncubate();
return;
}
@@ -591,33 +571,37 @@ void QSGRenderThread::syncAndRender()
if (profileFrames)
syncTime = threadTimer.nsecsElapsed();
#endif
- RLDEBUG(" Render: - rendering starting");
+ QSG_RT_DEBUG(" - rendering starting");
+
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
- if (animatorDriver->isRunning())
+ if (animatorDriver->isRunning()) {
+ d->animationController->lock();
animatorDriver->advance();
+ d->animationController->unlock();
+ }
- for (int i=0; i<m_windows.size(); ++i) {
- Window &w = const_cast<Window &>(m_windows.at(i));
- QQuickWindowPrivate *d = QQuickWindowPrivate::get(w.window);
- if (!d->renderer || w.size.width() == 0 || w.size.height() == 0) {
- RLDEBUG(" Render: - Window not yet ready, skipping render...");
- continue;
- }
- gl->makeCurrent(w.window);
- d->renderSceneGraph(w.size);
+ bool current = false;
+ if (d->renderer && windowSize.width() > 0 && windowSize.height() > 0)
+ current = gl->makeCurrent(window);
+ if (current) {
+ d->renderSceneGraph(windowSize);
#ifndef QSG_NO_RENDER_TIMING
- if (profileFrames && i == 0)
+ if (profileFrames)
renderTime = threadTimer.nsecsElapsed();
#endif
- gl->swapBuffers(w.window);
+ gl->swapBuffers(window);
d->fireFrameSwapped();
+ } else {
+ QSG_RT_DEBUG(" - Window not yet ready, skipping render...");
}
- RLDEBUG(" Render: - rendering done");
- emit wm->timeToIncubate();
+
+ QSG_RT_DEBUG(" - rendering done");
#ifndef QSG_NO_RENDER_TIMING
if (qsg_render_timing)
- qDebug("Render Thread: framedelta=%d, sync=%d, first render=%d, after final swap=%d",
+ qDebug("Render Thread: window=%p, framedelta=%d, sync=%d, first render=%d, after final swap=%d",
+ window,
int(sinceLastTime/1000000),
int(syncTime/1000000),
int((renderTime - syncTime)/1000000),
@@ -644,78 +628,73 @@ void QSGRenderThread::postEvent(QEvent *e)
void QSGRenderThread::processEvents()
{
- RLDEBUG(" Render: processEvents()");
+ QSG_RT_DEBUG("processEvents()");
while (eventQueue.hasMoreEvents()) {
QEvent *e = eventQueue.takeEvent(false);
event(e);
delete e;
}
- RLDEBUG(" Render: - done with processEvents()");
+ QSG_RT_DEBUG(" - done with processEvents()");
}
void QSGRenderThread::processEventsAndWaitForMore()
{
- RLDEBUG(" Render: processEventsAndWaitForMore()");
+ QSG_RT_DEBUG("processEventsAndWaitForMore()");
stopEventProcessing = false;
while (!stopEventProcessing) {
QEvent *e = eventQueue.takeEvent(true);
event(e);
delete e;
}
- RLDEBUG(" Render: - done with processEventsAndWaitForMore()");
+ QSG_RT_DEBUG(" - done with processEventsAndWaitForMore()");
}
void QSGRenderThread::run()
{
- RLDEBUG1(" Render: run()");
- animatorDriver = sg->createAnimationDriver(0);
+ QSG_RT_DEBUG("run()");
+ animatorDriver = sgrc->sceneGraphContext()->createAnimationDriver(0);
animatorDriver->install();
QUnifiedTimer::instance(true)->setConsistentTiming(QSGRenderLoop::useConsistentTiming());
- while (!shouldExit) {
+ while (active) {
- if (m_windows.size() > 0) {
- if (!sg->isReady()) {
- gl->makeCurrent(m_windows.at(0).window);
- sg->initialize(gl);
- }
+ if (window) {
+ if (!sgrc->openglContext() && windowSize.width() > 0 && windowSize.height() > 0 && gl->makeCurrent(window))
+ sgrc->initialize(gl);
syncAndRender();
}
processEvents();
QCoreApplication::processEvents();
- if (!shouldExit
- && (pendingUpdate == 0 || m_windows.size() == 0)) {
- RLDEBUG(" Render: enter event loop (going to sleep)");
+ if (active && (pendingUpdate == 0 || !window)) {
+ QSG_RT_DEBUG("enter event loop (going to sleep)");
sleeping = true;
processEventsAndWaitForMore();
sleeping = false;
}
-
}
Q_ASSERT_X(!gl, "QSGRenderThread::run()", "The OpenGL context should be cleaned up before exiting the render thread...");
- RLDEBUG1(" Render: run() completed...");
+ QSG_RT_DEBUG("run() completed...");
delete animatorDriver;
animatorDriver = 0;
+
+ sgrc->moveToThread(wm->thread());
+ moveToThread(wm->thread());
}
QSGThreadedRenderLoop::QSGThreadedRenderLoop()
- : m_animation_timer(0)
- , m_update_timer(0)
- , m_sync_triggered_update(false)
+ : sg(QSGContext::createDefaultContext())
+ , m_animation_timer(0)
{
#if defined(QSG_RENDER_LOOP_DEBUG_BASIC) || defined (QSG_RENDER_LOOP_DEBUG_FULL)
qsgrl_timer.start();
#endif
- m_thread = new QSGRenderThread(this);
- m_thread->moveToThread(m_thread);
-
- m_animation_driver = m_thread->sg->createAnimationDriver(this);
+ m_animation_driver = sg->createAnimationDriver(this);
m_exhaust_delay = get_env_int("QML_EXHAUST_DELAY", 5);
@@ -723,14 +702,19 @@ QSGThreadedRenderLoop::QSGThreadedRenderLoop()
connect(m_animation_driver, SIGNAL(stopped()), this, SLOT(animationStopped()));
m_animation_driver->install();
- RLDEBUG1("GUI: QSGThreadedRenderLoop() created");
+ QSG_GUI_DEBUG((void *) 0, "QSGThreadedRenderLoop() created");
+}
+
+QSGRenderContext *QSGThreadedRenderLoop::createRenderContext(QSGContext *sg) const
+{
+ return new QSGRenderContext(sg);
}
-void QSGThreadedRenderLoop::maybePostPolishRequest()
+void QSGThreadedRenderLoop::maybePostPolishRequest(Window *w)
{
- if (m_update_timer == 0) {
- RLDEBUG("GUI: - posting update");
- m_update_timer = startTimer(m_exhaust_delay, Qt::PreciseTimer);
+ if (w->timerId == 0) {
+ QSG_GUI_DEBUG(w->window, " - posting update");
+ w->timerId = startTimer(m_exhaust_delay, Qt::PreciseTimer);
}
}
@@ -741,7 +725,7 @@ QAnimationDriver *QSGThreadedRenderLoop::animationDriver() const
QSGContext *QSGThreadedRenderLoop::sceneGraphContext() const
{
- return m_thread->sg;
+ return sg;
}
bool QSGThreadedRenderLoop::anyoneShowing() const
@@ -761,35 +745,79 @@ bool QSGThreadedRenderLoop::interleaveIncubation() const
void QSGThreadedRenderLoop::animationStarted()
{
- RLDEBUG("GUI: animationStarted()");
- if (!anyoneShowing() && m_animation_timer == 0)
- m_animation_timer = startTimer(qsgrl_animation_interval());
- maybePostPolishRequest();
+ QSG_GUI_DEBUG((void *) 0, "animationStarted()");
+ startOrStopAnimationTimer();
+
+ for (int i=0; i<m_windows.size(); ++i)
+ maybePostPolishRequest(const_cast<Window *>(&m_windows.at(i)));
}
void QSGThreadedRenderLoop::animationStopped()
{
- RLDEBUG("GUI: animationStopped()");
- if (!anyoneShowing()) {
+ QSG_GUI_DEBUG((void *) 0, "animationStopped()");
+ startOrStopAnimationTimer();
+}
+
+
+void QSGThreadedRenderLoop::startOrStopAnimationTimer()
+{
+ int exposedWindows = 0;
+ Window *theOne = 0;
+ for (int i=0; i<m_windows.size(); ++i) {
+ Window &w = m_windows[i];
+ if (w.window->isVisible() && w.window->isExposed()) {
+ ++exposedWindows;
+ theOne = &w;
+ }
+ }
+
+ if (m_animation_timer != 0 && (exposedWindows == 1 || !m_animation_driver->isRunning())) {
killTimer(m_animation_timer);
m_animation_timer = 0;
+ // If animations are running, make sure we keep on animating
+ if (m_animation_driver->isRunning())
+ maybePostPolishRequest(theOne);
+
+ } else if (m_animation_timer == 0 && exposedWindows != 1 && m_animation_driver->isRunning()) {
+ m_animation_timer = startTimer(qsgrl_animation_interval());
}
}
-
-
/*
- Adds this window to the list of tracked windowes in this window
+ Adds this window to the list of tracked windows in this window
manager. show() does not trigger rendering to start, that happens
in expose.
*/
void QSGThreadedRenderLoop::show(QQuickWindow *window)
{
- RLDEBUG1("GUI: show()");
+ QSG_GUI_DEBUG(window, "show()");
+
+ if (Window *w = windowFor(m_windows, window)) {
+ /* Safeguard ourselves against misbehaving platform plugins.
+ *
+ * When being shown, the window should not be exposed as the
+ * platform plugin is only told to show after we send the show
+ * event. If we are already shown at this time and we don't have
+ * an active rendering thread we don't trust the plugin to send
+ * us another expose event, so make this explicit call to
+ * handleExposure.
+ *
+ * REF: QTCREATORBUG-10699
+ */
+ if (window->isExposed() && (!w->thread || !w->thread->window))
+ handleExposure(w);
+ return;
+ }
+
+ QSG_GUI_DEBUG(window, " - now tracking new window");
Window win;
win.window = window;
+ win.thread = new QSGRenderThread(this, QQuickWindowPrivate::get(window)->context);
+ win.timerId = 0;
+ win.updateDuringSync = false;
+ win.gotBrokenExposeFromPlatformPlugin = false;
m_windows << win;
}
@@ -803,19 +831,12 @@ void QSGThreadedRenderLoop::show(QQuickWindow *window)
void QSGThreadedRenderLoop::hide(QQuickWindow *window)
{
- RLDEBUG1("GUI: hide()");
+ QSG_GUI_DEBUG(window, "hide()");
if (window->isExposed())
- handleObscurity(window);
+ handleObscurity(windowFor(m_windows, window));
releaseResources(window);
-
- for (int i=0; i<m_windows.size(); ++i) {
- if (m_windows.at(i).window == window) {
- m_windows.removeAt(i);
- break;
- }
- }
}
@@ -826,26 +847,51 @@ void QSGThreadedRenderLoop::hide(QQuickWindow *window)
*/
void QSGThreadedRenderLoop::windowDestroyed(QQuickWindow *window)
{
- RLDEBUG1("GUI: windowDestroyed()");
+ QSG_GUI_DEBUG(window, "windowDestroyed()");
if (window->isVisible())
hide(window);
releaseResources(window, true);
- RLDEBUG1("GUI: - done with windowDestroyed()");
+ for (int i=0; i<m_windows.size(); ++i) {
+ if (m_windows.at(i).window == window) {
+ QSGRenderThread *thread = m_windows.at(i).thread;
+ while (thread->isRunning())
+ QThread::yieldCurrentThread();
+ Q_ASSERT(thread->thread() == QThread::currentThread());
+ delete thread;
+ m_windows.removeAt(i);
+ break;
+ }
+ }
+
+ QSG_GUI_DEBUG(window, " - done with windowDestroyed()");
}
void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window)
{
- RLDEBUG1("GUI: exposureChanged()");
- if (windowFor(m_windows, window) == 0)
+ QSG_GUI_DEBUG(window, "exposureChanged()");
+ Window *w = windowFor(m_windows, window);
+ if (!w)
return;
if (window->isExposed()) {
- handleExposure(window);
+ handleExposure(w);
} else {
- handleObscurity(window);
+ handleObscurity(w);
+ }
+}
+
+void QSGThreadedRenderLoop::resize(QQuickWindow *window)
+{
+ Window *w = windowFor(m_windows, window);
+ if (w
+ && w->gotBrokenExposeFromPlatformPlugin
+ && window->width() > 0 && window->height() > 0
+ && w->window->geometry().intersects(w->window->screen()->availableGeometry())) {
+ w->gotBrokenExposeFromPlatformPlugin = false;
+ handleExposure(w);
}
}
@@ -854,49 +900,64 @@ void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window)
Will post an event to the render thread that this window should
start to render.
*/
-void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
+void QSGThreadedRenderLoop::handleExposure(Window *w)
{
- RLDEBUG1("GUI: handleExposure");
+ QSG_GUI_DEBUG(w->window, "handleExposure");
+
+ if (w->window->width() <= 0 || w->window->height() <= 0
+ || !w->window->geometry().intersects(w->window->screen()->availableGeometry())) {
+#ifndef QT_NO_DEBUG
+ qWarning("QSGThreadedRenderLoop: expose event received for window with invalid geometry.");
+#endif
+ w->gotBrokenExposeFromPlatformPlugin = true;
+ return;
+ }
// Because we are going to bind a GL context to it, make sure it
// is created.
- if (!window->handle())
- window->create();
-
- m_thread->postEvent(new WMExposeEvent(window));
+ if (!w->window->handle())
+ w->window->create();
// Start render thread if it is not running
- if (!m_thread->isRunning()) {
- m_thread->shouldExit = false;
-
- RLDEBUG1("GUI: - starting render thread...");
+ if (!w->thread->isRunning()) {
+
+ QSG_GUI_DEBUG(w->window, " - starting render thread...");
+
+ if (!w->thread->gl) {
+ w->thread->gl = new QOpenGLContext();
+ if (QSGContext::sharedOpenGLContext())
+ w->thread->gl->setShareContext(QSGContext::sharedOpenGLContext());
+ w->thread->gl->setFormat(w->window->requestedFormat());
+ if (!w->thread->gl->create()) {
+ delete w->thread->gl;
+ w->thread->gl = 0;
+ qWarning("QtQuick: failed to create OpenGL context");
+ return;
+ }
- if (!m_thread->gl) {
- QOpenGLContext *ctx = new QOpenGLContext();
- ctx->setFormat(window->requestedFormat());
- ctx->create();
- ctx->moveToThread(m_thread);
- m_thread->gl = ctx;
+ w->thread->gl->moveToThread(w->thread);
+ QSG_GUI_DEBUG(w->window, " - OpenGL context created...");
}
- QQuickAnimatorController *controller = QQuickWindowPrivate::get(window)->animationController;
- if (controller->thread() != m_thread)
- controller->moveToThread(m_thread);
+ QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController;
+ if (controller->thread() != w->thread)
+ controller->moveToThread(w->thread);
- m_thread->start();
+ w->thread->active = true;
+ if (w->thread->thread() == QThread::currentThread()) {
+ w->thread->sgrc->moveToThread(w->thread);
+ w->thread->moveToThread(w->thread);
+ }
+ w->thread->start();
} else {
- RLDEBUG1("GUI: - render thread already running");
+ QSG_GUI_DEBUG(w->window, " - render thread already running");
}
- polishAndSync();
-
- // Kill non-visual animation timer if it is running
- if (m_animation_timer) {
- killTimer(m_animation_timer);
- m_animation_timer = 0;
- }
+ w->thread->postEvent(new WMExposeEvent(w->window));
+ polishAndSync(w);
+ startOrStopAnimationTimer();
}
/*!
@@ -906,43 +967,51 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
It also starts up the non-vsync animation tick if no more windows
are showing.
*/
-void QSGThreadedRenderLoop::handleObscurity(QQuickWindow *window)
+void QSGThreadedRenderLoop::handleObscurity(Window *w)
{
- RLDEBUG1("GUI: handleObscurity");
- if (m_thread->isRunning())
- m_thread->postEvent(new WMWindowEvent(window, WM_Obscure));
-
- if (!anyoneShowing() && m_animation_driver->isRunning() && m_animation_timer == 0) {
- m_animation_timer = startTimer(qsgrl_animation_interval());
+ QSG_GUI_DEBUG(w->window, "handleObscurity");
+ if (w->thread->isRunning()) {
+ w->thread->mutex.lock();
+ w->thread->postEvent(new WMWindowEvent(w->window, WM_Obscure));
+ w->thread->waitCondition.wait(&w->thread->mutex);
+ w->thread->mutex.unlock();
}
+
+ startOrStopAnimationTimer();
}
+void QSGThreadedRenderLoop::maybeUpdate(QQuickWindow *window)
+{
+ Window *w = windowFor(m_windows, window);
+ if (w)
+ maybeUpdate(w);
+}
+
/*!
Called whenever the QML scene has changed. Will post an event to
ourselves that a sync is needed.
*/
-void QSGThreadedRenderLoop::maybeUpdate(QQuickWindow *window)
+void QSGThreadedRenderLoop::maybeUpdate(Window *w)
{
- Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread() || m_thread->guiIsLocked,
+ Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread() || m_locked,
"QQuickItem::update()",
"Function can only be called from GUI thread or during QQuickItem::updatePaintNode()");
- RLDEBUG("GUI: maybeUpdate...");
- Window *w = windowFor(m_windows, window);
- if (!w || !m_thread->isRunning()) {
+ QSG_GUI_DEBUG(w->window, "maybeUpdate...");
+ if (!w || !w->thread->isRunning()) {
return;
}
// Call this function from the Gui thread later as startTimer cannot be
// called from the render thread.
- if (QThread::currentThread() == m_thread) {
- RLDEBUG("GUI: - on render thread, will update later..");
- m_sync_triggered_update = true;
+ if (QThread::currentThread() == w->thread) {
+ QSG_GUI_DEBUG(w->window, " - on render thread, will update later..");
+ w->updateDuringSync = true;
return;
}
- maybePostPolishRequest();
+ maybePostPolishRequest(w);
}
/*!
@@ -952,15 +1021,19 @@ void QSGThreadedRenderLoop::maybeUpdate(QQuickWindow *window)
*/
void QSGThreadedRenderLoop::update(QQuickWindow *window)
{
- if (QThread::currentThread() == m_thread) {
- RLDEBUG("Gui: update called on render thread");
- m_thread->requestRepaint();
+ Window *w = windowFor(m_windows, window);
+ if (!w)
+ return;
+
+ if (w->thread == QThread::currentThread()) {
+ QSG_RT_DEBUG("QQuickWindow::update called on render thread");
+ w->thread->requestRepaint();
return;
}
- RLDEBUG("Gui: update called");
- m_thread->postEvent(new QEvent(WM_RequestRepaint));
- maybeUpdate(window);
+ QSG_GUI_DEBUG(w->window, "update called");
+ w->thread->postEvent(new QEvent(WM_RequestRepaint));
+ maybeUpdate(w);
}
@@ -971,28 +1044,34 @@ void QSGThreadedRenderLoop::update(QQuickWindow *window)
*/
void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestructor)
{
- RLDEBUG1("GUI: releaseResources requested...");
+ QSG_GUI_DEBUG(window, "releaseResources requested...");
+
+ Window *w = windowFor(m_windows, window);
+ if (!w)
+ return;
- m_thread->mutex.lock();
- if (m_thread->isRunning() && !m_thread->shouldExit) {
- RLDEBUG1("GUI: - posting release request to render thread");
- m_thread->postEvent(new WMTryReleaseEvent(window, inDestructor));
- m_thread->waitCondition.wait(&m_thread->mutex);
+ w->thread->mutex.lock();
+ if (w->thread->isRunning() && w->thread->active) {
+ QSG_GUI_DEBUG(w->window, " - posting release request to render thread");
+ w->thread->postEvent(new WMTryReleaseEvent(window, inDestructor));
+ w->thread->waitCondition.wait(&w->thread->mutex);
}
- m_thread->mutex.unlock();
+ w->thread->mutex.unlock();
}
-void QSGThreadedRenderLoop::polishAndSync()
+void QSGThreadedRenderLoop::polishAndSync(Window *w)
{
- if (!anyoneShowing()) {
- killTimer(m_update_timer);
- m_update_timer = 0;
+ QSG_GUI_DEBUG(w->window, "polishAndSync()");
+
+ if (!w->window->isExposed() || !w->window->isVisible() || w->window->size().isEmpty()) {
+ QSG_GUI_DEBUG(w->window, " - not exposed, aborting...");
+ killTimer(w->timerId);
+ w->timerId = 0;
return;
}
- RLDEBUG("GUI: polishAndSync()");
#ifndef QSG_NO_RENDER_TIMING
QElapsedTimer timer;
@@ -1004,52 +1083,51 @@ void QSGThreadedRenderLoop::polishAndSync()
timer.start();
#endif
- // Polish as the last thing we do before we allow the sync to take place
- for (int i=0; i<m_windows.size(); ++i) {
- const Window &w = m_windows.at(i);
- QQuickWindowPrivate *d = QQuickWindowPrivate::get(w.window);
- d->polishItems();
- }
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(w->window);
+ d->polishItems();
+
#ifndef QSG_NO_RENDER_TIMING
if (profileFrames)
polishTime = timer.nsecsElapsed();
#endif
- m_sync_triggered_update = false;
+ w->updateDuringSync = false;
- RLDEBUG("GUI: - lock for sync...");
- m_thread->mutex.lock();
- m_thread->guiIsLocked = true;
- m_thread->postEvent(new QEvent(WM_RequestSync));
+ QSG_GUI_DEBUG(w->window, " - lock for sync...");
+ w->thread->mutex.lock();
+ m_locked = true;
+ w->thread->postEvent(new QEvent(WM_RequestSync));
- RLDEBUG("GUI: - wait for sync...");
+ QSG_GUI_DEBUG(w->window, " - wait for sync...");
#ifndef QSG_NO_RENDER_TIMING
if (profileFrames)
waitTime = timer.nsecsElapsed();
#endif
- m_thread->waitCondition.wait(&m_thread->mutex);
- m_thread->guiIsLocked = false;
- m_thread->mutex.unlock();
- RLDEBUG("GUI: - unlocked after sync...");
+ w->thread->waitCondition.wait(&w->thread->mutex);
+ m_locked = false;
+ w->thread->mutex.unlock();
+ QSG_GUI_DEBUG(w->window, " - unlocked after sync...");
#ifndef QSG_NO_RENDER_TIMING
if (profileFrames)
syncTime = timer.nsecsElapsed();
#endif
- killTimer(m_update_timer);
- m_update_timer = 0;
+ killTimer(w->timerId);
+ w->timerId = 0;
- if (m_animation_driver->isRunning()) {
- RLDEBUG("GUI: - animations advancing");
+ if (m_animation_timer == 0 && m_animation_driver->isRunning()) {
+ QSG_GUI_DEBUG(w->window, " - animations advancing");
m_animation_driver->advance();
- RLDEBUG("GUI: - animations done");
+ QSG_GUI_DEBUG(w->window, " - animations done");
// We need to trigger another sync to keep animations running...
- maybePostPolishRequest();
- } else if (m_sync_triggered_update) {
- maybePostPolishRequest();
+ maybePostPolishRequest(w);
+ emit timeToIncubate();
+ } else if (w->updateDuringSync) {
+ maybePostPolishRequest(w);
}
+
#ifndef QSG_NO_RENDER_TIMING
if (qsg_render_timing)
qDebug(" - on GUI: polish=%d, lock=%d, block/sync=%d -- animations=%d",
@@ -1073,15 +1151,26 @@ bool QSGThreadedRenderLoop::event(QEvent *e)
{
switch ((int) e->type()) {
- case QEvent::Timer:
- if (static_cast<QTimerEvent *>(e)->timerId() == m_animation_timer) {
- RLDEBUG("GUI: QEvent::Timer -> non-visual animation");
+ case QEvent::Timer: {
+ QTimerEvent *te = static_cast<QTimerEvent *>(e);
+ if (te->timerId() == m_animation_timer) {
+ QSG_GUI_DEBUG((void *) 0, "QEvent::Timer -> non-visual animation");
m_animation_driver->advance();
- } else if (static_cast<QTimerEvent *>(e)->timerId() == m_update_timer) {
- RLDEBUG("GUI: QEvent::Timer -> Polish & Sync");
- polishAndSync();
+ emit timeToIncubate();
+ } else {
+ QSG_GUI_DEBUG((void *) 0, "QEvent::Timer -> Polish & Sync");
+ Window *w = 0;
+ for (int i=0; i<m_windows.size(); ++i) {
+ if (m_windows.at(i).timerId == te->timerId()) {
+ w = const_cast<Window *>(&m_windows.at(i));
+ break;
+ }
+ }
+ if (w)
+ polishAndSync(w);
}
return true;
+ }
default:
break;
@@ -1104,26 +1193,30 @@ bool QSGThreadedRenderLoop::event(QEvent *e)
QImage QSGThreadedRenderLoop::grab(QQuickWindow *window)
{
- RLDEBUG("GUI: grab");
- if (!m_thread->isRunning())
+ QSG_GUI_DEBUG(window, "grab");
+
+ Window *w = windowFor(m_windows, window);
+ Q_ASSERT(w);
+
+ if (!w->thread->isRunning())
return QImage();
if (!window->handle())
window->create();
- RLDEBUG1("GUI: - polishing items...");
+ QSG_GUI_DEBUG(w->window, " - polishing items...");
QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
d->polishItems();
QImage result;
- m_thread->mutex.lock();
- RLDEBUG1("GUI: - locking, posting grab event");
- m_thread->postEvent(new WMGrabEvent(window, &result));
- m_thread->waitCondition.wait(&m_thread->mutex);
- RLDEBUG1("GUI: - locking, grab done, unlocking");
- m_thread->mutex.unlock();
-
- RLDEBUG1("Gui: - grab complete");
+ w->thread->mutex.lock();
+ QSG_GUI_DEBUG(w->window, " - locking, posting grab event");
+ w->thread->postEvent(new WMGrabEvent(window, &result));
+ w->thread->waitCondition.wait(&w->thread->mutex);
+ QSG_GUI_DEBUG(w->window, " - locking, grab done, unlocking");
+ w->thread->mutex.unlock();
+
+ QSG_GUI_DEBUG(w->window, " - grab complete");
return result;
}
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
index b943739a0d..844d180788 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h
+++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
@@ -60,18 +60,17 @@ public:
void show(QQuickWindow *window);
void hide(QQuickWindow *window);
+ void resize(QQuickWindow *window);
void windowDestroyed(QQuickWindow *window);
void exposureChanged(QQuickWindow *window);
- void handleExposure(QQuickWindow *window);
- void handleObscurity(QQuickWindow *window);
-
QImage grab(QQuickWindow *);
void update(QQuickWindow *window);
void maybeUpdate(QQuickWindow *window);
QSGContext *sceneGraphContext() const;
+ QSGRenderContext *createRenderContext(QSGContext *) const;
QAnimationDriver *animationDriver() const;
@@ -86,6 +85,14 @@ public Q_SLOTS:
void animationStopped();
private:
+ struct Window {
+ QQuickWindow *window;
+ QSGRenderThread *thread;
+ int timerId;
+ uint updateDuringSync : 1;
+ uint gotBrokenExposeFromPlatformPlugin : 1;
+ };
+
friend class QSGRenderThread;
void releaseResources(QQuickWindow *window, bool inDestructor);
@@ -94,25 +101,24 @@ private:
bool anyoneShowing() const;
void initialize();
- void maybePostPolishRequest();
-
+ void startOrStopAnimationTimer();
+ void maybePostPolishRequest(Window *w);
void waitForReleaseComplete();
+ void polishAndSync(Window *w);
+ void maybeUpdate(Window *window);
- void polishAndSync();
+ void handleExposure(Window *w);
+ void handleObscurity(Window *w);
- struct Window {
- QQuickWindow *window;
- };
- QSGRenderThread *m_thread;
+ QSGContext *sg;
QAnimationDriver *m_animation_driver;
QList<Window> m_windows;
int m_animation_timer;
- int m_update_timer;
int m_exhaust_delay;
- bool m_sync_triggered_update;
+ bool m_locked;
};
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index 95584d0f5d..0c128d5cae 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -85,6 +85,8 @@ QSGWindowsRenderLoop::QSGWindowsRenderLoop()
qsg_debug_timer.start();
#endif
+ m_rc = new QSGRenderContext(m_sg);
+
m_animationDriver = m_sg->createAnimationDriver(m_sg);
m_animationDriver->install();
@@ -102,6 +104,12 @@ QSGWindowsRenderLoop::QSGWindowsRenderLoop()
#endif
}
+QSGWindowsRenderLoop::~QSGWindowsRenderLoop()
+{
+ delete m_rc;
+ delete m_sg;
+}
+
bool QSGWindowsRenderLoop::interleaveIncubation() const
{
return m_animationDriver->isRunning() && anyoneShowing();
@@ -170,13 +178,22 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window)
RLDEBUG(" - creating GL context");
m_gl = new QOpenGLContext();
m_gl->setFormat(window->requestedFormat());
- m_gl->create();
+ if (QSGContext::sharedOpenGLContext())
+ m_gl->setShareContext(QSGContext::sharedOpenGLContext());
+ bool created = m_gl->create();
+ if (!created) {
+ qWarning("QtQuick: failed to create OpenGL context");
+ delete m_gl;
+ m_gl = 0;
+ return;
+ }
QSG_RENDER_TIMING_SAMPLE(time_created);
RLDEBUG(" - making current");
- m_gl->makeCurrent(window);
+ bool current = m_gl->makeCurrent(window);
RLDEBUG(" - initializing SG");
QSG_RENDER_TIMING_SAMPLE(time_current);
- m_sg->initialize(m_gl);
+ if (current)
+ m_rc->initialize(m_gl);
#ifndef QSG_NO_RENDER_TIMING
if (qsg_render_timing) {
@@ -230,7 +247,8 @@ void QSGWindowsRenderLoop::hide(QQuickWindow *window)
// potentially clean up.
if (m_windows.size() == 0) {
if (!cd->persistentSceneGraph) {
- m_sg->invalidate();
+ QQuickWindowPrivate::get(window)->context->invalidate();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
if (!cd->persistentGLContext) {
delete m_gl;
m_gl = 0;
@@ -246,7 +264,8 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window)
// If this is the last tracked window, clean up SG and GL.
if (m_windows.size() == 0) {
- m_sg->invalidate();
+ QQuickWindowPrivate::get(window)->context->invalidate();
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
delete m_gl;
m_gl = 0;
}
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop_p.h b/src/quick/scenegraph/qsgwindowsrenderloop_p.h
index cb01e1e04b..e4ee688c9f 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop_p.h
+++ b/src/quick/scenegraph/qsgwindowsrenderloop_p.h
@@ -51,11 +51,14 @@
QT_BEGIN_NAMESPACE
+class QSGRenderContext;
+
class QSGWindowsRenderLoop : public QSGRenderLoop
{
Q_OBJECT
public:
explicit QSGWindowsRenderLoop();
+ ~QSGWindowsRenderLoop();
void show(QQuickWindow *window);
void hide(QQuickWindow *window);
@@ -71,14 +74,13 @@ public:
QAnimationDriver *animationDriver() const { return m_animationDriver; }
QSGContext *sceneGraphContext() const { return m_sg; }
+ QSGRenderContext *createRenderContext(QSGContext *) const { return m_rc; }
void releaseResources(QQuickWindow *) { }
void render();
void renderWindow(QQuickWindow *window);
- void resize(QQuickWindow *, const QSize &) { }
-
bool event(QEvent *event);
bool anyoneShowing() const;
@@ -102,6 +104,7 @@ private:
QOpenGLContext *m_gl;
QSGContext *m_sg;
+ QSGRenderContext *m_rc;
QAnimationDriver *m_animationDriver;
diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri
index 3b8221264b..6f64c881a8 100644
--- a/src/quick/scenegraph/scenegraph.pri
+++ b/src/quick/scenegraph/scenegraph.pri
@@ -10,7 +10,8 @@ HEADERS += \
$$PWD/coreapi/qsgnodeupdater_p.h \
$$PWD/coreapi/qsgrenderer_p.h \
$$PWD/coreapi/qsgrendernode_p.h \
- $$PWD/coreapi/qsggeometry_p.h
+ $$PWD/coreapi/qsggeometry_p.h \
+ $$PWD/coreapi/qsgmaterialshader_p.h
SOURCES += \
$$PWD/coreapi/qsgbatchrenderer.cpp \
@@ -20,8 +21,7 @@ SOURCES += \
$$PWD/coreapi/qsgnodeupdater.cpp \
$$PWD/coreapi/qsgrenderer.cpp \
$$PWD/coreapi/qsgrendernode.cpp \
- $$PWD/coreapi/qsgshaderrewriter.cpp \
- scenegraph/util/qsgsimplematerial.cpp
+ $$PWD/coreapi/qsgshaderrewriter.cpp
# Util API
HEADERS += \
@@ -39,7 +39,8 @@ HEADERS += \
$$PWD/util/qsgtexture_p.h \
$$PWD/util/qsgtextureprovider.h \
$$PWD/util/qsgpainternode_p.h \
- $$PWD/util/qsgdistancefieldutil_p.h
+ $$PWD/util/qsgdistancefieldutil_p.h \
+ $$PWD/util/qsgshadersourcebuilder_p.h
SOURCES += \
$$PWD/util/qsgareaallocator.cpp \
@@ -53,7 +54,9 @@ SOURCES += \
$$PWD/util/qsgtexture.cpp \
$$PWD/util/qsgtextureprovider.cpp \
$$PWD/util/qsgpainternode.cpp \
- $$PWD/util/qsgdistancefieldutil.cpp
+ $$PWD/util/qsgdistancefieldutil.cpp \
+ $$PWD/util/qsgsimplematerial.cpp \
+ $$PWD/util/qsgshadersourcebuilder.cpp
# QML / Adaptations API
HEADERS += \
@@ -67,7 +70,6 @@ HEADERS += \
$$PWD/qsgdefaultglyphnode_p_p.h \
$$PWD/qsgdefaultimagenode_p.h \
$$PWD/qsgdefaultrectanglenode_p.h \
- $$PWD/qsgflashnode_p.h \
$$PWD/qsgshareddistancefieldglyphcache_p.h \
$$PWD/qsgrenderloop_p.h \
$$PWD/qsgthreadedrenderloop_p.h \
@@ -84,8 +86,77 @@ SOURCES += \
$$PWD/qsgdistancefieldglyphnode_p.cpp \
$$PWD/qsgdefaultimagenode.cpp \
$$PWD/qsgdefaultrectanglenode.cpp \
- $$PWD/qsgflashnode.cpp \
$$PWD/qsgshareddistancefieldglyphcache.cpp \
$$PWD/qsgrenderloop.cpp \
$$PWD/qsgthreadedrenderloop.cpp \
$$PWD/qsgwindowsrenderloop.cpp
+
+RESOURCES += \
+ $$PWD/scenegraph.qrc
+
+OTHER_FILES += \
+ $$PWD/shaders/24bittextmask.frag \
+ $$PWD/shaders/8bittextmask.frag \
+ $$PWD/shaders/distancefieldoutlinetext.frag \
+ $$PWD/shaders/distancefieldshiftedtext.frag \
+ $$PWD/shaders/distancefieldshiftedtext.vert \
+ $$PWD/shaders/distancefieldtext.frag \
+ $$PWD/shaders/distancefieldtext.vert \
+ $$PWD/shaders/flatcolor.frag \
+ $$PWD/shaders/flatcolor.vert \
+ $$PWD/shaders/hiqsubpixeldistancefieldtext.frag \
+ $$PWD/shaders/hiqsubpixeldistancefieldtext.vert \
+ $$PWD/shaders/loqsubpixeldistancefieldtext.frag \
+ $$PWD/shaders/loqsubpixeldistancefieldtext.vert \
+ $$PWD/shaders/opaquetexture.frag \
+ $$PWD/shaders/opaquetexture.vert \
+ $$PWD/shaders/outlinedtext.frag \
+ $$PWD/shaders/outlinedtext.vert \
+ $$PWD/shaders/rendernode.frag \
+ $$PWD/shaders/rendernode.vert \
+ $$PWD/shaders/smoothcolor.frag \
+ $$PWD/shaders/smoothcolor.vert \
+ $$PWD/shaders/smoothtexture.frag \
+ $$PWD/shaders/smoothtexture.vert \
+ $$PWD/shaders/stencilclip.frag \
+ $$PWD/shaders/stencilclip.vert \
+ $$PWD/shaders/styledtext.frag \
+ $$PWD/shaders/styledtext.vert \
+ $$PWD/shaders/textmask.frag \
+ $$PWD/shaders/textmask.vert \
+ $$PWD/shaders/texture.frag \
+ $$PWD/shaders/vertexcolor.frag \
+ $$PWD/shaders/vertexcolor.vert \
+ $$PWD/shaders/24bittextmask_core.frag \
+ $$PWD/shaders/8bittextmask_core.frag \
+ $$PWD/shaders/distancefieldoutlinetext_core.frag \
+ $$PWD/shaders/distancefieldshiftedtext_core.frag \
+ $$PWD/shaders/distancefieldshiftedtext_core.vert \
+ $$PWD/shaders/distancefieldtext_core.frag \
+ $$PWD/shaders/distancefieldtext_core.vert \
+ $$PWD/shaders/flatcolor_core.frag \
+ $$PWD/shaders/flatcolor_core.vert \
+ $$PWD/shaders/hiqsubpixeldistancefieldtext_core.frag \
+ $$PWD/shaders/hiqsubpixeldistancefieldtext_core.vert \
+ $$PWD/shaders/loqsubpixeldistancefieldtext_core.frag \
+ $$PWD/shaders/loqsubpixeldistancefieldtext_core.vert \
+ $$PWD/shaders/opaquetexture_core.frag \
+ $$PWD/shaders/opaquetexture_core.vert \
+ $$PWD/shaders/outlinedtext_core.frag \
+ $$PWD/shaders/outlinedtext_core.vert \
+ $$PWD/shaders/rendernode_core.frag \
+ $$PWD/shaders/rendernode_core.vert \
+ $$PWD/shaders/smoothcolor_core.frag \
+ $$PWD/shaders/smoothcolor_core.vert \
+ $$PWD/shaders/smoothtexture_core.frag \
+ $$PWD/shaders/smoothtexture_core.vert \
+ $$PWD/shaders/stencilclip_core.frag \
+ $$PWD/shaders/stencilclip_core.vert \
+ $$PWD/shaders/styledtext_core.frag \
+ $$PWD/shaders/styledtext_core.vert \
+ $$PWD/shaders/textmask_core.frag \
+ $$PWD/shaders/textmask_core.vert \
+ $$PWD/shaders/texture_core.frag \
+ $$PWD/shaders/vertexcolor_core.frag \
+ $$PWD/shaders/vertexcolor_core.vert
+
diff --git a/src/quick/scenegraph/scenegraph.qrc b/src/quick/scenegraph/scenegraph.qrc
new file mode 100644
index 0000000000..2be8b246d3
--- /dev/null
+++ b/src/quick/scenegraph/scenegraph.qrc
@@ -0,0 +1,68 @@
+<RCC>
+ <qresource prefix="/scenegraph">
+ <file>shaders/flatcolor.frag</file>
+ <file>shaders/flatcolor.vert</file>
+ <file>shaders/8bittextmask.frag</file>
+ <file>shaders/24bittextmask.frag</file>
+ <file>shaders/opaquetexture.frag</file>
+ <file>shaders/opaquetexture.vert</file>
+ <file>shaders/outlinedtext.frag</file>
+ <file>shaders/outlinedtext.vert</file>
+ <file>shaders/smoothcolor.frag</file>
+ <file>shaders/smoothcolor.vert</file>
+ <file>shaders/smoothtexture.frag</file>
+ <file>shaders/smoothtexture.vert</file>
+ <file>shaders/styledtext.frag</file>
+ <file>shaders/styledtext.vert</file>
+ <file>shaders/textmask.frag</file>
+ <file>shaders/textmask.vert</file>
+ <file>shaders/texture.frag</file>
+ <file>shaders/distancefieldoutlinetext.frag</file>
+ <file>shaders/distancefieldshiftedtext.frag</file>
+ <file>shaders/distancefieldshiftedtext.vert</file>
+ <file>shaders/distancefieldtext.frag</file>
+ <file>shaders/distancefieldtext.vert</file>
+ <file>shaders/hiqsubpixeldistancefieldtext.frag</file>
+ <file>shaders/hiqsubpixeldistancefieldtext.vert</file>
+ <file>shaders/loqsubpixeldistancefieldtext.frag</file>
+ <file>shaders/loqsubpixeldistancefieldtext.vert</file>
+ <file>shaders/vertexcolor.frag</file>
+ <file>shaders/vertexcolor.vert</file>
+ <file>shaders/rendernode.vert</file>
+ <file>shaders/rendernode.frag</file>
+ <file>shaders/stencilclip.frag</file>
+ <file>shaders/stencilclip.vert</file>
+ <file>shaders/8bittextmask_core.frag</file>
+ <file>shaders/24bittextmask_core.frag</file>
+ <file>shaders/distancefieldoutlinetext_core.frag</file>
+ <file>shaders/distancefieldshiftedtext_core.frag</file>
+ <file>shaders/distancefieldshiftedtext_core.vert</file>
+ <file>shaders/distancefieldtext_core.frag</file>
+ <file>shaders/distancefieldtext_core.vert</file>
+ <file>shaders/flatcolor_core.frag</file>
+ <file>shaders/flatcolor_core.vert</file>
+ <file>shaders/hiqsubpixeldistancefieldtext_core.frag</file>
+ <file>shaders/hiqsubpixeldistancefieldtext_core.vert</file>
+ <file>shaders/loqsubpixeldistancefieldtext_core.frag</file>
+ <file>shaders/loqsubpixeldistancefieldtext_core.vert</file>
+ <file>shaders/opaquetexture_core.frag</file>
+ <file>shaders/opaquetexture_core.vert</file>
+ <file>shaders/outlinedtext_core.frag</file>
+ <file>shaders/outlinedtext_core.vert</file>
+ <file>shaders/rendernode_core.frag</file>
+ <file>shaders/rendernode_core.vert</file>
+ <file>shaders/smoothcolor_core.frag</file>
+ <file>shaders/smoothcolor_core.vert</file>
+ <file>shaders/smoothtexture_core.frag</file>
+ <file>shaders/smoothtexture_core.vert</file>
+ <file>shaders/stencilclip_core.frag</file>
+ <file>shaders/stencilclip_core.vert</file>
+ <file>shaders/styledtext_core.frag</file>
+ <file>shaders/styledtext_core.vert</file>
+ <file>shaders/textmask_core.frag</file>
+ <file>shaders/textmask_core.vert</file>
+ <file>shaders/texture_core.frag</file>
+ <file>shaders/vertexcolor_core.frag</file>
+ <file>shaders/vertexcolor_core.vert</file>
+ </qresource>
+</RCC>
diff --git a/src/quick/scenegraph/shaders/24bittextmask.frag b/src/quick/scenegraph/shaders/24bittextmask.frag
new file mode 100644
index 0000000000..5c21e202f9
--- /dev/null
+++ b/src/quick/scenegraph/shaders/24bittextmask.frag
@@ -0,0 +1,10 @@
+varying highp vec2 sampleCoord;
+
+uniform lowp sampler2D _qt_texture;
+uniform lowp float color; // just the alpha, really...
+
+void main()
+{
+ lowp vec4 glyph = texture2D(_qt_texture, sampleCoord);
+ gl_FragColor = vec4(glyph.rgb * color, glyph.a);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/24bittextmask_core.frag b/src/quick/scenegraph/shaders/24bittextmask_core.frag
new file mode 100644
index 0000000000..29d1f23017
--- /dev/null
+++ b/src/quick/scenegraph/shaders/24bittextmask_core.frag
@@ -0,0 +1,14 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform float color; // just the alpha, really...
+
+void main()
+{
+ vec4 glyph = texture(_qt_texture, sampleCoord);
+ fragColor = vec4(glyph.rgb * color, glyph.a);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/8bittextmask.frag b/src/quick/scenegraph/shaders/8bittextmask.frag
new file mode 100644
index 0000000000..44ffb279cb
--- /dev/null
+++ b/src/quick/scenegraph/shaders/8bittextmask.frag
@@ -0,0 +1,9 @@
+varying highp vec2 sampleCoord;
+
+uniform lowp sampler2D _qt_texture;
+uniform lowp vec4 color;
+
+void main()
+{
+ gl_FragColor = color * texture2D(_qt_texture, sampleCoord).a;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/8bittextmask_core.frag b/src/quick/scenegraph/shaders/8bittextmask_core.frag
new file mode 100644
index 0000000000..2d67a4676a
--- /dev/null
+++ b/src/quick/scenegraph/shaders/8bittextmask_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+
+void main()
+{
+ fragColor = color * texture(_qt_texture, sampleCoord).r;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldoutlinetext.frag b/src/quick/scenegraph/shaders/distancefieldoutlinetext.frag
new file mode 100644
index 0000000000..250ed322a1
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldoutlinetext.frag
@@ -0,0 +1,16 @@
+varying highp vec2 sampleCoord;
+
+uniform sampler2D _qt_texture;
+uniform lowp vec4 color;
+uniform lowp vec4 styleColor;
+uniform mediump float alphaMin;
+uniform mediump float alphaMax;
+uniform mediump float outlineAlphaMax0;
+uniform mediump float outlineAlphaMax1;
+
+void main()
+{
+ mediump float d = texture2D(_qt_texture, sampleCoord).a;
+ gl_FragColor = mix(styleColor, color, smoothstep(alphaMin, alphaMax, d))
+ * smoothstep(outlineAlphaMax0, outlineAlphaMax1, d);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag b/src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag
new file mode 100644
index 0000000000..80fa05ca3c
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag
@@ -0,0 +1,20 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+uniform float alphaMin;
+uniform float alphaMax;
+uniform float outlineAlphaMax0;
+uniform float outlineAlphaMax1;
+
+void main()
+{
+ float d = texture(_qt_texture, sampleCoord).r;
+ fragColor = mix(styleColor, color, smoothstep(alphaMin, alphaMax, d))
+ * smoothstep(outlineAlphaMax0, outlineAlphaMax1, d);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldshiftedtext.frag b/src/quick/scenegraph/shaders/distancefieldshiftedtext.frag
new file mode 100644
index 0000000000..60c1c7468b
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldshiftedtext.frag
@@ -0,0 +1,17 @@
+varying highp vec2 sampleCoord;
+varying highp vec2 shiftedSampleCoord;
+
+uniform sampler2D _qt_texture;
+uniform lowp vec4 color;
+uniform lowp vec4 styleColor;
+uniform mediump float alphaMin;
+uniform mediump float alphaMax;
+
+void main()
+{
+ highp float a = smoothstep(alphaMin, alphaMax, texture2D(_qt_texture, sampleCoord).a);
+ highp vec4 shifted = styleColor * smoothstep(alphaMin,
+ alphaMax,
+ texture2D(_qt_texture, shiftedSampleCoord).a);
+ gl_FragColor = mix(shifted, color, a);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldshiftedtext.vert b/src/quick/scenegraph/shaders/distancefieldshiftedtext.vert
new file mode 100644
index 0000000000..800eadc4f1
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldshiftedtext.vert
@@ -0,0 +1,17 @@
+uniform highp mat4 matrix;
+uniform highp vec2 textureScale;
+
+attribute highp vec4 vCoord;
+attribute highp vec2 tCoord;
+
+uniform highp vec2 shift;
+
+varying highp vec2 sampleCoord;
+varying highp vec2 shiftedSampleCoord;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ shiftedSampleCoord = (tCoord - shift) * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag
new file mode 100644
index 0000000000..3f66965e78
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag
@@ -0,0 +1,20 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec2 shiftedSampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+ float a = smoothstep(alphaMin, alphaMax, texture(_qt_texture, sampleCoord).r);
+ vec4 shifted = styleColor * smoothstep(alphaMin, alphaMax,
+ texture(_qt_texture, shiftedSampleCoord).r);
+ fragColor = mix(shifted, color, a);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert
new file mode 100644
index 0000000000..b7a3ecc667
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert
@@ -0,0 +1,18 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec2 shiftedSampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform vec2 shift;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ shiftedSampleCoord = (tCoord - shift) * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldtext.frag b/src/quick/scenegraph/shaders/distancefieldtext.frag
new file mode 100644
index 0000000000..951fb2a825
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldtext.frag
@@ -0,0 +1,13 @@
+varying highp vec2 sampleCoord;
+
+uniform mediump sampler2D _qt_texture;
+uniform lowp vec4 color;
+uniform mediump float alphaMin;
+uniform mediump float alphaMax;
+
+void main()
+{
+ gl_FragColor = color * smoothstep(alphaMin,
+ alphaMax,
+ texture2D(_qt_texture, sampleCoord).a);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldtext.vert b/src/quick/scenegraph/shaders/distancefieldtext.vert
new file mode 100644
index 0000000000..c4963977a5
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldtext.vert
@@ -0,0 +1,13 @@
+uniform highp mat4 matrix;
+uniform highp vec2 textureScale;
+
+attribute highp vec4 vCoord;
+attribute highp vec2 tCoord;
+
+varying highp vec2 sampleCoord;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldtext_core.frag b/src/quick/scenegraph/shaders/distancefieldtext_core.frag
new file mode 100644
index 0000000000..9c64a60d3d
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldtext_core.frag
@@ -0,0 +1,16 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+ fragColor = color * smoothstep(alphaMin, alphaMax,
+ texture(_qt_texture, sampleCoord).r);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/distancefieldtext_core.vert b/src/quick/scenegraph/shaders/distancefieldtext_core.vert
new file mode 100644
index 0000000000..7fc693d139
--- /dev/null
+++ b/src/quick/scenegraph/shaders/distancefieldtext_core.vert
@@ -0,0 +1,15 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/flatcolor.frag b/src/quick/scenegraph/shaders/flatcolor.frag
new file mode 100644
index 0000000000..8c225bf5a4
--- /dev/null
+++ b/src/quick/scenegraph/shaders/flatcolor.frag
@@ -0,0 +1,6 @@
+uniform lowp vec4 color;
+
+void main()
+{
+ gl_FragColor = color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/flatcolor.vert b/src/quick/scenegraph/shaders/flatcolor.vert
new file mode 100644
index 0000000000..a61de97f85
--- /dev/null
+++ b/src/quick/scenegraph/shaders/flatcolor.vert
@@ -0,0 +1,7 @@
+attribute highp vec4 vCoord;
+uniform highp mat4 matrix;
+
+void main()
+{
+ gl_Position = matrix * vCoord;
+}
diff --git a/src/quick/scenegraph/shaders/flatcolor_core.frag b/src/quick/scenegraph/shaders/flatcolor_core.frag
new file mode 100644
index 0000000000..23a957ad7b
--- /dev/null
+++ b/src/quick/scenegraph/shaders/flatcolor_core.frag
@@ -0,0 +1,10 @@
+#version 150 core
+
+out vec4 fragColor;
+
+uniform vec4 color;
+
+void main()
+{
+ fragColor = color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/flatcolor_core.vert b/src/quick/scenegraph/shaders/flatcolor_core.vert
new file mode 100644
index 0000000000..e33c591b95
--- /dev/null
+++ b/src/quick/scenegraph/shaders/flatcolor_core.vert
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 vCoord;
+
+uniform mat4 matrix;
+
+void main()
+{
+ gl_Position = matrix * vCoord;
+}
diff --git a/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag
new file mode 100644
index 0000000000..9b65e5f79b
--- /dev/null
+++ b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag
@@ -0,0 +1,58 @@
+varying highp vec2 sampleCoord;
+varying highp vec3 sampleFarLeft;
+varying highp vec3 sampleNearLeft;
+varying highp vec3 sampleNearRight;
+varying highp vec3 sampleFarRight;
+
+uniform sampler2D _qt_texture;
+uniform lowp vec4 color;
+uniform mediump float alphaMin;
+uniform mediump float alphaMax;
+
+void main()
+{
+ highp vec4 n;
+ n.x = texture2DProj(_qt_texture, sampleFarLeft).a;
+ n.y = texture2DProj(_qt_texture, sampleNearLeft).a;
+ highp float c = texture2D(_qt_texture, sampleCoord).a;
+ n.z = texture2DProj(_qt_texture, sampleNearRight).a;
+ n.w = texture2DProj(_qt_texture, sampleFarRight).a;
+#if 0
+ // Blurrier, faster.
+ n = smoothstep(alphaMin, alphaMax, n);
+ c = smoothstep(alphaMin, alphaMax, c);
+#else
+ // Sharper, slower.
+ highp vec2 d = min(abs(n.yw - n.xz) * 2., 0.67);
+ highp vec2 lo = mix(vec2(alphaMin), vec2(0.5), d);
+ highp vec2 hi = mix(vec2(alphaMax), vec2(0.5), d);
+ n = smoothstep(lo.xxyy, hi.xxyy, n);
+ c = smoothstep(lo.x + lo.y, hi.x + hi.y, 2. * c);
+#endif
+ gl_FragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w;
+}
+
+/*
+#extension GL_OES_standard_derivatives: enable
+
+varying highp vec2 sampleCoord;
+
+uniform sampler2D _qt_texture;
+uniform lowp vec4 color;
+uniform highp float alphaMin;
+uniform highp float alphaMax;
+
+void main()
+{
+ highp vec2 delta = dFdx(sampleCoord);
+ highp vec4 n;
+ n.x = texture2D(_qt_texture, sampleCoord - 0.667 * delta).a;
+ n.y = texture2D(_qt_texture, sampleCoord - 0.333 * delta).a;
+ highp float c = texture2D(_qt_texture, sampleCoord).a;
+ n.z = texture2D(_qt_texture, sampleCoord + 0.333 * delta).a;
+ n.w = texture2D(_qt_texture, sampleCoord + 0.667 * delta).a;
+ n = smoothstep(alphaMin, alphaMax, n);
+ c = smoothstep(alphaMin, alphaMax, c);
+ gl_FragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w;
+};
+*/ \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert
new file mode 100644
index 0000000000..62768e88e1
--- /dev/null
+++ b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert
@@ -0,0 +1,34 @@
+uniform highp mat4 matrix;
+uniform highp vec2 textureScale;
+uniform highp float fontScale;
+uniform highp vec4 vecDelta;
+
+attribute highp vec4 vCoord;
+attribute highp vec2 tCoord;
+
+varying highp vec2 sampleCoord;
+varying highp vec3 sampleFarLeft;
+varying highp vec3 sampleNearLeft;
+varying highp vec3 sampleNearRight;
+varying highp vec3 sampleFarRight;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+
+ // Calculate neighbor pixel position in item space.
+ highp vec3 wDelta = gl_Position.w * vecDelta.xyw;
+ highp vec3 farLeft = vCoord.xyw - 0.667 * wDelta;
+ highp vec3 nearLeft = vCoord.xyw - 0.333 * wDelta;
+ highp vec3 nearRight = vCoord.xyw + 0.333 * wDelta;
+ highp vec3 farRight = vCoord.xyw + 0.667 * wDelta;
+
+ // Calculate neighbor texture coordinate.
+ highp vec2 scale = textureScale / fontScale;
+ highp vec2 base = sampleCoord - scale * vCoord.xy;
+ sampleFarLeft = vec3(base * farLeft.z + scale * farLeft.xy, farLeft.z);
+ sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z);
+ sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z);
+ sampleFarRight = vec3(base * farRight.z + scale * farRight.xy, farRight.z);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag
new file mode 100644
index 0000000000..cf6ba2b8d9
--- /dev/null
+++ b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag
@@ -0,0 +1,32 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec3 sampleFarLeft;
+in vec3 sampleNearLeft;
+in vec3 sampleNearRight;
+in vec3 sampleFarRight;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+ vec4 n;
+ n.x = textureProj(_qt_texture, sampleFarLeft).r;
+ n.y = textureProj(_qt_texture, sampleNearLeft).r;
+ float c = texture(_qt_texture, sampleCoord).r;
+ n.z = textureProj(_qt_texture, sampleNearRight).r;
+ n.w = textureProj(_qt_texture, sampleFarRight).r;
+
+ vec2 d = min(abs(n.yw - n.xz) * 2., 0.67);
+ vec2 lo = mix(vec2(alphaMin), vec2(0.5), d);
+ vec2 hi = mix(vec2(alphaMax), vec2(0.5), d);
+ n = smoothstep(lo.xxyy, hi.xxyy, n);
+ c = smoothstep(lo.x + lo.y, hi.x + hi.y, 2. * c);
+
+ fragColor = vec4(0.333 * (n.xyz + n.yzw + c), c) * color.w;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert
new file mode 100644
index 0000000000..936f74725b
--- /dev/null
+++ b/src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert
@@ -0,0 +1,36 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec3 sampleFarLeft;
+out vec3 sampleNearLeft;
+out vec3 sampleNearRight;
+out vec3 sampleFarRight;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform float fontScale;
+uniform vec4 vecDelta;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+
+ // Calculate neighbor pixel position in item space.
+ vec3 wDelta = gl_Position.w * vecDelta.xyw;
+ vec3 farLeft = vCoord.xyw - 0.667 * wDelta;
+ vec3 nearLeft = vCoord.xyw - 0.333 * wDelta;
+ vec3 nearRight = vCoord.xyw + 0.333 * wDelta;
+ vec3 farRight = vCoord.xyw + 0.667 * wDelta;
+
+ // Calculate neighbor texture coordinate.
+ vec2 scale = textureScale / fontScale;
+ vec2 base = sampleCoord - scale * vCoord.xy;
+ sampleFarLeft = vec3(base * farLeft.z + scale * farLeft.xy, farLeft.z);
+ sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z);
+ sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z);
+ sampleFarRight = vec3(base * farRight.z + scale * farRight.xy, farRight.z);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext.frag b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext.frag
new file mode 100644
index 0000000000..61b6c8dd9a
--- /dev/null
+++ b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext.frag
@@ -0,0 +1,17 @@
+varying highp vec3 sampleNearLeft;
+varying highp vec3 sampleNearRight;
+
+uniform sampler2D _qt_texture;
+uniform lowp vec4 color;
+uniform mediump float alphaMin;
+uniform mediump float alphaMax;
+
+void main()
+{
+ highp vec2 n;
+ n.x = texture2DProj(_qt_texture, sampleNearLeft).a;
+ n.y = texture2DProj(_qt_texture, sampleNearRight).a;
+ n = smoothstep(alphaMin, alphaMax, n);
+ highp float c = 0.5 * (n.x + n.y);
+ gl_FragColor = vec4(n.x, c, n.y, c) * color.w;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext.vert b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext.vert
new file mode 100644
index 0000000000..33cb7efb19
--- /dev/null
+++ b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext.vert
@@ -0,0 +1,27 @@
+uniform highp mat4 matrix;
+uniform highp vec2 textureScale;
+uniform highp float fontScale;
+uniform highp vec4 vecDelta;
+
+attribute highp vec4 vCoord;
+attribute highp vec2 tCoord;
+
+varying highp vec3 sampleNearLeft;
+varying highp vec3 sampleNearRight;
+
+void main()
+{
+ highp vec2 sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+
+ // Calculate neighbor pixel position in item space.
+ highp vec3 wDelta = gl_Position.w * vecDelta.xyw;
+ highp vec3 nearLeft = vCoord.xyw - 0.25 * wDelta;
+ highp vec3 nearRight = vCoord.xyw + 0.25 * wDelta;
+
+ // Calculate neighbor texture coordinate.
+ highp vec2 scale = textureScale / fontScale;
+ highp vec2 base = sampleCoord - scale * vCoord.xy;
+ sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z);
+ sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag
new file mode 100644
index 0000000000..2dd588d307
--- /dev/null
+++ b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag
@@ -0,0 +1,21 @@
+#version 150 core
+
+in vec3 sampleNearLeft;
+in vec3 sampleNearRight;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform float alphaMin;
+uniform float alphaMax;
+
+void main()
+{
+ vec2 n;
+ n.x = textureProj(_qt_texture, sampleNearLeft).r;
+ n.y = textureProj(_qt_texture, sampleNearRight).r;
+ n = smoothstep(alphaMin, alphaMax, n);
+ float c = 0.5 * (n.x + n.y);
+ fragColor = vec4(n.x, c, n.y, c) * color.w;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert
new file mode 100644
index 0000000000..b887a70001
--- /dev/null
+++ b/src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert
@@ -0,0 +1,29 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec3 sampleNearLeft;
+out vec3 sampleNearRight;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform float fontScale;
+uniform vec4 vecDelta;
+
+void main()
+{
+ vec2 sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+
+ // Calculate neighbor pixel position in item space.
+ vec3 wDelta = gl_Position.w * vecDelta.xyw;
+ vec3 nearLeft = vCoord.xyw - 0.25 * wDelta;
+ vec3 nearRight = vCoord.xyw + 0.25 * wDelta;
+
+ // Calculate neighbor texture coordinate.
+ vec2 scale = textureScale / fontScale;
+ vec2 base = sampleCoord - scale * vCoord.xy;
+ sampleNearLeft = vec3(base * nearLeft.z + scale * nearLeft.xy, nearLeft.z);
+ sampleNearRight = vec3(base * nearRight.z + scale * nearRight.xy, nearRight.z);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/opaquetexture.frag b/src/quick/scenegraph/shaders/opaquetexture.frag
new file mode 100644
index 0000000000..b7e07de385
--- /dev/null
+++ b/src/quick/scenegraph/shaders/opaquetexture.frag
@@ -0,0 +1,8 @@
+varying highp vec2 qt_TexCoord;
+
+uniform sampler2D qt_Texture;
+
+void main()
+{
+ gl_FragColor = texture2D(qt_Texture, qt_TexCoord);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/opaquetexture.vert b/src/quick/scenegraph/shaders/opaquetexture.vert
new file mode 100644
index 0000000000..32cf02df25
--- /dev/null
+++ b/src/quick/scenegraph/shaders/opaquetexture.vert
@@ -0,0 +1,12 @@
+uniform highp mat4 qt_Matrix;
+
+attribute highp vec4 qt_VertexPosition;
+attribute highp vec2 qt_VertexTexCoord;
+
+varying highp vec2 qt_TexCoord;
+
+void main()
+{
+ qt_TexCoord = qt_VertexTexCoord;
+ gl_Position = qt_Matrix * qt_VertexPosition;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/opaquetexture_core.frag b/src/quick/scenegraph/shaders/opaquetexture_core.frag
new file mode 100644
index 0000000000..5f30e68677
--- /dev/null
+++ b/src/quick/scenegraph/shaders/opaquetexture_core.frag
@@ -0,0 +1,12 @@
+#version 150 core
+
+in vec2 qt_TexCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D qt_Texture;
+
+void main()
+{
+ fragColor = texture(qt_Texture, qt_TexCoord);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/opaquetexture_core.vert b/src/quick/scenegraph/shaders/opaquetexture_core.vert
new file mode 100644
index 0000000000..419b1a825c
--- /dev/null
+++ b/src/quick/scenegraph/shaders/opaquetexture_core.vert
@@ -0,0 +1,14 @@
+#version 150 core
+
+uniform mat4 qt_Matrix;
+
+in vec4 qt_VertexPosition;
+in vec2 qt_VertexTexCoord;
+
+out vec2 qt_TexCoord;
+
+void main()
+{
+ qt_TexCoord = qt_VertexTexCoord;
+ gl_Position = qt_Matrix * qt_VertexPosition;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/outlinedtext.frag b/src/quick/scenegraph/shaders/outlinedtext.frag
new file mode 100644
index 0000000000..b3e5475d5d
--- /dev/null
+++ b/src/quick/scenegraph/shaders/outlinedtext.frag
@@ -0,0 +1,21 @@
+varying highp vec2 sampleCoord;
+varying highp vec2 sCoordUp;
+varying highp vec2 sCoordDown;
+varying highp vec2 sCoordLeft;
+varying highp vec2 sCoordRight;
+
+uniform sampler2D _qt_texture;
+uniform lowp vec4 color;
+uniform lowp vec4 styleColor;
+
+void main()
+{
+ lowp float glyph = texture2D(_qt_texture, sampleCoord).a;
+ lowp float outline = clamp(clamp(texture2D(_qt_texture, sCoordUp).a +
+ texture2D(_qt_texture, sCoordDown).a +
+ texture2D(_qt_texture, sCoordLeft).a +
+ texture2D(_qt_texture, sCoordRight).a,
+ 0.0, 1.0) - glyph,
+ 0.0, 1.0);
+ gl_FragColor = outline * styleColor + glyph * color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/outlinedtext.vert b/src/quick/scenegraph/shaders/outlinedtext.vert
new file mode 100644
index 0000000000..ced8afd034
--- /dev/null
+++ b/src/quick/scenegraph/shaders/outlinedtext.vert
@@ -0,0 +1,22 @@
+uniform highp mat4 matrix;
+uniform highp vec2 textureScale;
+uniform highp vec2 shift;
+
+attribute highp vec4 vCoord;
+attribute highp vec2 tCoord;
+
+varying highp vec2 sampleCoord;
+varying highp vec2 sCoordUp;
+varying highp vec2 sCoordDown;
+varying highp vec2 sCoordLeft;
+varying highp vec2 sCoordRight;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ sCoordUp = (tCoord - vec2(0.0, -1.0)) * textureScale;
+ sCoordDown = (tCoord - vec2(0.0, 1.0)) * textureScale;
+ sCoordLeft = (tCoord - vec2(-1.0, 0.0)) * textureScale;
+ sCoordRight = (tCoord - vec2(1.0, 0.0)) * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/outlinedtext_core.frag b/src/quick/scenegraph/shaders/outlinedtext_core.frag
new file mode 100644
index 0000000000..e19c8937f9
--- /dev/null
+++ b/src/quick/scenegraph/shaders/outlinedtext_core.frag
@@ -0,0 +1,25 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec2 sCoordUp;
+in vec2 sCoordDown;
+in vec2 sCoordLeft;
+in vec2 sCoordRight;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+
+void main()
+{
+ float glyph = texture(_qt_texture, sampleCoord).r;
+ float outline = clamp(clamp(texture(_qt_texture, sCoordUp).r +
+ texture(_qt_texture, sCoordDown).r +
+ texture(_qt_texture, sCoordLeft).r +
+ texture(_qt_texture, sCoordRight).r,
+ 0.0, 1.0) - glyph,
+ 0.0, 1.0);
+ fragColor = outline * styleColor + glyph * color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/outlinedtext_core.vert b/src/quick/scenegraph/shaders/outlinedtext_core.vert
new file mode 100644
index 0000000000..4aa13101fd
--- /dev/null
+++ b/src/quick/scenegraph/shaders/outlinedtext_core.vert
@@ -0,0 +1,24 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec2 sCoordUp;
+out vec2 sCoordDown;
+out vec2 sCoordLeft;
+out vec2 sCoordRight;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform vec2 shift;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ sCoordUp = (tCoord - vec2(0.0, -1.0)) * textureScale;
+ sCoordDown = (tCoord - vec2(0.0, 1.0)) * textureScale;
+ sCoordLeft = (tCoord - vec2(-1.0, 0.0)) * textureScale;
+ sCoordRight = (tCoord - vec2(1.0, 0.0)) * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/rendernode.frag b/src/quick/scenegraph/shaders/rendernode.frag
new file mode 100644
index 0000000000..b4e9b0209c
--- /dev/null
+++ b/src/quick/scenegraph/shaders/rendernode.frag
@@ -0,0 +1,8 @@
+uniform lowp sampler2D tex;
+
+varying highp vec2 t;
+
+void main()
+{
+ gl_FragColor = texture2D(tex, t);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/rendernode.vert b/src/quick/scenegraph/shaders/rendernode.vert
new file mode 100644
index 0000000000..fbfe9ef8ae
--- /dev/null
+++ b/src/quick/scenegraph/shaders/rendernode.vert
@@ -0,0 +1,10 @@
+attribute highp vec4 av;
+attribute highp vec2 at;
+
+varying highp vec2 t;
+
+void main()
+{
+ gl_Position = av;
+ t = at;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/rendernode_core.frag b/src/quick/scenegraph/shaders/rendernode_core.frag
new file mode 100644
index 0000000000..7c187265df
--- /dev/null
+++ b/src/quick/scenegraph/shaders/rendernode_core.frag
@@ -0,0 +1,12 @@
+#version 150 core
+
+uniform sampler2D tex;
+
+in vec2 t;
+
+out vec4 color;
+
+void main()
+{
+ fragColor = texture(tex, t);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/rendernode_core.vert b/src/quick/scenegraph/shaders/rendernode_core.vert
new file mode 100644
index 0000000000..a76d519a5a
--- /dev/null
+++ b/src/quick/scenegraph/shaders/rendernode_core.vert
@@ -0,0 +1,12 @@
+#version 150 core
+
+in vec4 av;
+in vec2 at;
+
+out vec2 t;
+
+void main()
+{
+ gl_Position = av;
+ t = at;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothcolor.frag b/src/quick/scenegraph/shaders/smoothcolor.frag
new file mode 100644
index 0000000000..71de9dbfc2
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothcolor.frag
@@ -0,0 +1,6 @@
+varying lowp vec4 color;
+
+void main()
+{
+ gl_FragColor = color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothcolor.vert b/src/quick/scenegraph/shaders/smoothcolor.vert
new file mode 100644
index 0000000000..df70fea92a
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothcolor.vert
@@ -0,0 +1,45 @@
+uniform highp vec2 pixelSize;
+uniform highp mat4 matrix;
+uniform lowp float opacity;
+
+attribute highp vec4 vertex;
+attribute lowp vec4 vertexColor;
+attribute highp vec2 vertexOffset;
+
+varying lowp vec4 color;
+
+void main()
+{
+ highp vec4 pos = matrix * vertex;
+ gl_Position = pos;
+
+ if (vertexOffset.x != 0.) {
+ highp vec4 delta = matrix[0] * vertexOffset.x;
+ highp vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ highp vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ highp float numerator = dot(dir, ndir * pos.w * pos.w);
+ highp float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ }
+
+ if (vertexOffset.y != 0.) {
+ highp vec4 delta = matrix[1] * vertexOffset.y;
+ highp vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ highp vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ highp float numerator = dot(dir, ndir * pos.w * pos.w);
+ highp float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ }
+
+ color = vertexColor * opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothcolor_core.frag b/src/quick/scenegraph/shaders/smoothcolor_core.frag
new file mode 100644
index 0000000000..84533c2b40
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothcolor_core.frag
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 color;
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothcolor_core.vert b/src/quick/scenegraph/shaders/smoothcolor_core.vert
new file mode 100644
index 0000000000..1eed751ccd
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothcolor_core.vert
@@ -0,0 +1,47 @@
+#version 150 core
+
+in vec4 vertex;
+in vec4 vertexColor;
+in vec2 vertexOffset;
+
+out vec4 color;
+
+uniform vec2 pixelSize;
+uniform mat4 matrix;
+uniform float opacity;
+
+void main()
+{
+ vec4 pos = matrix * vertex;
+ gl_Position = pos;
+
+ if (vertexOffset.x != 0.) {
+ vec4 delta = matrix[0] * vertexOffset.x;
+ vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ float numerator = dot(dir, ndir * pos.w * pos.w);
+ float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ }
+
+ if (vertexOffset.y != 0.) {
+ vec4 delta = matrix[1] * vertexOffset.y;
+ vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ float numerator = dot(dir, ndir * pos.w * pos.w);
+ float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ }
+
+ color = vertexColor * opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothtexture.frag b/src/quick/scenegraph/shaders/smoothtexture.frag
new file mode 100644
index 0000000000..e4f6359f3d
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothtexture.frag
@@ -0,0 +1,9 @@
+uniform sampler2D qt_Texture;
+
+varying highp vec2 texCoord;
+varying lowp float vertexOpacity;
+
+void main()
+{
+ gl_FragColor = texture2D(qt_Texture, texCoord) * vertexOpacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothtexture.vert b/src/quick/scenegraph/shaders/smoothtexture.vert
new file mode 100644
index 0000000000..1ce824a68f
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothtexture.vert
@@ -0,0 +1,52 @@
+uniform highp vec2 pixelSize;
+uniform highp mat4 qt_Matrix;
+uniform lowp float opacity;
+
+attribute highp vec4 vertex;
+attribute highp vec2 multiTexCoord;
+attribute highp vec2 vertexOffset;
+attribute highp vec2 texCoordOffset;
+
+varying highp vec2 texCoord;
+varying lowp float vertexOpacity;
+
+void main()
+{
+ highp vec4 pos = qt_Matrix * vertex;
+ gl_Position = pos;
+ texCoord = multiTexCoord;
+
+ if (vertexOffset.x != 0.) {
+ highp vec4 delta = qt_Matrix[0] * vertexOffset.x;
+ highp vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ highp vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ highp float numerator = dot(dir, ndir * pos.w * pos.w);
+ highp float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ texCoord.x += scale * texCoordOffset.x;
+ }
+
+ if (vertexOffset.y != 0.) {
+ highp vec4 delta = qt_Matrix[1] * vertexOffset.y;
+ highp vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ highp vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ highp float numerator = dot(dir, ndir * pos.w * pos.w);
+ highp float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ texCoord.y += scale * texCoordOffset.y;
+ }
+
+ bool onEdge = any(notEqual(vertexOffset, vec2(0.)));
+ bool outerEdge = all(equal(texCoordOffset, vec2(0.)));
+ vertexOpacity = onEdge && outerEdge ? 0. : opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothtexture_core.frag b/src/quick/scenegraph/shaders/smoothtexture_core.frag
new file mode 100644
index 0000000000..8a9aefd4c8
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothtexture_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 texCoord;
+in float vertexOpacity;
+
+out vec4 fragColor;
+
+uniform sampler2D qt_Texture;
+
+void main()
+{
+ fragColor = texture(qt_Texture, texCoord) * vertexOpacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/smoothtexture_core.vert b/src/quick/scenegraph/shaders/smoothtexture_core.vert
new file mode 100644
index 0000000000..a2489a39c5
--- /dev/null
+++ b/src/quick/scenegraph/shaders/smoothtexture_core.vert
@@ -0,0 +1,54 @@
+#version 150 core
+
+in vec4 vertex;
+in vec2 multiTexCoord;
+in vec2 vertexOffset;
+in vec2 texCoordOffset;
+
+out vec2 texCoord;
+out float vertexOpacity;
+
+uniform vec2 pixelSize;
+uniform mat4 qt_Matrix;
+uniform float opacity;
+
+void main()
+{
+ vec4 pos = qt_Matrix * vertex;
+ gl_Position = pos;
+ texCoord = multiTexCoord;
+
+ if (vertexOffset.x != 0.) {
+ vec4 delta = qt_Matrix[0] * vertexOffset.x;
+ vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ float numerator = dot(dir, ndir * pos.w * pos.w);
+ float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ texCoord.x += scale * texCoordOffset.x;
+ }
+
+ if (vertexOffset.y != 0.) {
+ vec4 delta = qt_Matrix[1] * vertexOffset.y;
+ vec2 dir = delta.xy * pos.w - pos.xy * delta.w;
+ vec2 ndir = .5 * pixelSize * normalize(dir / pixelSize);
+ dir -= ndir * delta.w * pos.w;
+ float numerator = dot(dir, ndir * pos.w * pos.w);
+ float scale = 0.0;
+ if (numerator < 0.0)
+ scale = 1.0;
+ else
+ scale = min(1.0, numerator / dot(dir, dir));
+ gl_Position += scale * delta;
+ texCoord.y += scale * texCoordOffset.y;
+ }
+
+ bool onEdge = any(notEqual(vertexOffset, vec2(0.)));
+ bool outerEdge = all(equal(texCoordOffset, vec2(0.)));
+ vertexOpacity = onEdge && outerEdge ? 0. : opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/stencilclip.frag b/src/quick/scenegraph/shaders/stencilclip.frag
new file mode 100644
index 0000000000..70b7717977
--- /dev/null
+++ b/src/quick/scenegraph/shaders/stencilclip.frag
@@ -0,0 +1,4 @@
+void main()
+{
+ gl_FragColor = vec4(0.81, 0.83, 0.12, 1.0); // Trolltech green ftw!
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/stencilclip.vert b/src/quick/scenegraph/shaders/stencilclip.vert
new file mode 100644
index 0000000000..0e546c8112
--- /dev/null
+++ b/src/quick/scenegraph/shaders/stencilclip.vert
@@ -0,0 +1,8 @@
+attribute highp vec4 vCoord;
+
+uniform highp mat4 matrix;
+
+void main()
+{
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/stencilclip_core.frag b/src/quick/scenegraph/shaders/stencilclip_core.frag
new file mode 100644
index 0000000000..4d05de4ca9
--- /dev/null
+++ b/src/quick/scenegraph/shaders/stencilclip_core.frag
@@ -0,0 +1,8 @@
+#version 150 core
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(0.81, 0.83, 0.12, 1.0); // Trolltech green ftw!
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/stencilclip_core.vert b/src/quick/scenegraph/shaders/stencilclip_core.vert
new file mode 100644
index 0000000000..37e240c735
--- /dev/null
+++ b/src/quick/scenegraph/shaders/stencilclip_core.vert
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 vCoord;
+
+uniform mat4 matrix;
+
+void main()
+{
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/styledtext.frag b/src/quick/scenegraph/shaders/styledtext.frag
new file mode 100644
index 0000000000..662dbef2fc
--- /dev/null
+++ b/src/quick/scenegraph/shaders/styledtext.frag
@@ -0,0 +1,14 @@
+varying highp vec2 sampleCoord;
+varying highp vec2 shiftedSampleCoord;
+
+uniform sampler2D _qt_texture;
+uniform lowp vec4 color;
+uniform lowp vec4 styleColor;
+
+void main()
+{
+ lowp float glyph = texture2D(_qt_texture, sampleCoord).a;
+ lowp float style = clamp(texture2D(_qt_texture, shiftedSampleCoord).a - glyph,
+ 0.0, 1.0);
+ gl_FragColor = style * styleColor + glyph * color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/styledtext.vert b/src/quick/scenegraph/shaders/styledtext.vert
new file mode 100644
index 0000000000..3ad9497b65
--- /dev/null
+++ b/src/quick/scenegraph/shaders/styledtext.vert
@@ -0,0 +1,16 @@
+uniform highp mat4 matrix;
+uniform highp vec2 textureScale;
+uniform highp vec2 shift;
+
+attribute highp vec4 vCoord;
+attribute highp vec2 tCoord;
+
+varying highp vec2 sampleCoord;
+varying highp vec2 shiftedSampleCoord;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ shiftedSampleCoord = (tCoord - shift) * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/styledtext_core.frag b/src/quick/scenegraph/shaders/styledtext_core.frag
new file mode 100644
index 0000000000..50f64c64a2
--- /dev/null
+++ b/src/quick/scenegraph/shaders/styledtext_core.frag
@@ -0,0 +1,18 @@
+#version 150 core
+
+in vec2 sampleCoord;
+in vec2 shiftedSampleCoord;
+
+out vec4 color;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 styleColor;
+
+void main()
+{
+ float glyph = texture(_qt_texture, sampleCoord).a;
+ float style = clamp(texture(_qt_texture, shiftedSampleCoord).r - glyph,
+ 0.0, 1.0);
+ fragColor = style * styleColor + glyph * color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/styledtext_core.vert b/src/quick/scenegraph/shaders/styledtext_core.vert
new file mode 100644
index 0000000000..b7a3ecc667
--- /dev/null
+++ b/src/quick/scenegraph/shaders/styledtext_core.vert
@@ -0,0 +1,18 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+out vec2 shiftedSampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+uniform vec2 shift;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ shiftedSampleCoord = (tCoord - shift) * textureScale;
+ gl_Position = matrix * vCoord;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/textmask.frag b/src/quick/scenegraph/shaders/textmask.frag
new file mode 100644
index 0000000000..7715688ecc
--- /dev/null
+++ b/src/quick/scenegraph/shaders/textmask.frag
@@ -0,0 +1,10 @@
+varying highp vec2 sampleCoord;
+
+uniform sampler2D _qt_texture;
+uniform lowp vec4 color;
+
+void main()
+{
+ lowp vec4 glyph = texture2D(_qt_texture, sampleCoord);
+ gl_FragColor = vec4(glyph.rgb * color.a, glyph.a);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/textmask.vert b/src/quick/scenegraph/shaders/textmask.vert
new file mode 100644
index 0000000000..1f45e9cf71
--- /dev/null
+++ b/src/quick/scenegraph/shaders/textmask.vert
@@ -0,0 +1,13 @@
+uniform highp mat4 matrix;
+uniform highp vec2 textureScale;
+
+attribute highp vec4 vCoord;
+attribute highp vec2 tCoord;
+
+varying highp vec2 sampleCoord;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+}
diff --git a/src/quick/scenegraph/shaders/textmask_core.frag b/src/quick/scenegraph/shaders/textmask_core.frag
new file mode 100644
index 0000000000..17dda53c97
--- /dev/null
+++ b/src/quick/scenegraph/shaders/textmask_core.frag
@@ -0,0 +1,14 @@
+#version 150 core
+
+in vec2 sampleCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+
+void main()
+{
+ vec4 glyph = texture(_qt_texture, sampleCoord);
+ fragColor = vec4(glyph.rgb * color.a, glyph.a);
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/textmask_core.vert b/src/quick/scenegraph/shaders/textmask_core.vert
new file mode 100644
index 0000000000..619248dccb
--- /dev/null
+++ b/src/quick/scenegraph/shaders/textmask_core.vert
@@ -0,0 +1,15 @@
+#version 150 core
+
+in vec4 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+
+uniform mat4 matrix;
+uniform vec2 textureScale;
+
+void main()
+{
+ sampleCoord = tCoord * textureScale;
+ gl_Position = matrix * vCoord;
+}
diff --git a/src/quick/scenegraph/shaders/texture.frag b/src/quick/scenegraph/shaders/texture.frag
new file mode 100644
index 0000000000..2d97f2e66a
--- /dev/null
+++ b/src/quick/scenegraph/shaders/texture.frag
@@ -0,0 +1,9 @@
+varying highp vec2 qt_TexCoord;
+
+uniform sampler2D qt_Texture;
+uniform lowp float opacity;
+
+void main()
+{
+ gl_FragColor = texture2D(qt_Texture, qt_TexCoord) * opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/texture_core.frag b/src/quick/scenegraph/shaders/texture_core.frag
new file mode 100644
index 0000000000..d9bdf6a238
--- /dev/null
+++ b/src/quick/scenegraph/shaders/texture_core.frag
@@ -0,0 +1,13 @@
+#version 150 core
+
+in vec2 qt_TexCoord;
+
+out vec4 fragColor;
+
+uniform sampler2D qt_Texture;
+uniform float opacity;
+
+void main()
+{
+ fragColor = texture(qt_Texture, qt_TexCoord) * opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/vertexcolor.frag b/src/quick/scenegraph/shaders/vertexcolor.frag
new file mode 100644
index 0000000000..71de9dbfc2
--- /dev/null
+++ b/src/quick/scenegraph/shaders/vertexcolor.frag
@@ -0,0 +1,6 @@
+varying lowp vec4 color;
+
+void main()
+{
+ gl_FragColor = color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/vertexcolor.vert b/src/quick/scenegraph/shaders/vertexcolor.vert
new file mode 100644
index 0000000000..750d520114
--- /dev/null
+++ b/src/quick/scenegraph/shaders/vertexcolor.vert
@@ -0,0 +1,13 @@
+attribute highp vec4 vertexCoord;
+attribute highp vec4 vertexColor;
+
+uniform highp mat4 matrix;
+uniform highp float opacity;
+
+varying lowp vec4 color;
+
+void main()
+{
+ gl_Position = matrix * vertexCoord;
+ color = vertexColor * opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/vertexcolor_core.frag b/src/quick/scenegraph/shaders/vertexcolor_core.frag
new file mode 100644
index 0000000000..84533c2b40
--- /dev/null
+++ b/src/quick/scenegraph/shaders/vertexcolor_core.frag
@@ -0,0 +1,10 @@
+#version 150 core
+
+in vec4 color;
+
+out vec4 fragColor;
+
+void main()
+{
+ fragColor = color;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/shaders/vertexcolor_core.vert b/src/quick/scenegraph/shaders/vertexcolor_core.vert
new file mode 100644
index 0000000000..219b840913
--- /dev/null
+++ b/src/quick/scenegraph/shaders/vertexcolor_core.vert
@@ -0,0 +1,15 @@
+#version 150 core
+
+in vec4 vertexCoord;
+in vec4 vertexColor;
+
+out vec4 color;
+
+uniform mat4 matrix;
+uniform float opacity;
+
+void main()
+{
+ gl_Position = matrix * vertexCoord;
+ color = vertexColor * opacity;
+} \ No newline at end of file
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 3710f05b9a..8678d106ff 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -47,11 +47,14 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
+#include <QtGui/QSurface>
#include <private/qsgtexture_p.h>
#include <private/qqmlprofilerservice_p.h>
+QT_BEGIN_NAMESPACE
+
#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif
@@ -89,26 +92,36 @@ static int qsg_envInt(const char *name, int defaultValue)
Manager::Manager()
: m_atlas(0)
{
- QSize screenSize = QGuiApplication::primaryScreen()->geometry().size();
+ QOpenGLContext *gl = QOpenGLContext::currentContext();
+ Q_ASSERT(gl);
+ QSurface *surface = gl->surface();
+ QSize surfaceSize = surface->size();
int max;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
- int w = qMin(max, qsg_envInt("QSG_ATLAS_WIDTH", qsg_powerOfTwo(screenSize.width())));
- int h = qMin(max, qsg_envInt("QSG_ATLAS_HEIGHT", qsg_powerOfTwo(screenSize.height())));
+
+ int w = qMin(max, qsg_envInt("QSG_ATLAS_WIDTH", qMax(512, qsg_powerOfTwo(surfaceSize.width()))));
+ int h = qMin(max, qsg_envInt("QSG_ATLAS_HEIGHT", qMax(512, qsg_powerOfTwo(surfaceSize.height()))));
m_atlas_size_limit = qsg_envInt("QSG_ATLAS_SIZE_LIMIT", qMax(w, h) / 2);
m_atlas_size = QSize(w, h);
+
+ if (qEnvironmentVariableIsSet("QSG_INFO"))
+ qDebug() << "QSG: texture atlas dimensions:" << w << "x" << h;
}
Manager::~Manager()
{
- invalidate();
+ Q_ASSERT(m_atlas == 0);
}
void Manager::invalidate()
{
- delete m_atlas;
- m_atlas = 0;
+ if (m_atlas) {
+ m_atlas->invalidate();
+ m_atlas->deleteLater();
+ m_atlas = 0;
+ }
}
QSGTexture *Manager::create(const QImage &image)
@@ -118,10 +131,7 @@ QSGTexture *Manager::create(const QImage &image)
if (!m_atlas)
m_atlas = new Atlas(m_atlas_size);
t = m_atlas->create(image);
- if (t)
- return t;
}
-
return t;
}
@@ -139,6 +149,11 @@ Atlas::Atlas(const QSize &size)
|| strstr(ext, "GL_EXT_texture_format_BGRA8888")
|| strstr(ext, "GL_IMG_texture_format_BGRA8888")) {
m_internalFormat = m_externalFormat = GL_BGRA;
+#ifdef Q_OS_IOS
+ } else if (strstr(ext, "GL_APPLE_texture_format_BGRA8888")) {
+ m_internalFormat = GL_RGBA;
+ m_externalFormat = GL_BGRA;
+#endif
} else {
m_internalFormat = m_externalFormat = GL_RGBA;
}
@@ -153,13 +168,21 @@ Atlas::Atlas(const QSize &size)
Atlas::~Atlas()
{
- if (m_texture_id)
- glDeleteTextures(1, &m_texture_id);
+ Q_ASSERT(!m_texture_id);
}
+void Atlas::invalidate()
+{
+ Q_ASSERT(QOpenGLContext::currentContext());
+ if (m_texture_id) {
+ glDeleteTextures(1, &m_texture_id);
+ m_texture_id = 0;
+ }
+}
Texture *Atlas::create(const QImage &image)
{
+ // No need to lock, as manager already locked it.
QRect rect = m_allocator.allocate(QSize(image.width() + 2, image.height() + 2));
if (rect.width() > 0 && rect.height() > 0) {
Texture *t = new Texture(this, rect, image);
@@ -293,6 +316,9 @@ bool Atlas::bind(QSGTexture::Filtering filtering)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#if !defined(QT_OPENGL_ES_2)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+#endif
glTexImage2D(GL_TEXTURE_2D, 0, m_internalFormat, m_size.width(), m_size.height(), 0, m_externalFormat, GL_UNSIGNED_BYTE, 0);
#if 0
@@ -383,7 +409,6 @@ void Atlas::remove(Texture *t)
{
QRect atlasRect = t->atlasSubRect();
m_allocator.deallocate(atlasRect);
-
m_pending_uploads.removeOne(t);
}
@@ -428,3 +453,5 @@ QSGTexture *Texture::removedFromAtlas() const
}
}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h
index f8edd96f47..ade7b8f00e 100644
--- a/src/quick/scenegraph/util/qsgatlastexture_p.h
+++ b/src/quick/scenegraph/util/qsgatlastexture_p.h
@@ -50,6 +50,8 @@
#include <QtQuick/private/qsgtexture_p.h>
#include <QtQuick/private/qsgareaallocator_p.h>
+QT_BEGIN_NAMESPACE
+
namespace QSGAtlasTexture
{
@@ -69,19 +71,18 @@ public:
private:
Atlas *m_atlas;
- Atlas *m_secondary_atlas;
QSize m_atlas_size;
int m_atlas_size_limit;
};
-class Atlas
+class Atlas : public QObject
{
public:
Atlas(const QSize &size);
~Atlas();
- void initialize();
+ void invalidate();
int textureId() const;
bool bind(QSGTexture::Filtering filteing);
@@ -95,7 +96,6 @@ public:
QSize size() const { return m_size; }
private:
-
QSGAreaAllocator m_allocator;
GLuint m_texture_id;
QSize m_size;
@@ -153,4 +153,6 @@ private:
}
+QT_END_NAMESPACE
+
#endif
diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
index 83264e2930..c603c62a20 100644
--- a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
+++ b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qsgflatcolormaterial.h"
+#include <private/qsgmaterialshader_p.h>
#include <qopenglshaderprogram.h>
@@ -48,6 +49,8 @@ QT_BEGIN_NAMESPACE
class FlatColorMaterialShader : public QSGMaterialShader
{
public:
+ FlatColorMaterialShader();
+
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
virtual char const *const *attributeNames() const;
@@ -55,8 +58,6 @@ public:
private:
virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
int m_matrix_id;
int m_color_id;
@@ -64,6 +65,13 @@ private:
QSGMaterialType FlatColorMaterialShader::type;
+FlatColorMaterialShader::FlatColorMaterialShader()
+ : QSGMaterialShader(*new QSGMaterialShaderPrivate)
+{
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/flatcolor.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/flatcolor.frag"));
+}
+
void FlatColorMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
{
Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
@@ -98,23 +106,6 @@ void FlatColorMaterialShader::initialize()
m_color_id = program()->uniformLocation("color");
}
-const char *FlatColorMaterialShader::vertexShader() const {
- return
- "attribute highp vec4 vCoord; \n"
- "uniform highp mat4 matrix; \n"
- "void main() { \n"
- " gl_Position = matrix * vCoord; \n"
- "}";
-}
-
-const char *FlatColorMaterialShader::fragmentShader() const {
- return
- "uniform lowp vec4 color; \n"
- "void main() { \n"
- " gl_FragColor = color; \n"
- "}";
-}
-
/*!
diff --git a/src/quick/scenegraph/util/qsgpainternode.cpp b/src/quick/scenegraph/util/qsgpainternode.cpp
index d6bec550d3..797fc4d145 100644
--- a/src/quick/scenegraph/util/qsgpainternode.cpp
+++ b/src/quick/scenegraph/util/qsgpainternode.cpp
@@ -111,7 +111,7 @@ QSGPainterNode::QSGPainterNode(QQuickPaintedItem *item)
, m_dirtyRenderTarget(false)
, m_dirtyTexture(false)
{
- m_context = static_cast<QQuickPaintedItemPrivate *>(QObjectPrivate::get(item))->sceneGraphContext();
+ m_context = static_cast<QQuickPaintedItemPrivate *>(QObjectPrivate::get(item))->sceneGraphRenderContext();
setMaterial(&m_materialO);
setOpaqueMaterial(&m_material);
@@ -260,7 +260,7 @@ void QSGPainterNode::updateRenderTarget()
if (m_actualRenderTarget == QQuickPaintedItem::FramebufferObject ||
m_actualRenderTarget == QQuickPaintedItem::InvertedYFramebufferObject) {
- const QOpenGLContext *ctx = m_context->glContext();
+ const QOpenGLContext *ctx = m_context->openglContext();
if (m_fbo && !m_dirtyGeometry && (!ctx->format().samples() || !m_multisamplingSupported))
return;
@@ -323,7 +323,7 @@ void QSGPainterNode::updateFBOSize()
fboWidth = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qt_next_power_of_two(m_size.width()));
fboHeight = qMax(QT_MINIMUM_DYNAMIC_FBO_SIZE, qt_next_power_of_two(m_size.height()));
} else {
- QSize minimumFBOSize = m_context->minimumFBOSize();
+ QSize minimumFBOSize = m_context->sceneGraphContext()->minimumFBOSize();
fboWidth = qMax(minimumFBOSize.width(), m_size.width());
fboHeight = qMax(minimumFBOSize.height(), m_size.height());
}
diff --git a/src/quick/scenegraph/util/qsgpainternode_p.h b/src/quick/scenegraph/util/qsgpainternode_p.h
index bc1556672c..df0943d38e 100644
--- a/src/quick/scenegraph/util/qsgpainternode_p.h
+++ b/src/quick/scenegraph/util/qsgpainternode_p.h
@@ -113,7 +113,7 @@ private:
void updateRenderTarget();
void updateFBOSize();
- QSGContext *m_context;
+ QSGRenderContext *m_context;
QQuickPaintedItem::RenderTarget m_preferredRenderTarget;
QQuickPaintedItem::RenderTarget m_actualRenderTarget;
diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
new file mode 100644
index 0000000000..1a1963dbca
--- /dev/null
+++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp
@@ -0,0 +1,403 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQuick module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgshadersourcebuilder_p.h"
+
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qopenglshaderprogram.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QSGShaderParser {
+
+struct Tokenizer {
+
+ enum Token {
+ Token_Invalid,
+ Token_Void,
+ Token_OpenBrace,
+ Token_CloseBrace,
+ Token_SemiColon,
+ Token_Identifier,
+ Token_Macro,
+ Token_Version,
+ Token_Extension,
+ Token_SingleLineComment,
+ Token_MultiLineCommentStart,
+ Token_MultiLineCommentEnd,
+ Token_NewLine,
+ Token_Unspecified,
+ Token_EOF
+ };
+
+ static const char *NAMES[];
+
+ void initialize(const char *input);
+ Token next();
+
+ const char *stream;
+ const char *pos;
+ const char *identifier;
+};
+
+const char *Tokenizer::NAMES[] = {
+ "Invalid",
+ "Void",
+ "OpenBrace",
+ "CloseBrace",
+ "SemiColon",
+ "Identifier",
+ "Macro",
+ "Version",
+ "Extension",
+ "SingleLineComment",
+ "MultiLineCommentStart",
+ "MultiLineCommentEnd",
+ "NewLine",
+ "Unspecified",
+ "EOF"
+};
+
+void Tokenizer::initialize(const char *input)
+{
+ stream = input;
+ pos = input;
+ identifier = input;
+}
+
+Tokenizer::Token Tokenizer::next()
+{
+ while (*pos != 0) {
+ char c = *pos++;
+ switch (c) {
+ case '/':
+ if (*pos == '/') {
+ // '//' comment
+ return Token_SingleLineComment;
+ } else if (*pos == '*') {
+ // /* */ comment
+ return Token_MultiLineCommentStart;
+ }
+ break;
+
+ case '*':
+ if (*pos == '/')
+ return Token_MultiLineCommentEnd;
+
+ case '\n':
+ return Token_NewLine;
+
+ case '\r':
+ if (*pos == '\n')
+ return Token_NewLine;
+
+ case '#': {
+ if (*pos == 'v' && pos[1] == 'e' && pos[2] == 'r' && pos[3] == 's'
+ && pos[4] == 'i' && pos[5] == 'o' && pos[6] == 'n') {
+ return Token_Version;
+ } else if (*pos == 'e' && pos[1] == 'x' && pos[2] == 't' && pos[3] == 'e'
+ && pos[4] == 'n' && pos[5] == 's' && pos[6] == 'i'&& pos[7] == 'o'
+ && pos[8] == 'n') {
+ return Token_Extension;
+ } else {
+ while (*pos != 0) {
+ if (*pos == '\n') {
+ ++pos;
+ break;
+ } else if (*pos == '\\') {
+ ++pos;
+ while (*pos != 0 && (*pos == ' ' || *pos == '\t'))
+ ++pos;
+ if (*pos != 0 && (*pos == '\n' || (*pos == '\r' && pos[1] == '\n')))
+ pos+=2;
+ } else {
+ ++pos;
+ }
+ }
+ }
+ break;
+ }
+
+ case ';':
+ return Token_SemiColon;
+
+ case 0:
+ return Token_EOF;
+
+ case '{':
+ return Token_OpenBrace;
+
+ case '}':
+ return Token_CloseBrace;
+
+ case ' ':
+ break;
+
+ case 'v': {
+ if (*pos == 'o' && pos[1] == 'i' && pos[2] == 'd') {
+ pos += 3;
+ return Token_Void;
+ }
+ // Fall-thru
+ }
+ default:
+ // Identifier...
+ if ((c >= 'a' && c <= 'z' ) || (c >= 'A' && c <= 'Z' ) || c == '_') {
+ identifier = pos - 1;
+ while (*pos != 0 && ((*pos >= 'a' && *pos <= 'z')
+ || (*pos >= 'A' && *pos <= 'Z')
+ || *pos == '_'
+ || (*pos >= '0' && *pos <= '9'))) {
+ ++pos;
+ }
+ return Token_Identifier;
+ } else {
+ return Token_Unspecified;
+ }
+ }
+ }
+
+ return Token_Invalid;
+}
+
+} // namespace QSGShaderParser
+
+using namespace QSGShaderParser;
+
+QSGShaderSourceBuilder::QSGShaderSourceBuilder()
+{
+}
+
+void QSGShaderSourceBuilder::initializeProgramFromFiles(QOpenGLShaderProgram *program,
+ const QString &vertexShader,
+ const QString &fragmentShader)
+{
+ Q_ASSERT(program);
+ program->removeAllShaders();
+
+ QSGShaderSourceBuilder builder;
+
+ builder.appendSourceFile(vertexShader);
+ program->addShaderFromSourceCode(QOpenGLShader::Vertex, builder.source());
+ builder.clear();
+
+ builder.appendSourceFile(fragmentShader);
+ program->addShaderFromSourceCode(QOpenGLShader::Fragment, builder.source());
+}
+
+QByteArray QSGShaderSourceBuilder::source() const
+{
+ return m_source;
+}
+
+void QSGShaderSourceBuilder::clear()
+{
+ m_source.clear();
+}
+
+void QSGShaderSourceBuilder::appendSource(const QByteArray &source)
+{
+ m_source += source;
+}
+
+void QSGShaderSourceBuilder::appendSourceFile(const QString &fileName)
+{
+ const QString resolvedFileName = resolveShaderPath(fileName);
+ QFile f(resolvedFileName);
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning() << "Failed to find shader" << resolvedFileName;
+ return;
+ }
+ m_source += f.readAll();
+}
+
+void QSGShaderSourceBuilder::addDefinition(const QByteArray &definition)
+{
+ if (definition.isEmpty())
+ return;
+
+ Tokenizer tok;
+ const char *input = m_source.constData();
+ tok.initialize(input);
+
+ // First find #version, #extension's and "void main() { ... "
+ const char *versionPos = 0;
+ const char *extensionPos = 0;
+ bool inSingleLineComment = false;
+ bool inMultiLineComment = false;
+ bool foundVersionStart = false;
+ bool foundExtensionStart = false;
+
+ Tokenizer::Token lt = Tokenizer::Token_Unspecified;
+ Tokenizer::Token t = tok.next();
+ while (t != Tokenizer::Token_EOF) {
+ // Handle comment blocks
+ if (t == Tokenizer::Token_MultiLineCommentStart )
+ inMultiLineComment = true;
+ if (t == Tokenizer::Token_MultiLineCommentEnd)
+ inMultiLineComment = false;
+ if (t == Tokenizer::Token_SingleLineComment)
+ inSingleLineComment = true;
+ if (t == Tokenizer::Token_NewLine && inSingleLineComment && !inMultiLineComment)
+ inSingleLineComment = false;
+
+ // Have we found #version, #extension or void main()?
+ if (t == Tokenizer::Token_Version && !inSingleLineComment && !inMultiLineComment)
+ foundVersionStart = true;
+
+ if (t == Tokenizer::Token_Extension && !inSingleLineComment && !inMultiLineComment)
+ foundExtensionStart = true;
+
+ if (foundVersionStart && t == Tokenizer::Token_NewLine) {
+ versionPos = tok.pos;
+ foundVersionStart = false;
+ } else if (foundExtensionStart && t == Tokenizer::Token_NewLine) {
+ extensionPos = tok.pos;
+ foundExtensionStart = false;
+ } else if (lt == Tokenizer::Token_Void && t == Tokenizer::Token_Identifier) {
+ if (qstrncmp("main", tok.identifier, 4) == 0)
+ break;
+ }
+
+ // Scan to next token
+ lt = t;
+ t = tok.next();
+ }
+
+ // Determine where to insert the definition.
+ // If we found #extension directives, insert after last one,
+ // else, if we found #version insert after #version
+ // otherwise, insert at beginning.
+ const char *insertionPos = extensionPos ? extensionPos : (versionPos ? versionPos : input);
+
+ // Construct a new shader string, inserting the definition
+ QByteArray newSource;
+ newSource.reserve(m_source.size() + definition.size() + 9);
+ newSource += QByteArray::fromRawData(input, insertionPos - input);
+ newSource += QByteArrayLiteral("#define ") + definition + QByteArrayLiteral("\n");
+ newSource += QByteArray::fromRawData(insertionPos, m_source.size() - (insertionPos - input));
+
+ m_source = newSource;
+}
+
+void QSGShaderSourceBuilder::removeVersion()
+{
+ Tokenizer tok;
+ const char *input = m_source.constData();
+ tok.initialize(input);
+
+ // First find #version beginning and end (if present)
+ const char *versionStartPos = 0;
+ const char *versionEndPos = 0;
+ bool inSingleLineComment = false;
+ bool inMultiLineComment = false;
+ bool foundVersionStart = false;
+
+ Tokenizer::Token lt = Tokenizer::Token_Unspecified;
+ Tokenizer::Token t = tok.next();
+ while (t != Tokenizer::Token_EOF) {
+ // Handle comment blocks
+ if (t == Tokenizer::Token_MultiLineCommentStart )
+ inMultiLineComment = true;
+ if (t == Tokenizer::Token_MultiLineCommentEnd)
+ inMultiLineComment = false;
+ if (t == Tokenizer::Token_SingleLineComment)
+ inSingleLineComment = true;
+ if (t == Tokenizer::Token_NewLine && inSingleLineComment && !inMultiLineComment)
+ inSingleLineComment = false;
+
+ // Have we found #version, #extension or void main()?
+ if (t == Tokenizer::Token_Version && !inSingleLineComment && !inMultiLineComment) {
+ versionStartPos = tok.pos - 1;
+ foundVersionStart = true;
+ } else if (foundVersionStart && t == Tokenizer::Token_NewLine) {
+ versionEndPos = tok.pos;
+ break;
+ } else if (lt == Tokenizer::Token_Void && t == Tokenizer::Token_Identifier) {
+ if (qstrncmp("main", tok.identifier, 4) == 0)
+ break;
+ }
+
+ // Scan to next token
+ lt = t;
+ t = tok.next();
+ }
+
+ if (versionStartPos == 0)
+ return;
+
+ // Construct a new shader string, inserting the definition
+ QByteArray newSource;
+ newSource.reserve(m_source.size() - (versionEndPos - versionStartPos));
+ newSource += QByteArray::fromRawData(input, versionStartPos - input);
+ newSource += QByteArray::fromRawData(versionEndPos, m_source.size() - (versionEndPos - versionStartPos));
+
+ m_source = newSource;
+}
+
+QString QSGShaderSourceBuilder::resolveShaderPath(const QString &path) const
+{
+ if (contextProfile() != QSurfaceFormat::CoreProfile) {
+ return path;
+ } else {
+ int idx = path.lastIndexOf(QStringLiteral("."));
+ QString resolvedPath;
+ if (idx != -1)
+ resolvedPath = path.left(idx)
+ + QStringLiteral("_core")
+ + path.right(path.length() - idx);
+ return resolvedPath;
+ }
+}
+
+QSurfaceFormat::OpenGLContextProfile QSGShaderSourceBuilder::contextProfile() const
+{
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ QSurfaceFormat::OpenGLContextProfile profile = QSurfaceFormat::NoProfile;
+ Q_ASSERT(context);
+ profile = context->format().profile();
+ return profile;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgflashnode.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
index 7fbe673e15..63f2d78767 100644
--- a/src/quick/scenegraph/qsgflashnode.cpp
+++ b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -39,24 +39,44 @@
**
****************************************************************************/
-#include "qsgflashnode_p.h"
+#ifndef QSGSHADERSOURCEBUILDER_P_H
+#define QSGSHADERSOURCEBUILDER_P_H
+
+#include <private/qtquickglobal_p.h>
+
+#include <QtGui/qsurfaceformat.h>
+#include <QtCore/qbytearray.h>
QT_BEGIN_NAMESPACE
-QSGFlashNode::QSGFlashNode()
- : m_counter(1)
-{
- setFlag(UsePreprocess);
- setColor(QColor(rand()%56 + 200, rand()%56 + 200, rand()%156 + 100)); // A random, mostly yellow, color
-}
+class QOpenGLShaderProgram;
-void QSGFlashNode::preprocess()
+class Q_QUICK_PRIVATE_EXPORT QSGShaderSourceBuilder
{
- if (m_counter) {
- --m_counter;
- } else {
- delete this;
- }
-}
+public:
+ QSGShaderSourceBuilder();
+
+ static void initializeProgramFromFiles(QOpenGLShaderProgram *program,
+ const QString &vertexShader,
+ const QString &fragmentShader);
+
+ QByteArray source() const;
+ void clear();
+
+ void appendSource(const QByteArray &source);
+ void appendSourceFile(const QString &fileName);
+ void addDefinition(const QByteArray &definition);
+ void removeVersion();
+
+protected:
+ virtual QString resolveShaderPath(const QString &path) const;
+
+private:
+ QSurfaceFormat::OpenGLContextProfile contextProfile() const;
+
+ QByteArray m_source;
+};
QT_END_NAMESPACE
+
+#endif // QSGSHADERSOURCEBUILDER_P_H
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index b079100a37..51b3bafaf7 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -682,16 +682,21 @@ void QSGPlainTexture::bind()
GLenum externalFormat = GL_RGBA;
GLenum internalFormat = GL_RGBA;
- const char *extensions = (const char *) glGetString(GL_EXTENSIONS);
- if (strstr(extensions, "GL_EXT_bgra")) {
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ if (context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"))) {
externalFormat = GL_BGRA;
#ifdef QT_OPENGL_ES
internalFormat = GL_BGRA;
#endif
- } else if (strstr(extensions, "GL_EXT_texture_format_BGRA8888")
- || strstr(extensions, "GL_IMG_texture_format_BGRA8888")) {
+ } else if (context->hasExtension(QByteArrayLiteral("GL_EXT_texture_format_BGRA8888"))
+ || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888"))) {
externalFormat = GL_BGRA;
internalFormat = GL_BGRA;
+#ifdef Q_OS_IOS
+ } else if (context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) {
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGBA;
+#endif
} else {
qsg_swizzleBGRAToRGBA(&tmp);
}
@@ -711,8 +716,7 @@ void QSGPlainTexture::bind()
if (m_has_mipmaps) {
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
+ context->functions()->glGenerateMipmap(GL_TEXTURE_2D);
m_mipmaps_generated = true;
}
diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp
index ba98c83682..df55404504 100644
--- a/src/quick/scenegraph/util/qsgtexturematerial.cpp
+++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp
@@ -54,36 +54,15 @@ inline static bool isPowerOfTwo(int x)
}
#endif
-const char qt_scenegraph_texture_material_vertex_code[] =
- "uniform highp mat4 qt_Matrix; \n"
- "attribute highp vec4 qt_VertexPosition; \n"
- "attribute highp vec2 qt_VertexTexCoord; \n"
- "varying highp vec2 qt_TexCoord; \n"
- "void main() { \n"
- " qt_TexCoord = qt_VertexTexCoord; \n"
- " gl_Position = qt_Matrix * qt_VertexPosition; \n"
- "}";
-
-const char qt_scenegraph_texture_material_fragment[] =
- "varying highp vec2 qt_TexCoord; \n"
- "uniform sampler2D qt_Texture; \n"
- "void main() { \n"
- " gl_FragColor = texture2D(qt_Texture, qt_TexCoord);\n"
- "}";
-
-
-const char *QSGOpaqueTextureMaterialShader::vertexShader() const
-{
- return qt_scenegraph_texture_material_vertex_code;
-}
+QSGMaterialType QSGOpaqueTextureMaterialShader::type;
-const char *QSGOpaqueTextureMaterialShader::fragmentShader() const
+QSGOpaqueTextureMaterialShader::QSGOpaqueTextureMaterialShader()
+ : QSGMaterialShader()
{
- return qt_scenegraph_texture_material_fragment;
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/opaquetexture.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/opaquetexture.frag"));
}
-QSGMaterialType QSGOpaqueTextureMaterialShader::type;
-
char const *const *QSGOpaqueTextureMaterialShader::attributeNames() const
{
static char const *const attr[] = { "qt_VertexPosition", "qt_VertexTexCoord", 0 };
@@ -353,14 +332,6 @@ int QSGOpaqueTextureMaterial::compare(const QSGMaterial *o) const
a material in the scene graph.
*/
-static const char qt_scenegraph_texture_material_opacity_fragment[] =
- "varying highp vec2 qt_TexCoord; \n"
- "uniform sampler2D qt_Texture; \n"
- "uniform lowp float opacity; \n"
- "void main() { \n"
- " gl_FragColor = texture2D(qt_Texture, qt_TexCoord) * opacity; \n"
- "}";
-
QSGMaterialType QSGTextureMaterialShader::type;
@@ -385,6 +356,12 @@ QSGMaterialShader *QSGTextureMaterial::createShader() const
return new QSGTextureMaterialShader;
}
+QSGTextureMaterialShader::QSGTextureMaterialShader()
+ : QSGOpaqueTextureMaterialShader()
+{
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/texture.frag"));
+}
+
void QSGTextureMaterialShader::updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
{
Q_ASSERT(oldEffect == 0 || newEffect->type() == oldEffect->type());
@@ -400,9 +377,4 @@ void QSGTextureMaterialShader::initialize()
m_opacity_id = program()->uniformLocation("opacity");
}
-const char *QSGTextureMaterialShader::fragmentShader() const
-{
- return qt_scenegraph_texture_material_opacity_fragment;
-}
-
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgtexturematerial_p.h b/src/quick/scenegraph/util/qsgtexturematerial_p.h
index 077337d211..db65d85738 100644
--- a/src/quick/scenegraph/util/qsgtexturematerial_p.h
+++ b/src/quick/scenegraph/util/qsgtexturematerial_p.h
@@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE
class Q_QUICK_PRIVATE_EXPORT QSGOpaqueTextureMaterialShader : public QSGMaterialShader
{
public:
+ QSGOpaqueTextureMaterialShader();
+
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
virtual char const *const *attributeNames() const;
@@ -57,8 +59,6 @@ public:
protected:
virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
int m_matrix_id;
};
@@ -66,14 +66,14 @@ protected:
class QSGTextureMaterialShader : public QSGOpaqueTextureMaterialShader
{
public:
+ QSGTextureMaterialShader();
+
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
virtual void initialize();
static QSGMaterialType type;
protected:
- virtual const char *fragmentShader() const;
-
int m_opacity_id;
};
diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
index f205f34ce4..ef2455f702 100644
--- a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
+++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
@@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE
class QSGVertexColorMaterialShader : public QSGMaterialShader
{
public:
+ QSGVertexColorMaterialShader();
+
virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
virtual char const *const *attributeNames() const;
@@ -55,8 +57,6 @@ public:
private:
virtual void initialize();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
int m_matrix_id;
int m_opacity_id;
@@ -64,6 +64,13 @@ private:
QSGMaterialType QSGVertexColorMaterialShader::type;
+QSGVertexColorMaterialShader::QSGVertexColorMaterialShader()
+ : QSGMaterialShader()
+{
+ setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/scenegraph/shaders/vertexcolor.vert"));
+ setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/scenegraph/shaders/vertexcolor.frag"));
+}
+
void QSGVertexColorMaterialShader::updateState(const RenderState &state, QSGMaterial * /*newEffect*/, QSGMaterial *)
{
if (state.isOpacityDirty())
@@ -85,28 +92,6 @@ void QSGVertexColorMaterialShader::initialize()
m_opacity_id = program()->uniformLocation("opacity");
}
-const char *QSGVertexColorMaterialShader::vertexShader() const {
- return
- "attribute highp vec4 vertexCoord; \n"
- "attribute highp vec4 vertexColor; \n"
- "uniform highp mat4 matrix; \n"
- "uniform highp float opacity; \n"
- "varying lowp vec4 color; \n"
- "void main() { \n"
- " gl_Position = matrix * vertexCoord; \n"
- " color = vertexColor * opacity; \n"
- "}";
-}
-
-const char *QSGVertexColorMaterialShader::fragmentShader() const {
- return
- "varying lowp vec4 color; \n"
- "void main() { \n"
- " gl_FragColor = color; \n"
- "}";
-}
-
-
/*!
\class QSGVertexColorMaterial
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index 6a762bea68..f743acc249 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -673,7 +673,7 @@ QQuickAbstractAnimation::ThreadingModel QQuickAbstractAnimation::threadingModel(
}
\endcode
- \sa {Animation and Transitions in Qt Quick}, {qml/animation/basics}{Animation basics example}
+ \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
QQuickPauseAnimation::QQuickPauseAnimation(QObject *parent)
: QQuickAbstractAnimation(*(new QQuickPauseAnimationPrivate), parent)
@@ -752,7 +752,7 @@ QAbstractAnimationJob* QQuickPauseAnimation::transition(QQuickStateActions &acti
\l{PropertyAnimation::}{properties} are explicitly set for the animation,
then those are used instead.
- \sa {Animation and Transitions in Qt Quick}, {qml/animation/basics}{Animation basics example}
+ \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
QQuickColorAnimation::QQuickColorAnimation(QObject *parent)
: QQuickPropertyAnimation(parent)
@@ -1275,7 +1275,7 @@ QAbstractAnimationJob* QQuickPropertyAction::transition(QQuickStateActions &acti
changes in the number value that it is tracking. If this is the case, use
SmoothedAnimation instead.
- \sa {Animation and Transitions in Qt Quick}, {qml/animation/basics}{Animation basics example}
+ \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
QQuickNumberAnimation::QQuickNumberAnimation(QObject *parent)
: QQuickPropertyAnimation(parent)
@@ -1378,7 +1378,7 @@ void QQuickNumberAnimation::setTo(qreal t)
sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
variety of methods for creating animations.
- \sa {Animation and Transitions in Qt Quick}, {qml/animation/basics}{Animation basics example}
+ \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
QQuickVector3dAnimation::QQuickVector3dAnimation(QObject *parent)
: QQuickPropertyAnimation(parent)
@@ -1478,7 +1478,7 @@ void QQuickVector3dAnimation::setTo(QVector3D t)
sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
variety of methods for creating animations.
- \sa {Animation and Transitions in Qt Quick}, {qml/animation/basics}{Animation basics example}
+ \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
QVariant _q_interpolateShortestRotation(qreal &f, qreal &t, qreal progress)
{
@@ -1648,7 +1648,8 @@ QQuickAnimationGroup::QQuickAnimationGroup(QQuickAnimationGroupPrivate &dd, QObj
void QQuickAnimationGroupPrivate::append_animation(QQmlListProperty<QQuickAbstractAnimation> *list, QQuickAbstractAnimation *a)
{
- if (QQuickAnimationGroup *q = qmlobject_cast<QQuickAnimationGroup *>(list->object))
+ QQuickAnimationGroup *q = qmlobject_cast<QQuickAnimationGroup *>(list->object);
+ if (q && a)
a->setGroup(q);
}
@@ -1711,7 +1712,7 @@ QQmlListProperty<QQuickAbstractAnimation> QQuickAnimationGroup::animations()
ParallelAnimation, it cannot be individually started and stopped; the
SequentialAnimation or ParallelAnimation must be started and stopped as a group.
- \sa ParallelAnimation, {Animation and Transitions in Qt Quick}, {qml/animation/basics}{Animation basics example}
+ \sa ParallelAnimation, {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
QQuickSequentialAnimation::QQuickSequentialAnimation(QObject *parent) :
@@ -1801,7 +1802,7 @@ QAbstractAnimationJob* QQuickSequentialAnimation::transition(QQuickStateActions
ParallelAnimation, it cannot be individually started and stopped; the
SequentialAnimation or ParallelAnimation must be started and stopped as a group.
- \sa SequentialAnimation, {Animation and Transitions in Qt Quick}, {qml/animation/basics}{Animation basics example}
+ \sa SequentialAnimation, {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
QQuickParallelAnimation::QQuickParallelAnimation(QObject *parent) :
QQuickAnimationGroup(parent)
@@ -1984,7 +1985,7 @@ void QQuickBulkValueAnimator::topLevelAnimationLoopChanged()
Note that PropertyAnimation inherits the abstract \l Animation type.
This includes additional properties and methods for controlling the animation.
- \sa {Animation and Transitions in Qt Quick}, {qml/animation/basics}{Animation basics example}
+ \sa {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
QQuickPropertyAnimation::QQuickPropertyAnimation(QObject *parent)
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
index 82c66b431d..7991dd8110 100644
--- a/src/quick/util/qquickanimatorcontroller.cpp
+++ b/src/quick/util/qquickanimatorcontroller.cpp
@@ -48,54 +48,82 @@
#include <QtGui/qscreen.h>
+#include <QtCore/qcoreapplication.h>
+
QT_BEGIN_NAMESPACE
QQuickAnimatorController::QQuickAnimatorController()
- : window(0)
+ : m_window(0)
{
}
QQuickAnimatorController::~QQuickAnimatorController()
{
- qDeleteAll(activeRootAnimations);
+ // The proxy job might already have been deleted, in which case we
+ // need to avoid calling functions on them. Then delete the job.
+ foreach (QAbstractAnimationJob *job, m_deleting) {
+ m_starting.take(job);
+ m_stopping.take(job);
+ m_animatorRoots.take(job);
+ delete job;
+ }
+
+ foreach (QQuickAnimatorProxyJob *proxy, m_animatorRoots)
+ proxy->controllerWasDeleted();
+ qDeleteAll(m_animatorRoots.keys());
+
+ // Delete those who have been started, stopped and are now still
+ // pending for restart.
+ foreach (QAbstractAnimationJob *job, m_starting.keys()) {
+ if (!m_animatorRoots.contains(job))
+ delete job;
+ }
}
void QQuickAnimatorController::itemDestroyed(QObject *o)
{
- deletedSinceLastFrame << (QQuickItem *) o;
+ m_deletedSinceLastFrame << (QQuickItem *) o;
}
void QQuickAnimatorController::advance()
{
bool running = false;
- for (QSet<QAbstractAnimationJob *>::const_iterator it = activeRootAnimations.constBegin();
- !running && it != activeRootAnimations.constEnd(); ++it) {
- if ((*it)->isRunning())
+ for (QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *>::const_iterator it = m_animatorRoots.constBegin();
+ !running && it != m_animatorRoots.constEnd(); ++it) {
+ if (it.key()->isRunning())
running = true;
}
// It was tempting to only run over the active animations, but we need to push
// the values for the transforms that finished in the last frame and those will
// have been removed already...
- for (QHash<QQuickItem *, QQuickTransformAnimatorJob::Helper *>::const_iterator it = transforms.constBegin();
- it != transforms.constEnd(); ++it) {
+ lock();
+ for (QHash<QQuickItem *, QQuickTransformAnimatorJob::Helper *>::const_iterator it = m_transforms.constBegin();
+ it != m_transforms.constEnd(); ++it) {
+ QQuickTransformAnimatorJob::Helper *xform = *it;
+ // Set to zero when the item was deleted in beforeNodeSync().
+ if (!xform->item)
+ continue;
(*it)->apply();
}
+ unlock();
if (running)
- window->update();
+ m_window->update();
}
static void qquick_initialize_helper(QAbstractAnimationJob *job, QQuickAnimatorController *c)
{
if (job->isRenderThreadJob()) {
QQuickAnimatorJob *j = static_cast<QQuickAnimatorJob *>(job);
- if (!j->target())
+ if (!j->target()) {
return;
- else if (c->deletedSinceLastFrame.contains(j->target()))
+ } else if (c->m_deletedSinceLastFrame.contains(j->target())) {
j->targetWasDeleted();
- else
+ } else {
+ j->addAnimationChangeListener(c, QAbstractAnimationJob::StateChange);
j->initialize(c);
+ }
} else if (job->isGroup()) {
QAnimationGroupJob *g = static_cast<QAnimationGroupJob *>(job);
for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling())
@@ -105,90 +133,117 @@ static void qquick_initialize_helper(QAbstractAnimationJob *job, QQuickAnimatorC
void QQuickAnimatorController::beforeNodeSync()
{
- // Force a render pass if we are adding new animations
- // so that advance will be called..
- if (starting.size())
- window->update();
-
- for (int i=0; i<starting.size(); ++i) {
- QAbstractAnimationJob *job = starting.at(i);
- job->addAnimationChangeListener(this, QAbstractAnimationJob::StateChange);
+ foreach (QAbstractAnimationJob *job, m_deleting) {
+ m_starting.take(job);
+ m_stopping.take(job);
+ m_animatorRoots.take(job);
+ job->stop();
+ delete job;
+ }
+ m_deleting.clear();
+
+ if (m_starting.size())
+ m_window->update();
+ foreach (QQuickAnimatorProxyJob *proxy, m_starting) {
+ QAbstractAnimationJob *job = proxy->job();
+ job->addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
qquick_initialize_helper(job, this);
+ m_animatorRoots[job] = proxy;
job->start();
+ proxy->startedByController();
}
- starting.clear();
+ m_starting.clear();
- for (QSet<QQuickAnimatorJob *>::const_iterator it = activeLeafAnimations.constBegin();
- it != activeLeafAnimations.constEnd(); ++it) {
- QQuickAnimatorJob *job = *it;
+ foreach (QQuickAnimatorProxyJob *proxy, m_stopping) {
+ QAbstractAnimationJob *job = proxy->job();
+ job->stop();
+ }
+ m_stopping.clear();
+
+ foreach (QQuickAnimatorJob *job, m_activeLeafAnimations) {
if (!job->target())
continue;
- else if (deletedSinceLastFrame.contains(job->target()))
+ else if (m_deletedSinceLastFrame.contains(job->target()))
job->targetWasDeleted();
else if (job->isTransform()) {
- QQuickTransformAnimatorJob *xform = static_cast<QQuickTransformAnimatorJob *>(*it);
+ QQuickTransformAnimatorJob *xform = static_cast<QQuickTransformAnimatorJob *>(job);
xform->transformHelper()->sync();
}
}
- deletedSinceLastFrame.clear();
+ foreach (QQuickItem *wiped, m_deletedSinceLastFrame) {
+ QQuickTransformAnimatorJob::Helper *helper = m_transforms.value(wiped);
+ if (helper)
+ helper->item = 0;
+ }
+
+ m_deletedSinceLastFrame.clear();
}
void QQuickAnimatorController::afterNodeSync()
{
- for (QSet<QQuickAnimatorJob *>::const_iterator it = activeLeafAnimations.constBegin();
- it != activeLeafAnimations.constEnd(); ++it) {
- QQuickAnimatorJob *job = *it;
- if (job->isUniform() && job->target()) {
- QQuickUniformAnimatorJob *job = static_cast<QQuickUniformAnimatorJob *>(*it);
- job->afterNodeSync();
- }
+ foreach (QQuickAnimatorJob *job, m_activeLeafAnimations) {
+ if (job->isUniform() && job->target())
+ static_cast<QQuickUniformAnimatorJob *>(job)->afterNodeSync();
}
}
-
-void QQuickAnimatorController::startAnimation(QAbstractAnimationJob *job)
+void QQuickAnimatorController::animationFinished(QAbstractAnimationJob *job)
{
- mutex.lock();
- starting << job;
- mutex.unlock();
+ /* We are currently on the render thread and m_deleting is primarily
+ * being written on the GUI Thread and read during sync. However, we don't
+ * need to lock here as this is a direct result of animationDriver->advance()
+ * which is already locked. For non-threaded render loops no locking is
+ * needed in any case.
+ */
+ if (!m_deleting.contains(job)) {
+ QQuickAnimatorProxyJob *proxy = m_animatorRoots[job];
+ if (proxy)
+ QCoreApplication::postEvent(proxy, new QEvent(QEvent::User));
+ // else already gone...
+ }
}
-void QQuickAnimatorController::animationsStarted()
+void QQuickAnimatorController::animationStateChanged(QAbstractAnimationJob *job,
+ QAbstractAnimationJob::State newState,
+ QAbstractAnimationJob::State oldState)
{
- window->update();
+ Q_ASSERT(job->isRenderThreadJob());
+ QQuickAnimatorJob *animator = static_cast<QQuickAnimatorJob *>(job);
+ if (newState == QAbstractAnimationJob::Running) {
+ m_activeLeafAnimations << animator;
+ animator->setHasBeenRunning(true);
+ } else if (oldState == QAbstractAnimationJob::Running) {
+ m_activeLeafAnimations.remove(animator);
+ }
}
-void QQuickAnimatorController::animationStateChanged(QAbstractAnimationJob *job,
- QAbstractAnimationJob::State newState,
- QAbstractAnimationJob::State)
+
+
+void QQuickAnimatorController::requestSync()
{
- if (newState == QAbstractAnimationJob::Running)
- activeRootAnimations << job;
- else
- activeRootAnimations.remove(job);
+ // Force a "sync" pass as the newly started animation needs to sync properties from GUI.
+ m_window->maybeUpdate();
}
-bool QQuickAnimatorController::event(QEvent *e)
+// These functions are called on the GUI thread.
+void QQuickAnimatorController::startJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job)
{
- if ((int) e->type() == StopAnimation) {
- QAbstractAnimationJob *job = static_cast<Event *>(e)->job;
- mutex.lock();
- starting.removeOne(job);
- mutex.unlock();
- job->stop();
- return true;
+ m_starting[job] = proxy;
+ requestSync();
+}
- } else if ((uint) e->type() == DeleteAnimation) {
- QAbstractAnimationJob *job = static_cast<Event *>(e)->job;
- mutex.lock();
- starting.removeOne(job);
- mutex.unlock();
- job->stop();
- delete job;
- return true;
- }
+void QQuickAnimatorController::stopJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job)
+{
+ m_stopping[job] = proxy;
+ requestSync();
+}
- return QObject::event(e);
+void QQuickAnimatorController::deleteJob(QAbstractAnimationJob *job)
+{
+ lock();
+ m_deleting << job;
+ requestSync();
+ unlock();
}
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimatorcontroller_p.h b/src/quick/util/qquickanimatorcontroller_p.h
index ab08bf05db..6223a9938f 100644
--- a/src/quick/util/qquickanimatorcontroller_p.h
+++ b/src/quick/util/qquickanimatorcontroller_p.h
@@ -47,6 +47,7 @@
#include <QtQuick/qquickitem.h>
#include <QtCore/qmutex.h>
+#include <QtCore/qthread.h>
QT_BEGIN_NAMESPACE
@@ -55,27 +56,6 @@ class QQuickAnimatorController : public QObject, public QAnimationJobChangeListe
Q_OBJECT
public:
-
- enum EventType {
- // GUI to RT events
- StartAnimation = QEvent::User + 1,
- StopAnimation,
- DeleteAnimation,
-
- // RT back to GUI events
- AnimationFinished
- };
-
- class Event : public QEvent {
- public:
- Event(QAbstractAnimationJob *j, EventType type)
- : QEvent(QEvent::Type(type))
- , job(j)
- {
- }
- QAbstractAnimationJob *job;
- };
-
QQuickAnimatorController();
~QQuickAnimatorController();
@@ -83,32 +63,35 @@ public:
void beforeNodeSync();
void afterNodeSync();
- bool event(QEvent *);
+ void animationFinished(QAbstractAnimationJob *job);
+ void animationStateChanged(QAbstractAnimationJob *job, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);
- void startAnimation(QAbstractAnimationJob *job);
+ void requestSync();
- void animationStateChanged(QAbstractAnimationJob *job,
- QAbstractAnimationJob::State newState,
- QAbstractAnimationJob::State oldState);
+ // These are called from the GUI thread (the proxy)
+ void startJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job);
+ void stopJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job);
+ void deleteJob(QAbstractAnimationJob *job);
+
+ void lock() { m_mutex.lock(); }
+ void unlock() { m_mutex.unlock(); }
public Q_SLOTS:
- void animationsStarted();
void itemDestroyed(QObject *);
public:
- QList<QAbstractAnimationJob *> starting;
- QList<QAbstractAnimationJob *> stopped;
-
- QSet<QAbstractAnimationJob *> activeRootAnimations;
- QSet<QQuickAnimatorJob *> activeLeafAnimations;
-
- QHash<QQuickItem *, QQuickTransformAnimatorJob::Helper *> transforms;
-
- QSet<QQuickItem *> deletedSinceLastFrame;
-
- QQuickWindow *window;
-
- QMutex mutex;
+ // These are manipulated from the GUI thread and should only
+ // be updated during the sync() phase.
+ QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *> m_starting;
+ QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *> m_stopping;
+ QSet<QAbstractAnimationJob *> m_deleting;
+
+ QHash<QAbstractAnimationJob *, QQuickAnimatorProxyJob *> m_animatorRoots;
+ QSet<QQuickAnimatorJob *> m_activeLeafAnimations;
+ QHash<QQuickItem *, QQuickTransformAnimatorJob::Helper *> m_transforms;
+ QSet<QQuickItem *> m_deletedSinceLastFrame;
+ QQuickWindow *m_window;
+ QMutex m_mutex;
};
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 78708bdf81..fa6f615649 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -72,8 +72,6 @@ QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObje
// be negligiblie compared to animating and re-rendering the scene on the render thread.
m_duration = -1;
- job->addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
-
QObject *ctx = findAnimationContext(m_animation);
if (!ctx) {
qWarning("QtQuick: unable to find animation context for RT animation...");
@@ -100,7 +98,7 @@ void QQuickAnimatorProxyJob::deleteJob()
{
if (m_job) {
if (m_controller && m_internalState != State_Starting)
- QCoreApplication::postEvent(m_controller, new QQuickAnimatorController::Event(m_job, QQuickAnimatorController::DeleteAnimation));
+ m_controller->deleteJob(m_job);
else if (m_internalState == State_Starting)
delete m_job;
m_job = 0;
@@ -122,18 +120,15 @@ void QQuickAnimatorProxyJob::updateCurrentTime(int)
void QQuickAnimatorProxyJob::updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
{
if (m_state == Running) {
- if (m_controller) {
- m_internalState = State_Running;
- startOnRenderThread();
- } else {
- m_internalState = State_Starting;
- }
+ m_internalState = State_Starting;
+ if (m_controller)
+ m_controller->startJob(this, m_job);
} else if (newState == Stopped) {
syncBackCurrentValues();
if (m_internalState == State_Starting)
m_internalState = State_Stopped;
else if (m_controller) {
- QCoreApplication::postEvent(m_controller, new QQuickAnimatorController::Event(m_job, QQuickAnimatorController::StopAnimation));
+ m_controller->stopJob(this, m_job);
}
}
}
@@ -143,23 +138,28 @@ void QQuickAnimatorProxyJob::windowChanged(QQuickWindow *window)
setWindow(window);
}
+void QQuickAnimatorProxyJob::controllerWasDeleted()
+{
+ m_controller = 0;
+ m_job = 0;
+}
+
void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window)
{
if (!window) {
- m_controller = 0;
// Stop will trigger syncBackCurrentValues so best to do it before
// we delete m_job.
stop();
deleteJob();
return;
- }
- m_controller = QQuickWindowPrivate::get(window)->animationController;
-
- if (window->openglContext())
- readyToAnimate();
- else
- connect(window, SIGNAL(sceneGraphInitialized()), this, SLOT(sceneGraphInitialized()));
+ } else if (!m_controller && m_job) {
+ m_controller = QQuickWindowPrivate::get(window)->animationController;
+ if (window->openglContext())
+ readyToAnimate();
+ else
+ connect(window, SIGNAL(sceneGraphInitialized()), this, SLOT(sceneGraphInitialized()));
+ }
}
void QQuickAnimatorProxyJob::sceneGraphInitialized()
@@ -170,36 +170,24 @@ void QQuickAnimatorProxyJob::sceneGraphInitialized()
void QQuickAnimatorProxyJob::readyToAnimate()
{
- if (m_internalState == State_Starting) {
- startOnRenderThread();
- }
+ if (m_internalState == State_Starting)
+ m_controller->startJob(this, m_job);
}
-void QQuickAnimatorProxyJob::animationFinished(QAbstractAnimationJob *job)
+void QQuickAnimatorProxyJob::startedByController()
{
- QCoreApplication::postEvent(this, new QQuickAnimatorController::Event(job, QQuickAnimatorController::AnimationFinished));
+ m_internalState = State_Running;
}
bool QQuickAnimatorProxyJob::event(QEvent *e)
{
- if ((uint) e->type() == QQuickAnimatorController::AnimationFinished) {
- // Update the duration of this proxy to the current time and stop it so
- // that parent animations can progress gracefully
+ if (e->type() == QEvent::User) {
stop();
return true;
}
-
return QObject::event(e);
}
-void QQuickAnimatorProxyJob::startOnRenderThread()
-{
- m_internalState = State_Running;
- // Force a "sync" pass as the newly started animation needs to sync properties from GUI.
- m_controller->startAnimation(m_job);
- QQuickWindowPrivate::get(m_controller->window)->dirtyItem(0);
-}
-
static void qquick_syncback_helper(QAbstractAnimationJob *job)
{
if (job->isRenderThreadJob()) {
@@ -216,7 +204,8 @@ static void qquick_syncback_helper(QAbstractAnimationJob *job)
void QQuickAnimatorProxyJob::syncBackCurrentValues()
{
- qquick_syncback_helper(m_job);
+ if (m_job)
+ qquick_syncback_helper(m_job);
}
QQuickAnimatorJob::QQuickAnimatorJob()
@@ -236,9 +225,9 @@ QQuickAnimatorJob::QQuickAnimatorJob()
qreal QQuickAnimatorJob::value() const
{
qreal v;
- m_controller->mutex.lock();
+ m_controller->lock();
v = m_value;
- m_controller->mutex.unlock();
+ m_controller->unlock();
return v;
}
@@ -258,21 +247,6 @@ void QQuickAnimatorJob::targetWasDeleted()
m_controller = 0;
}
-void QQuickAnimatorJob::updateState(State newState, State oldState)
-{
- if (!m_controller) {
- stop();
- return;
- }
-
- if (newState == Running) {
- m_controller->activeLeafAnimations << this;
- m_hasBeenRunning = true;
- } else if (oldState == Running) {
- m_controller->activeLeafAnimations.remove(this);
- }
-}
-
QQuickTransformAnimatorJob::QQuickTransformAnimatorJob()
: m_helper(0)
{
@@ -282,7 +256,7 @@ QQuickTransformAnimatorJob::QQuickTransformAnimatorJob()
QQuickTransformAnimatorJob::~QQuickTransformAnimatorJob()
{
if (m_helper && --m_helper->ref == 0) {
- m_controller->transforms.remove(m_helper->item);
+ m_controller->m_transforms.remove(m_helper->item);
delete m_helper;
}
}
@@ -292,11 +266,11 @@ void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller
QQuickAnimatorJob::initialize(controller);
if (m_controller) {
- m_helper = m_controller->transforms.value(m_target);
+ m_helper = m_controller->m_transforms.value(m_target);
if (!m_helper) {
m_helper = new Helper();
m_helper->item = m_target;
- m_controller->transforms.insert(m_target, m_helper);
+ m_controller->m_transforms.insert(m_target, m_helper);
QObject::connect(m_target, SIGNAL(destroyed(QObject *)), m_controller, SLOT(itemDestroyed(QObject*)), Qt::DirectConnection);
} else {
++m_helper->ref;
@@ -307,16 +281,12 @@ void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller
}
}
-QQuickTransformAnimatorJob::Helper::~Helper()
-{
-}
-
-
void QQuickTransformAnimatorJob::Helper::sync()
{
const quint32 mask = QQuickItemPrivate::Position
| QQuickItemPrivate::BasicTransform
- | QQuickItemPrivate::TransformOrigin;
+ | QQuickItemPrivate::TransformOrigin
+ | QQuickItemPrivate::Size;
QQuickItemPrivate *d = QQuickItemPrivate::get(item);
if (d->extra.isAllocated()
@@ -347,7 +317,7 @@ void QQuickTransformAnimatorJob::Helper::sync()
rotation = item->rotation();
}
- if (dirty & QQuickItemPrivate::TransformOrigin) {
+ if (dirty & (QQuickItemPrivate::TransformOrigin | QQuickItemPrivate::Size)) {
QPointF o = item->transformOriginPoint();
ox = o.x();
oy = o.y();
@@ -382,7 +352,7 @@ void QQuickXAnimatorJob::updateCurrentTime(int time)
{
if (!m_controller)
return;
- Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+ Q_ASSERT(m_controller->m_window->openglContext()->thread() == QThread::currentThread());
m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
m_helper->dx = m_value;
@@ -399,7 +369,7 @@ void QQuickYAnimatorJob::updateCurrentTime(int time)
{
if (!m_controller)
return;
- Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+ Q_ASSERT(m_controller->m_window->openglContext()->thread() == QThread::currentThread());
m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
m_helper->dy = m_value;
@@ -452,7 +422,7 @@ void QQuickOpacityAnimatorJob::updateCurrentTime(int time)
{
if (!m_controller)
return;
- Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+ Q_ASSERT(m_controller->m_window->openglContext()->thread() == QThread::currentThread());
m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
m_opacityNode->setOpacity(m_value);
@@ -468,7 +438,7 @@ void QQuickScaleAnimatorJob::updateCurrentTime(int time)
{
if (!m_controller)
return;
- Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+ Q_ASSERT(m_controller->m_window->openglContext()->thread() == QThread::currentThread());
m_value = m_from + (m_to - m_from) * m_easing.valueForProgress(time / (qreal) m_duration);
m_helper->scale = m_value;
@@ -488,7 +458,7 @@ void QQuickRotationAnimatorJob::updateCurrentTime(int time)
{
if (!m_controller)
return;
- Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+ Q_ASSERT(m_controller->m_window->openglContext()->thread() == QThread::currentThread());
float t = m_easing.valueForProgress(time / (qreal) m_duration);
switch (m_direction) {
@@ -563,7 +533,7 @@ void QQuickUniformAnimatorJob::updateCurrentTime(int time)
{
if (!m_controller)
return;
- Q_ASSERT(m_controller->window->openglContext()->thread() == QThread::currentThread());
+ Q_ASSERT(m_controller->m_window->openglContext()->thread() == QThread::currentThread());
if (!m_node || m_uniformIndex == -1 || m_uniformType == -1)
return;
diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
index bc9c65c347..8aae121106 100644
--- a/src/quick/util/qquickanimatorjob_p.h
+++ b/src/quick/util/qquickanimatorjob_p.h
@@ -63,7 +63,7 @@ class QQuickShaderEffectNode;
class QSGOpacityNode;
-class Q_QUICK_PRIVATE_EXPORT QQuickAnimatorProxyJob : public QObject, public QAbstractAnimationJob, public QAnimationJobChangeListener
+class Q_QUICK_PRIVATE_EXPORT QQuickAnimatorProxyJob : public QObject, public QAbstractAnimationJob
{
Q_OBJECT
@@ -73,7 +73,10 @@ public:
int duration() const { return m_duration; }
- virtual void animationFinished(QAbstractAnimationJob *);
+ QAbstractAnimationJob *job() const { return m_job; }
+
+ void startedByController();
+ void controllerWasDeleted();
protected:
bool event(QEvent *);
@@ -91,7 +94,6 @@ private:
void readyToAnimate();
void setWindow(QQuickWindow *window);
static QObject *findAnimationContext(QQuickAbstractAnimation *);
- void startOnRenderThread();
QQuickAnimatorController *m_controller;
QQuickAbstractAnimation *m_animation;
@@ -134,6 +136,7 @@ public:
bool isUniform() const { return m_isUniform; }
bool hasBeenRunning() const { return m_hasBeenRunning; }
+ void setHasBeenRunning(bool has) { m_hasBeenRunning = has; }
qreal value() const;
@@ -141,7 +144,6 @@ public:
protected:
QQuickAnimatorJob();
- void updateState(State newState, State oldState);
QQuickItem *m_target;
QQuickAnimatorController *m_controller;
@@ -180,8 +182,6 @@ public:
{
}
- ~Helper();
-
void sync();
void apply();
diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp
index 53e3520bde..9e9e6cb419 100644
--- a/src/quick/util/qquicksmoothedanimation.cpp
+++ b/src/quick/util/qquicksmoothedanimation.cpp
@@ -242,6 +242,9 @@ qreal QSmoothedAnimation::easeFollow(qreal time_seconds)
void QSmoothedAnimation::updateCurrentTime(int t)
{
+ if (!isRunning() && !isPaused()) // This can happen if init() stops the animation in some cases
+ return;
+
qreal time_seconds = useDelta ? qreal(QQmlAnimationTimer::instance()->currentDelta()) / 1000. : qreal(t - lastTime) / 1000.;
if (useDelta)
useDelta = false;
@@ -351,7 +354,7 @@ void QSmoothedAnimation::init()
sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
variety of methods for creating animations.
- \sa SpringAnimation, NumberAnimation, {Animation and Transitions in Qt Quick}, {declarative/animation/basics}{Animation basics example}
+ \sa SpringAnimation, NumberAnimation, {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}
*/
QQuickSmoothedAnimation::QQuickSmoothedAnimation(QObject *parent)
diff --git a/src/quick/util/qquickspringanimation.cpp b/src/quick/util/qquickspringanimation.cpp
index f663491a58..36aae36459 100644
--- a/src/quick/util/qquickspringanimation.cpp
+++ b/src/quick/util/qquickspringanimation.cpp
@@ -308,7 +308,8 @@ void QSpringAnimation::updateCurrentTime(int time)
QQmlPropertyPrivate::DontRemoveBinding);
if (stopped && old_to == to) { // do not stop if we got restarted
- stopTime = animationTemplate->elapsed.elapsed();
+ if (animationTemplate)
+ stopTime = animationTemplate->elapsed.elapsed();
stop();
}
}
@@ -365,7 +366,7 @@ void QQuickSpringAnimationPrivate::updateMode()
sources. The \l {Animation and Transitions in Qt Quick} documentation shows a
variety of methods for creating animations.
- \sa SmoothedAnimation, {Animation and Transitions in Qt Quick}, {declarative/animation/basics}{Animation basics example}, {declarative/toys/clocks}{Clocks example}
+ \sa SmoothedAnimation, {Animation and Transitions in Qt Quick}, {Qt Quick Examples - Animation}, {Qt Quick Demo - Clocks}
*/
QQuickSpringAnimation::QQuickSpringAnimation(QObject *parent)