From 49f39d9e70d45a1fbdf9f05f59620b9a25a369f5 Mon Sep 17 00:00:00 2001 From: Venu Date: Wed, 23 Oct 2013 15:53:49 +0200 Subject: Doc: Fixed broken links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There were many links (including the broken) on the Qt Quick index page and QML type reference page using the html file name to link to a page or a section within a page. Using html file reference in a link is not a good approach as qdoc does not give complete control to the author to define the html file name. This change updates all such links to use the page \title and \target names, which are considered to be better ways to link. Task-number:QTBUG-33360 Change-Id: Ibd1b1e3223a7e205bbdcf21b1b7f6e515749c5c9 Reviewed-by: Nico Vertriest Reviewed-by: Topi Reiniö Reviewed-by: Martin Smith Reviewed-by: Jerome Pasion --- src/quick/doc/src/cppextensionpoints.qdoc | 6 ++-- src/quick/doc/src/qmltypereference.qdoc | 27 +++++++------- src/quick/doc/src/qtquick.qdoc | 60 +++++++++++++++---------------- 3 files changed, 47 insertions(+), 46 deletions(-) (limited to 'src/quick') 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..3c35575b8a 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 @@ -231,7 +232,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 +269,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 +280,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 +292,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..0c5a721863 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,13 +115,13 @@ 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 -- cgit v1.2.3 From 42cf36ae020628f5b1ecf68a222f8c2e3317bebe Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Wed, 23 Oct 2013 13:20:39 -0700 Subject: Clear text node references after sub-tree has been cleaned up. Task-number: QTBUG-34181 Change-Id: I861e192cee2c683efee79e7404a5c9d70b60691f Reviewed-by: Gunnar Sletta --- src/quick/items/qquicktextedit.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/quick') diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 48518f1ba3..be2cd37dee 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(oldNode); TextNodeIterator nodeIterator = d->textNodeMap.begin(); while (nodeIterator != d->textNodeMap.end() && !(*nodeIterator)->dirty()) -- cgit v1.2.3 From fdd99051290da290cdbdea109f45f4043c27d6cf Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 25 Oct 2013 08:53:52 +0200 Subject: Item documentation: visibleChildren is a list of items, not a real Followup to I5ec541226fabd72c05ce8ccb8bb7e56f6ec7717a Task-number: QTBUG-22724 Change-Id: I3f74fda29faba4054c5bb97aad4735f7c5f0f278 Reviewed-by: Jerome Pasion Reviewed-by: J-P Nurmi --- src/quick/items/qquickitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index c3b221b2c8..cd526a0dae 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4125,7 +4125,7 @@ QQmlListProperty QQuickItemPrivate::children() } /*! - \qmlproperty real QtQuick::Item::visibleChildren + \qmlproperty list 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. -- cgit v1.2.3 From b3bff5bb3c8ee0e1c45d20d04b1c3c0236aa9d38 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 24 Oct 2013 19:59:12 +0200 Subject: Make sure QQuickBorderImage sets its pixmapChanged dirtyflag Task-number: QTBUG-34298 Change-Id: Ie66f0bdd705335491496f5d583193b32cb7749f3 Reviewed-by: Alan Alpert --- src/quick/items/qquickborderimage.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index 9fc9752707..a2e4e91755 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 @@ -561,6 +561,7 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat QSGImageNode *node = static_cast(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(); } -- cgit v1.2.3 From cca9522e7ca0c040ae354b20f09983005ef955bd Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 25 Oct 2013 15:16:46 +0200 Subject: Screen attached property: expose pixelDensity property Because logicalPixelDensity is different than physical density on multiple platforms, having the actual density is critical to be able to design resolution-independent controls. Change-Id: I06bbdc6e6869718058a796ca737668ce69802f2b Reviewed-by: Jens Bache-Wiig --- src/quick/items/qquickscreen.cpp | 18 ++++++++++++++++++ src/quick/items/qquickscreen_p.h | 3 +++ 2 files changed, 21 insertions(+) (limited to 'src/quick') diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp index 75eccf6c59..e32f31308e 100644 --- a/src/quick/items/qquickscreen.cpp +++ b/src/quick/items/qquickscreen.cpp @@ -135,6 +135,13 @@ QT_BEGIN_NAMESPACE usual units in QML; on some systems they may be different than physical pixels. */ +/*! + \qmlattachedproperty real QtQuick.Window::Screen::pixelDensity + \readonly + \since 5.2 + + The number of physical pixels per millimeter. +*/ /*! \qmlattachedproperty Qt::ScreenOrientation QtQuick.Window::Screen::primaryOrientation \readonly @@ -233,6 +240,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 +305,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 +320,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..6f837eea14 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) 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(); -- cgit v1.2.3 From 8d6500560eb5f7f72588d9d01e663a04af592e99 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 24 Oct 2013 20:44:17 +0200 Subject: Fix rendernode bug and enable rendernode test. The bug in the renderer was that the viewport was set before we called the render node, leaving us with the viewport set by the render node as opposed to the viewport of the renderer. The render node API is a crude and intrusive hack which was added for webkit back in the day. With the introduction of webengine it becomes less relevant, but it should still work. Change-Id: I66a1e3047e018ad6c0bb28044851e9fc65da59cc Reviewed-by: Alan Alpert --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index f25e144674..bf31b94e46 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -2031,14 +2031,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::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); -- cgit v1.2.3 From af22149dd8daf593182fec978f15dc1667c9cf8d Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 21 Oct 2013 09:57:58 +0200 Subject: Avoid side effects when en exception has been thrown. We don't want to check for exceptions after every single line on our runtime methods. A better way to handle this is to add the check in all methods that have direct side effects (as e.g. writing to a property of the JS stack). We also need to return whereever we throw an exception. To simplify the code, ExecutionContext::throwXxx methods now return a ReturnedValue (always undefined) for convenience. Change-Id: Ide6c804f819c731a3f14c6c43121d08029c9fb90 Reviewed-by: Simon Hausmann --- src/quick/items/context2d/qquickcontext2d.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 2fb6cb9f63..5abab8500b 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -1318,7 +1318,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); @@ -1882,7 +1882,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; @@ -2667,6 +2667,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_font(QV4::SimpleCallContext *ct CHECK_CONTEXT_SETTER(r) QV4::Scoped s(scope, ctx->argument(0), QV4::Scoped::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; @@ -2717,6 +2719,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textAlign(QV4::SimpleCallContex CHECK_CONTEXT_SETTER(r) QV4::Scoped s(scope, ctx->argument(0), QV4::Scoped::Convert); + if (scope.engine->hasException) + return QV4::Encode::undefined(); QString textAlign = s->toQString(); QQuickContext2D::TextAlignType ta; @@ -2782,6 +2786,8 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(QV4::SimpleCallCon QV4::Scoped r(scope, ctx->callData->thisObject); CHECK_CONTEXT_SETTER(r) QV4::Scoped s(scope, ctx->argument(0), QV4::Scoped::Convert); + if (scope.engine->hasException) + return QV4::Encode::undefined(); QString textBaseline = s->toQString(); QQuickContext2D::TextBaseLineType tb; @@ -3088,7 +3094,7 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_width(QV4::SimpleCallC QV4::Scope scope(ctx); QV4::Scoped imageData(scope, ctx->callData->thisObject); if (!imageData) - ctx->throwTypeError(); + return ctx->throwTypeError(); QV4::Scoped r(scope, imageData->pixelData.as()); if (!r) return QV4::Encode(0); @@ -3104,7 +3110,7 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_height(QV4::SimpleCall QV4::Scope scope(ctx); QV4::Scoped imageData(scope, ctx->callData->thisObject); if (!imageData) - ctx->throwTypeError(); + return ctx->throwTypeError(); QV4::Scoped r(scope, imageData->pixelData.as()); if (!r) return QV4::Encode(0); @@ -3120,7 +3126,7 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_data(QV4::SimpleCallCo QV4::Scope scope(ctx); QV4::Scoped imageData(scope, ctx->callData->thisObject); if (!imageData) - ctx->throwTypeError(); + return ctx->throwTypeError(); return imageData->pixelData.asReturnedValue(); } @@ -3158,7 +3164,7 @@ QV4::ReturnedValue QQuickJSContext2DPixelData::getIndexed(QV4::Managed *m, uint QV4::Scope scope(v4); QV4::Scoped r(scope, m->as()); if (!m) - m->engine()->current->throwTypeError(); + return m->engine()->current->throwTypeError(); if (r && index < static_cast(r->image.width() * r->image.height() * 4)) { if (hasProperty) @@ -3189,8 +3195,10 @@ void QQuickJSContext2DPixelData::putIndexed(QV4::Managed *m, uint index, const Q QV4::ExecutionEngine *v4 = m->engine(); QV4::Scope scope(v4); QV4::Scoped r(scope, m->as()); - if (!r) - m->engine()->current->throwTypeError(); + if (!r) { + v4->current->throwTypeError(); + return; + } const int v = value->toInt32(); if (r && index < static_cast(r->image.width() * r->image.height() * 4) && v >= 0 && v <= 255) { -- cgit v1.2.3 From ffcdbfa03f8bb36b521f8c1a703ee24085fe25bd Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 22 Oct 2013 13:26:08 +0200 Subject: Protect write accesses to objects Don't write to objects if we have a pending exception to avoid any side effects. Change-Id: I9f93a9195a652dbae7033cc6ebb355d5d86e9b5e Reviewed-by: Simon Hausmann --- src/quick/items/context2d/qquickcontext2d.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/quick') diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 5abab8500b..2b2504daf2 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -3194,6 +3194,9 @@ 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 r(scope, m->as()); if (!r) { v4->current->throwTypeError(); -- cgit v1.2.3 From 16242b144e3a886514000909c446201b3de06a67 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 28 Oct 2013 14:35:51 +0100 Subject: Add references to Animators from the QML Type Reference Task-number: QTBUG-34221 Change-Id: Iaa1d7f4dd70d2d8150e8360545a33ac984e6bebd Reviewed-by: Jerome Pasion --- src/quick/doc/src/qmltypereference.qdoc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/quick') diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc index 3c35575b8a..cf40fbe37c 100644 --- a/src/quick/doc/src/qmltypereference.qdoc +++ b/src/quick/doc/src/qmltypereference.qdoc @@ -212,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 -- cgit v1.2.3 From 192cb97fa6229b8e2b149e90ac49dddd228405d4 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 28 Oct 2013 14:02:25 +0100 Subject: Track size changes from transform animators. When the size changes, so will most likely also the transform origin, so we need to check for it and update accordingly. Task-number: QTBUG-34140 Change-Id: Ic3d6c1ac599db499ab196a8cbe550308a75e837f Reviewed-by: Laszlo Agocs Reviewed-by: Alan Alpert --- src/quick/util/qquickanimatorjob.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/quick') diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp index 78708bdf81..fffb9fc65f 100644 --- a/src/quick/util/qquickanimatorjob.cpp +++ b/src/quick/util/qquickanimatorjob.cpp @@ -316,7 +316,8 @@ 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 +348,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(); -- cgit v1.2.3 From 4fa67b9ef3201214db0b7e6d61288faa33d6ea8d Mon Sep 17 00:00:00 2001 From: Sean Harmer Date: Wed, 2 Oct 2013 23:57:29 +0100 Subject: Prevent bogus warning message flood on nVidia driver related to mipmaps When using QtQuick2 Text elements on nVidia with the KHR_debug extension active we get flooded by messages of the form: "Texture state usage warning: Waste of memory: Texture 0 has mipmaps, while its min filter is inconsistent with mipmaps." This is totally bogus as there really aren't any mipmaps created here. However, it is very annoying and hides genuine errors. Setting the mipmap max level to 0 works around the issue. nVidia seem unwilling to fix it in the driver. Change-Id: I56632ba1ee777fb54fc8d17e1828669baa183a55 Reviewed-by: Giuseppe D'Angelo Reviewed-by: James Turner Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp | 12 +++++++++--- src/quick/scenegraph/util/qsgatlastexture.cpp | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index 8a1a87cdc0..bc09ed83d7 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -212,11 +212,14 @@ 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); +#endif + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0); texInfo->size = QSize(width, height); @@ -278,12 +281,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); diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index 3710f05b9a..12ab48e193 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -293,6 +293,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 -- cgit v1.2.3 From b9bf1f53395621deb106245cb80c7bbbce09b0ce Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 29 Oct 2013 10:54:06 +0100 Subject: Remove superfluous code. I suspect this was to work around that a very early version of the previous renderer some times left vertex pointers active, but this has not been the case for a very long time, so this code is just wasting time and memory. Change-Id: I4b79ff67d17bf47af515e8db203960c9bceae247 Reviewed-by: Alan Alpert --- src/quick/items/qquickanimatedsprite.cpp | 12 ------------ src/quick/items/qquickspritesequence.cpp | 12 ------------ 2 files changed, 24 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index 846de15581..c90adc24a5 100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@ -138,14 +138,6 @@ public: { } - void deactivate() { - QSGMaterialShader::deactivate(); - - for (int i=0; i<8; ++i) { - program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0); - } - } - virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) { QQuickAnimatedSpriteMaterial *m = static_cast(newEffect); @@ -182,12 +174,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; diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index 3c1492e0b3..8a6789bb9f 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -137,14 +137,6 @@ public: { } - void deactivate() { - QSGMaterialShader::deactivate(); - - for (int i=0; i<8; ++i) { - program()->setAttributeArray(i, GL_FLOAT, chunkOfBytes, 1, 0); - } - } - virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) { QQuickSpriteSequenceMaterial *m = static_cast(newEffect); @@ -181,12 +173,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; -- cgit v1.2.3 From 906d5c5c40183468f9521277c6244a6c46730de6 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 17 Oct 2013 14:53:33 +0200 Subject: Use one render loop per QQuickWindow See the task for the full reasoning behind this patch. The threaded renderloop has been refactored to have one window per thread. This is mostly a simplification of the current code path where for loops over multiple windows are turned into if (window). The QSGContext has been split into two classes, QSGRenderContext for which there is one per OpenGLContext. The rest of the patch is name changes and a couple of cleanups in the hopes of simplifying this change. Task-number: QTBUG-33993 Change-Id: I31c81f9694d7da7474a72333169be38de62613c4 Reviewed-by: Sean Harmer --- src/quick/designer/designerwindowmanager.cpp | 5 +- src/quick/designer/designerwindowmanager_p.h | 3 + src/quick/items/context2d/qquickcanvasitem.cpp | 2 +- src/quick/items/context2d/qquickcontext2d.cpp | 2 +- src/quick/items/qquickborderimage.cpp | 2 +- src/quick/items/qquickimage.cpp | 16 +- src/quick/items/qquickitem_p.h | 7 + src/quick/items/qquickshadereffectsource.cpp | 31 +- src/quick/items/qquickshadereffectsource_p.h | 5 +- src/quick/items/qquicktext.cpp | 7 +- src/quick/items/qquicktextedit.cpp | 2 +- src/quick/items/qquicktextinput.cpp | 2 +- src/quick/items/qquicktextnode.cpp | 15 +- src/quick/items/qquicktextnode_p.h | 3 +- src/quick/items/qquickwindow.cpp | 34 +- src/quick/items/qquickwindow_p.h | 2 +- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 3 +- src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h | 2 +- src/quick/scenegraph/coreapi/qsgmaterial.cpp | 2 +- src/quick/scenegraph/coreapi/qsgnodeupdater_p.h | 5 - src/quick/scenegraph/coreapi/qsgrenderer.cpp | 17 +- src/quick/scenegraph/coreapi/qsgrenderer_p.h | 8 +- src/quick/scenegraph/qsgadaptationlayer.cpp | 5 +- src/quick/scenegraph/qsgadaptationlayer_p.h | 4 +- src/quick/scenegraph/qsgcontext.cpp | 550 ++++++++++----------- src/quick/scenegraph/qsgcontext_p.h | 102 ++-- .../qsgdefaultdistancefieldglyphcache.cpp | 9 +- .../qsgdefaultdistancefieldglyphcache_p.h | 2 +- src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 9 + src/quick/scenegraph/qsgdistancefieldglyphnode.cpp | 2 +- src/quick/scenegraph/qsgdistancefieldglyphnode_p.h | 6 +- src/quick/scenegraph/qsgflashnode.cpp | 62 --- src/quick/scenegraph/qsgflashnode_p.h | 63 --- src/quick/scenegraph/qsgrenderloop.cpp | 17 +- src/quick/scenegraph/qsgrenderloop_p.h | 2 + .../qsgshareddistancefieldglyphcache.cpp | 5 +- .../qsgshareddistancefieldglyphcache_p.h | 1 - src/quick/scenegraph/qsgthreadedrenderloop.cpp | 473 ++++++++++-------- src/quick/scenegraph/qsgthreadedrenderloop_p.h | 28 +- src/quick/scenegraph/qsgwindowsrenderloop.cpp | 14 +- src/quick/scenegraph/qsgwindowsrenderloop_p.h | 5 + src/quick/scenegraph/scenegraph.pri | 2 - src/quick/scenegraph/util/qsgatlastexture.cpp | 40 +- src/quick/scenegraph/util/qsgatlastexture_p.h | 10 +- src/quick/scenegraph/util/qsgpainternode.cpp | 6 +- src/quick/scenegraph/util/qsgpainternode_p.h | 2 +- 46 files changed, 762 insertions(+), 832 deletions(-) delete mode 100644 src/quick/scenegraph/qsgflashnode.cpp delete mode 100644 src/quick/scenegraph/qsgflashnode_p.h (limited to 'src/quick') diff --git a/src/quick/designer/designerwindowmanager.cpp b/src/quick/designer/designerwindowmanager.cpp index 76789cd3a8..c4a95d254b 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 #include @@ -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); } diff --git a/src/quick/designer/designerwindowmanager_p.h b/src/quick/designer/designerwindowmanager_p.h index a822ead64e..1bab8c8508 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; @@ -91,12 +92,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 m_openGlContext; QScopedPointer m_sgContext; + QScopedPointer m_renderContext; }; QT_END_NAMESPACE 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 2b2504daf2..3088c41cd7 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -4112,7 +4112,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/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index a2e4e91755..0bed5e96a2 100644 --- a/src/quick/items/qquickborderimage.cpp +++ b/src/quick/items/qquickborderimage.cpp @@ -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; 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(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_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; @@ -838,6 +839,12 @@ Qt::MouseButtons QQuickItemPrivate::acceptedMouseButtons() const } QSGContext *QQuickItemPrivate::sceneGraphContext() const +{ + Q_ASSERT(window); + return static_cast(QObjectPrivate::get(window))->context->sceneGraphContext(); +} + +QSGRenderContext *QQuickItemPrivate::sceneGraphRenderContext() const { Q_ASSERT(window); return static_cast(QObjectPrivate::get(window))->context; diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index e86550d731..c05545c292 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -45,6 +45,7 @@ #include "qquickwindow_p.h" #include #include +#include #include "qopenglframebufferobject.h" #include "qmath.h" @@ -143,7 +144,7 @@ QQuickShaderEffectTexture::QQuickShaderEffectTexture(QQuickItem *shaderSource) #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) @@ -326,7 +327,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 extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' '); @@ -342,7 +343,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 +386,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 +588,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 +600,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(this)->m_provider = new QQuickShaderEffectSourceTextureProvider(); const_cast(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..85b58e67e4 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; @@ -139,10 +140,10 @@ private: QSharedPointer m_depthStencilBuffer; #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/qquicktext.cpp b/src/quick/items/qquicktext.cpp index fbda2df2dc..6335c83b2b 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -2241,11 +2241,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(oldNode); - } node->setUseNativeRenderer(d->renderType == NativeRendering && d->window->devicePixelRatio() <= 1); node->deleteContent(); diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index be2cd37dee..ffc732621d 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -2370,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..93ea677d2c 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -1834,7 +1834,7 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData QQuickTextNode *node = static_cast(oldNode); if (node == 0) - node = new QQuickTextNode(QQuickItemPrivate::get(this)->sceneGraphContext(), this); + node = new QQuickTextNode(this); d->textNode = node; if (!d->textLayoutDirty && oldNode != 0) { diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp index 1f4ca34b13..6acfaaf396 100644 --- a/src/quick/items/qquicktextnode.cpp +++ b/src/quick/items/qquicktextnode.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -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,10 @@ QSGGlyphNode *QQuickTextNode::addGlyphs(const QPointF &position, const QGlyphRun QQuickText::TextStyle style, const QColor &styleColor, QSGNode *parentNode) { + QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext(); QSGGlyphNode *node = m_useNativeRenderer - ? m_context->createNativeGlyphNode() - : m_context->createGlyphNode(); + ? 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 +191,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 m_textures; QQuickItem *m_ownerElement; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index fd0313aed5..ed97325c85 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -50,8 +50,6 @@ #include #include -#include - #include #include @@ -416,9 +414,10 @@ 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; @@ -2319,10 +2318,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; @@ -2546,19 +2541,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() @@ -2598,9 +2580,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(); } /*! @@ -2796,7 +2776,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(); } @@ -2993,7 +2973,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 @@ -3021,7 +3001,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); diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index c02f7107d4..2cf98bfe21 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -194,7 +194,7 @@ public: void fireFrameSwapped() { Q_EMIT q_func()->frameSwapped(); } - QSGContext *context; + QSGRenderContext *context; QSGRenderer *renderer; QSGRenderLoop *windowManager; diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index bf31b94e46..8514203f57 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -283,7 +283,6 @@ Updater::Updater(Renderer *r) void Updater::updateStates(QSGNode *n) { - m_toplevel_alpha = 1; m_current_clip = 0; m_added = 0; @@ -683,7 +682,7 @@ static int qsg_countNodesInBatches(const QDataBuffer &batches) return sum; } -Renderer::Renderer(QSGContext *ctx) +Renderer::Renderer(QSGRenderContext *ctx) : QSGRenderer(ctx) , m_opaqueRenderList(64) , m_alphaRenderList(64) diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 94e8ba5d96..a205306b77 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -389,7 +389,7 @@ public: class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer { public: - Renderer(QSGContext *); + Renderer(QSGRenderContext *); ~Renderer(); protected: diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp index 25d256158e..d186823958 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp +++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp @@ -478,7 +478,7 @@ QRect QSGMaterialShader::RenderState::deviceRect() const QOpenGLContext *QSGMaterialShader::RenderState::context() const { - return static_cast(m_data)->glContext(); + return static_cast(m_data)->context()->openglContext(); } 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..7d982cee36 100644 --- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp @@ -133,7 +133,7 @@ void QSGBindableFboId::bind() const */ -QSGRenderer::QSGRenderer(QSGContext *context) +QSGRenderer::QSGRenderer(QSGRenderContext *context) : QObject() , m_clear_color(Qt::transparent) , m_clear_mode(ClearColorBuffer | ClearDepthBuffer) @@ -161,20 +161,6 @@ QSGRenderer::~QSGRenderer() delete m_node_updater; } -/*! - 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 +384,6 @@ void QSGRenderer::preprocess() preprocessTime = frameTimer.nsecsElapsed(); #endif - nodeUpdater()->setToplevelOpacity(context()->renderAlpha()); nodeUpdater()->updateStates(m_root_node); #ifndef QSG_NO_RENDER_TIMING 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/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index cdf63be5f2..8585caa22d 100644 --- a/src/quick/scenegraph/qsgadaptationlayer.cpp +++ b/src/quick/scenegraph/qsgadaptationlayer.cpp @@ -60,9 +60,8 @@ static QElapsedTimer qsg_render_timer; QSGDistanceFieldGlyphCache::Texture QSGDistanceFieldGlyphCache::s_emptyTexture; -QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font) - : ctx(c) - , m_manager(man) +QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font) + : m_manager(man) , m_pendingGlyphs(64) { Q_ASSERT(font.isValid()); diff --git a/src/quick/scenegraph/qsgadaptationlayer_p.h b/src/quick/scenegraph/qsgadaptationlayer_p.h index ebeb449be5..f9e59f9c7f 100644 --- a/src/quick/scenegraph/qsgadaptationlayer_p.h +++ b/src/quick/scenegraph/qsgadaptationlayer_p.h @@ -149,7 +149,7 @@ public: class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldGlyphCache { public: - QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font); + QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font); virtual ~QSGDistanceFieldGlyphCache(); struct Metrics { @@ -246,8 +246,6 @@ protected: GlyphData &glyphData(glyph_t glyph); - QOpenGLContext *ctx; - private: QSGDistanceFieldGlyphCacheManager *m_manager; diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index bb8e3c4b36..558711ea0e 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -72,11 +72,8 @@ #include -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,49 +91,32 @@ 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 textures; - QSGDepthStencilBufferManager *depthStencilBufferManager; - QSGDistanceFieldGlyphCacheManager *distanceFieldCacheManager; - - QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing; - - QSGAtlasTexture::Manager *atlasManager; - - bool flashMode; - float renderAlpha; + QMutex mutex; + QSGContext::AntialiasingMethod antialiasingMethod; bool distanceFieldDisabled; - - bool msaa; + QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing; }; class QSGTextureCleanupEvent : public QEvent @@ -188,143 +168,158 @@ QSGContext::QSGContext(QObject *parent) : QSGContext::~QSGContext() { - invalidate(); } - - -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. - */ - - if (d->atlasManager) { - d->atlasManager->deleteLater(); - d->atlasManager = 0; + 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; + } } + 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(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(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) +{ + return new QAnimationDriver(parent); +} + +QSGRenderContext::QSGRenderContext(QSGContext *context) + : m_gl(0) + , m_sg(context) + , m_atlasManager(0) + , m_depthStencilManager(0) + , m_distanceFieldCacheManager(0) { - Q_D(const QSGContext); - return d->gl; } +QSGRenderContext::~QSGRenderContext() +{ + invalidate(); +} -void QSGContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId) +void QSGRenderContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId) { if (fboId) { QSGBindableFboId bindable(fboId); @@ -335,37 +330,15 @@ void QSGContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId) } -/*! - 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 +360,114 @@ QSGDistanceFieldGlyphCache *QSGContext::distanceFieldGlyphCache(const QRawFont & QPlatformSharedGraphicsCache::Alpha8); cache = new QSGSharedDistanceFieldGlyphCache(keyName, - sharedGraphicsCache, - d->distanceFieldCacheManager, - glContext(), - font); + sharedGraphicsCache, + m_distanceFieldCacheManager, + font); } } } if (!cache) - cache = new QSGDefaultDistanceFieldGlyphCache(d->distanceFieldCacheManager, glContext(), font); - d->distanceFieldCacheManager->insertCache(font, cache); + cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, 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(context->property(QSG_RENDERCONTEXT_PROPERTY).value()); } -/*! - 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); -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::const_iterator it = m_fontEnginesToClean.constBegin(), + end = m_fontEnginesToClean.constEnd(); it != end; ++it) { + (*it)->clearGlyphCache(m_gl); + } -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 QSGContext::depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo) +QSharedPointer QSGRenderContext::depthStencilBufferForFbo(QOpenGLFramebufferObject *fbo) { - Q_D(QSGContext); - if (!d->gl) + if (!m_gl) return QSharedPointer(); QSGDepthStencilBufferManager *manager = depthStencilBufferManager(); QSGDepthStencilBuffer::Format format; @@ -514,7 +476,7 @@ QSharedPointer QSGContext::depthStencilBufferForFbo(QOpen format.attachments = QSGDepthStencilBuffer::DepthAttachment | QSGDepthStencilBuffer::StencilAttachment; QSharedPointer buffer = manager->bufferForFormat(format); if (buffer.isNull()) { - buffer = QSharedPointer(new QSGDefaultDepthStencilBuffer(d->gl, format)); + buffer = QSharedPointer(new QSGDefaultDepthStencilBuffer(m_gl, format)); manager->insertBuffer(buffer); } return buffer; @@ -524,89 +486,81 @@ QSharedPointer 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; -/*! - Returns true if the scene graph uses the distance field technique to render text - */ -bool QSGContext::isDistanceFieldEnabled() const -{ - return !d_func()->distanceFieldDisabled; -} + m_mutex.lock(); + QSGTexture *texture = m_textures.value(factory); + m_mutex.unlock(); + if (!texture) { + if (QQuickDefaultTextureFactory *dtf = qobject_cast(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(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..a11a4856c4 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,95 @@ 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 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 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(); +Q_SIGNALS: + void initialized(); + void invalidated(); - void setFlashModeEnabled(bool enabled); - bool isFlashModeEnabled() const; - void setRenderAlpha(qreal renderAlpha); - qreal renderAlpha() const; +public Q_SLOTS: + void textureFactoryDestroyed(QObject *o); - void setDistanceFieldEnabled(bool enabled); - bool isDistanceFieldEnabled() const; +protected: + QOpenGLContext *m_gl; + QSGContext *m_sg; - virtual QAnimationDriver *createAnimationDriver(QObject *parent); + QMutex m_mutex; + QHash m_textures; + QSGAtlasTexture::Manager *m_atlasManager; - static QQuickTextureFactory *createTextureFactoryFromImage(const QImage &image); - static QSGRenderLoop *createWindowManager(); + QSGDepthStencilBufferManager *m_depthStencilManager; + QSGDistanceFieldGlyphCacheManager *m_distanceFieldCacheManager; + QSet m_fontEnginesToClean; +}; -public Q_SLOTS: - void textureFactoryDestroyed(QObject *o); -Q_SIGNALS: - void initialized(); - void invalidated(); +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); + + virtual QSize minimumFBOSize() const; + virtual QSurfaceFormat defaultSurfaceFormat() const; + + void setDistanceFieldEnabled(bool enabled); + bool isDistanceFieldEnabled() const; + + 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 bc09ed83d7..635f07f2ea 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -52,8 +52,8 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(qmlUseGlyphCacheWorkaround, QML_USE_GLYPHCACHE_WORKAROUND) -QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font) - : QSGDistanceFieldGlyphCache(man, c, font) +QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font) + : QSGDistanceFieldGlyphCache(man, font) , m_maxTextureSize(0) , m_maxTextureCount(3) , m_blitProgram(0) @@ -239,6 +239,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) @@ -361,7 +364,7 @@ bool QSGDefaultDistanceFieldGlyphCache::useWorkaround() const static bool set = false; static bool useWorkaround = false; if (!set) { - QOpenGLContextPrivate *ctx_p = static_cast(QOpenGLContextPrivate::get(ctx)); + QOpenGLContextPrivate *ctx_p = static_cast(QOpenGLContextPrivate::get(QOpenGLContext::currentContext())); useWorkaround = ctx_p->workaround_brokenFBOReadBack || qmlUseGlyphCacheWorkaround(); // on some hardware the workaround is faster (see QTBUG-29264) set = true; diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h index cd6fa00852..54b0bcb889 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h @@ -54,7 +54,7 @@ class QOpenGLSharedResourceGuard; class Q_QUICK_PRIVATE_EXPORT QSGDefaultDistanceFieldGlyphCache : public QSGDistanceFieldGlyphCache { public: - QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font); + QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font); virtual ~QSGDefaultDistanceFieldGlyphCache(); void requestGlyphs(const QSet &glyphs); diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index 39d9832f58..bf92bf8b39 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -480,6 +480,12 @@ void QSGTextMaskMaterial::init(int cacheType) QOpenGLContext *ctx = const_cast(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 +500,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/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp index 876a9ea9ad..49b56494db 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) 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/qsgflashnode.cpp b/src/quick/scenegraph/qsgflashnode.cpp deleted file mode 100644 index 7fbe673e15..0000000000 --- a/src/quick/scenegraph/qsgflashnode.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** 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 "qsgflashnode_p.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 -} - -void QSGFlashNode::preprocess() -{ - if (m_counter) { - --m_counter; - } else { - delete this; - } -} - -QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgflashnode_p.h b/src/quick/scenegraph/qsgflashnode_p.h deleted file mode 100644 index 96496158ae..0000000000 --- a/src/quick/scenegraph/qsgflashnode_p.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** 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$ -** -****************************************************************************/ - -#ifndef QSGFLASHNODE_H -#define QSGFLASHNODE_H - -#include - -QT_BEGIN_NAMESPACE - -class QSGFlashNode : public QSGSimpleRectNode -{ -public: - QSGFlashNode(); - - void preprocess(); - -private: - int m_counter; -}; - -QT_END_NAMESPACE - -#endif // QSGFLASHNODE_H - diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 163d1d35c5..fc1e98d87f 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,7 +142,6 @@ bool QSGRenderLoop::useConsistentTiming() QSGRenderLoop *QSGRenderLoop::instance() { if (!s_instance) { - s_instance = QSGContext::createWindowManager(); if (useConsistentTiming()) @@ -202,8 +203,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 +233,7 @@ void QSGGuiThreadRenderLoop::hide(QQuickWindow *window) if (m_windows.size() == 0) { if (!cd->persistentSceneGraph) { - sg->invalidate(); + rc->invalidate(); if (!cd->persistentGLContext) { delete gl; gl = 0; @@ -239,7 +246,7 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window) { hide(window); if (m_windows.size() == 0) { - sg->invalidate(); + rc->invalidate(); delete gl; gl = 0; } @@ -264,7 +271,7 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) 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..7b06399f08 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 @@ -72,6 +73,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..20e1210b68 100644 --- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp @@ -199,9 +199,8 @@ namespace { QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId, QPlatformSharedGraphicsCache *sharedGraphicsCache, QSGDistanceFieldGlyphCacheManager *man, - QOpenGLContext *c, const QRawFont &font) - : QSGDistanceFieldGlyphCache(man, c, font) + : QSGDistanceFieldGlyphCache(man, font) , m_cacheId(cacheId) , m_sharedGraphicsCache(sharedGraphicsCache) , m_isInSceneGraphUpdate(false) @@ -228,6 +227,8 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr this, SLOT(reportItemsInvalidated(QByteArray,QVector)), Qt::DirectConnection); + QOpenGLContext *c = QOpenGLContext::currentContext(); + Q_ASSERT(c); QQuickWindow *window = static_cast(c->surface()); Q_ASSERT(window != 0); diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h index d72d2a740f..a8d70be732 100644 --- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h @@ -55,7 +55,6 @@ public: explicit QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId, QPlatformSharedGraphicsCache *sharedGraphicsCache, QSGDistanceFieldGlyphCacheManager *man, - QOpenGLContext *c, const QRawFont &font); ~QSGSharedDistanceFieldGlyphCache(); diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 7421db1db1..bb0bd67d6b 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 @@ -98,6 +109,7 @@ 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 @@ -276,23 +288,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 +321,7 @@ public: { if (sleeping) stopEventProcessing = true; - if (m_windows.size() > 0) + if (window) pendingUpdate |= RepaintRequest; } @@ -329,16 +343,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 +360,8 @@ public: QElapsedTimer m_timer; - struct Window { - QQuickWindow *window; - QSize size; - }; - QList m_windows; + QQuickWindow *window; // Will be 0 when window is not exposed + QSize windowSize; // Local event queue stuff... bool stopEventProcessing; @@ -368,33 +378,29 @@ bool QSGRenderThread::event(QEvent *e) pendingUpdate |= RepaintRequest; - if (Window *w = windowFor(m_windows, se->window)) { - w->size = se->size; + Q_ASSERT(!window || window == se->window); + + windowSize = se->size; + if (window) { RLDEBUG1(" Render: - window already added..."); return true; } - Window window; - window.window = se->window; - window.size = se->size; - m_windows << window; + window = se->window; connect(animatorDriver, SIGNAL(started()), QQuickWindowPrivate::get(se->window)->animationController, SLOT(animationsStarted())); return true; } case WM_Obscure: { RLDEBUG1(" Render: WM_Obscure"); + WMWindowEvent *ce = static_cast(e); - for (int i=0; iwindow) { - RLDEBUG1(" Render: - removed one..."); - m_windows.removeAt(i); - disconnect(animatorDriver, SIGNAL(started()), QQuickWindowPrivate::get(ce->window)->animationController, SLOT(animationsStarted())); - break; - } - } + Q_ASSERT(!window || window == ce->window); - if (sleeping && m_windows.size()) - stopEventProcessing = true; + if (window) { + RLDEBUG1(" Render: - removed one..."); + window = 0; + disconnect(animatorDriver, SIGNAL(started()), QQuickWindowPrivate::get(ce->window)->animationController, SLOT(animationsStarted())); + } return true; } @@ -402,23 +408,20 @@ bool QSGRenderThread::event(QEvent *e) RLDEBUG(" Render: WM_RequestSync"); if (sleeping) stopEventProcessing = true; - if (m_windows.size() > 0) + if (window) pendingUpdate |= SyncRequest; return true; case WM_TryRelease: { RLDEBUG1(" Render: WM_TryRelease"); mutex.lock(); - WMTryReleaseEvent *wme = static_cast(e); - if (m_windows.size() == 0) { + if (!window) { + WMTryReleaseEvent *wme = static_cast(e); RLDEBUG1(" Render: - 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..."); } @@ -430,20 +433,20 @@ bool QSGRenderThread::event(QEvent *e) case WM_Grab: { RLDEBUG1(" Render: WM_Grab"); WMGrabEvent *ce = static_cast(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); + QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); d->syncSceneGraph(); RLDEBUG1(" Render: - rendering scene graph"); - QQuickWindowPrivate::get(ce->window)->renderSceneGraph(w->size); + QQuickWindowPrivate::get(window)->renderSceneGraph(windowSize); RLDEBUG1(" Render: - grabbing result..."); - *ce->image = qt_gl_read_framebuffer(w->size, false, false); + *ce->image = qt_gl_read_framebuffer(windowSize, false, false); } RLDEBUG1(" Render: - waking gui to handle grab result"); waitCondition.wakeOne(); @@ -476,38 +479,27 @@ 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; im_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) { + } else { RLDEBUG1(" Render: - persistent SG, avoiding cleanup"); return; } - sg->invalidate(); + sgrc->invalidate(); + QCoreApplication::processEvents(); QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); gl->doneCurrent(); RLDEBUG1(" Render: - invalidated scenegraph.."); - if (!persistentGL) { + if (wipeGL) { delete gl; gl = 0; RLDEBUG1(" Render: - invalidated OpenGL"); @@ -525,16 +517,11 @@ void QSGRenderThread::sync() RLDEBUG(" Render: 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.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); + if (windowSize.width() > 0 && windowSize.height() > 0) { + gl->makeCurrent(window); + QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); bool hadRenderer = d->renderer != 0; d->syncSceneGraph(); if (!hadRenderer && d->renderer) { @@ -542,12 +529,16 @@ void QSGRenderThread::sync() 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 { + RLDEBUG(" Render: - window has bad size, waiting..."); + } + RLDEBUG(" Render: - window has bad size, waiting..."); waitCondition.wakeOne(); mutex.unlock(); } @@ -583,7 +574,6 @@ void QSGRenderThread::syncAndRender() int waitTime = vsyncDelta - (int) waitTimer.elapsed(); if (waitTime > 0) msleep(waitTime); - emit wm->timeToIncubate(); return; } @@ -596,28 +586,26 @@ void QSGRenderThread::syncAndRender() if (animatorDriver->isRunning()) animatorDriver->advance(); - for (int i=0; i(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); + QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); + if (d->renderer && windowSize.width() > 0 && windowSize.height() > 0) { + gl->makeCurrent(window); + 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 { + RLDEBUG(" Render: - Window not yet ready, skipping render..."); } + RLDEBUG(" Render: - rendering done"); - emit wm->timeToIncubate(); #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), @@ -668,16 +656,16 @@ void QSGRenderThread::processEventsAndWaitForMore() void QSGRenderThread::run() { RLDEBUG1(" Render: run()"); - animatorDriver = sg->createAnimationDriver(0); + 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()) { + gl->makeCurrent(window); + sgrc->initialize(gl); } syncAndRender(); } @@ -685,14 +673,12 @@ void QSGRenderThread::run() processEvents(); QCoreApplication::processEvents(); - if (!shouldExit - && (pendingUpdate == 0 || m_windows.size() == 0)) { + if (active && (pendingUpdate == 0 || !window)) { RLDEBUG(" Render: 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..."); @@ -701,21 +687,20 @@ void QSGRenderThread::run() 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); @@ -726,11 +711,16 @@ QSGThreadedRenderLoop::QSGThreadedRenderLoop() RLDEBUG1("GUI: QSGThreadedRenderLoop() created"); } -void QSGThreadedRenderLoop::maybePostPolishRequest() +QSGRenderContext *QSGThreadedRenderLoop::createRenderContext(QSGContext *sg) const { - if (m_update_timer == 0) { + return new QSGRenderContext(sg); +} + +void QSGThreadedRenderLoop::maybePostPolishRequest(Window *w) +{ + if (w->timerId == 0) { RLDEBUG("GUI: - posting update"); - m_update_timer = startTimer(m_exhaust_delay, Qt::PreciseTimer); + w->timerId = startTimer(m_exhaust_delay, Qt::PreciseTimer); } } @@ -741,7 +731,7 @@ QAnimationDriver *QSGThreadedRenderLoop::animationDriver() const QSGContext *QSGThreadedRenderLoop::sceneGraphContext() const { - return m_thread->sg; + return sg; } bool QSGThreadedRenderLoop::anyoneShowing() const @@ -762,24 +752,39 @@ bool QSGThreadedRenderLoop::interleaveIncubation() const void QSGThreadedRenderLoop::animationStarted() { RLDEBUG("GUI: animationStarted()"); - if (!anyoneShowing() && m_animation_timer == 0) - m_animation_timer = startTimer(qsgrl_animation_interval()); - maybePostPolishRequest(); + startOrStopAnimationTimer(); + + for (int i=0; i(&m_windows.at(i))); } void QSGThreadedRenderLoop::animationStopped() { RLDEBUG("GUI: animationStopped()"); - if (!anyoneShowing()) { + startOrStopAnimationTimer(); +} + + +void QSGThreadedRenderLoop::startOrStopAnimationTimer() +{ + int exposedWindows = 0; + for (int i=0; iisVisible() && w.window->isExposed()) + ++exposedWindows; + } + + if (m_animation_timer != 0 && (exposedWindows == 1 || !m_animation_driver->isRunning())) { killTimer(m_animation_timer); m_animation_timer = 0; + + } 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. */ @@ -788,8 +793,16 @@ void QSGThreadedRenderLoop::show(QQuickWindow *window) { RLDEBUG1("GUI: show()"); + if (windowFor(m_windows, window)) { + RLDEBUG1("GUI: - already showing"); + return; + } + Window win; win.window = window; + win.thread = new QSGRenderThread(this, QQuickWindowPrivate::get(window)->context); + win.timerId = 0; + win.updateDuringSync = false; m_windows << win; } @@ -806,16 +819,9 @@ void QSGThreadedRenderLoop::hide(QQuickWindow *window) RLDEBUG1("GUI: hide()"); if (window->isExposed()) - handleObscurity(window); + handleObscurity(windowFor(m_windows, window)); releaseResources(window); - - for (int i=0; iisRunning()) + QThread::yieldCurrentThread(); + Q_ASSERT(thread->thread() == QThread::currentThread()); + delete thread; + m_windows.removeAt(i); + break; + } + } + RLDEBUG1("GUI: - done with windowDestroyed()"); } @@ -839,13 +857,14 @@ void QSGThreadedRenderLoop::windowDestroyed(QQuickWindow *window) void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window) { RLDEBUG1("GUI: exposureChanged()"); - if (windowFor(m_windows, window) == 0) + Window *w = windowFor(m_windows, window); + if (!w) return; if (window->isExposed()) { - handleExposure(window); + handleExposure(w); } else { - handleObscurity(window); + handleObscurity(w); } } @@ -854,49 +873,53 @@ 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"); // 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; + if (!w->thread->isRunning()) { RLDEBUG1("GUI: - starting render thread..."); - if (!m_thread->gl) { - QOpenGLContext *ctx = new QOpenGLContext(); - ctx->setFormat(window->requestedFormat()); - ctx->create(); - ctx->moveToThread(m_thread); - m_thread->gl = ctx; + if (!w->thread->gl) { + w->thread->gl = new QOpenGLContext(); + 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; + } + + w->thread->gl->moveToThread(w->thread); + RLDEBUG1("GUI: - 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"); } - 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 +929,47 @@ 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 (w->thread->isRunning()) + w->thread->postEvent(new WMWindowEvent(w->window, WM_Obscure)); - if (!anyoneShowing() && m_animation_driver->isRunning() && m_animation_timer == 0) { - m_animation_timer = startTimer(qsgrl_animation_interval()); - } + 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()) { + 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) { + if (QThread::currentThread() == w->thread) { RLDEBUG("GUI: - on render thread, will update later.."); - m_sync_triggered_update = true; + w->updateDuringSync = true; return; } - maybePostPolishRequest(); + maybePostPolishRequest(w); } /*! @@ -952,15 +979,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()) { + RLDEBUG(" Render: QQuickWindow::update called on render thread"); + w->thread->requestRepaint(); return; } - RLDEBUG("Gui: update called"); - m_thread->postEvent(new QEvent(WM_RequestRepaint)); - maybeUpdate(window); + RLDEBUG("GUI: update called"); + w->thread->postEvent(new QEvent(WM_RequestRepaint)); + maybeUpdate(w); } @@ -973,26 +1004,32 @@ void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestru { RLDEBUG1("GUI: releaseResources requested..."); - m_thread->mutex.lock(); - if (m_thread->isRunning() && !m_thread->shouldExit) { + Window *w = windowFor(m_windows, window); + if (!w) + return; + + w->thread->mutex.lock(); + if (w->thread->isRunning() && w->thread->active) { RLDEBUG1("GUI: - posting release request to render thread"); - m_thread->postEvent(new WMTryReleaseEvent(window, inDestructor)); - m_thread->waitCondition.wait(&m_thread->mutex); + 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; + RLDEBUG("GUI: polishAndSync()"); + + if (!w->window->isExposed() || !w->window->isVisible()) { + RLDEBUG("GUI: - not exposed, aborting..."); + killTimer(w->timerId); + w->timerId = 0; return; } - RLDEBUG("GUI: polishAndSync()"); #ifndef QSG_NO_RENDER_TIMING QElapsedTimer timer; @@ -1004,32 +1041,29 @@ 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; ipolishItems(); - } + 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)); + w->thread->mutex.lock(); + m_locked = true; + w->thread->postEvent(new QEvent(WM_RequestSync)); RLDEBUG("GUI: - 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(); + w->thread->waitCondition.wait(&w->thread->mutex); + m_locked = false; + w->thread->mutex.unlock(); RLDEBUG("GUI: - unlocked after sync..."); #ifndef QSG_NO_RENDER_TIMING @@ -1037,19 +1071,21 @@ void QSGThreadedRenderLoop::polishAndSync() syncTime = timer.nsecsElapsed(); #endif - killTimer(m_update_timer); - m_update_timer = 0; + killTimer(w->timerId); + w->timerId = 0; - if (m_animation_driver->isRunning()) { + if (m_windows.size() == 1 && m_animation_driver->isRunning()) { RLDEBUG("GUI: - animations advancing"); m_animation_driver->advance(); RLDEBUG("GUI: - 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 +1109,26 @@ bool QSGThreadedRenderLoop::event(QEvent *e) { switch ((int) e->type()) { - case QEvent::Timer: - if (static_cast(e)->timerId() == m_animation_timer) { + case QEvent::Timer: { + QTimerEvent *te = static_cast(e); + if (te->timerId() == m_animation_timer) { RLDEBUG("GUI: QEvent::Timer -> non-visual animation"); m_animation_driver->advance(); - } else if (static_cast(e)->timerId() == m_update_timer) { + emit timeToIncubate(); + } else { RLDEBUG("GUI: QEvent::Timer -> Polish & Sync"); - polishAndSync(); + Window *w = 0; + for (int i=0; itimerId()) { + w = const_cast(&m_windows.at(i)); + break; + } + } + if (w) + polishAndSync(w); } return true; + } default: break; @@ -1105,7 +1152,11 @@ bool QSGThreadedRenderLoop::event(QEvent *e) QImage QSGThreadedRenderLoop::grab(QQuickWindow *window) { RLDEBUG("GUI: grab"); - if (!m_thread->isRunning()) + + Window *w = windowFor(m_windows, window); + Q_ASSERT(w); + + if (!w->thread->isRunning()) return QImage(); if (!window->handle()) @@ -1116,12 +1167,12 @@ QImage QSGThreadedRenderLoop::grab(QQuickWindow *window) d->polishItems(); QImage result; - m_thread->mutex.lock(); + w->thread->mutex.lock(); RLDEBUG1("GUI: - locking, posting grab event"); - m_thread->postEvent(new WMGrabEvent(window, &result)); - m_thread->waitCondition.wait(&m_thread->mutex); + w->thread->postEvent(new WMGrabEvent(window, &result)); + w->thread->waitCondition.wait(&w->thread->mutex); RLDEBUG1("GUI: - locking, grab done, unlocking"); - m_thread->mutex.unlock(); + w->thread->mutex.unlock(); RLDEBUG1("Gui: - grab complete"); diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h index b943739a0d..5943d0bd08 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h +++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h @@ -64,14 +64,12 @@ public: 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 +84,13 @@ public Q_SLOTS: void animationStopped(); private: + struct Window { + QQuickWindow *window; + QSGRenderThread *thread; + int timerId; + uint updateDuringSync : 1; + }; + friend class QSGRenderThread; void releaseResources(QQuickWindow *window, bool inDestructor); @@ -94,25 +99,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 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..f1d09c3785 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(); @@ -176,7 +184,7 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window) m_gl->makeCurrent(window); RLDEBUG(" - initializing SG"); QSG_RENDER_TIMING_SAMPLE(time_current); - m_sg->initialize(m_gl); + QQuickWindowPrivate::get(window)->context->initialize(m_gl); #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) { @@ -230,7 +238,7 @@ void QSGWindowsRenderLoop::hide(QQuickWindow *window) // potentially clean up. if (m_windows.size() == 0) { if (!cd->persistentSceneGraph) { - m_sg->invalidate(); + QQuickWindowPrivate::get(window)->context->invalidate(); if (!cd->persistentGLContext) { delete m_gl; m_gl = 0; @@ -246,7 +254,7 @@ 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(); delete m_gl; m_gl = 0; } diff --git a/src/quick/scenegraph/qsgwindowsrenderloop_p.h b/src/quick/scenegraph/qsgwindowsrenderloop_p.h index cb01e1e04b..ff5529646b 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,6 +74,7 @@ public: QAnimationDriver *animationDriver() const { return m_animationDriver; } QSGContext *sceneGraphContext() const { return m_sg; } + QSGRenderContext *createRenderContext(QSGContext *) const { return m_rc; } void releaseResources(QQuickWindow *) { } @@ -102,6 +106,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..2bcef43843 100644 --- a/src/quick/scenegraph/scenegraph.pri +++ b/src/quick/scenegraph/scenegraph.pri @@ -67,7 +67,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,7 +83,6 @@ SOURCES += \ $$PWD/qsgdistancefieldglyphnode_p.cpp \ $$PWD/qsgdefaultimagenode.cpp \ $$PWD/qsgdefaultrectanglenode.cpp \ - $$PWD/qsgflashnode.cpp \ $$PWD/qsgshareddistancefieldglyphcache.cpp \ $$PWD/qsgrenderloop.cpp \ $$PWD/qsgthreadedrenderloop.cpp \ diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index 12ab48e193..b180bc43bd 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -47,11 +47,14 @@ #include #include #include +#include #include #include +QT_BEGIN_NAMESPACE + #ifndef GL_BGRA #define GL_BGRA 0x80E1 #endif @@ -89,11 +92,15 @@ 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); @@ -102,13 +109,16 @@ Manager::Manager() 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 +128,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; } @@ -153,13 +160,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); @@ -386,7 +401,6 @@ void Atlas::remove(Texture *t) { QRect atlasRect = t->atlasSubRect(); m_allocator.deallocate(atlasRect); - m_pending_uploads.removeOne(t); } @@ -431,3 +445,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 #include +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/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(QObjectPrivate::get(item))->sceneGraphContext(); + m_context = static_cast(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; -- cgit v1.2.3 From 388fc07cf28417f6e755ad8a105a71aa55ab13c8 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Fri, 18 Oct 2013 15:21:43 +0200 Subject: Don't let contentItem be FINAL in order to allow shadowing. For subclasses that adds menubars, toolbars etc, the plan is to expose another item (the item excluding the menubars, toolbars) as a contentItem. Task-number: QTBUG-32443 Change-Id: Id12fc50efde3fdf363e4528dd5de17177ddef24f Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com> --- src/quick/items/qquickwindow.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index 420b13eeff..6fd01a3119 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 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) -- cgit v1.2.3 From 4a7f1326e3d342148a4a9147505a4d8d531b4a06 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 30 Oct 2013 14:09:18 +0100 Subject: Work around Nouveau driver bugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I25311a2bd88f41087352e0a43ba505f4e27b7e85 Reviewed-by: Jørgen Lind --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 26 +++++++++++++++++------ src/quick/scenegraph/qsgcontext.cpp | 7 ++++++ src/quick/scenegraph/qsgcontext_p.h | 5 ++++- 3 files changed, 31 insertions(+), 7 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 8514203f57..7a62dccc0f 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -1889,7 +1889,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(); @@ -1924,7 +1931,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)); } } @@ -1957,8 +1964,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; @@ -1977,7 +1991,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(); @@ -2008,7 +2022,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()); diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 558711ea0e..4fbefb37d8 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -311,6 +311,7 @@ QSGRenderContext::QSGRenderContext(QSGContext *context) , m_atlasManager(0) , m_depthStencilManager(0) , m_distanceFieldCacheManager(0) + , m_brokenIBOs(false) { } @@ -408,6 +409,12 @@ void QSGRenderContext::initialize(QOpenGLContext *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; +#endif + emit initialized(); } diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index a11a4856c4..08fafb0713 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -109,11 +109,12 @@ public: static QSGRenderContext *from(QOpenGLContext *context); + bool hasBrokenIndexBufferObjects() const { return m_brokenIBOs; } + Q_SIGNALS: void initialized(); void invalidated(); - public Q_SLOTS: void textureFactoryDestroyed(QObject *o); @@ -129,6 +130,8 @@ protected: QSGDistanceFieldGlyphCacheManager *m_distanceFieldCacheManager; QSet m_fontEnginesToClean; + + bool m_brokenIBOs; }; -- cgit v1.2.3 From 426f6aa672b94d8324321bc6c6d4f1a358eebedc Mon Sep 17 00:00:00 2001 From: Sean Harmer Date: Sat, 26 Oct 2013 18:48:56 +0100 Subject: Refactor shaders into seprate GLSL source files The default implementation of QSGShaderMaterial::vertexShader() and fragmentShader() now loads the GLSL source from a list of source files that can be specified via the setShaderSourceFile() or setShaderSourceFiles() functions. Multiple shader source files for each shader stage are supported. Each source file will be read in the order specified and concatenated together before being compiled. The other places where Qt Quick 2 loads shader source code have been adapted to use the new QSGShaderSourceBuilder, which is also used internally by QSGMaterial. This puts Qt Quick 2 into a better state ready to support OpenGL core profile and to load different shaders based upon OpenGL version, profile, GPU vendor, platform, etc. Change-Id: I1a66213c2ce788413168eb48c7bc5317e61988a2 Reviewed-by: Gunnar Sletta --- src/quick/items/items.pri | 11 +- src/quick/items/items.qrc | 10 + src/quick/items/qquickanimatedsprite.cpp | 41 +--- src/quick/items/qquickshadereffect.cpp | 33 +-- src/quick/items/qquickshadereffectnode.cpp | 16 +- src/quick/items/qquickspritesequence.cpp | 41 +--- src/quick/items/shaders/shadereffect.frag | 9 + src/quick/items/shaders/shadereffect.vert | 12 + src/quick/items/shaders/shadereffectfallback.frag | 4 + src/quick/items/shaders/shadereffectfallback.vert | 8 + src/quick/items/shaders/sprite.frag | 12 + src/quick/items/shaders/sprite.vert | 23 ++ src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 23 +- src/quick/scenegraph/coreapi/qsgmaterial.cpp | 61 +++++- src/quick/scenegraph/coreapi/qsgmaterial.h | 15 +- src/quick/scenegraph/coreapi/qsgmaterialshader_p.h | 61 ++++++ src/quick/scenegraph/coreapi/qsgrenderer.cpp | 15 +- src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 159 ++------------ src/quick/scenegraph/qsgdefaultimagenode.cpp | 76 +------ src/quick/scenegraph/qsgdefaultrectanglenode.cpp | 66 +----- .../scenegraph/qsgdistancefieldglyphnode_p.cpp | 243 ++------------------- src/quick/scenegraph/scenegraph.pri | 51 ++++- src/quick/scenegraph/scenegraph.qrc | 36 +++ src/quick/scenegraph/shaders/24bittextmask.frag | 10 + src/quick/scenegraph/shaders/8bittextmask.frag | 9 + .../shaders/distancefieldoutlinetext.frag | 16 ++ .../shaders/distancefieldshiftedtext.frag | 17 ++ .../shaders/distancefieldshiftedtext.vert | 17 ++ .../scenegraph/shaders/distancefieldtext.frag | 13 ++ .../scenegraph/shaders/distancefieldtext.vert | 13 ++ src/quick/scenegraph/shaders/flatcolor.frag | 6 + src/quick/scenegraph/shaders/flatcolor.vert | 7 + .../shaders/hiqsubpixeldistancefieldtext.frag | 58 +++++ .../shaders/hiqsubpixeldistancefieldtext.vert | 34 +++ .../shaders/loqsubpixeldistancefieldtext.frag | 17 ++ .../shaders/loqsubpixeldistancefieldtext.vert | 27 +++ src/quick/scenegraph/shaders/opaquetexture.frag | 8 + src/quick/scenegraph/shaders/opaquetexture.vert | 12 + src/quick/scenegraph/shaders/outlinedtext.frag | 21 ++ src/quick/scenegraph/shaders/outlinedtext.vert | 22 ++ src/quick/scenegraph/shaders/rendernode.frag | 8 + src/quick/scenegraph/shaders/rendernode.vert | 10 + src/quick/scenegraph/shaders/smoothcolor.frag | 6 + src/quick/scenegraph/shaders/smoothcolor.vert | 45 ++++ src/quick/scenegraph/shaders/smoothtexture.frag | 9 + src/quick/scenegraph/shaders/smoothtexture.vert | 52 +++++ src/quick/scenegraph/shaders/stencilclip.frag | 4 + src/quick/scenegraph/shaders/stencilclip.vert | 8 + src/quick/scenegraph/shaders/styledtext.frag | 14 ++ src/quick/scenegraph/shaders/styledtext.vert | 16 ++ src/quick/scenegraph/shaders/textmask.frag | 10 + src/quick/scenegraph/shaders/textmask.vert | 13 ++ src/quick/scenegraph/shaders/texture.frag | 9 + src/quick/scenegraph/shaders/vertexcolor.frag | 6 + src/quick/scenegraph/shaders/vertexcolor.vert | 13 ++ src/quick/scenegraph/util/qsgflatcolormaterial.cpp | 29 +-- .../scenegraph/util/qsgshadersourcebuilder.cpp | 106 +++++++++ .../scenegraph/util/qsgshadersourcebuilder_p.h | 77 +++++++ src/quick/scenegraph/util/qsgtexturematerial.cpp | 50 +---- src/quick/scenegraph/util/qsgtexturematerial_p.h | 8 +- .../scenegraph/util/qsgvertexcolormaterial.cpp | 33 +-- 61 files changed, 1144 insertions(+), 715 deletions(-) create mode 100644 src/quick/items/items.qrc create mode 100644 src/quick/items/shaders/shadereffect.frag create mode 100644 src/quick/items/shaders/shadereffect.vert create mode 100644 src/quick/items/shaders/shadereffectfallback.frag create mode 100644 src/quick/items/shaders/shadereffectfallback.vert create mode 100644 src/quick/items/shaders/sprite.frag create mode 100644 src/quick/items/shaders/sprite.vert create mode 100644 src/quick/scenegraph/coreapi/qsgmaterialshader_p.h create mode 100644 src/quick/scenegraph/scenegraph.qrc create mode 100644 src/quick/scenegraph/shaders/24bittextmask.frag create mode 100644 src/quick/scenegraph/shaders/8bittextmask.frag create mode 100644 src/quick/scenegraph/shaders/distancefieldoutlinetext.frag create mode 100644 src/quick/scenegraph/shaders/distancefieldshiftedtext.frag create mode 100644 src/quick/scenegraph/shaders/distancefieldshiftedtext.vert create mode 100644 src/quick/scenegraph/shaders/distancefieldtext.frag create mode 100644 src/quick/scenegraph/shaders/distancefieldtext.vert create mode 100644 src/quick/scenegraph/shaders/flatcolor.frag create mode 100644 src/quick/scenegraph/shaders/flatcolor.vert create mode 100644 src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext.frag create mode 100644 src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext.vert create mode 100644 src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext.frag create mode 100644 src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext.vert create mode 100644 src/quick/scenegraph/shaders/opaquetexture.frag create mode 100644 src/quick/scenegraph/shaders/opaquetexture.vert create mode 100644 src/quick/scenegraph/shaders/outlinedtext.frag create mode 100644 src/quick/scenegraph/shaders/outlinedtext.vert create mode 100644 src/quick/scenegraph/shaders/rendernode.frag create mode 100644 src/quick/scenegraph/shaders/rendernode.vert create mode 100644 src/quick/scenegraph/shaders/smoothcolor.frag create mode 100644 src/quick/scenegraph/shaders/smoothcolor.vert create mode 100644 src/quick/scenegraph/shaders/smoothtexture.frag create mode 100644 src/quick/scenegraph/shaders/smoothtexture.vert create mode 100644 src/quick/scenegraph/shaders/stencilclip.frag create mode 100644 src/quick/scenegraph/shaders/stencilclip.vert create mode 100644 src/quick/scenegraph/shaders/styledtext.frag create mode 100644 src/quick/scenegraph/shaders/styledtext.vert create mode 100644 src/quick/scenegraph/shaders/textmask.frag create mode 100644 src/quick/scenegraph/shaders/textmask.vert create mode 100644 src/quick/scenegraph/shaders/texture.frag create mode 100644 src/quick/scenegraph/shaders/vertexcolor.frag create mode 100644 src/quick/scenegraph/shaders/vertexcolor.vert create mode 100644 src/quick/scenegraph/util/qsgshadersourcebuilder.cpp create mode 100644 src/quick/scenegraph/util/qsgshadersourcebuilder_p.h (limited to 'src/quick') diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri index cbdc5fd80f..d0ebbcfcdb 100644 --- a/src/quick/items/items.pri +++ b/src/quick/items/items.pri @@ -139,6 +139,15 @@ 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 +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..837cffb65a --- /dev/null +++ b/src/quick/items/items.qrc @@ -0,0 +1,10 @@ + + + shaders/sprite.frag + shaders/sprite.vert + shaders/shadereffect.vert + shaders/shadereffect.frag + shaders/shadereffectfallback.frag + shaders/shadereffectfallback.vert + + diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index c90adc24a5..4c16a1e9e2 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,8 +101,11 @@ QQuickAnimatedSpriteMaterial::~QQuickAnimatedSpriteMaterial() class AnimatedSpriteMaterialData : public QSGMaterialShader { public: - AnimatedSpriteMaterialData(const char * /* vertexFile */ = 0, const char * /* fragmentFile */ = 0) + AnimatedSpriteMaterialData() + : QSGMaterialShader() { + 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 *) @@ -158,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", diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index 354b9f751b..9c766a1622 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -43,6 +43,7 @@ #include #include +#include #include "qquickitem_p.h" #include @@ -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"; @@ -979,10 +962,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..8788fa8362 100644 --- a/src/quick/items/qquickshadereffectnode.cpp +++ b/src/quick/items/qquickshadereffectnode.cpp @@ -45,6 +45,7 @@ #include "qquickshadereffect_p.h" #include #include +#include QT_BEGIN_NAMESPACE @@ -276,20 +277,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/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp index 8a6789bb9f..28f1397cc9 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,8 +100,11 @@ QQuickSpriteSequenceMaterial::~QQuickSpriteSequenceMaterial() class SpriteSequenceMaterialData : public QSGMaterialShader { public: - SpriteSequenceMaterialData(const char * /* vertexFile */ = 0, const char * /* fragmentFile */ = 0) + SpriteSequenceMaterialData() + : QSGMaterialShader() { + 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 *) @@ -157,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", 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/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/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/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 7a62dccc0f..e7c611029d 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qsgbatchrenderer_p.h" +#include #include @@ -2322,23 +2323,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/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp index d186823958..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 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 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 d_ptr; }; struct QSGMaterialType { }; diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h new file mode 100644 index 0000000000..fc8a35c41d --- /dev/null +++ b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QSGMATERIALSHADER_P_H +#define QSGMATERIALSHADER_P_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_QUICK_PRIVATE_EXPORT QSGMaterialShaderPrivate +{ +public: + const char *loadShaderSource(QOpenGLShader::ShaderType type) const; + + QHash m_sourceFiles; + mutable QHash m_sources; +}; + +QT_END_NAMESPACE + +#endif // QSGMATERIALSHADER_P_H diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp index 7d982cee36..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 +#include #include #include @@ -481,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/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index bf92bf8b39..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 #include @@ -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) 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 #include #include @@ -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_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp index 125243847a..ac936b6663 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() { @@ -554,107 +475,24 @@ QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader() cons 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 +550,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/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri index 2bcef43843..aebc2ece9c 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 += \ @@ -87,3 +90,41 @@ SOURCES += \ $$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 + diff --git a/src/quick/scenegraph/scenegraph.qrc b/src/quick/scenegraph/scenegraph.qrc new file mode 100644 index 0000000000..5299ec6d9f --- /dev/null +++ b/src/quick/scenegraph/scenegraph.qrc @@ -0,0 +1,36 @@ + + + shaders/flatcolor.frag + shaders/flatcolor.vert + shaders/8bittextmask.frag + shaders/24bittextmask.frag + shaders/opaquetexture.frag + shaders/opaquetexture.vert + shaders/outlinedtext.frag + shaders/outlinedtext.vert + shaders/smoothcolor.frag + shaders/smoothcolor.vert + shaders/smoothtexture.frag + shaders/smoothtexture.vert + shaders/styledtext.frag + shaders/styledtext.vert + shaders/textmask.frag + shaders/textmask.vert + shaders/texture.frag + shaders/distancefieldoutlinetext.frag + shaders/distancefieldshiftedtext.frag + shaders/distancefieldshiftedtext.vert + shaders/distancefieldtext.frag + shaders/distancefieldtext.vert + shaders/hiqsubpixeldistancefieldtext.frag + shaders/hiqsubpixeldistancefieldtext.vert + shaders/loqsubpixeldistancefieldtext.frag + shaders/loqsubpixeldistancefieldtext.vert + shaders/vertexcolor.frag + shaders/vertexcolor.vert + shaders/rendernode.vert + shaders/rendernode.frag + shaders/stencilclip.frag + shaders/stencilclip.vert + + diff --git a/src/quick/scenegraph/shaders/24bittextmask.frag b/src/quick/scenegraph/shaders/24bittextmask.frag new file mode 100644 index 0000000000..ac62e7b642 --- /dev/null +++ b/src/quick/scenegraph/shaders/24bittextmask.frag @@ -0,0 +1,10 @@ +varying highp vec2 sampleCoord; + +uniform lowp sampler2D texture; +uniform lowp float color; // just the alpha, really... + +void main() +{ + lowp vec4 glyph = texture2D(texture, sampleCoord); + gl_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..f2f06e8e07 --- /dev/null +++ b/src/quick/scenegraph/shaders/8bittextmask.frag @@ -0,0 +1,9 @@ +varying highp vec2 sampleCoord; + +uniform lowp sampler2D texture; +uniform lowp vec4 color; + +void main() +{ + gl_FragColor = color * texture2D(texture, sampleCoord).a; +} \ 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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 #include @@ -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/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp new file mode 100644 index 0000000000..c7dd1a9799 --- /dev/null +++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** 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 + +#include +#include + +QT_BEGIN_NAMESPACE + +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(fileName); + if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning() << "Failed to find shader" << resolvedFileName; + return; + } + m_source += f.readAll(); +} + +QString QSGShaderSourceBuilder::resolveShaderPath(const QString &path) const +{ + // For now, just return the path unaltered. + // TODO: Resolve to more specific filename based upon OpenGL profile and + // version, platform, GPU type etc + return path; +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h new file mode 100644 index 0000000000..8def250d4f --- /dev/null +++ b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QSGSHADERSOURCEBUILDER_P_H +#define QSGSHADERSOURCEBUILDER_P_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QOpenGLShaderProgram; + +class Q_QUICK_PRIVATE_EXPORT QSGShaderSourceBuilder +{ +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); + +protected: + virtual QString resolveShaderPath(const QString &path) const; + +private: + QByteArray m_source; +}; + +QT_END_NAMESPACE + +#endif // QSGSHADERSOURCEBUILDER_P_H 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 -- cgit v1.2.3 From c7a3089c146d6063f3b3201149e42c720c8ca5b3 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 31 Oct 2013 10:28:22 +0100 Subject: Be consistent when checking for blocked subtrees. This code was a leftover from before we started sending notifications for changes in QSGNode::isSubtreeBlocked. It would accumulate opacity and return blocked for nested blocks, even when QSGNode::isSubtreeBlocked would return non-blocked. The result is that the renderer would not respond correctly to DirtySubtreeBlocked and would not add/remove shadow nodes for that subtree. Change-Id: Iea83e89c6da4d0a3cb3ee7ea74cd96b7cda9fd6d Reviewed-by: Laszlo Agocs --- src/quick/scenegraph/coreapi/qsgnodeupdater.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src/quick') 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(node)->opacity(); - if (opacity < 0.001) - return true; - } + if (node->isSubtreeBlocked()) + return true; node = node->parent(); } - return false; } -- cgit v1.2.3 From 2192e5005b3ba3cff22388a4907e01c7c514d812 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 31 Oct 2013 22:14:12 +0100 Subject: Fix rendering bug with batched translucent elements. When one item in a batch of other translucent items would change opacity, we need to rebuild batches under the current root as all items in a batch are expected to have the same opacity. Task-number: QTBUG-34311 Change-Id: I2b9db19f05bd3a82be65cfa8a91e9398e8d58d0f Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 12 ++++++++++++ src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h | 1 + 2 files changed, 13 insertions(+) (limited to 'src/quick') diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index e7c611029d..c27217bf44 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -389,6 +389,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); @@ -1344,6 +1347,15 @@ void Renderer::buildRenderListsFromScratch() buildRenderLists(rootNode()); } +void Renderer::invalidateAlphaBatchesForRoot(Node *root) +{ + for (int i=0; iroot == 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. */ diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index a205306b77..23985729ef 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -420,6 +420,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); -- cgit v1.2.3 From 5b05a78d0055757adb3b2703ea990e07dbcd145a Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 30 Oct 2013 14:32:54 +0100 Subject: Added private API for enabling sharing between the QQuickwindow instances. This API is primarily a hook which is needed by the Qt WebEngine to set up sharing with the scene graph's OpenGL contexts. Change-Id: I5bb03abd9ab99f502db8e413fe838a8b30365b8d Reviewed-by: Jocelyn Turcotte --- src/quick/scenegraph/qsgcontext.cpp | 18 ++++++++++++++++++ src/quick/scenegraph/qsgcontext_p.h | 3 +++ src/quick/scenegraph/qsgrenderloop.cpp | 2 ++ src/quick/scenegraph/qsgthreadedrenderloop.cpp | 2 ++ src/quick/scenegraph/qsgwindowsrenderloop.cpp | 2 ++ 5 files changed, 27 insertions(+) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 4fbefb37d8..c6dbf350b6 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -117,8 +117,12 @@ public: QSGContext::AntialiasingMethod antialiasingMethod; bool distanceFieldDisabled; QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing; + + static QOpenGLContext *sharedOpenGLContext; }; +QOpenGLContext *QSGContextPrivate::sharedOpenGLContext = 0; + class QSGTextureCleanupEvent : public QEvent { public: @@ -170,6 +174,20 @@ QSGContext::~QSGContext() { } +/*! + * 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::renderContextInitialized(QSGRenderContext *renderContext) { Q_D(QSGContext); diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index 08fafb0713..270f108373 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -162,6 +162,9 @@ public: virtual QSize minimumFBOSize() const; virtual QSurfaceFormat defaultSurfaceFormat() const; + static void setSharedOpenGLContext(QOpenGLContext *context); + static QOpenGLContext *sharedOpenGLContext(); + void setDistanceFieldEnabled(bool enabled); bool isDistanceFieldEnabled() const; diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index fc1e98d87f..f294cb4a2d 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -264,6 +264,8 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) if (!gl) { gl = new QOpenGLContext(); gl->setFormat(window->requestedFormat()); + if (QSGContext::sharedOpenGLContext()) + gl->setShareContext(QSGContext::sharedOpenGLContext()); if (!gl->create()) { delete gl; gl = 0; diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index bb0bd67d6b..42c7c9c0ba 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -889,6 +889,8 @@ void QSGThreadedRenderLoop::handleExposure(Window *w) 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; diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index f1d09c3785..d5d12bd138 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -178,6 +178,8 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window) RLDEBUG(" - creating GL context"); m_gl = new QOpenGLContext(); m_gl->setFormat(window->requestedFormat()); + if (QSGContext::sharedOpenGLContext()) + m_gl->setShareContext(QSGContext::sharedOpenGLContext()); m_gl->create(); QSG_RENDER_TIMING_SAMPLE(time_created); RLDEBUG(" - making current"); -- cgit v1.2.3 From a7415035ed375d31e0e6d503ea8af43bf98d3fb7 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 1 Oct 2013 21:09:52 +0200 Subject: KeyNavigation should use forceActiveFocus It would only set focus which works fine as long as the target is in the same FocusScope. But as user one would expect that the target actually receives the focus. Using forceActiveFocus is sensible since the current item needs to have the "activeFocus" anyway and within the same focus scope setting focus=true on another item will take away the active focus. Task-number: QTBUG-34209 Change-Id: I824f15fd0d4d42eb2f0c6c1b02660f2e007b3362 Reviewed-by: Shawn Rutledge Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com> --- src/quick/items/qquickitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index cd526a0dae..55ba25c63f 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(currentItem, false); -- cgit v1.2.3 From f82e2df554f3d66f88e0b6c8c02b1efe894248cb Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 30 Oct 2013 13:19:42 +0100 Subject: QQuickWindowPrivate: implement clearFocusObject Ref change: cfa85c7 (qtbase) Implement QQuickWindowPrivate::clearFocus() to enable platform plugins to remove focus from the focus object when the virtual keyboard closes. On mobile platforms line edits etc are not supposed to be drawn with focus and blinking cursors unless the virtual keyboard (or another keyboard) is open. With the new virtual QWindowPrivate::clearFocus() the platforms can remove focus without deactivating the whole window. The old implementation on iOS deactivated the whole window when the keyboard was closed. But this was unfortunate, especially in QtQuick, since a qquicktextinput would not get active focus unless the window was active. But the platform would not activate the window unless the keybaord was open. So, a classic chicken - egg problem. Change-Id: I62e652a3cd85f1313713c5d086d9537cc2f9826f Reviewed-by: Paul Olav Tvete Reviewed-by: Shawn Rutledge --- src/quick/items/qquickwindow.cpp | 5 +++++ src/quick/items/qquickwindow_p.h | 1 + 2 files changed, 6 insertions(+) (limited to 'src/quick') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index ed97325c85..dd338af1e3 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -819,6 +819,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 item(*items); diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 2cf98bfe21..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(); -- cgit v1.2.3 From 2f1e4ca5ce48b838b37e0b49ee23e481f822fae4 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 4 Nov 2013 13:08:43 +0100 Subject: Doc: Add missing image to XmlListModel documentation The image was originally part of QtQuick1 docs - copy it over to qtdeclarative repository. Task-number: QTBUG-34556 Change-Id: Ic7089ce157ff7722e5f42b201ff4b01dcff2564e Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Jerome Pasion --- src/quick/doc/images/qml-xmllistmodel-example.png | Bin 0 -> 5252 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/quick/doc/images/qml-xmllistmodel-example.png (limited to 'src/quick') 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 Binary files /dev/null and b/src/quick/doc/images/qml-xmllistmodel-example.png differ -- cgit v1.2.3 From aeb1d48c9938241b1ffcf8e42e3864595e90b168 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 4 Nov 2013 14:18:15 +0100 Subject: Handle glyph runs with >65536 glyphs Done-with: Aaron Kennedy Change-Id: Ica3a1dccc798186414b92f900b858966ac8dc8c9 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgdistancefieldglyphnode.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp index 49b56494db..a9faf12096 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode.cpp @@ -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); -- cgit v1.2.3 From d87c1471f1f61133edad313d5159f9fee9e938c5 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 4 Nov 2013 14:18:26 +0100 Subject: Fix preedit text layout preeditPosition is relative to the block position Done-with: Aaron Kennedy Change-Id: If96a1d0939f84ab11f0642d5fe78d786c30f418a Reviewed-by: Gunnar Sletta --- src/quick/items/qquicktextnodeengine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/quick') 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 -- cgit v1.2.3 From 2b8dd863601cffbe04fa510395a19318e2fcca24 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 4 Nov 2013 15:45:22 +0100 Subject: Tolerate NaN in the geometry without asserting If we come across NaN geometry, we treat it as spanning the entire viewport, similar to other geometries with undefined geometry. Task-number: QTBUG-34520 Change-Id: Ia4171f9f13d876c6c587043ad7decaa19bb85f01 Reviewed-by: Laszlo Agocs --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/quick') diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index c27217bf44..bb98682b20 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -553,6 +553,15 @@ 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; } RenderNodeElement::~RenderNodeElement() -- cgit v1.2.3 From 1cd51d23446ba8945b14522157af9a4d96abb6dd Mon Sep 17 00:00:00 2001 From: Sze Howe Koh Date: Sun, 3 Nov 2013 22:08:47 +0800 Subject: Doc: Fix typos Task-number: QTBUG-33360 Change-Id: I913c14d3d6a90d2c20e40e246ad11f50a26c3ad9 Reviewed-by: Jerome Pasion --- src/quick/doc/src/qtquick.qdoc | 1 - src/quick/items/qquickpainteditem.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/quick') diff --git a/src/quick/doc/src/qtquick.qdoc b/src/quick/doc/src/qtquick.qdoc index 0c5a721863..392ae0af92 100644 --- a/src/quick/doc/src/qtquick.qdoc +++ b/src/quick/doc/src/qtquick.qdoc @@ -128,7 +128,6 @@ Additional Qt Quick information: \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/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() */ -- cgit v1.2.3 From 2a1fc76f4ed1680e78b740c47fa736768aed82e9 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 31 Oct 2013 09:45:57 +0100 Subject: Added QSG_INFO=1 environment variable to spit out graphics info Change-Id: I12bc0bc475b3e99185aefcd58eef5a0fb5e9852e Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/qsgcontext.cpp | 10 ++++++++++ src/quick/scenegraph/qsgrenderloop.cpp | 10 +++++++++- src/quick/scenegraph/util/qsgatlastexture.cpp | 3 +++ 3 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index c6dbf350b6..4ccbaca08e 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -206,6 +206,16 @@ void QSGContext::renderContextInitialized(QSGRenderContext *renderContext) d->antialiasingMethod = VertexAntialiasing; } } + + 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(); } diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index f294cb4a2d..0cc2a15c51 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -144,8 +144,13 @@ 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) { @@ -178,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; } diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index b180bc43bd..2bc106a025 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -104,6 +104,9 @@ Manager::Manager() 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; } -- cgit v1.2.3 From 22c138abfce871a1d23f1cf1b98b448bcd3ec74f Mon Sep 17 00:00:00 2001 From: Sze Howe Koh Date: Tue, 5 Nov 2013 20:17:06 +0800 Subject: Doc: Fix broken links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ie7408409ddbaa354370267f2dd74326ec56a4186 Reviewed-by: Jerome Pasion Reviewed-by: Topi Reiniö --- src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc | 2 +- src/quick/doc/src/concepts/positioning/layouts.qdoc | 2 +- src/quick/doc/src/concepts/positioning/righttoleft.qdoc | 2 +- .../doc/src/concepts/statesanimations/animations.qdoc | 5 ++--- src/quick/doc/src/tutorial.qdoc | 1 - src/quick/items/qquickanimatedsprite.cpp | 2 +- src/quick/items/qquickgridview.cpp | 2 +- src/quick/items/qquickitemanimation.cpp | 2 +- src/quick/items/qquicklistview.cpp | 5 +++-- src/quick/items/qquickpathview.cpp | 2 +- src/quick/items/qquicksprite.cpp | 2 +- src/quick/items/qquickspritesequence.cpp | 2 +- src/quick/items/qquicktranslate.cpp | 2 +- src/quick/items/qquickwindow.cpp | 2 +- src/quick/util/qquickanimation.cpp | 16 ++++++++-------- src/quick/util/qquicksmoothedanimation.cpp | 2 +- src/quick/util/qquickspringanimation.cpp | 2 +- 17 files changed, 26 insertions(+), 27 deletions(-) (limited to 'src/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..1a324b1983 100644 --- a/src/quick/doc/src/concepts/statesanimations/animations.qdoc +++ b/src/quick/doc/src/concepts/statesanimations/animations.qdoc @@ -65,6 +65,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 +220,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/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/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index 4c16a1e9e2..64b8f257dc 100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@ -174,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/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/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/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/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index d8132bdd12..696cf145da 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) 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 28f1397cc9..a90aa9ace2 100644 --- a/src/quick/items/qquickspritesequence.cpp +++ b/src/quick/items/qquickspritesequence.cpp @@ -172,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/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 dd338af1e3..9798974788 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2768,7 +2768,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. diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp index 6a762bea68..342cf2eaff 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) { @@ -1711,7 +1711,7 @@ QQmlListProperty 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 +1801,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 +1984,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/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp index 53e3520bde..017fe39003 100644 --- a/src/quick/util/qquicksmoothedanimation.cpp +++ b/src/quick/util/qquicksmoothedanimation.cpp @@ -351,7 +351,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..efaa5ba56c 100644 --- a/src/quick/util/qquickspringanimation.cpp +++ b/src/quick/util/qquickspringanimation.cpp @@ -365,7 +365,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) -- cgit v1.2.3 From b14c5e934846e660c0809b5afb882ec56128d202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 5 Nov 2013 15:11:31 +0100 Subject: Add missing namespace wrappers for QQuickItemsModule Change-Id: I75b576eda67db7172fc6579dbc42a690d0386b88 Reviewed-by: Simon Hausmann --- src/quick/items/qquickitemsmodule.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/quick') diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index daf76c377e..23fd75756a 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -268,6 +268,8 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType(uri, 2, 2, "TextEdit"); } +QT_BEGIN_NAMESPACE + void QQuickItemsModule::defineModule() { QByteArray name = "QtQuick"; @@ -277,3 +279,4 @@ void QQuickItemsModule::defineModule() qt_quickitems_defineModule(name, majorVersion, minorVersion); } +QT_END_NAMESPACE -- cgit v1.2.3 From c9a90b3181723061e27e7545b70a66dda4f4306d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 4 Nov 2013 14:24:26 +0100 Subject: Add missing Q_INIT_RESOURCE The library needs to do Q_INIT_RESOURCE for all resources it uses internally, otherwise static linking will fail, and the user has no idea how to rectify it as the name of the missing resource is not known. Change-Id: I8ea766e63cff22bbb0c45e6125c3a07948de2274 Reviewed-by: Simon Hausmann --- src/quick/items/qquickitemsmodule.cpp | 7 +++++++ src/quick/qtquick2.cpp | 7 +++++++ 2 files changed, 14 insertions(+) (limited to 'src/quick') diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 23fd75756a..ebc32c89eb 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -268,10 +268,17 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType(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; 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 #include +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(); -- cgit v1.2.3 From 025365f1dc6dc9c3244a125882433e55b57fa672 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sat, 2 Nov 2013 16:30:26 +0100 Subject: Refactor marking GC'ed objects Don't use recursive function calls anymore. Instead, push marked objects onto the JS stack, and then pop them off when their children are being marked. Should reduce stack memory usage, and improves performance by ~5%. Change-Id: I2d37d97579144fcba87ec8e9fd545dd220c01fbb Reviewed-by: Simon Hausmann --- src/quick/items/context2d/qquickcontext2d.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 3088c41cd7..99dfff47a2 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -908,8 +908,9 @@ struct QQuickJSContext2DImageData : public QV4::Object static QV4::ReturnedValue method_get_height(QV4::SimpleCallContext *ctx); static QV4::ReturnedValue method_get_data(QV4::SimpleCallContext *ctx); - static void markObjects(Managed *that) { - static_cast(that)->pixelData.mark(); + static void markObjects(Managed *that, QV4::ExecutionEngine *engine) { + static_cast(that)->pixelData.mark(engine); + QV4::Object::markObjects(that, engine); } -- cgit v1.2.3 From 41f447272f9c7e1c632770bb952f2515494edce0 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Mon, 4 Nov 2013 13:29:12 -0800 Subject: Don't propagate mouse events to disabled MouseAreas Task-number: QTBUG-34368 Change-Id: I28d4f57e51300f12a7bab5d215933762102f3916 Reviewed-by: Michael Brasser Reviewed-by: Gunnar Sletta Reviewed-by: Shawn Rutledge --- src/quick/items/qquickmousearea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') 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(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()) -- cgit v1.2.3 From 22b83ec28a7dfebe9d47ff5c98fddfdb492e4304 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 29 Oct 2013 17:25:00 +0100 Subject: Fix QQuickText hover event handling Catch hover events only when the item contains either rich or styled text, and make sure to ignore hover events as appropriate to propagate them further. Task-number: QTBUG-33842 Change-Id: Idef5be7c502711393ab532c4ace31663b0e0a872 Reviewed-by: Alan Alpert --- src/quick/items/qquicktext.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 6335c83b2b..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); } @@ -2634,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 -- cgit v1.2.3 From fe18d98229be80071cb3dde07621d10f3dfc6099 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Tue, 5 Nov 2013 13:13:56 +0100 Subject: Doc: Updated url variable in qdocconf files. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In 5.2, the HTML output is in a flatter structure and when they are hosted in qt-project.org/doc, the documentation will be found at http://qt-project.org/doc/qt-$QT_VER The url variable is used by projects outside of Qt 5 which need to link to Qt 5 documentation, such as Qt Creator. Task-number: QTBUG-34584 Change-Id: Ie23c3748fbe780fa00f98404238099809df5ef06 Reviewed-by: Topi Reiniö Reviewed-by: Leena Miettinen Reviewed-by: J-P Nurmi --- src/quick/doc/qtquick.qdocconf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') 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 -- cgit v1.2.3 From e0458defdfadeb3a1fb92eb12b14fce9191fe1ee Mon Sep 17 00:00:00 2001 From: Alan Alpert <416365416c@gmail.com> Date: Tue, 5 Nov 2013 21:16:29 -0800 Subject: Version pixelDensity consistently Change-Id: I06bbdc6e6869718058a796ca737668ce69802f2c Reviewed-by: Shawn Rutledge Reviewed-by: Alan Alpert --- src/quick/items/qquickscreen_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickscreen_p.h b/src/quick/items/qquickscreen_p.h index 6f837eea14..a155ff1843 100644 --- a/src/quick/items/qquickscreen_p.h +++ b/src/quick/items/qquickscreen_p.h @@ -64,7 +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) + 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) -- cgit v1.2.3 From 63e0ffb32a4a432ed57f31388fabff89b05cb8cc Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 1 Nov 2013 15:49:33 +0100 Subject: Refactored Animator internals Change the design from posting events for starting and stopping to use the scene graph's existing 'sync' point. This gives much higher predictability and makes both ownership and cleanup cleaner and also reduces intermediate states while events are waiting to be delivered. Task-number: QTBUG-34137 Change-Id: I069ac22acbddaa47925b8172ba98ac340fe9bf8d Reviewed-by: Michael Brasser --- src/quick/items/qquickwindow.cpp | 2 +- src/quick/items/qquickwindow.h | 2 +- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 13 +- src/quick/util/qquickanimatorcontroller.cpp | 185 ++++++++++++++++--------- src/quick/util/qquickanimatorcontroller_p.h | 63 +++------ src/quick/util/qquickanimatorjob.cpp | 103 +++++--------- src/quick/util/qquickanimatorjob_p.h | 12 +- 7 files changed, 193 insertions(+), 187 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 9798974788..28a5df789f 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -420,7 +420,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c) 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); diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index 6fd01a3119..9f31ee708a 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -177,7 +177,7 @@ private Q_SLOTS: private: friend class QQuickItem; - friend class QQuickWindowRenderLoop; + friend class QQuickAnimatorController; Q_DISABLE_COPY(QQuickWindow) }; diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 42c7c9c0ba..1d69034f5e 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -387,19 +387,16 @@ bool QSGRenderThread::event(QEvent *e) } window = se->window; - connect(animatorDriver, SIGNAL(started()), QQuickWindowPrivate::get(se->window)->animationController, SLOT(animationsStarted())); return true; } case WM_Obscure: { RLDEBUG1(" Render: WM_Obscure"); - WMWindowEvent *ce = static_cast(e); - Q_ASSERT(!window || window == ce->window); + Q_ASSERT(!window || window == static_cast(e)->window); if (window) { RLDEBUG1(" Render: - removed one..."); window = 0; - disconnect(animatorDriver, SIGNAL(started()), QQuickWindowPrivate::get(ce->window)->animationController, SLOT(animationsStarted())); } return true; } @@ -583,10 +580,14 @@ void QSGRenderThread::syncAndRender() #endif RLDEBUG(" Render: - rendering starting"); - if (animatorDriver->isRunning()) + QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); + + if (animatorDriver->isRunning()) { + d->animationController->lock(); animatorDriver->advance(); + d->animationController->unlock(); + } - QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); if (d->renderer && windowSize.width() > 0 && windowSize.height() > 0) { gl->makeCurrent(window); d->renderSceneGraph(windowSize); diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp index 82c66b431d..a2364f4586 100644 --- a/src/quick/util/qquickanimatorcontroller.cpp +++ b/src/quick/util/qquickanimatorcontroller.cpp @@ -48,54 +48,80 @@ #include +#include + 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_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::const_iterator it = activeRootAnimations.constBegin(); - !running && it != activeRootAnimations.constEnd(); ++it) { - if ((*it)->isRunning()) + for (QHash::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::const_iterator it = transforms.constBegin(); - it != transforms.constEnd(); ++it) { + lock(); + for (QHash::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(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(job); for (QAbstractAnimationJob *a = g->firstChild(); a; a = a->nextSibling()) @@ -105,90 +131,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; iaddAnimationChangeListener(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::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(*it); + QQuickTransformAnimatorJob *xform = static_cast(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::const_iterator it = activeLeafAnimations.constBegin(); - it != activeLeafAnimations.constEnd(); ++it) { - QQuickAnimatorJob *job = *it; - if (job->isUniform() && job->target()) { - QQuickUniformAnimatorJob *job = static_cast(*it); - job->afterNodeSync(); - } + foreach (QQuickAnimatorJob *job, m_activeLeafAnimations) { + if (job->isUniform() && job->target()) + static_cast(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(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(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(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 #include +#include 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 starting; - QList stopped; - - QSet activeRootAnimations; - QSet activeLeafAnimations; - - QHash transforms; - - QSet deletedSinceLastFrame; - - QQuickWindow *window; - - QMutex mutex; + // These are manipulated from the GUI thread and should only + // be updated during the sync() phase. + QHash m_starting; + QHash m_stopping; + QSet m_deleting; + + QHash m_animatorRoots; + QSet m_activeLeafAnimations; + QHash m_transforms; + QSet 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 fffb9fc65f..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,11 +281,6 @@ void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller } } -QQuickTransformAnimatorJob::Helper::~Helper() -{ -} - - void QQuickTransformAnimatorJob::Helper::sync() { const quint32 mask = QQuickItemPrivate::Position @@ -383,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; @@ -400,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; @@ -453,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); @@ -469,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; @@ -489,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) { @@ -564,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(); -- cgit v1.2.3 From 9d90a33c7f83a49919133cd8647b0503e18e6444 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Tue, 5 Nov 2013 15:17:03 +0100 Subject: Fix crash when invalidating QSGContext. A pointer list was not cleared when invalidating the context, potentially holding dangling pointers after that. Change-Id: I0618c54ffa67b31b115901e8be3a6d3cd16dc844 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgcontext.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 4ccbaca08e..1f219e735f 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -483,6 +483,7 @@ void QSGRenderContext::invalidate() end = m_fontEnginesToClean.constEnd(); it != end; ++it) { (*it)->clearGlyphCache(m_gl); } + m_fontEnginesToClean.clear(); delete m_depthStencilManager; m_depthStencilManager = 0; -- cgit v1.2.3 From 734f424ee97fc74027f2717c592c0b329e41573b Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 7 Nov 2013 11:08:49 +0100 Subject: Fill recursive ShaderEffectSource with transparent when using alpha. The logic relies on m_fbo being 0 on the first render pass, in which case it will pick texture id 0 which is solid black. Though this works ok, it results in recursive shader effect sources starting out black which is ugly. Change-Id: I22b1d50e02c00583837b8152c5fb850263038a93 Reviewed-by: Laszlo Agocs --- src/quick/items/qquickshadereffectsource.cpp | 19 +++++++++++++++++-- src/quick/items/qquickshadereffectsource_p.h | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index c05545c292..e076a342df 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -141,6 +141,7 @@ 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 @@ -165,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 @@ -189,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() diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h index 85b58e67e4..6218775700 100644 --- a/src/quick/items/qquickshadereffectsource_p.h +++ b/src/quick/items/qquickshadereffectsource_p.h @@ -139,6 +139,8 @@ private: QOpenGLFramebufferObject *m_secondaryFbo; QSharedPointer m_depthStencilBuffer; + GLuint m_transparentTexture; + #ifdef QSG_DEBUG_FBO_OVERLAY QSGSimpleRectNode *m_debugOverlay; #endif -- cgit v1.2.3 From e367f75d7285d2bcd10cbb35d088c96f33c02aff Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Sat, 9 Nov 2013 01:58:28 +0100 Subject: Fix crash in animation controller upon destruction Triggered by tst_examples, it appears that we can have jobs in m_deleting that are also still listed in m_starting. So similar to what we do in beforeNodeSync, we now also take any deletion-scheduled jobs out of m_starting/m_stopping in the destructor. Change-Id: I2e00570a4e4669f8172354bf5806c5285920030a Reviewed-by: Lars Knoll --- src/quick/util/qquickanimatorcontroller.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/quick') diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp index a2364f4586..7991dd8110 100644 --- a/src/quick/util/qquickanimatorcontroller.cpp +++ b/src/quick/util/qquickanimatorcontroller.cpp @@ -62,6 +62,8 @@ QQuickAnimatorController::~QQuickAnimatorController() // 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; } -- cgit v1.2.3 From 412eb94de4cae754130ae855236420ebd5c42482 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sun, 3 Nov 2013 15:23:05 +0100 Subject: Simplify & speed up function calling Get rid of the SimpleCallContext, instead simply use the CallContext data structure, but don't initialize the unused variables. Change-Id: I11b311986da180c62c815b516a2c55844156d0ab Reviewed-by: Simon Hausmann --- src/quick/items/context2d/qquickcontext2d.cpp | 336 +++++++++++++------------- 1 file changed, 168 insertions(+), 168 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 99dfff47a2..908e0c91a4 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,9 +904,9 @@ 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, QV4::ExecutionEngine *engine) { static_cast(that)->pixelData.mark(engine); @@ -950,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); @@ -966,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); @@ -981,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); @@ -1023,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); @@ -1053,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); @@ -1082,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); @@ -1128,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); @@ -1158,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); @@ -1185,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); @@ -1206,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); @@ -1225,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); @@ -1246,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); @@ -1256,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); @@ -1301,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); @@ -1311,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); @@ -1356,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); @@ -1378,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); @@ -1426,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); @@ -1437,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); @@ -1471,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); @@ -1493,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); @@ -1548,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); @@ -1595,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); @@ -1650,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); @@ -1726,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); @@ -1798,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); @@ -1817,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); @@ -1856,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); @@ -1875,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); @@ -1907,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); @@ -1917,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); @@ -1938,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); @@ -1948,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); @@ -1969,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); @@ -1979,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); @@ -1999,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); @@ -2009,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); @@ -2034,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); @@ -2044,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); @@ -2064,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); @@ -2074,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); @@ -2089,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); @@ -2099,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); @@ -2124,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); @@ -2146,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); @@ -2168,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); @@ -2202,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); @@ -2254,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); @@ -2282,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); @@ -2313,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); @@ -2362,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); @@ -2380,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); @@ -2402,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); @@ -2417,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 r(scope, ctx->callData->thisObject); @@ -2442,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 r(scope, ctx->callData->thisObject); @@ -2466,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 r(scope, ctx->callData->thisObject); @@ -2492,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 r(scope, ctx->callData->thisObject); @@ -2509,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 r(scope, ctx->callData->thisObject); @@ -2533,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 r(scope, ctx->callData->thisObject); @@ -2552,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 r(scope, ctx->callData->thisObject); @@ -2578,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 r(scope, ctx->callData->thisObject); @@ -2595,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); @@ -2608,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); @@ -2652,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 r(scope, ctx->callData->thisObject); @@ -2661,7 +2661,7 @@ 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 r(scope, ctx->callData->thisObject); @@ -2691,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 r(scope, ctx->callData->thisObject); @@ -2713,7 +2713,7 @@ 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 r(scope, ctx->callData->thisObject); @@ -2759,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 r(scope, ctx->callData->thisObject); @@ -2781,7 +2781,7 @@ 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 r(scope, ctx->callData->thisObject); @@ -2819,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 r(scope, ctx->callData->thisObject); @@ -2843,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 r(scope, ctx->callData->thisObject); @@ -2878,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 r(scope, ctx->callData->thisObject); @@ -2954,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 r(scope, ctx->callData->thisObject); @@ -3090,7 +3090,7 @@ 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 imageData(scope, ctx->callData->thisObject); @@ -3106,7 +3106,7 @@ 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 imageData(scope, ctx->callData->thisObject); @@ -3122,7 +3122,7 @@ 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 imageData(scope, ctx->callData->thisObject); @@ -3149,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 r(scope, ctx->callData->thisObject.as()); @@ -3249,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 r(scope, ctx->callData->thisObject.as()); @@ -3289,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 r(scope, ctx->callData->thisObject.as()); @@ -3317,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 r(scope, ctx->callData->thisObject.as()); @@ -3418,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 style(scope, ctx->callData->thisObject.as()); -- cgit v1.2.3 From 040c835dca2fdf56d7ff37da8b72a52b69be0284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 8 Nov 2013 15:40:30 +0100 Subject: Make QQuickWindow::forcePolish() private. Adding public API was not the intention when adding this slot. Change-Id: If477917c434b32d5e5cd1fa6c640f1a6b167dd24 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickwindow.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index 9f31ee708a..5063b3b5db 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -143,7 +143,6 @@ Q_SIGNALS: public Q_SLOTS: void update(); - void forcePolish(); void releaseResources(); protected: @@ -173,6 +172,7 @@ protected: private Q_SLOTS: void maybeUpdate(); void cleanupSceneGraph(); + void forcePolish(); void setTransientParent_helper(QQuickWindow *window); private: -- cgit v1.2.3 From 4f63f43cf2da59c2e87ae96e8bd84950490a070b Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 8 Nov 2013 15:55:15 +0100 Subject: Workaround for glyph upload bug with the Mali-400 GPU. Uploading unaligned and alpha-only data seems to be broken with that GPU, uploading line by line does the trick. Task-number: QTBUG-33951 Change-Id: I2790990ca1d3a3016ec3d9fefaea7002b92faeb7 Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Shawn Rutledge --- .../qsgdefaultdistancefieldglyphcache.cpp | 55 +++++++++++++++++++--- .../qsgdefaultdistancefieldglyphcache_p.h | 3 +- 2 files changed, 50 insertions(+), 8 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index 635f07f2ea..25ff98bc67 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -167,7 +167,7 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList 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 +177,19 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList } } - glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), GL_ALPHA, GL_UNSIGNED_BYTE, glyph.constBits()); + if (useTextureUploadWorkaround()) { + for (int i = 0; i < glyph.height(); ++i) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + c.x, c.y + i, glyph.width(),1, + GL_ALPHA, GL_UNSIGNED_BYTE, + glyph.scanLine(i)); + } + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, + c.x, c.y, glyph.width(), glyph.height(), + GL_ALPHA, GL_UNSIGNED_BYTE, + glyph.constBits()); + } } // restore to previous alignment @@ -204,7 +216,7 @@ void QSGDefaultDistanceFieldGlyphCache::releaseGlyphs(const QSet &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) { } @@ -255,12 +267,24 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int updateTexture(oldTexture, texInfo->texture, texInfo->size); - if (useWorkaround()) { + if (useTextureResizeWorkaround()) { 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 (useTextureUploadWorkaround()) { + for (int i = 0; i < texInfo->image.height(); ++i) { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, i, oldWidth, 1, + GL_ALPHA, GL_UNSIGNED_BYTE, + texInfo->image.scanLine(i)); + } + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, + 0, 0, oldWidth, oldHeight, + GL_ALPHA, GL_UNSIGNED_BYTE, + texInfo->image.constBits()); + } glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); // restore to previous value @@ -334,7 +358,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); @@ -359,7 +388,7 @@ 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; @@ -372,6 +401,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(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 54b0bcb889..3fee6c9ef3 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h @@ -62,7 +62,8 @@ public: void referenceGlyphs(const QSet &glyphs); void releaseGlyphs(const QSet &glyphs); - bool useWorkaround() const; + bool useTextureResizeWorkaround() const; + bool useTextureUploadWorkaround() const; int maxTextureSize() const; void setMaxTextureCount(int max) { m_maxTextureCount = max; } -- cgit v1.2.3 From bed4d0de7e4bf57dd70e44be28eb361b4f4fe9e2 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 30 Oct 2013 18:03:23 +0100 Subject: Fallback to native font rendering for bitmap fonts. Distance field rendering requires glyph outlines, which are not available for bitmap fonts. Task-number: QTBUG-32737 Change-Id: I64569e4e6b2285ca998b5f80ec31ab04cf1f3d09 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/items/qquicktextnode.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp index 6acfaaf396..dd314c892d 100644 --- a/src/quick/items/qquicktextnode.cpp +++ b/src/quick/items/qquicktextnode.cpp @@ -143,7 +143,8 @@ QSGGlyphNode *QQuickTextNode::addGlyphs(const QPointF &position, const QGlyphRun QSGNode *parentNode) { QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext(); - QSGGlyphNode *node = m_useNativeRenderer + QRawFontPrivate *fontP = QRawFontPrivate::get(glyphs.rawFont()); + QSGGlyphNode *node = m_useNativeRenderer || !fontP->fontEngine->smoothScalable ? sg->sceneGraphContext()->createNativeGlyphNode(sg) : sg->sceneGraphContext()->createGlyphNode(sg); node->setOwnerElement(m_ownerElement); -- cgit v1.2.3 From afee694ce5d65518e5908b97e9a691c03fe0a844 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 6 Nov 2013 10:06:27 +0100 Subject: Avoid using huge floating point values in the renderer. We pretransform vertices relative to their batch root and upload these using single-precision floats. If the offsets are huge then the floating point numbers start to get unstable and we get rendering artifacts as a result. This typically happens for lists/tables with huge models. Task-number: QTBUG-34312 Change-Id: I2516f2b4fa93f44a1288659d05458fb1af0df943 Reviewed-by: Laszlo Agocs --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 24 +++++++++++++++++++---- src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h | 13 +++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index bb98682b20..3ea4b2ee1e 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -562,6 +562,8 @@ void Element::computeBounds() bounds.br.x = FLT_MAX; if (!qIsFinite(bounds.br.y)) bounds.br.y = FLT_MAX; + + boundsOutsideFloatRange = bounds.isOutsideFloatRange(); } RenderNodeElement::~RenderNodeElement() @@ -662,12 +664,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; @@ -1637,7 +1653,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; diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 23985729ef..6d95f83d7a 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -53,6 +53,8 @@ QT_BEGIN_NAMESPACE namespace QSGBatchRenderer { +#define QSG_RENDERER_COORD_LIMIT 1000000.0f + struct Vec; struct Rect; struct Buffer; @@ -136,6 +138,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 +167,7 @@ struct Element { , root(0) , order(0) , boundsComputed(false) + , boundsOutsideFloatRange(false) , translateOnlyToRoot(false) , removed(false) , orphaned(false) @@ -181,6 +191,7 @@ struct Element { int order; uint boundsComputed : 1; + uint boundsOutsideFloatRange : 1; uint translateOnlyToRoot : 1; uint removed : 1; uint orphaned : 1; @@ -242,7 +253,7 @@ struct Batch void cleanupRemovedElements(); bool isTranslateOnlyToRoot() const; - bool allMatricesAre2DSafe() const; + bool isSafeToBatch() const; // pseudo-constructor... void init() { -- cgit v1.2.3 From 59fb0d88a0ad354311d0f2e8f27c738f05f524c0 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 6 Nov 2013 12:08:42 +0100 Subject: Fix assert with native text rendering. The renderer only passed the very first node's material to updateState() as "new", yet pass the following node's materials to updateState() as "old". This triggered an assert in the QSGTextMaskMaterial's updateState as the native text nodes are invalid until they get called with their own material as "new". This goes against how the scene graph is supposed to be used, but update the code in the renderer regardless as this used to work and the fix there is not wrong. Every node in a batch has identical material, so pass the same instance for both "new" and "old" except for the first node in the batch which gets old==0. Change-Id: Ie8ae6fcd63adde08d80e9083e910836ede6694ee Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 3ea4b2ee1e..940b8dd02b 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -2045,7 +2045,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(); -- cgit v1.2.3 From 1738e4ee119bbcd20d33353e7018f04d92766639 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 6 Nov 2013 13:00:12 +0100 Subject: moveOffset in QQuickPathView::modelUpdated uninitialized Get a error for compiling with gcc 2.8.1. Change-Id: If93ed69695fb523eff05cae2960e3743dc496310 Reviewed-by: Gunnar Sletta --- src/quick/items/qquickpathview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 696cf145da..1f41fe04e5 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -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()) { -- cgit v1.2.3 From b31d47e5b87f92178ced4adc15984d9960e9e01c Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 8 Nov 2013 07:34:55 +0100 Subject: Animate when only one out of several windows is exposed. Change-Id: I7f76ed722f91076ee308a47c699984d371a220f0 Reviewed-by: Bernd Weimer Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com> --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 1d69034f5e..db3f34883f 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -769,15 +769,21 @@ void QSGThreadedRenderLoop::animationStopped() void QSGThreadedRenderLoop::startOrStopAnimationTimer() { int exposedWindows = 0; + Window *theOne = 0; for (int i=0; iisVisible() && w.window->isExposed()) + 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()); @@ -1077,7 +1083,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w) killTimer(w->timerId); w->timerId = 0; - if (m_windows.size() == 1 && m_animation_driver->isRunning()) { + if (m_animation_timer == 0 && m_animation_driver->isRunning()) { RLDEBUG("GUI: - animations advancing"); m_animation_driver->advance(); RLDEBUG("GUI: - animations done"); -- cgit v1.2.3 From 98c47db70a72a8afbd86afd355dadb1ce9113361 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 11 Nov 2013 08:30:43 +0100 Subject: Implement missing compare() function for Raised/Sunken text Task-number: QTBUG-34715 Change-Id: Ifdac2511b7f642b1ea4bd06847c840b5a951a753 Reviewed-by: Sean Harmer --- src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp | 7 +++++++ src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h | 1 + 2 files changed, 8 insertions(+) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp index ac936b6663..12a431246c 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp @@ -471,6 +471,13 @@ QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader() cons return new DistanceFieldShiftedStyleTextMaterialShader; } +int QSGDistanceFieldShiftedStyleTextMaterial::compare(const QSGMaterial *o) const +{ + const QSGDistanceFieldShiftedStyleTextMaterial *other = static_cast(o); + if (m_shift != other->m_shift) + return &m_shift < &other->m_shift ? -1 : 1; + return QSGDistanceFieldStyledTextMaterial::compare(o); +} class QSGHiQSubPixelDistanceFieldTextMaterialShader : public QSGDistanceFieldTextMaterialShader { 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; } -- cgit v1.2.3 From e353d9e9fab71fd734b5f69bb39febed826abb9b Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 12 Nov 2013 13:41:53 +0100 Subject: Fix Canvas2d.createConicalGradient The method requires 3 arguments, not 6 Task-number: QTBUG-34718 Change-Id: Ib6c117ba18844acecea3707720c0c88449b50fb6 Reviewed-by: Gunnar Sletta --- src/quick/items/context2d/qquickcontext2d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 908e0c91a4..3c97452d3d 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -1660,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()); -- cgit v1.2.3 From 508ad2e9b3af24f453720e3a3a8b7c561944abf3 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 12 Nov 2013 12:13:11 +0100 Subject: Fix boundingbox calculation of rotated items. Task-number: QTBUG-34328 Change-Id: If0202a67d95500333a0fb6f4ca3eb19ecb027770 Reviewed-by: Lars Knoll --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 33 +++++++++++++++++++++++ src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h | 9 +------ 2 files changed, 34 insertions(+), 8 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 940b8dd02b..3782cab5d3 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -113,6 +113,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; } }; @@ -533,6 +534,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); diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 6d95f83d7a..aacf482ead 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -119,14 +119,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); -- cgit v1.2.3 From 3afffa47feabc80e1bc20ffd2143a722a1c360a2 Mon Sep 17 00:00:00 2001 From: Sean Harmer Date: Wed, 6 Nov 2013 13:07:58 +0000 Subject: Adapt Qt Quick 2 renderer to work with OpenGL Core Profile The basic approach is to have the batched renderer create and bind a vertex array object if it detects we are using an OpenGL Core profile context. The VAO is bound for the duration of the QQ2 renderer's work cycle and unbound at the end so as to not interfere with any other VAO's a user may wish to use. All shaders have been copied and ported to be compliant with the GLSL 150 core specification which is the minimum for a Core profile context (OpenGL 3.2 Core). We are not using any newer features as yet so this will work anywhere we can get a Core profile context. The QSGShaderSourceBuilder class has been extended to resolve any requests for shaders to the same basefilename with "_core" appended prior to any file extension. This could be extended in the future to allow version, or GPU or platform specific shaders. The QSGShaderSourceBuilder has also been extended to allow it to insert #define definitions in the prologue of a shader. Any such definition is inserted: * After the last #extension directive (if any are found) * Otherwise after the #version directive (if found) * Otherwise at the start of the shader source This is required by the custom particle shaders which make extensive use of such #defines. In addition the mechanism used by the distance field glyph cache to extend the cache with new glyphs has been modified to work (and work more efficiently) when using a Core profile context. Rather than using a shader program and a buffer filling quad to blit the old texture into the new cache texture, we instead use the technique of framebuffer blitting. The existing fallback implementation using glTexSubImage2D() is still available if needed. The DECLARATIVE_EXAMPLE_MAIN macro has been extended to allow easy testing of any of the QtDeclarative examples with a core profile context. Just run the example with QT_QUICK_CORE_PROFILE=1 ./text for e.g. The only ones that may not work out of the box are those that provide GLSL shader source e.g. the customparticles or shader effect examples. These work fine if the shader source is adapted to GLSL 150 core. In the future it may be a good idea to expose some context property to QML that the user can use to determine what shader source variation to provide to Qt Quick. Along these lines it would also be very nice to allow the provision of shader source to ShaderEffect or CustomParticle from a separate source file just as we now do within Qt Quick. Task-number: QTBUG-32050 Change-Id: Ia6e9f06dbb8508af9ae03c6b60fb418b4cc9e41f Reviewed-by: Lars Knoll --- src/quick/items/items.pri | 8 +- src/quick/items/items.qrc | 6 + src/quick/items/shaders/shadereffect_core.frag | 13 + src/quick/items/shaders/shadereffect_core.vert | 14 + .../items/shaders/shadereffectfallback_core.frag | 8 + .../items/shaders/shadereffectfallback_core.vert | 10 + src/quick/items/shaders/sprite_core.frag | 16 ++ src/quick/items/shaders/sprite_core.vert | 24 ++ src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 29 +- src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h | 6 + src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp | 29 +- src/quick/scenegraph/qsgadaptationlayer.cpp | 4 +- src/quick/scenegraph/qsgadaptationlayer_p.h | 6 +- src/quick/scenegraph/qsgcontext.cpp | 3 +- .../qsgdefaultdistancefieldglyphcache.cpp | 84 +++++- .../qsgdefaultdistancefieldglyphcache_p.h | 9 +- .../qsgshareddistancefieldglyphcache.cpp | 4 +- .../qsgshareddistancefieldglyphcache_p.h | 1 + src/quick/scenegraph/scenegraph.pri | 34 ++- src/quick/scenegraph/scenegraph.qrc | 32 +++ src/quick/scenegraph/shaders/24bittextmask.frag | 4 +- .../scenegraph/shaders/24bittextmask_core.frag | 14 + src/quick/scenegraph/shaders/8bittextmask.frag | 4 +- .../scenegraph/shaders/8bittextmask_core.frag | 13 + .../shaders/distancefieldoutlinetext_core.frag | 20 ++ .../shaders/distancefieldshiftedtext_core.frag | 20 ++ .../shaders/distancefieldshiftedtext_core.vert | 18 ++ .../scenegraph/shaders/distancefieldtext_core.frag | 16 ++ .../scenegraph/shaders/distancefieldtext_core.vert | 15 + src/quick/scenegraph/shaders/flatcolor_core.frag | 10 + src/quick/scenegraph/shaders/flatcolor_core.vert | 10 + .../shaders/hiqsubpixeldistancefieldtext_core.frag | 32 +++ .../shaders/hiqsubpixeldistancefieldtext_core.vert | 36 +++ .../shaders/loqsubpixeldistancefieldtext_core.frag | 21 ++ .../shaders/loqsubpixeldistancefieldtext_core.vert | 29 ++ .../scenegraph/shaders/opaquetexture_core.frag | 12 + .../scenegraph/shaders/opaquetexture_core.vert | 14 + .../scenegraph/shaders/outlinedtext_core.frag | 25 ++ .../scenegraph/shaders/outlinedtext_core.vert | 24 ++ src/quick/scenegraph/shaders/rendernode_core.frag | 12 + src/quick/scenegraph/shaders/rendernode_core.vert | 12 + src/quick/scenegraph/shaders/smoothcolor_core.frag | 10 + src/quick/scenegraph/shaders/smoothcolor_core.vert | 47 ++++ .../scenegraph/shaders/smoothtexture_core.frag | 13 + .../scenegraph/shaders/smoothtexture_core.vert | 54 ++++ src/quick/scenegraph/shaders/stencilclip_core.frag | 8 + src/quick/scenegraph/shaders/stencilclip_core.vert | 10 + src/quick/scenegraph/shaders/styledtext_core.frag | 18 ++ src/quick/scenegraph/shaders/styledtext_core.vert | 18 ++ src/quick/scenegraph/shaders/textmask_core.frag | 14 + src/quick/scenegraph/shaders/textmask_core.vert | 15 + src/quick/scenegraph/shaders/texture_core.frag | 13 + src/quick/scenegraph/shaders/vertexcolor_core.frag | 10 + src/quick/scenegraph/shaders/vertexcolor_core.vert | 15 + .../scenegraph/util/qsgshadersourcebuilder.cpp | 307 ++++++++++++++++++++- .../scenegraph/util/qsgshadersourcebuilder_p.h | 5 + src/quick/scenegraph/util/qsgtexture.cpp | 11 +- 57 files changed, 1230 insertions(+), 39 deletions(-) create mode 100644 src/quick/items/shaders/shadereffect_core.frag create mode 100644 src/quick/items/shaders/shadereffect_core.vert create mode 100644 src/quick/items/shaders/shadereffectfallback_core.frag create mode 100644 src/quick/items/shaders/shadereffectfallback_core.vert create mode 100644 src/quick/items/shaders/sprite_core.frag create mode 100644 src/quick/items/shaders/sprite_core.vert create mode 100644 src/quick/scenegraph/shaders/24bittextmask_core.frag create mode 100644 src/quick/scenegraph/shaders/8bittextmask_core.frag create mode 100644 src/quick/scenegraph/shaders/distancefieldoutlinetext_core.frag create mode 100644 src/quick/scenegraph/shaders/distancefieldshiftedtext_core.frag create mode 100644 src/quick/scenegraph/shaders/distancefieldshiftedtext_core.vert create mode 100644 src/quick/scenegraph/shaders/distancefieldtext_core.frag create mode 100644 src/quick/scenegraph/shaders/distancefieldtext_core.vert create mode 100644 src/quick/scenegraph/shaders/flatcolor_core.frag create mode 100644 src/quick/scenegraph/shaders/flatcolor_core.vert create mode 100644 src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.frag create mode 100644 src/quick/scenegraph/shaders/hiqsubpixeldistancefieldtext_core.vert create mode 100644 src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.frag create mode 100644 src/quick/scenegraph/shaders/loqsubpixeldistancefieldtext_core.vert create mode 100644 src/quick/scenegraph/shaders/opaquetexture_core.frag create mode 100644 src/quick/scenegraph/shaders/opaquetexture_core.vert create mode 100644 src/quick/scenegraph/shaders/outlinedtext_core.frag create mode 100644 src/quick/scenegraph/shaders/outlinedtext_core.vert create mode 100644 src/quick/scenegraph/shaders/rendernode_core.frag create mode 100644 src/quick/scenegraph/shaders/rendernode_core.vert create mode 100644 src/quick/scenegraph/shaders/smoothcolor_core.frag create mode 100644 src/quick/scenegraph/shaders/smoothcolor_core.vert create mode 100644 src/quick/scenegraph/shaders/smoothtexture_core.frag create mode 100644 src/quick/scenegraph/shaders/smoothtexture_core.vert create mode 100644 src/quick/scenegraph/shaders/stencilclip_core.frag create mode 100644 src/quick/scenegraph/shaders/stencilclip_core.vert create mode 100644 src/quick/scenegraph/shaders/styledtext_core.frag create mode 100644 src/quick/scenegraph/shaders/styledtext_core.vert create mode 100644 src/quick/scenegraph/shaders/textmask_core.frag create mode 100644 src/quick/scenegraph/shaders/textmask_core.vert create mode 100644 src/quick/scenegraph/shaders/texture_core.frag create mode 100644 src/quick/scenegraph/shaders/vertexcolor_core.frag create mode 100644 src/quick/scenegraph/shaders/vertexcolor_core.vert (limited to 'src/quick') diff --git a/src/quick/items/items.pri b/src/quick/items/items.pri index d0ebbcfcdb..3996512f9d 100644 --- a/src/quick/items/items.pri +++ b/src/quick/items/items.pri @@ -145,7 +145,13 @@ OTHER_FILES += \ $$PWD/shaders/shadereffect.vert \ $$PWD/shaders/shadereffect.frag \ $$PWD/shaders/shadereffectfallback.vert \ - $$PWD/shaders/shadereffectfallback.frag + $$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 diff --git a/src/quick/items/items.qrc b/src/quick/items/items.qrc index 837cffb65a..671d8acdbb 100644 --- a/src/quick/items/items.qrc +++ b/src/quick/items/items.qrc @@ -6,5 +6,11 @@ shaders/shadereffect.frag shaders/shadereffectfallback.frag shaders/shadereffectfallback.vert + shaders/shadereffect_core.frag + shaders/shadereffect_core.vert + shaders/shadereffectfallback_core.frag + shaders/shadereffectfallback_core.vert + shaders/sprite_core.frag + shaders/sprite_core.vert 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_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_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/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 3782cab5d3..49c2cc8178 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -46,6 +46,7 @@ #include #include +#include #include @@ -57,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 { @@ -132,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()); @@ -761,6 +764,7 @@ Renderer::Renderer(QSGRenderContext *ctx) , m_zRange(0) , m_currentMaterial(0) , m_currentShader(0) + , m_vao(0) { setNodeUpdater(new Updater(this)); @@ -801,6 +805,13 @@ Renderer::Renderer(QSGRenderContext *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) @@ -2211,6 +2222,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)) { @@ -2318,6 +2340,9 @@ void Renderer::render() renderBatches(); m_rebuild = 0; + + if (m_vao) + m_vao->release(); } void Renderer::prepareRenderNode(RenderNodeElement *e) diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index aacf482ead..95e111552d 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE +class QOpenGLVertexArrayObject; + namespace QSGBatchRenderer { @@ -398,6 +400,7 @@ public: protected: void nodeChanged(QSGNode *node, QSGNode::DirtyState state); + void preprocess() Q_DECL_OVERRIDE; void render(); private: @@ -481,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/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp index eade198cd0..8c7c806cad 100644 --- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp +++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include +#include // 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; 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;\n"); result += QByteArray(tok.pos - 1); return result; } diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index 8585caa22d..58c843a286 100644 --- a/src/quick/scenegraph/qsgadaptationlayer.cpp +++ b/src/quick/scenegraph/qsgadaptationlayer.cpp @@ -60,7 +60,7 @@ static QElapsedTimer qsg_render_timer; QSGDistanceFieldGlyphCache::Texture QSGDistanceFieldGlyphCache::s_emptyTexture; -QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font) +QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font) : m_manager(man) , m_pendingGlyphs(64) { @@ -74,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 f9e59f9c7f..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 { @@ -149,7 +150,7 @@ public: class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldGlyphCache { public: - QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font); + QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font); virtual ~QSGDistanceFieldGlyphCache(); struct Metrics { @@ -246,6 +247,8 @@ protected: GlyphData &glyphData(glyph_t glyph); + inline bool isCoreProfile() const { return m_coreProfile; } + private: QSGDistanceFieldGlyphCacheManager *m_manager; @@ -253,6 +256,7 @@ private: int m_glyphCount; bool m_doubleGlyphResolution; + bool m_coreProfile; QList m_textures; QHash m_glyphsData; diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 1f219e735f..fa095b8165 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -391,12 +391,13 @@ QSGDistanceFieldGlyphCache *QSGRenderContext::distanceFieldGlyphCache(const QRaw cache = new QSGSharedDistanceFieldGlyphCache(keyName, sharedGraphicsCache, m_distanceFieldCacheManager, + openglContext(), font); } } } if (!cache) - cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, font); + cache = new QSGDefaultDistanceFieldGlyphCache(m_distanceFieldCacheManager, openglContext(), font); m_distanceFieldCacheManager->insertCache(font, cache); } diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index 25ff98bc67..c5c4e18e37 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -48,16 +48,23 @@ #include #include +#if !defined(QT_OPENGL_ES_2) +#include +#endif + QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(qmlUseGlyphCacheWorkaround, QML_USE_GLYPHCACHE_WORKAROUND) -QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font) - : QSGDistanceFieldGlyphCache(man, font) +QSGDefaultDistanceFieldGlyphCache::QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font) + : QSGDistanceFieldGlyphCache(man, c, font) , m_maxTextureSize(0) , 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; @@ -177,17 +184,22 @@ void QSGDefaultDistanceFieldGlyphCache::storeGlyphs(const QList } } +#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, - GL_ALPHA, GL_UNSIGNED_BYTE, + format, GL_UNSIGNED_BYTE, glyph.scanLine(i)); } } else { glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, glyph.width(), glyph.height(), - GL_ALPHA, GL_UNSIGNED_BYTE, + format, GL_UNSIGNED_BYTE, glyph.constBits()); } } @@ -230,8 +242,14 @@ void QSGDefaultDistanceFieldGlyphCache::createTexture(TextureInfo *texInfo, int 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, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0); + + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, 0); texInfo->size = QSize(width, height); @@ -267,22 +285,74 @@ void QSGDefaultDistanceFieldGlyphCache::resizeTexture(TextureInfo *texInfo, int updateTexture(oldTexture, texInfo->texture, texInfo->size); +#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(); + 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); +#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, - GL_ALPHA, GL_UNSIGNED_BYTE, + format, GL_UNSIGNED_BYTE, texInfo->image.scanLine(i)); } } else { glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, - GL_ALPHA, GL_UNSIGNED_BYTE, + format, GL_UNSIGNED_BYTE, texInfo->image.constBits()); } diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h index 3fee6c9ef3..a5833af5fb 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache_p.h @@ -51,10 +51,14 @@ 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: - QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QRawFont &font); + QSGDefaultDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font); virtual ~QSGDefaultDistanceFieldGlyphCache(); void requestGlyphs(const QSet &glyphs); @@ -133,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/qsgshareddistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp index 20e1210b68..cc0218aefd 100644 --- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache.cpp @@ -199,8 +199,9 @@ namespace { QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId, QPlatformSharedGraphicsCache *sharedGraphicsCache, QSGDistanceFieldGlyphCacheManager *man, + QOpenGLContext *c, const QRawFont &font) - : QSGDistanceFieldGlyphCache(man, font) + : QSGDistanceFieldGlyphCache(man, c, font) , m_cacheId(cacheId) , m_sharedGraphicsCache(sharedGraphicsCache) , m_isInSceneGraphUpdate(false) @@ -227,7 +228,6 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr this, SLOT(reportItemsInvalidated(QByteArray,QVector)), Qt::DirectConnection); - QOpenGLContext *c = QOpenGLContext::currentContext(); Q_ASSERT(c); QQuickWindow *window = static_cast(c->surface()); Q_ASSERT(window != 0); diff --git a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h index a8d70be732..d72d2a740f 100644 --- a/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h +++ b/src/quick/scenegraph/qsgshareddistancefieldglyphcache_p.h @@ -55,6 +55,7 @@ public: explicit QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId, QPlatformSharedGraphicsCache *sharedGraphicsCache, QSGDistanceFieldGlyphCacheManager *man, + QOpenGLContext *c, const QRawFont &font); ~QSGSharedDistanceFieldGlyphCache(); diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri index aebc2ece9c..6f64c881a8 100644 --- a/src/quick/scenegraph/scenegraph.pri +++ b/src/quick/scenegraph/scenegraph.pri @@ -126,5 +126,37 @@ OTHER_FILES += \ $$PWD/shaders/textmask.vert \ $$PWD/shaders/texture.frag \ $$PWD/shaders/vertexcolor.frag \ - $$PWD/shaders/vertexcolor.vert + $$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 index 5299ec6d9f..2be8b246d3 100644 --- a/src/quick/scenegraph/scenegraph.qrc +++ b/src/quick/scenegraph/scenegraph.qrc @@ -32,5 +32,37 @@ shaders/rendernode.frag shaders/stencilclip.frag shaders/stencilclip.vert + shaders/8bittextmask_core.frag + shaders/24bittextmask_core.frag + shaders/distancefieldoutlinetext_core.frag + shaders/distancefieldshiftedtext_core.frag + shaders/distancefieldshiftedtext_core.vert + shaders/distancefieldtext_core.frag + shaders/distancefieldtext_core.vert + shaders/flatcolor_core.frag + shaders/flatcolor_core.vert + shaders/hiqsubpixeldistancefieldtext_core.frag + shaders/hiqsubpixeldistancefieldtext_core.vert + shaders/loqsubpixeldistancefieldtext_core.frag + shaders/loqsubpixeldistancefieldtext_core.vert + shaders/opaquetexture_core.frag + shaders/opaquetexture_core.vert + shaders/outlinedtext_core.frag + shaders/outlinedtext_core.vert + shaders/rendernode_core.frag + shaders/rendernode_core.vert + shaders/smoothcolor_core.frag + shaders/smoothcolor_core.vert + shaders/smoothtexture_core.frag + shaders/smoothtexture_core.vert + shaders/stencilclip_core.frag + shaders/stencilclip_core.vert + shaders/styledtext_core.frag + shaders/styledtext_core.vert + shaders/textmask_core.frag + shaders/textmask_core.vert + shaders/texture_core.frag + shaders/vertexcolor_core.frag + shaders/vertexcolor_core.vert diff --git a/src/quick/scenegraph/shaders/24bittextmask.frag b/src/quick/scenegraph/shaders/24bittextmask.frag index ac62e7b642..5c21e202f9 100644 --- a/src/quick/scenegraph/shaders/24bittextmask.frag +++ b/src/quick/scenegraph/shaders/24bittextmask.frag @@ -1,10 +1,10 @@ varying highp vec2 sampleCoord; -uniform lowp sampler2D texture; +uniform lowp sampler2D _qt_texture; uniform lowp float color; // just the alpha, really... void main() { - lowp vec4 glyph = texture2D(texture, sampleCoord); + 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 index f2f06e8e07..44ffb279cb 100644 --- a/src/quick/scenegraph/shaders/8bittextmask.frag +++ b/src/quick/scenegraph/shaders/8bittextmask.frag @@ -1,9 +1,9 @@ varying highp vec2 sampleCoord; -uniform lowp sampler2D texture; +uniform lowp sampler2D _qt_texture; uniform lowp vec4 color; void main() { - gl_FragColor = color * texture2D(texture, sampleCoord).a; + 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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/qsgshadersourcebuilder.cpp b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp index c7dd1a9799..1a1963dbca 100644 --- a/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp +++ b/src/quick/scenegraph/util/qsgshadersourcebuilder.cpp @@ -41,6 +41,7 @@ #include "qsgshadersourcebuilder_p.h" +#include #include #include @@ -48,6 +49,162 @@ 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() { } @@ -87,7 +244,7 @@ void QSGShaderSourceBuilder::appendSource(const QByteArray &source) void QSGShaderSourceBuilder::appendSourceFile(const QString &fileName) { const QString resolvedFileName = resolveShaderPath(fileName); - QFile f(fileName); + QFile f(resolvedFileName); if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() << "Failed to find shader" << resolvedFileName; return; @@ -95,12 +252,152 @@ void QSGShaderSourceBuilder::appendSourceFile(const QString &fileName) 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 { - // For now, just return the path unaltered. - // TODO: Resolve to more specific filename based upon OpenGL profile and - // version, platform, GPU type etc - return path; + 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/util/qsgshadersourcebuilder_p.h b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h index 8def250d4f..63f2d78767 100644 --- a/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h +++ b/src/quick/scenegraph/util/qsgshadersourcebuilder_p.h @@ -44,6 +44,7 @@ #include +#include #include QT_BEGIN_NAMESPACE @@ -64,11 +65,15 @@ public: 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; }; diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index b079100a37..ddee887bd1 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -682,14 +682,14 @@ 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; } else { @@ -711,8 +711,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; } -- cgit v1.2.3 From cd0f3fba787aab1b153e5dcba281a241f30b7e59 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 13 Nov 2013 09:42:08 +0100 Subject: Add support for quaternion in ShaderEffect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-32605 Change-Id: I4e90a3505740dd9a8b369dac6ce05ce066d14d44 Reviewed-by: Jørgen Lind --- src/quick/items/qquickshadereffect.cpp | 1 + src/quick/items/qquickshadereffectnode.cpp | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'src/quick') diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index 9c766a1622..9a20703f18 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -559,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 diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp index 8788fa8362..3ab13dbbc7 100644 --- a/src/quick/items/qquickshadereffectnode.cpp +++ b/src/quick/items/qquickshadereffectnode.cpp @@ -197,6 +197,12 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri case QMetaType::QVector4D: program()->setUniformValue(loc, qvariant_cast(d.value)); break; + case QMetaType::QQuaternion: + { + QQuaternion q = qvariant_cast(d.value); + program()->setUniformValue(loc, q.x(), q.y(), q.z(), q.scalar()); + } + break; case QMetaType::QMatrix4x4: program()->setUniformValue(loc, qvariant_cast(d.value)); break; -- cgit v1.2.3 From c4ced2a9d4b75b100eae945220b4791d8003598f Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 14 Nov 2013 15:01:36 +0100 Subject: Improve internal debug statements. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have one thread per window it is useful to know which thread and window prints out the messages. Change-Id: I699eae180575fd3355551ebe0bfe6fd6ac8837c9 Reviewed-by: Jørgen Lind --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 171 ++++++++++++------------- 1 file changed, 79 insertions(+), 92 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index db3f34883f..0e8c189405 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -108,27 +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 @@ -331,7 +318,7 @@ public: public slots: void sceneGraphChanged() { - RLDEBUG(" Render: sceneGraphChanged()"); + QSG_RT_DEBUG("sceneGraphChanged()"); syncResultedInChanges = true; } @@ -373,7 +360,7 @@ 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(e); pendingUpdate |= RepaintRequest; @@ -382,7 +369,7 @@ bool QSGRenderThread::event(QEvent *e) windowSize = se->size; if (window) { - RLDEBUG1(" Render: - window already added..."); + QSG_RT_DEBUG(" - window already added..."); return true; } @@ -390,19 +377,19 @@ bool QSGRenderThread::event(QEvent *e) return true; } case WM_Obscure: { - RLDEBUG1(" Render: WM_Obscure"); + QSG_RT_DEBUG("WM_Obscure"); Q_ASSERT(!window || window == static_cast(e)->window); if (window) { - RLDEBUG1(" Render: - removed one..."); + QSG_RT_DEBUG(" - removed one..."); window = 0; } return true; } case WM_RequestSync: - RLDEBUG(" Render: WM_RequestSync"); + QSG_RT_DEBUG("WM_RequestSync"); if (sleeping) stopEventProcessing = true; if (window) @@ -410,17 +397,17 @@ bool QSGRenderThread::event(QEvent *e) return true; case WM_TryRelease: { - RLDEBUG1(" Render: WM_TryRelease"); + QSG_RT_DEBUG("WM_TryRelease"); mutex.lock(); if (!window) { WMTryReleaseEvent *wme = static_cast(e); - RLDEBUG1(" Render: - setting exit flag and invalidating GL"); + QSG_RT_DEBUG(" - setting exit flag and invalidating GL"); invalidateOpenGL(wme->window, wme->inDestructor); active = gl; if (sleeping) stopEventProcessing = true; } 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 +415,24 @@ bool QSGRenderThread::event(QEvent *e) } case WM_Grab: { - RLDEBUG1(" Render: WM_Grab"); + QSG_RT_DEBUG("WM_Grab"); WMGrabEvent *ce = static_cast(e); Q_ASSERT(ce->window == window); mutex.lock(); if (window) { gl->makeCurrent(window); - RLDEBUG1(" Render: - syncing scene graph"); + QSG_RT_DEBUG(" - syncing scene graph"); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); d->syncSceneGraph(); - RLDEBUG1(" Render: - rendering scene graph"); + QSG_RT_DEBUG(" - rendering scene graph"); QQuickWindowPrivate::get(window)->renderSceneGraph(windowSize); - RLDEBUG1(" Render: - grabbing result..."); + 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 +452,7 @@ bool QSGRenderThread::event(QEvent *e) void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor) { - RLDEBUG1(" Render: invalidateOpenGL()"); + QSG_RT_DEBUG("invalidateOpenGL()"); if (!gl) return; @@ -486,7 +473,7 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor) QQuickWindowPrivate *dd = QQuickWindowPrivate::get(window); dd->cleanupNodesOnShutdown(); } else { - RLDEBUG1(" Render: - persistent SG, avoiding cleanup"); + QSG_RT_DEBUG(" - persistent SG, avoiding cleanup"); return; } @@ -494,14 +481,14 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor) QCoreApplication::processEvents(); QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); gl->doneCurrent(); - RLDEBUG1(" Render: - invalidated scenegraph.."); + QSG_RT_DEBUG(" - invalidated scenegraph.."); 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"); } } @@ -511,7 +498,7 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor) */ void QSGRenderThread::sync() { - RLDEBUG(" Render: sync()"); + QSG_RT_DEBUG("sync()"); mutex.lock(); Q_ASSERT_X(wm->m_locked, "QSGRenderThread::sync()", "sync triggered on bad terms as gui is not already locked..."); @@ -522,7 +509,7 @@ void QSGRenderThread::sync() 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); } @@ -532,10 +519,10 @@ void QSGRenderThread::sync() // and the delete is a safe operation. QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); } else { - RLDEBUG(" Render: - window has bad size, waiting..."); + QSG_RT_DEBUG(" - window has bad size, waiting..."); } - RLDEBUG(" Render: - window has bad size, waiting..."); + QSG_RT_DEBUG(" - window has bad size, waiting..."); waitCondition.wakeOne(); mutex.unlock(); } @@ -553,7 +540,7 @@ void QSGRenderThread::syncAndRender() QElapsedTimer waitTimer; waitTimer.start(); - RLDEBUG(" Render: syncAndRender()"); + QSG_RT_DEBUG("syncAndRender()"); syncResultedInChanges = false; @@ -562,12 +549,12 @@ 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); @@ -578,7 +565,7 @@ void QSGRenderThread::syncAndRender() if (profileFrames) syncTime = threadTimer.nsecsElapsed(); #endif - RLDEBUG(" Render: - rendering starting"); + QSG_RT_DEBUG(" - rendering starting"); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); @@ -598,10 +585,10 @@ void QSGRenderThread::syncAndRender() gl->swapBuffers(window); d->fireFrameSwapped(); } else { - RLDEBUG(" Render: - Window not yet ready, skipping render..."); + QSG_RT_DEBUG(" - Window not yet ready, skipping render..."); } - RLDEBUG(" Render: - rendering done"); + QSG_RT_DEBUG(" - rendering done"); #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) @@ -633,30 +620,30 @@ 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()"); + QSG_RT_DEBUG("run()"); animatorDriver = sgrc->sceneGraphContext()->createAnimationDriver(0); animatorDriver->install(); QUnifiedTimer::instance(true)->setConsistentTiming(QSGRenderLoop::useConsistentTiming()); @@ -675,7 +662,7 @@ void QSGRenderThread::run() QCoreApplication::processEvents(); if (active && (pendingUpdate == 0 || !window)) { - RLDEBUG(" Render: enter event loop (going to sleep)"); + QSG_RT_DEBUG("enter event loop (going to sleep)"); sleeping = true; processEventsAndWaitForMore(); sleeping = false; @@ -684,7 +671,7 @@ void QSGRenderThread::run() 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; @@ -709,7 +696,7 @@ 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 @@ -720,7 +707,7 @@ QSGRenderContext *QSGThreadedRenderLoop::createRenderContext(QSGContext *sg) con void QSGThreadedRenderLoop::maybePostPolishRequest(Window *w) { if (w->timerId == 0) { - RLDEBUG("GUI: - posting update"); + QSG_GUI_DEBUG(w->window, " - posting update"); w->timerId = startTimer(m_exhaust_delay, Qt::PreciseTimer); } } @@ -752,7 +739,7 @@ bool QSGThreadedRenderLoop::interleaveIncubation() const void QSGThreadedRenderLoop::animationStarted() { - RLDEBUG("GUI: animationStarted()"); + QSG_GUI_DEBUG((void *) 0, "animationStarted()"); startOrStopAnimationTimer(); for (int i=0; iisExposed()) handleObscurity(windowFor(m_windows, window)); @@ -839,7 +826,7 @@ void QSGThreadedRenderLoop::hide(QQuickWindow *window) */ void QSGThreadedRenderLoop::windowDestroyed(QQuickWindow *window) { - RLDEBUG1("GUI: windowDestroyed()"); + QSG_GUI_DEBUG(window, "windowDestroyed()"); if (window->isVisible()) hide(window); @@ -857,13 +844,13 @@ void QSGThreadedRenderLoop::windowDestroyed(QQuickWindow *window) } } - RLDEBUG1("GUI: - done with windowDestroyed()"); + QSG_GUI_DEBUG(window, " - done with windowDestroyed()"); } void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window) { - RLDEBUG1("GUI: exposureChanged()"); + QSG_GUI_DEBUG(window, "exposureChanged()"); Window *w = windowFor(m_windows, window); if (!w) return; @@ -882,7 +869,7 @@ void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window) */ void QSGThreadedRenderLoop::handleExposure(Window *w) { - RLDEBUG1("GUI: handleExposure"); + QSG_GUI_DEBUG(w->window, "handleExposure"); // Because we are going to bind a GL context to it, make sure it // is created. @@ -892,7 +879,7 @@ void QSGThreadedRenderLoop::handleExposure(Window *w) // Start render thread if it is not running if (!w->thread->isRunning()) { - RLDEBUG1("GUI: - starting render thread..."); + QSG_GUI_DEBUG(w->window, " - starting render thread..."); if (!w->thread->gl) { w->thread->gl = new QOpenGLContext(); @@ -907,7 +894,7 @@ void QSGThreadedRenderLoop::handleExposure(Window *w) } w->thread->gl->moveToThread(w->thread); - RLDEBUG1("GUI: - OpenGL context created..."); + QSG_GUI_DEBUG(w->window, " - OpenGL context created..."); } QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController; @@ -922,7 +909,7 @@ void QSGThreadedRenderLoop::handleExposure(Window *w) w->thread->start(); } else { - RLDEBUG1("GUI: - render thread already running"); + QSG_GUI_DEBUG(w->window, " - render thread already running"); } w->thread->postEvent(new WMExposeEvent(w->window)); @@ -940,7 +927,7 @@ void QSGThreadedRenderLoop::handleExposure(Window *w) */ void QSGThreadedRenderLoop::handleObscurity(Window *w) { - RLDEBUG1("GUI: handleObscurity"); + QSG_GUI_DEBUG(w->window, "handleObscurity"); if (w->thread->isRunning()) w->thread->postEvent(new WMWindowEvent(w->window, WM_Obscure)); @@ -965,7 +952,7 @@ void QSGThreadedRenderLoop::maybeUpdate(Window *w) "QQuickItem::update()", "Function can only be called from GUI thread or during QQuickItem::updatePaintNode()"); - RLDEBUG("GUI: maybeUpdate..."); + QSG_GUI_DEBUG(w->window, "maybeUpdate..."); if (!w || !w->thread->isRunning()) { return; } @@ -973,7 +960,7 @@ void QSGThreadedRenderLoop::maybeUpdate(Window *w) // Call this function from the Gui thread later as startTimer cannot be // called from the render thread. if (QThread::currentThread() == w->thread) { - RLDEBUG("GUI: - on render thread, will update later.."); + QSG_GUI_DEBUG(w->window, " - on render thread, will update later.."); w->updateDuringSync = true; return; } @@ -993,12 +980,12 @@ void QSGThreadedRenderLoop::update(QQuickWindow *window) return; if (w->thread == QThread::currentThread()) { - RLDEBUG(" Render: QQuickWindow::update called on render thread"); + QSG_RT_DEBUG("QQuickWindow::update called on render thread"); w->thread->requestRepaint(); return; } - RLDEBUG("GUI: update called"); + QSG_GUI_DEBUG(w->window, "update called"); w->thread->postEvent(new QEvent(WM_RequestRepaint)); maybeUpdate(w); } @@ -1011,7 +998,7 @@ 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) @@ -1019,7 +1006,7 @@ void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestru w->thread->mutex.lock(); if (w->thread->isRunning() && w->thread->active) { - RLDEBUG1("GUI: - posting release request to render thread"); + 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); } @@ -1030,10 +1017,10 @@ void QSGThreadedRenderLoop::releaseResources(QQuickWindow *window, bool inDestru void QSGThreadedRenderLoop::polishAndSync(Window *w) { - RLDEBUG("GUI: polishAndSync()"); + QSG_GUI_DEBUG(w->window, "polishAndSync()"); - if (!w->window->isExposed() || !w->window->isVisible()) { - RLDEBUG("GUI: - not exposed, aborting..."); + 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; @@ -1060,12 +1047,12 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w) w->updateDuringSync = false; - RLDEBUG("GUI: - lock for sync..."); + 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(); @@ -1073,7 +1060,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w) w->thread->waitCondition.wait(&w->thread->mutex); m_locked = false; w->thread->mutex.unlock(); - RLDEBUG("GUI: - unlocked after sync..."); + QSG_GUI_DEBUG(w->window, " - unlocked after sync..."); #ifndef QSG_NO_RENDER_TIMING if (profileFrames) @@ -1084,9 +1071,9 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w) w->timerId = 0; if (m_animation_timer == 0 && m_animation_driver->isRunning()) { - RLDEBUG("GUI: - animations advancing"); + 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(w); emit timeToIncubate(); @@ -1121,11 +1108,11 @@ bool QSGThreadedRenderLoop::event(QEvent *e) case QEvent::Timer: { QTimerEvent *te = static_cast(e); if (te->timerId() == m_animation_timer) { - RLDEBUG("GUI: QEvent::Timer -> non-visual animation"); + QSG_GUI_DEBUG((void *) 0, "QEvent::Timer -> non-visual animation"); m_animation_driver->advance(); emit timeToIncubate(); } else { - RLDEBUG("GUI: QEvent::Timer -> Polish & Sync"); + QSG_GUI_DEBUG((void *) 0, "QEvent::Timer -> Polish & Sync"); Window *w = 0; for (int i=0; itimerId()) { @@ -1160,7 +1147,7 @@ bool QSGThreadedRenderLoop::event(QEvent *e) QImage QSGThreadedRenderLoop::grab(QQuickWindow *window) { - RLDEBUG("GUI: grab"); + QSG_GUI_DEBUG(window, "grab"); Window *w = windowFor(m_windows, window); Q_ASSERT(w); @@ -1171,19 +1158,19 @@ QImage QSGThreadedRenderLoop::grab(QQuickWindow *window) 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; w->thread->mutex.lock(); - RLDEBUG1("GUI: - locking, posting grab event"); + QSG_GUI_DEBUG(w->window, " - locking, posting grab event"); w->thread->postEvent(new WMGrabEvent(window, &result)); w->thread->waitCondition.wait(&w->thread->mutex); - RLDEBUG1("GUI: - locking, grab done, unlocking"); + QSG_GUI_DEBUG(w->window, " - locking, grab done, unlocking"); w->thread->mutex.unlock(); - RLDEBUG1("Gui: - grab complete"); + QSG_GUI_DEBUG(w->window, " - grab complete"); return result; } -- cgit v1.2.3 From 44e204ea9dce4681b74181c6b4bf93fbad485c64 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 14 Nov 2013 15:41:29 +0100 Subject: Avoid deadlock in Qt Creator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTCREATORBUG-10699 Change-Id: Ia88df5ec4ea74fda6a0449aa739a9c6976fedb02 Reviewed-by: Jørgen Lind --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 0e8c189405..96dfd1c26f 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -787,8 +787,22 @@ void QSGThreadedRenderLoop::show(QQuickWindow *window) { QSG_GUI_DEBUG(window, "show()"); - if (windowFor(m_windows, window)) + 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->isRunning())) + handleExposure(w); return; + } QSG_GUI_DEBUG(window, " - now tracking new window"); -- cgit v1.2.3 From 23680b185dd6fa4eb1fef76f77b4c9acf0f161fe Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 13 Nov 2013 08:32:12 +0100 Subject: Don't dereference a null animationTemplate If the SpringAnimation gets used inside a Transition, the animationTemplate might get cleared, but updateCurrentTime() still gets called on the SpringAnimation after that. Task-number: QTBUG-34539 Change-Id: I1f27fdbfc594e6ff9a4343e45f7f4001964bb012 Reviewed-by: Shawn Rutledge --- src/quick/util/qquickspringanimation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/util/qquickspringanimation.cpp b/src/quick/util/qquickspringanimation.cpp index efaa5ba56c..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(); } } -- cgit v1.2.3 From ccc0e75fb6838fe58b4b22abc87cbe684fb4623e Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 15 Nov 2013 07:23:04 +0100 Subject: Fix stacking order bug in the renderer Since we are sorting batches based on the zorder of the first element it is crucial that we don't continue adding to batches once an overlap with a compatible element is found. Task-number: QTBUG-34864 Change-Id: Ic2194c5c17bba0bc9874a14e8a69c81bff75bd1c Reviewed-by: Sean Harmer --- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/quick') diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 49c2cc8178..79b5de72c0 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -1572,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; -- cgit v1.2.3 From d7a876d0025290e506622af85403fa3c5fed795b Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Thu, 14 Nov 2013 17:27:38 +0100 Subject: Doc: Fixed QtQuick.Window documentation -fixed import statement in \qmlmodule and \inqmlmodule command. -Removed extra identifier in property documentation. Task-number: QTBUG-33360 Change-Id: I1e7ca5f418c327d42247ab4f4a11733c63d8c273 Reviewed-by: Alan Alpert Reviewed-by: Shawn Rutledge Reviewed-by: Lars Knoll --- src/quick/items/qquickscreen.cpp | 22 +++++++++---------- src/quick/items/qquickwindow.cpp | 46 ++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 34 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp index e32f31308e..6957eeaea7 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,7 +127,7 @@ QT_BEGIN_NAMESPACE \endqml */ /*! - \qmlattachedproperty real QtQuick.Window::Screen::logicalPixelDensity + \qmlattachedproperty real Screen::logicalPixelDensity \readonly \since 5.1 @@ -136,14 +136,14 @@ QT_BEGIN_NAMESPACE pixels. */ /*! - \qmlattachedproperty real QtQuick.Window::Screen::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 @@ -160,7 +160,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 @@ -174,7 +174,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. */ diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 28a5df789f..41a1781394 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -865,7 +865,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 @@ -2114,7 +2114,7 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent } /*! - \qmlproperty list QtQuick.Window::Window::data + \qmlproperty list Window::data \default The data property allows you to freely mix visual children, resources @@ -2631,7 +2631,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 @@ -2644,7 +2644,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. @@ -2659,7 +2659,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. @@ -3019,7 +3019,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. @@ -3148,7 +3148,7 @@ void QQuickWindow::resetOpenGLState() } /*! - \qmlproperty string QtQuick.Window::Window::title + \qmlproperty string Window::title The window's title in the windowing system. @@ -3159,7 +3159,7 @@ void QQuickWindow::resetOpenGLState() */ /*! - \qmlproperty Qt::WindowModality QtQuick.Window::Window::modality + \qmlproperty Qt::WindowModality Window::modality The modality of the window. @@ -3169,7 +3169,7 @@ void QQuickWindow::resetOpenGLState() */ /*! - \qmlproperty Qt::WindowFlags QtQuick.Window::Window::flags + \qmlproperty Qt::WindowFlags Window::flags The window flags of the window. @@ -3182,10 +3182,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. @@ -3200,8 +3200,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. @@ -3211,8 +3211,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. @@ -3222,7 +3222,7 @@ void QQuickWindow::resetOpenGLState() */ /*! - \qmlproperty bool QtQuick.Window::Window::visible + \qmlproperty bool Window::visible Whether the window is visible on the screen. @@ -3232,7 +3232,7 @@ void QQuickWindow::resetOpenGLState() */ /*! - \qmlproperty QWindow::Visibility QtQuick.Window::Window::visibility + \qmlproperty QWindow::Visibility Window::visibility The screen-occupation state of the window. @@ -3252,7 +3252,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 @@ -3273,7 +3273,7 @@ void QQuickWindow::resetOpenGLState() */ /*! - \qmlproperty real QtQuick.Window::Window::opacity + \qmlproperty real Window::opacity The opacity of the window. @@ -3290,7 +3290,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 @@ -3298,7 +3298,7 @@ void QQuickWindow::resetOpenGLState() */ /*! - \qmlproperty QtQuick.Window::Window::active + \qmlproperty Window::active \since 5.1 The active status of the window. -- cgit v1.2.3 From 5eb2a916a4765564a61975833c2c154ed0431930 Mon Sep 17 00:00:00 2001 From: Alan Alpert <416365416c@gmail.com> Date: Tue, 12 Nov 2013 02:12:04 -0800 Subject: Deprecate logicalPixelDensity It's just not working out in practice, and we don't want to confuse users with having to pick their flavor of pixel density. Task-number: QTBUG-34798 Change-Id: I552e479515a6f5249685844143601cb7449ccccc Reviewed-by: Jerome Pasion Reviewed-by: Shawn Rutledge Reviewed-by: Paul Olav Tvete --- src/quick/items/qquickscreen.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp index 6957eeaea7..48c0f8e084 100644 --- a/src/quick/items/qquickscreen.cpp +++ b/src/quick/items/qquickscreen.cpp @@ -130,10 +130,17 @@ QT_BEGIN_NAMESPACE \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 -- cgit v1.2.3 From e2ca539562fd7fd2eb33c56c5d5d9c0e5196b7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Ca=C5=82usi=C5=84ski?= Date: Thu, 14 Nov 2013 17:53:58 +0100 Subject: Do not crash when one of group animation's children is null Check if pointer to QQuickAbstractAnimation for which we are setting group is valid. Task-number: QTBUG-34851 Change-Id: Iecb549f080804fd9489f884911fa51892def05a5 Reviewed-by: Lars Knoll --- src/quick/util/qquickanimation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp index 342cf2eaff..f743acc249 100644 --- a/src/quick/util/qquickanimation.cpp +++ b/src/quick/util/qquickanimation.cpp @@ -1648,7 +1648,8 @@ QQuickAnimationGroup::QQuickAnimationGroup(QQuickAnimationGroupPrivate &dd, QObj void QQuickAnimationGroupPrivate::append_animation(QQmlListProperty *list, QQuickAbstractAnimation *a) { - if (QQuickAnimationGroup *q = qmlobject_cast(list->object)) + QQuickAnimationGroup *q = qmlobject_cast(list->object); + if (q && a) a->setGroup(q); } -- cgit v1.2.3 From f189bb458179630b26a5b93e06eacaa2a138b793 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 15 Nov 2013 15:28:33 +0100 Subject: Fix lockup in creator. My previous fix to force expose when the render thread is inactive was not enough. We now lock down access to 'QSGRenderThread::window' so that it will always be set when the thread is in the "exposed" state and 0 when the thread is in the "obscured" state. This introduces another sync point in handleObscurity to protect the writing of window in the render thread. Task-number: QTCREATORBUG-10793 Change-Id: I1e1153189b3a3562705892b42625f88ef6329188 Reviewed-by: Ulf Hermann Reviewed-by: Kai Koehne --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 96dfd1c26f..0c46747e53 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -381,10 +381,13 @@ bool QSGRenderThread::event(QEvent *e) Q_ASSERT(!window || window == static_cast(e)->window); + mutex.lock(); if (window) { QSG_RT_DEBUG(" - removed one..."); window = 0; } + waitCondition.wakeOne(); + mutex.unlock(); return true; } @@ -799,7 +802,7 @@ void QSGThreadedRenderLoop::show(QQuickWindow *window) * * REF: QTCREATORBUG-10699 */ - if (window->isExposed() && (!w->thread || !w->thread->isRunning())) + if (window->isExposed() && (!w->thread || !w->thread->window)) handleExposure(w); return; } @@ -942,8 +945,12 @@ void QSGThreadedRenderLoop::handleExposure(Window *w) void QSGThreadedRenderLoop::handleObscurity(Window *w) { QSG_GUI_DEBUG(w->window, "handleObscurity"); - if (w->thread->isRunning()) + 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(); } -- cgit v1.2.3 From 3d145175fd50b3fe31c62348307c995717d4200d Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 18 Nov 2013 14:23:36 +0100 Subject: Don't assert in QQuickItem::update The method can actually be called from QML, so we can not have an assert in that method. Instead simply return if the item has no contents Task-number: QTBUG-34060 Change-Id: Ib28ffa5c6c63fbec956abe25020010ed73a9cfa9 Reviewed-by: Erik Verbruggen Reviewed-by: Gunnar Sletta --- src/quick/items/qquickitem.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 55ba25c63f..c11bf904be 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -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); } -- cgit v1.2.3 From 2991947c31b4abd9b1be099d27ecba58b4a2b5ea Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 14 Nov 2013 11:43:02 +0100 Subject: Make use of GL_APPLE_texture_format_BGRA8888. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Texture uploads on iOS is extremly slow without it. Change-Id: Icccd542b8122c7bfa0e839c25e988d107bc17d2a Reviewed-by: Tor Arne Vestbø Reviewed-by: Morten Johan Sørvig --- src/quick/scenegraph/util/qsgatlastexture.cpp | 5 +++++ src/quick/scenegraph/util/qsgtexture.cpp | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'src/quick') diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index 2bc106a025..8678d106ff 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -149,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; } diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index ddee887bd1..abf3002803 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -692,6 +692,11 @@ void QSGPlainTexture::bind() || context->hasExtension(QByteArrayLiteral("GL_IMG_texture_format_BGRA8888"))) { externalFormat = GL_BGRA; internalFormat = GL_BGRA; +#ifdef Q_OS_IOS + } else if (strstr(extensions, "GL_APPLE_texture_format_BGRA8888")) { + externalFormat = GL_BGRA; + internalFormat = GL_RGBA; +#endif } else { qsg_swizzleBGRAToRGBA(&tmp); } -- cgit v1.2.3 From 14518ca23766e407a31c2b5abaf8ba1d195a73d8 Mon Sep 17 00:00:00 2001 From: Jerome Pasion Date: Mon, 18 Nov 2013 13:21:29 +0100 Subject: Doc: Fixed list of animation types. -manually created list duplicates the generated list. -\generatelist{related} doesn't do anything for a regular \page. Task-number: QTBUG-33360 Change-Id: I0bf870c71d3985e232fa8c0d5ef7ad572f596e99 Reviewed-by: Lars Knoll --- src/quick/doc/src/concepts/statesanimations/animations.qdoc | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'src/quick') diff --git a/src/quick/doc/src/concepts/statesanimations/animations.qdoc b/src/quick/doc/src/concepts/statesanimations/animations.qdoc index 1a324b1983..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 -- cgit v1.2.3 From e1b51ed1dbe88a21dadc1680e75e3a4fe229277d Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 18 Nov 2013 15:27:20 +0100 Subject: Make sure we clean up GL resources before we delete the GL context. Task-number: QTBUG-34806 Change-Id: I5013baaff0ca86357292474976944c1a3056f219 Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs --- src/quick/scenegraph/qsgrenderloop.cpp | 2 ++ src/quick/scenegraph/qsgwindowsrenderloop.cpp | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 0cc2a15c51..9c39ef65f9 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -242,6 +242,7 @@ void QSGGuiThreadRenderLoop::hide(QQuickWindow *window) if (m_windows.size() == 0) { if (!cd->persistentSceneGraph) { rc->invalidate(); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); if (!cd->persistentGLContext) { delete gl; gl = 0; @@ -255,6 +256,7 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window) hide(window); if (m_windows.size() == 0) { rc->invalidate(); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); delete gl; gl = 0; } diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index d5d12bd138..03ee4992bc 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -241,6 +241,7 @@ void QSGWindowsRenderLoop::hide(QQuickWindow *window) if (m_windows.size() == 0) { if (!cd->persistentSceneGraph) { QQuickWindowPrivate::get(window)->context->invalidate(); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); if (!cd->persistentGLContext) { delete m_gl; m_gl = 0; @@ -257,6 +258,7 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window) // If this is the last tracked window, clean up SG and GL. if (m_windows.size() == 0) { QQuickWindowPrivate::get(window)->context->invalidate(); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); delete m_gl; m_gl = 0; } -- cgit v1.2.3 From 034cc94459260ad3494eafb9672dd02eda42782f Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Mon, 18 Nov 2013 17:57:32 +0100 Subject: Fix compiler warnings with mingw64. Task-number: QTBUG-34152 Change-Id: Ibb93d1cac8c343a7ca34ce7d010f24fc56ba89df Reviewed-by: Lars Knoll --- src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp index 8c7c806cad..909def2c19 100644 --- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp +++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp @@ -183,7 +183,7 @@ QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat Tokenizer::Token t = tok.next(); // First find "void main() { ... " - const char* voidPos; + 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) -- cgit v1.2.3 From 12eab91627816d2f59a53f01dc33a5577b61db31 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 12 Nov 2013 16:53:47 +0100 Subject: Safely abort when we don't succeed in creating a GL context. Task-number: QTBUG-33363 Change-Id: Ia2b0c329157786cb4ec703989f12d2fdb1ce6bc8 Reviewed-by: Laszlo Agocs --- src/quick/scenegraph/qsgrenderloop.cpp | 1 + src/quick/scenegraph/qsgwindowsrenderloop.cpp | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 0cc2a15c51..06a112b0a4 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -275,6 +275,7 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) if (QSGContext::sharedOpenGLContext()) gl->setShareContext(QSGContext::sharedOpenGLContext()); if (!gl->create()) { + qWarning("QtQuick: failed to create OpenGL context"); delete gl; gl = 0; } else { diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index d5d12bd138..bcd4f390b4 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -180,13 +180,20 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window) m_gl->setFormat(window->requestedFormat()); if (QSGContext::sharedOpenGLContext()) m_gl->setShareContext(QSGContext::sharedOpenGLContext()); - m_gl->create(); + 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); - QQuickWindowPrivate::get(window)->context->initialize(m_gl); + if (current) + m_rc->initialize(m_gl); #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) { -- cgit v1.2.3 From 13158e4bc3bd225210f9b04ca0de129be7107051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 19 Nov 2013 17:28:34 +0100 Subject: Fix build on iOS Icccd542b8122c7bfa0e83 and Ia6e9f06dbb850 clashed. Change-Id: Iaea844c9955eb29104ee32660499a67cb7224cbf Reviewed-by: Sean Harmer --- src/quick/scenegraph/util/qsgtexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index abf3002803..51b3bafaf7 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -693,7 +693,7 @@ void QSGPlainTexture::bind() externalFormat = GL_BGRA; internalFormat = GL_BGRA; #ifdef Q_OS_IOS - } else if (strstr(extensions, "GL_APPLE_texture_format_BGRA8888")) { + } else if (context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) { externalFormat = GL_BGRA; internalFormat = GL_RGBA; #endif -- cgit v1.2.3 From 8ae390e75bf589b1591cdf5caa77b254b9ac0d8a Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 20 Nov 2013 09:53:38 +0100 Subject: Fix bad refcounting for Context2D.drawImage with an image item source. The pixmap we get from createPixmap is cached internally in the QQuickCanvasItem's cache so we need to refcount it properly. Using take would result in the refcount going to zero in this function which would cause a crash. Task-number: QTBUG-34714 Change-Id: I5f0e75a7117c53e4b89ac133ba7d161bc7b9053d Reviewed-by: Lars Knoll --- src/quick/items/context2d/qquickcontext2d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 3c97452d3d..2a9e0f2ac2 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -2981,7 +2981,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_drawImage(QV4::CallContext } else if (arg->isObject()) { if (QV4::Referenced qobjectWrapper = arg->asRef()) { if (QQuickImage *imageItem = qobject_cast(qobjectWrapper->object())) { - pixmap.take(r->context->createPixmap(imageItem->source())); + pixmap = r->context->createPixmap(imageItem->source()); } else if (QQuickCanvasItem *canvas = qobject_cast(qobjectWrapper->object())) { QImage img = canvas->toImage(); if (!img.isNull()) -- cgit v1.2.3 From 8171e3f8c89410231d6f2c7377178f3e0cb36f5c Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Mon, 18 Nov 2013 14:59:33 +0100 Subject: Use the sharing context when grabbing a hidden QQuickWindow. This allows QtWebEngine auto tests to grab the window's contents without having to show it. Change-Id: I5989a9815d0f69a7eff655f322c99d6051fc4d25 Reviewed-by: Gunnar Sletta --- src/quick/items/qquickwindow.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/quick') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 41a1781394..85add667bd 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2793,6 +2793,7 @@ QImage QQuickWindow::grabWindow() QOpenGLContext context; context.setFormat(requestedFormat()); + context.setShareContext(QSGContext::sharedOpenGLContext()); context.create(); context.makeCurrent(this); d->context->initialize(&context); -- cgit v1.2.3 From 3f1245aabc125c416f26028a12923f9055765e4f Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 20 Nov 2013 12:05:49 +0100 Subject: Enforce window rendering in sequence on llvmpipe. When rendering multiple windows in parallel on llvmpipe we end up with crashes deep inside llvmpipe as multiple threads seem to access unprotected resources. Work around this bug by enforcing that scene graph rendering happens on one window at a time. Task-number: QTCREATORBUG-10666 Change-Id: I2f734e8f653b2a9b4108eb189280ab922581e2c0 Reviewed-by: Kai Koehne --- src/quick/scenegraph/qsgcontext.cpp | 12 ++++++++++++ src/quick/scenegraph/qsgcontext_p.h | 1 + 2 files changed, 13 insertions(+) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index fa095b8165..afde7939f2 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -340,6 +340,7 @@ QSGRenderContext::QSGRenderContext(QSGContext *context) , m_depthStencilManager(0) , m_distanceFieldCacheManager(0) , m_brokenIBOs(false) + , m_serializedRender(false) { } @@ -348,8 +349,13 @@ 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); @@ -357,6 +363,9 @@ void QSGRenderContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId) renderer->renderScene(); } + if (m_serializedRender) + qsg_framerender_mutex.unlock(); + } /*! @@ -442,6 +451,9 @@ void QSGRenderContext::initialize(QOpenGLContext *context) 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 emit initialized(); diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index 270f108373..c562a909c5 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -132,6 +132,7 @@ protected: QSet m_fontEnginesToClean; bool m_brokenIBOs; + bool m_serializedRender; }; -- cgit v1.2.3 From 8121ae60decde8e5c9de02500de1469b053f78e2 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 20 Nov 2013 22:29:54 +0100 Subject: Always check for dragging changed, not just when movement starts Otherwise, if you flick and then start a new drag before the flick completes, dragging remains false. Change-Id: I9bbe20107317a6edf765c87d2e0afe3e9e2618e9 Done-with: Aaron Kennedy Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com> --- src/quick/items/qquickflickable.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/quick') 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.; -- cgit v1.2.3 From 1a76a4926a7cfecbe2bf4d75589af54e98c201c5 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 21 Nov 2013 11:10:10 +1000 Subject: Fix assert after giving focus to a disabled item. If an item has focus stolen by another item remove activeFocus from it even if the item that gains focus doesn't gain activeFocus. Otherwise the focus tree will enter a state where an item that is not the subFocusItem of its focus scope has activeFocus which is invalid and will trigger an assert in QQuickWindowPrivate::clearFocusInScope(). Task-number: QTBUG-34779 Change-Id: I72408ec0e4fd9b05ef595147ef1ef95b6aed1c16 Reviewed-by: Alan Alpert --- src/quick/items/qquickwindow.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 85add667bd..f65ff469a5 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -664,14 +664,18 @@ void QQuickWindowPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, Q QVarLengthArray 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) { -- cgit v1.2.3 From 802921d40b8b48239958c6035c74d986fe606860 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Thu, 21 Nov 2013 11:06:24 +0100 Subject: TextInput: add editingFinished signal Autotest is included. Task-number: QTBUG-34780 [ChangeLog][QtDeclarative][TextInput] add editingFinished signal Change-Id: Ib633daee67cd4e5f15739a6004adbe882ab3d3fc Reviewed-by: Lars Knoll Reviewed-by: J-P Nurmi Reviewed-by: Thomas Hartmann Reviewed-by: Jens Bache-Wiig Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com> --- src/quick/items/qquickitemsmodule.cpp | 1 + src/quick/items/qquicktextinput.cpp | 15 +++++++++++++++ src/quick/items/qquicktextinput_p.h | 1 + 3 files changed, 17 insertions(+) (limited to 'src/quick') diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index ebc32c89eb..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(uri,major,minor,"TextEdit"); qmlRegisterType(uri,2,1,"TextEdit"); qmlRegisterType(uri,major,minor,"TextInput"); + qmlRegisterType(uri,2,2,"TextInput"); qmlRegisterType(uri,major,minor,"ViewSection"); qmlRegisterType(); diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 93ea677d2c..b46387ba47 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 { @@ -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())); @@ -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(); -- cgit v1.2.3 From 8eca830fab1f8a27d62602f2725afc7cdc3561aa Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 20 Nov 2013 13:27:02 +0100 Subject: Safeguard the threaded renderloop against incorrectly exposed windows. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Mac we had a situation where we got expose events for windows which were either 0x24 in size or completely off the screen. These would result in makeCurrent failing and lead to crashes later on in the scene graph. Safeguard against invalid dimensions during initialization and abort after a call to makeCurrent if any of them fail. Task-number: QTCREATORBUG-10814 Change-Id: I9063ea4d078eea3914666e4c155d141a1502e2ff Reviewed-by: Tor Arne Vestbø --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 0c46747e53..2de9827ab1 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -506,7 +506,10 @@ void QSGRenderThread::sync() Q_ASSERT_X(wm->m_locked, "QSGRenderThread::sync()", "sync triggered on bad terms as gui is not already locked..."); - if (windowSize.width() > 0 && windowSize.height() > 0) { + 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; @@ -578,8 +581,10 @@ void QSGRenderThread::syncAndRender() d->animationController->unlock(); } - if (d->renderer && windowSize.width() > 0 && windowSize.height() > 0) { - gl->makeCurrent(window); + 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) @@ -654,10 +659,8 @@ void QSGRenderThread::run() while (active) { if (window) { - if (!sgrc->openglContext()) { - gl->makeCurrent(window); + if (!sgrc->openglContext() && windowSize.width() > 0 && windowSize.height() > 0 && gl->makeCurrent(window)) sgrc->initialize(gl); - } syncAndRender(); } -- cgit v1.2.3 From 99480d5420c0beea6771be582c039b550a4461f5 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 21 Nov 2013 14:13:07 +0100 Subject: Be even more tolerant towards broken platform behavior. When the platform (Mac in particular) sends us exposes for windows which are not renderable, we store it for later and fake expose events when we get resized. Task-number: QTCREATORBUG-10814 Change-Id: I909bb5a920550589322afd97ae1834884754cf81 Reviewed-by: Lars Knoll --- src/quick/designer/designerwindowmanager.cpp | 4 ---- src/quick/designer/designerwindowmanager_p.h | 1 - src/quick/items/qquickwindow.cpp | 1 + src/quick/scenegraph/qsgrenderloop_p.h | 1 + src/quick/scenegraph/qsgthreadedrenderloop.cpp | 21 +++++++++++++++++++++ src/quick/scenegraph/qsgthreadedrenderloop_p.h | 2 ++ src/quick/scenegraph/qsgwindowsrenderloop_p.h | 2 -- 7 files changed, 25 insertions(+), 7 deletions(-) (limited to 'src/quick') diff --git a/src/quick/designer/designerwindowmanager.cpp b/src/quick/designer/designerwindowmanager.cpp index c4a95d254b..25ea5e7f93 100644 --- a/src/quick/designer/designerwindowmanager.cpp +++ b/src/quick/designer/designerwindowmanager.cpp @@ -90,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 1bab8c8508..7414f4e3ba 100644 --- a/src/quick/designer/designerwindowmanager_p.h +++ b/src/quick/designer/designerwindowmanager_p.h @@ -82,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. diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 41a1781394..796ddcfbe4 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -216,6 +216,7 @@ void QQuickWindow::exposeEvent(QExposeEvent *) /*! \reimp */ void QQuickWindow::resizeEvent(QResizeEvent *) { + d_func()->windowManager->resize(this); } /*! \reimp */ diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h index 7b06399f08..72bad16c63 100644 --- a/src/quick/scenegraph/qsgrenderloop_p.h +++ b/src/quick/scenegraph/qsgrenderloop_p.h @@ -61,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; diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 2de9827ab1..e50d034529 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -817,6 +817,7 @@ void QSGThreadedRenderLoop::show(QQuickWindow *window) win.thread = new QSGRenderThread(this, QQuickWindowPrivate::get(window)->context); win.timerId = 0; win.updateDuringSync = false; + win.gotBrokenExposeFromPlatformPlugin = false; m_windows << win; } @@ -882,6 +883,17 @@ void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window) } } +void QSGThreadedRenderLoop::resize(QQuickWindow *window) +{ + Window *w = windowFor(m_windows, window); + if (w->gotBrokenExposeFromPlatformPlugin + && window->width() > 0 && window->height() > 0 + && w->window->geometry().intersects(w->window->screen()->availableGeometry())) { + w->gotBrokenExposeFromPlatformPlugin = false; + handleExposure(w); + } +} + /*! Will post an event to the render thread that this window should @@ -891,6 +903,15 @@ void QSGThreadedRenderLoop::handleExposure(Window *w) { 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 (!w->window->handle()) diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h index 5943d0bd08..844d180788 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h +++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h @@ -60,6 +60,7 @@ public: void show(QQuickWindow *window); void hide(QQuickWindow *window); + void resize(QQuickWindow *window); void windowDestroyed(QQuickWindow *window); void exposureChanged(QQuickWindow *window); @@ -89,6 +90,7 @@ private: QSGRenderThread *thread; int timerId; uint updateDuringSync : 1; + uint gotBrokenExposeFromPlatformPlugin : 1; }; friend class QSGRenderThread; diff --git a/src/quick/scenegraph/qsgwindowsrenderloop_p.h b/src/quick/scenegraph/qsgwindowsrenderloop_p.h index ff5529646b..e4ee688c9f 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop_p.h +++ b/src/quick/scenegraph/qsgwindowsrenderloop_p.h @@ -81,8 +81,6 @@ public: void render(); void renderWindow(QQuickWindow *window); - void resize(QQuickWindow *, const QSize &) { } - bool event(QEvent *event); bool anyoneShowing() const; -- cgit v1.2.3 From 0bdb509e29a648d5920bc14c444619b1990ccc63 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 25 Nov 2013 10:33:20 +0100 Subject: Performance note about QQuickWindow::setColor vs top-level Rectangle Change-Id: I58d271b108734958b6e0cd55ff62417d5b649a63 Reviewed-by: Jerome Pasion --- src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/quick') 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 -- cgit v1.2.3 From c962cc45711e09dddc5690d581bee29bf52f8cf9 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 25 Nov 2013 08:25:21 +0100 Subject: Do not crash when resizing invisible (non-tracked) windows. Change-Id: I776c21a0f675d2dbe831325cef2c1c2a103e03e5 Reviewed-by: Simon Hausmann --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index e50d034529..bca7736e79 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -886,9 +886,10 @@ void QSGThreadedRenderLoop::exposureChanged(QQuickWindow *window) void QSGThreadedRenderLoop::resize(QQuickWindow *window) { Window *w = windowFor(m_windows, window); - if (w->gotBrokenExposeFromPlatformPlugin - && window->width() > 0 && window->height() > 0 - && w->window->geometry().intersects(w->window->screen()->availableGeometry())) { + if (w + && w->gotBrokenExposeFromPlatformPlugin + && window->width() > 0 && window->height() > 0 + && w->window->geometry().intersects(w->window->screen()->availableGeometry())) { w->gotBrokenExposeFromPlatformPlugin = false; handleExposure(w); } -- cgit v1.2.3 From 0d1e1ddbf5732f1755d31020f82c540f2a69f756 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Fri, 22 Nov 2013 19:13:20 +0100 Subject: No assert when the focus changes and a window has no active focus item. [ChangeLog][QtQuick] Fix crash when showing and hiding a window that has no active focus item. QtQuickControls hit the situation where a popup window was shown without ever having an active focus item. When then closing the popup, clearFocusInScope would assume it had to always modify the old focus, but in this case the focus would be on the window itself, so there is nothing to update. Task-number: QTBUG-35057 Change-Id: Ifbde4689d39f98b13e6f90573cb22e28bb86f2c4 Reviewed-by: J-P Nurmi Reviewed-by: Liang Qi --- src/quick/items/qquickwindow.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 796ddcfbe4..848eeca2a6 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -771,23 +771,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(); } } -- cgit v1.2.3 From c81632df3e9d52011487cfe0bd2e40ba5c5f2d54 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 25 Nov 2013 10:06:36 +0100 Subject: Fix rendering of Flipable content. When a batch is merged in the renderer, we use the z component to stack the item front to back. This works because each item is guaranteed to have a z-range of 0->1. However, when a projective matrix is used, we need to compensate for the implicit [x,y,z]/w, which GL applies to gl_Position after the vertex stage completes, so that this guarantee still holds. Task-number: QTBUG-35020 Change-Id: I254a3d4dc9ad22f53717160ec6ad8f3a27b43d1c Reviewed-by: Laszlo Agocs --- src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp index 909def2c19..2849eff304 100644 --- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp +++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp @@ -222,7 +222,7 @@ QByteArray qsgShaderRewriter_insertZAttributes(const char *input, QSurfaceFormat braceDepth--; if (braceDepth == 0) { result += QByteArray::fromRawData(voidPos, tok.pos - 1 - voidPos); - result += QByteArrayLiteral(" gl_Position.z = gl_Position.z * _qt_zRange + _qt_order;\n"); + result += QByteArrayLiteral(" gl_Position.z = (gl_Position.z * _qt_zRange + _qt_order) * gl_Position.w;\n"); result += QByteArray(tok.pos - 1); return result; } -- cgit v1.2.3 From 2331a5ef5765d1b99472cd05e1af4b84d59c0177 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 25 Nov 2013 11:40:12 +0100 Subject: Stop render thread regardless when the window is being destroyed When a window is shown and quickly hidden again we can get to a state, on a asynchronous windowing system API, where the isExposed=true event has been pushed to the event queue but not yet processed at the time the user calls hide(). As hide() immediately sets isVisible() to false, we end up with isExposed=true and isVisible=false which prevent the WM_Obscure event to be sent to render loop which means the render thread thought the window was still on screen when we reched the shutdown in WM_TryRelease. Changed WM_TryRelease handling to disregard window state when the window is being deleted. This forces SG and GL cleanup and stops the thread. Task-number: QTBUG-35055 Change-Id: Ibac5aa27354d6450f30a61450214cb785ab855bf Reviewed-by: J-P Nurmi Reviewed-by: Laszlo Agocs --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index bca7736e79..850a463c3e 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -402,8 +402,8 @@ bool QSGRenderThread::event(QEvent *e) case WM_TryRelease: { QSG_RT_DEBUG("WM_TryRelease"); mutex.lock(); - if (!window) { - WMTryReleaseEvent *wme = static_cast(e); + WMTryReleaseEvent *wme = static_cast(e); + if (!window || wme->inDestructor) { QSG_RT_DEBUG(" - setting exit flag and invalidating GL"); invalidateOpenGL(wme->window, wme->inDestructor); active = gl; -- cgit v1.2.3 From 87da2a2526aa03dd43254730a6e675e83c7c1342 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Fri, 22 Nov 2013 18:52:22 +0100 Subject: Use QFontDatabase to check if a font is scalable. The flag set in QFontEngine was not always correctly set, use QFontDatabase instead which is slower but should always be correct. We fallback to native font rendering when the font is not scalable. Change-Id: Ie9a2397abd42890d0fb05bc2f9c46a60040296f2 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/items/qquicktextnode.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp index dd314c892d..18ee1a479d 100644 --- a/src/quick/items/qquicktextnode.cpp +++ b/src/quick/items/qquicktextnode.cpp @@ -143,10 +143,13 @@ QSGGlyphNode *QQuickTextNode::addGlyphs(const QPointF &position, const QGlyphRun QSGNode *parentNode) { QSGRenderContext *sg = QQuickItemPrivate::get(m_ownerElement)->sceneGraphRenderContext(); - QRawFontPrivate *fontP = QRawFontPrivate::get(glyphs.rawFont()); - QSGGlyphNode *node = m_useNativeRenderer || !fontP->fontEngine->smoothScalable + 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); -- cgit v1.2.3 From 21a03c02848bb35fe665223f49ba9643cce343b7 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 20 Nov 2013 22:36:30 +0100 Subject: QSmoothedAnimation: Don't set property if animation isn't running This could cause things to get "stuck" in the wrong state under some rather hard to reproduce conditions. Change-Id: Ied23d2bdfcfd0b197f4b28fed9c82ffd64e52ebf Done-with: Aaron Kennedy Done-with: Alan Alpert <416365416c@gmail.com> Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com> --- src/quick/util/qquicksmoothedanimation.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/quick') diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp index 017fe39003..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; -- cgit v1.2.3 From f449534020adc8623ebfced5daae331ef56c4421 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Mon, 25 Nov 2013 23:54:47 +0100 Subject: Also update viewport size when header/footer size changes Task-number: QTBUG-24292 Change-Id: I8e7f5abe077b6e8d2ce6625dcf43a34a7260934e Done-with: Martin Jones Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com> --- src/quick/items/qquickitemview.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/quick') 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(); } -- cgit v1.2.3 From 900e3d4ad5f2bc4994ddf164c15c641f85630b81 Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Tue, 26 Nov 2013 09:48:42 +0100 Subject: Fix build with QT_NO_ACCESSIBILITY "q" was an unused variable, which triggered a warning/error. Change-Id: I83bdc63a7caa12a5cd48331729492c0f36ed6fa0 Reviewed-by: Frederik Gladhorn --- src/quick/items/qquicktextinput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index b46387ba47..c56f3648e6 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -3392,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) { @@ -3410,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); -- cgit v1.2.3