From 0360e5ed59813f5d7cb709cc7885d942e5fa2473 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Fri, 12 Apr 2013 16:24:47 +0200 Subject: Remove slow and buggy sub-image code The code was probably sub-optimal in most cases, and it broke on GLES 2 when using the BGRA texture extension. Done with Gunnar. Task-number: QTBUG-30656 Change-Id: I92f74cd39f408f145629bc0eb6f3ff43d2f4f000 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/util/qsgpainternode.cpp | 31 +--------------------------- 1 file changed, 1 insertion(+), 30 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/util/qsgpainternode.cpp b/src/quick/scenegraph/util/qsgpainternode.cpp index e5cf6b8295..97b3500ad0 100644 --- a/src/quick/scenegraph/util/qsgpainternode.cpp +++ b/src/quick/scenegraph/util/qsgpainternode.cpp @@ -73,10 +73,6 @@ QSGPainterTexture::QSGPainterTexture() m_retain_image = true; } -#ifdef QT_OPENGL_ES -extern void qsg_swizzleBGRAToRGBA(QImage *image); -#endif - void QSGPainterTexture::bind() { if (m_dirty_rect.isNull()) { @@ -84,33 +80,8 @@ void QSGPainterTexture::bind() return; } - bool oldMipmapsGenerated = m_mipmaps_generated; - m_mipmaps_generated = true; + setImage(m_image); QSGPlainTexture::bind(); - m_mipmaps_generated = oldMipmapsGenerated; - - QImage subImage = m_image.copy(m_dirty_rect); - - int w = m_dirty_rect.width(); - int h = m_dirty_rect.height(); - -#ifdef QT_OPENGL_ES - qsg_swizzleBGRAToRGBA(&subImage); - glTexSubImage2D(GL_TEXTURE_2D, 0, m_dirty_rect.x(), m_dirty_rect.y(), w, h, - GL_RGBA, GL_UNSIGNED_BYTE, subImage.constBits()); -#else - glTexSubImage2D(GL_TEXTURE_2D, 0, m_dirty_rect.x(), m_dirty_rect.y(), w, h, - GL_BGRA, GL_UNSIGNED_BYTE, subImage.constBits()); -#endif - - if (m_has_mipmaps && !m_mipmaps_generated) { - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D); - m_mipmaps_generated = true; - } - - m_dirty_texture = false; - m_dirty_bind_options = false; m_dirty_rect = QRect(); } -- cgit v1.2.3 From a6ccf8b484596091b9a38ac37dac43c456cdc730 Mon Sep 17 00:00:00 2001 From: Sean Harmer Date: Tue, 16 Apr 2013 11:25:14 +0100 Subject: Make QSGNode and friends extensible via a d-pointer Convert the private void *m_reserved to a d_ptr so as to make QSGNode inherited classes extensible without breaking binary compatibility. QSGNode and subclasses do not create a private instance by default. This is required by a follow-up commit where a new member needs to be added to QSGSimpleTextureNode. Protected ctors have been added to the superclasses of QSGSimpleTextureNode in the usual fashion. Change-Id: I30c5f5d057654145d87f18c34c5d13a6ff5f7b11 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/coreapi/qsgnode.cpp | 46 +++++++++++++++++++ src/quick/scenegraph/coreapi/qsgnode.h | 11 ++++- src/quick/scenegraph/coreapi/qsgnode_p.h | 76 ++++++++++++++++++++++++++++++++ src/quick/scenegraph/scenegraph.pri | 1 + 4 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 src/quick/scenegraph/coreapi/qsgnode_p.h (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp index 6a22e0e7f9..8bf9ae8e76 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.cpp +++ b/src/quick/scenegraph/coreapi/qsgnode.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "qsgnode.h" +#include "qsgnode_p.h" #include "qsgrenderer_p.h" #include "qsgnodeupdater_p.h" #include "qsgmaterial.h" @@ -266,6 +267,26 @@ QSGNode::QSGNode(NodeType type) init(); } +/*! + * Constructs a new node with the given node type. + * + * \internal + */ +QSGNode::QSGNode(QSGNodePrivate &dd, NodeType type) + : m_parent(0) + , m_type(type) + , m_firstChild(0) + , m_lastChild(0) + , m_nextSibling(0) + , m_previousSibling(0) + , m_subtreeRenderableCount(type == GeometryNodeType || type == RenderNodeType ? 1 : 0) + , m_nodeFlags(OwnedByParent) + , m_dirtyState(0) + , d_ptr(&dd) +{ + init(); +} + /*! * \internal */ @@ -677,6 +698,18 @@ QSGBasicGeometryNode::QSGBasicGeometryNode(NodeType type) } +/*! + \internal + */ +QSGBasicGeometryNode::QSGBasicGeometryNode(QSGBasicGeometryNodePrivate &dd, NodeType type) + : QSGNode(dd, type) + , m_geometry(0) + , m_matrix(0) + , m_clip_list(0) +{ +} + + /*! Deletes this QSGBasicGeometryNode. @@ -807,6 +840,19 @@ QSGGeometryNode::QSGGeometryNode() } +/*! + \internal + */ +QSGGeometryNode::QSGGeometryNode(QSGGeometryNodePrivate &dd) + : QSGBasicGeometryNode(dd, GeometryNodeType) + , m_render_order(0) + , m_material(0) + , m_opaque_material(0) + , m_opacity(1) +{ +} + + /*! Deletes this geometry node. diff --git a/src/quick/scenegraph/coreapi/qsgnode.h b/src/quick/scenegraph/coreapi/qsgnode.h index 3fa2f7fc04..d83e6bcc81 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.h +++ b/src/quick/scenegraph/coreapi/qsgnode.h @@ -58,6 +58,9 @@ class QSGRootNode; class QSGGeometryNode; class QSGTransformNode; class QSGClipNode; +class QSGNodePrivate; +class QSGBasicGeometryNodePrivate; +class QSGGeometryNodePrivate; class Q_QUICK_EXPORT QSGNode { @@ -149,6 +152,7 @@ public: protected: QSGNode(NodeType type); + QSGNode(QSGNodePrivate &dd, NodeType type); private: friend class QSGRootNode; @@ -167,7 +171,8 @@ private: Flags m_nodeFlags; DirtyState m_dirtyState; - void *m_reserved; +protected: + QScopedPointer d_ptr; }; class Q_QUICK_EXPORT QSGBasicGeometryNode : public QSGNode @@ -184,6 +189,7 @@ public: protected: QSGBasicGeometryNode(NodeType type); + QSGBasicGeometryNode(QSGBasicGeometryNodePrivate &dd, NodeType type); private: friend class QSGNodeUpdater; @@ -218,6 +224,9 @@ public: void setInheritedOpacity(qreal opacity); qreal inheritedOpacity() const { return m_opacity; } +protected: + QSGGeometryNode(QSGGeometryNodePrivate &dd); + private: friend class QSGNodeUpdater; diff --git a/src/quick/scenegraph/coreapi/qsgnode_p.h b/src/quick/scenegraph/coreapi/qsgnode_p.h new file mode 100644 index 0000000000..b0d8088af2 --- /dev/null +++ b/src/quick/scenegraph/coreapi/qsgnode_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB) +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml 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 QSGNODE_P_H +#define QSGNODE_P_H + +#include + +QT_BEGIN_NAMESPACE + +class QSGNodePrivate +{ +public: + QSGNodePrivate() {} + virtual ~QSGNodePrivate() {} +}; + + +class QSGBasicGeometryNodePrivate : public QSGNodePrivate +{ +public: + QSGBasicGeometryNodePrivate() + : QSGNodePrivate() + {} +}; + + +class QSGGeometryNodePrivate: public QSGBasicGeometryNodePrivate +{ +public: + QSGGeometryNodePrivate() + : QSGBasicGeometryNodePrivate() + {} +}; + +QT_END_NAMESPACE + +#endif // QSGNODE_P_H diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri index 8c87e23ac9..ebf886dace 100644 --- a/src/quick/scenegraph/scenegraph.pri +++ b/src/quick/scenegraph/scenegraph.pri @@ -6,6 +6,7 @@ HEADERS += \ $$PWD/coreapi/qsggeometry.h \ $$PWD/coreapi/qsgmaterial.h \ $$PWD/coreapi/qsgnode.h \ + $$PWD/coreapi/qsgnode_p.h \ $$PWD/coreapi/qsgnodeupdater_p.h \ $$PWD/coreapi/qsgrenderer_p.h \ $$PWD/coreapi/qsgrendernode_p.h \ -- cgit v1.2.3 From 5c7225572746201cc60496530f410178cdb4283b Mon Sep 17 00:00:00 2001 From: Sean Harmer Date: Mon, 15 Apr 2013 11:52:24 +0100 Subject: Add a way of transforming texture coordinates of a simple textured quad This commit introduces the enum TextureCoordinatesTransformFlag and corresponding QFlags OR combination TextureCoordinatesTransformMode. This enum is used to control the orientation of texture coordinates relative to window/item coordinates. The common use case addressed by this commit is when rendering to a texture via an FBO using some 3rd party OpenGL library. Some libraries do not offer a way to orient the rendered output which results in the texture being displayed upside down when used in conjunction with QSGSimpleTextureNode. There are a number of possible solutions to this: 1 Mirror the item by scaling by -1 in the y-direction in QML document 2 Use a custom material (shader) that transforms texture coordinates in GLSL 3 Generate texture coordinates differently This commit opts for approach 3. Approach 1 is ugly and visible to the end user and also causes more work when other transformations interact with the necessary scaling. Approach 2 has a performance cost in both switching material (shader) and also in additional per-vertex or per- fragment operations. The chosen approach hides it from the end user and has zero runtime cost delta compared to any other textured quad. Change-Id: I95870da50a09d113aeff2681bfd458669ec7a5a4 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/util/qsgsimpletexturenode.cpp | 81 ++++++++++++++++++++-- src/quick/scenegraph/util/qsgsimpletexturenode.h | 16 +++++ 2 files changed, 93 insertions(+), 4 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp index 318120e4bf..86e0d36f6c 100644 --- a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp +++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp @@ -41,18 +41,44 @@ #include "qsgsimpletexturenode.h" +#include QT_BEGIN_NAMESPACE +class QSGSimpleTextureNodePrivate : public QSGGeometryNodePrivate +{ +public: + QSGSimpleTextureNodePrivate() + : QSGGeometryNodePrivate() + , m_texCoordMode(QSGSimpleTextureNode::NoTransform) + {} + + QSGSimpleTextureNode::TextureCoordinatesTransformMode m_texCoordMode; +}; + static void qsgsimpletexturenode_update(QSGGeometry *g, QSGTexture *texture, - const QRectF &rect) + const QRectF &rect, + QSGSimpleTextureNode::TextureCoordinatesTransformMode texCoordMode) { if (!texture) return; QSize ts = texture->textureSize(); QRectF sourceRect(0, 0, ts.width(), ts.height()); + + // Maybe transform the texture coordinates + if (texCoordMode.testFlag(QSGSimpleTextureNode::MirrorHorizontally)) { + float tmp = sourceRect.left(); + sourceRect.setLeft(sourceRect.right()); + sourceRect.setRight(tmp); + } + if (texCoordMode.testFlag(QSGSimpleTextureNode::MirrorVertically)) { + float tmp = sourceRect.top(); + sourceRect.setTop(sourceRect.bottom()); + sourceRect.setBottom(tmp); + } + QSGGeometry::updateTexturedRectGeometry(g, rect, texture->convertToNormalizedSourceRect(sourceRect)); } @@ -71,7 +97,8 @@ static void qsgsimpletexturenode_update(QSGGeometry *g, Constructs a new simple texture node */ QSGSimpleTextureNode::QSGSimpleTextureNode() - : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) + : QSGGeometryNode(*new QSGSimpleTextureNodePrivate) + , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) { setGeometry(&m_geometry); setMaterial(&m_material); @@ -112,7 +139,8 @@ void QSGSimpleTextureNode::setRect(const QRectF &r) if (m_rect == r) return; m_rect = r; - qsgsimpletexturenode_update(&m_geometry, texture(), m_rect); + Q_D(QSGSimpleTextureNode); + qsgsimpletexturenode_update(&m_geometry, texture(), m_rect, d->m_texCoordMode); markDirty(DirtyGeometry); } @@ -144,7 +172,8 @@ void QSGSimpleTextureNode::setTexture(QSGTexture *texture) return; m_material.setTexture(texture); m_opaque_material.setTexture(texture); - qsgsimpletexturenode_update(&m_geometry, texture, m_rect); + Q_D(QSGSimpleTextureNode); + qsgsimpletexturenode_update(&m_geometry, texture, m_rect, d->m_texCoordMode); markDirty(DirtyMaterial); } @@ -158,4 +187,48 @@ QSGTexture *QSGSimpleTextureNode::texture() const return m_material.texture(); } +/*! + \enum QSGSimpleTextureNode::TextureCoordinatesTransformFlag + + The TextureCoordinatesTransformFlag enum is used to specify the + mode used to generate texture coordinates for a textured quad. + + \value NoTransform Texture coordinates are oriented with window coordinates + i.e. with origin at top-left. + + \value MirrorHorizontally Texture coordinates are inverted in the horizontal axis with + respect to window coordinates + + \value MirrorVertically Texture coordinates are inverted in the vertical axis with + respect to window coordinates + */ + +/*! + Sets the method used to generate texture coordinates to \a mode. This can be used to obtain + correct orientation of the texture. This is commonly needed when using a third party OpenGL + library to render to texture as OpenGL has an inverted y-axis relative to Qt Quick. + + \sa textureCoordinatesTransform() + */ +void QSGSimpleTextureNode::setTextureCoordinatesTransform(QSGSimpleTextureNode::TextureCoordinatesTransformMode mode) +{ + Q_D(QSGSimpleTextureNode); + if (d->m_texCoordMode == mode) + return; + d->m_texCoordMode = mode; + qsgsimpletexturenode_update(&m_geometry, texture(), m_rect, d->m_texCoordMode); + markDirty(DirtyMaterial); +} + +/*! + Returns the mode used to generate texture coordinates for this node. + + \sa setTextureCoordinatesTransform() + */ +QSGSimpleTextureNode::TextureCoordinatesTransformMode QSGSimpleTextureNode::textureCoordinatesTransform() const +{ + Q_D(const QSGSimpleTextureNode); + return d->m_texCoordMode; +} + QT_END_NAMESPACE diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.h b/src/quick/scenegraph/util/qsgsimpletexturenode.h index ffd10210ae..f5ab7fb3bb 100644 --- a/src/quick/scenegraph/util/qsgsimpletexturenode.h +++ b/src/quick/scenegraph/util/qsgsimpletexturenode.h @@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE +class QSGSimpleTextureNodePrivate; + class Q_QUICK_EXPORT QSGSimpleTextureNode : public QSGGeometryNode { public: @@ -63,14 +65,28 @@ public: void setFiltering(QSGTexture::Filtering filtering); QSGTexture::Filtering filtering() const; + enum TextureCoordinatesTransformFlag { + NoTransform = 0x00, + MirrorHorizontally = 0x01, + MirrorVertically = 0x02 + }; + Q_DECLARE_FLAGS(TextureCoordinatesTransformMode, TextureCoordinatesTransformFlag) + + void setTextureCoordinatesTransform(TextureCoordinatesTransformMode mode); + TextureCoordinatesTransformMode textureCoordinatesTransform() const; + private: QSGGeometry m_geometry; QSGOpaqueTextureMaterial m_opaque_material; QSGTextureMaterial m_material; QRectF m_rect; + + Q_DECLARE_PRIVATE(QSGSimpleTextureNode) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QSGSimpleTextureNode::TextureCoordinatesTransformMode) + QT_END_NAMESPACE #endif // QSGSIMPLETEXTURENODE_H -- cgit v1.2.3 From 2170a46ceef158eab6ccb7ecbeb26ae3053e6544 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Tue, 16 Apr 2013 16:29:21 +0200 Subject: Fixed alpha blending for native text. Change-Id: I3effd31849b21a9497fadfb22c959562bff7951b Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index 419062d025..3df11532e4 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -95,7 +95,8 @@ const char *QSGTextMaskMaterialData::fragmentShader() const { "uniform sampler2D texture; \n" "uniform lowp vec4 color; \n" "void main() { \n" - " gl_FragColor = vec4(texture2D(texture, sampleCoord).rgb * color.a, 1.0); \n" + " lowp vec4 glyph = texture2D(texture, sampleCoord); \n" + " gl_FragColor = vec4(glyph.rgb * color.a, glyph.a); \n" "}"; } @@ -162,7 +163,7 @@ void QSGTextMaskMaterialData::updateState(const RenderState &state, QSGMaterial state.context()->functions()->glBlendColor(c.redF(), c.greenF(), c.blueF(), - 1.0f); + c.alphaF()); } } -- cgit v1.2.3 From 909d3a57dfc279d8a8dee0751bf7635551d6ee3b Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 16 Apr 2013 10:51:31 +0200 Subject: Remove dead code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The renderWithoutShowing was a piece of functionality that we experimented on long ago and it never quite worked and has it currently only adds bloat. It would be sensible to be able to render a window without showing it on screen, such as for testing purposes, but then it should be done through proper public API and thouroughly supported cross platform. Change-Id: I6bea7335f769c038a8167bad77c2dba171359be9 Reviewed-by: Yoann Lopes Reviewed-by: Samuel Rødal --- src/quick/scenegraph/qsgrenderloop.cpp | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 33a99d1506..04981b54e7 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -215,49 +215,25 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window) void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) { - bool renderWithoutShowing = QQuickWindowPrivate::get(window)->renderWithoutShowing; - if ((!window->isExposed() && !renderWithoutShowing) || !m_windows.contains(window)) + if (!QQuickWindowPrivate::get(window)->isRenderable() || !m_windows.contains(window)) return; WindowData &data = const_cast(m_windows[window]); - QQuickWindow *masterWindow = 0; - if (!window->isVisible() && !renderWithoutShowing) { - // Find a "proper surface" to bind... - for (QHash::const_iterator it = m_windows.constBegin(); - it != m_windows.constEnd() && !masterWindow; ++it) { - if (it.key()->isVisible()) - masterWindow = it.key(); - } - } else { - masterWindow = window; - } - - if (!masterWindow) - return; - - if (!QQuickWindowPrivate::get(masterWindow)->isRenderable()) { - qWarning().nospace() - << "Unable to find a renderable master window " - << masterWindow << "when trying to render" - << window << " (" << window->geometry() << ")."; - return; - } - bool current = false; if (!gl) { gl = new QOpenGLContext(); - gl->setFormat(masterWindow->requestedFormat()); + gl->setFormat(window->requestedFormat()); if (!gl->create()) { delete gl; gl = 0; } - current = gl->makeCurrent(masterWindow); + current = gl->makeCurrent(window); if (current) sg->initialize(gl); } else { - current = gl->makeCurrent(masterWindow); + current = gl->makeCurrent(window); } bool alsoSwap = data.updatePending; -- cgit v1.2.3 From f56829662308e84a578a3816cc054538f7d91e44 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 16 Apr 2013 12:29:52 +0200 Subject: Don't use bitfields, reading/wrting them is not atomic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-30663 Change-Id: I952bb4cd9c254f085304ceeddced14b66e0f12b6 Reviewed-by: Samuel Rødal --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index b457c33bed..4cca87e990 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -328,9 +328,9 @@ public: QEventLoop eventLoop; - uint pendingUpdate : 2; - uint sleeping : 1; - uint syncResultedInChanges : 1; + uint pendingUpdate; + uint sleeping; + uint syncResultedInChanges; volatile bool guiIsLocked; volatile bool shouldExit; -- cgit v1.2.3 From 30eea7e16959152d3323f41c11464243665b15a0 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 22 Apr 2013 13:41:53 +0200 Subject: Clear the pendingUpdate flag every frame. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Icd9bf8ec63e46341f5a43dbb85fe6a3a885f6afb Reviewed-by: Morten Johan Sørvig Reviewed-by: Samuel Rødal --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 4cca87e990..de1e2517db 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -515,7 +515,6 @@ void QSGRenderThread::sync() mutex.lock(); Q_ASSERT_X(guiIsLocked, "QSGRenderThread::sync()", "sync triggered on bad terms as gui is not already locked..."); - pendingUpdate = 0; for (int i=0; i(m_windows.at(i)); @@ -557,8 +556,10 @@ void QSGRenderThread::syncAndRender() syncResultedInChanges = false; bool repaintRequested = pendingUpdate & RepaintRequest; + bool syncRequested = pendingUpdate & SyncRequest; + pendingUpdate = 0; - if (pendingUpdate & SyncRequest) { + if (syncRequested) { RLDEBUG(" Render: - update pending, doing sync"); sync(); } -- cgit v1.2.3 From 73d8bcda7d1b4317f38d8a2844294601325915aa Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 16 Apr 2013 17:25:04 +0200 Subject: Renderloop for Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The normal GUI thread render loop has several problems on windows. It does not do vsync animations and on some hardware, where the vsync delta is higher than the time it takes to fire a 16ms timer, the eventloop will always contain at least one event and we never return to processing non-client area events, like resize. Also, threaded OpenGL seems rather unstable, so the threaded renderer is not a stable option. So we introduce a windows based renderloop. It is fully cross platform but written to make the most out of the limitations which exist. The overall goal is: - vsync animations when allowed by the system. We get this by using an animation driver and advancing in sync with rendering - Keep system load low and allow for NC processing. The maybeUpdate function will start a short timer which will let the renderloop idle for few ms, allowing the eventloop to pick up system events. (this is similar to what the threaded renderer also does, btw) Change-Id: Ic192fd0ed7d5ecdaa2c887c08cbeb42c5de6b8a8 Reviewed-by: Friedemann Kleint Reviewed-by: Samuel Rødal --- src/quick/scenegraph/qsgrenderloop.cpp | 52 ++- src/quick/scenegraph/qsgwindowsrenderloop.cpp | 435 ++++++++++++++++++++++++++ src/quick/scenegraph/qsgwindowsrenderloop_p.h | 114 +++++++ src/quick/scenegraph/scenegraph.pri | 16 +- 4 files changed, 593 insertions(+), 24 deletions(-) create mode 100644 src/quick/scenegraph/qsgwindowsrenderloop.cpp create mode 100644 src/quick/scenegraph/qsgwindowsrenderloop_p.h (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 04981b54e7..f71ccea294 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -41,6 +41,7 @@ #include "qsgrenderloop_p.h" #include "qsgthreadedrenderloop_p.h" +#include "qsgwindowsrenderloop_p.h" #include #include @@ -130,15 +131,6 @@ QSGRenderLoop *QSGRenderLoop::instance() s_instance = QSGContext::createWindowManager(); bool bufferQueuing = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL); -#ifdef Q_OS_WIN - bool fancy = false; // QTBUG-28037 -#else - bool fancy = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL); -#endif - if (qmlNoThreadedRenderer()) - fancy = false; - else if (qmlForceThreadedRenderer()) - fancy = true; // Enable fixed animation steps... QByteArray fixed = qgetenv("QML_FIXED_ANIMATION_STEP"); @@ -151,9 +143,45 @@ QSGRenderLoop *QSGRenderLoop::instance() QUnifiedTimer::instance(true)->setConsistentTiming(true); if (!s_instance) { - s_instance = fancy - ? (QSGRenderLoop*) new QSGThreadedRenderLoop - : (QSGRenderLoop*) new QSGGuiThreadRenderLoop; + + enum RenderLoopType { + BasicRenderLoop, + ThreadedRenderLoop, + WindowsRenderLoop + }; + + RenderLoopType loopType = BasicRenderLoop; + +#ifdef Q_OS_WIN + loopType = WindowsRenderLoop; +#else + if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL)) + loopType = ThreadedRenderLoop; +#endif + if (qmlNoThreadedRenderer()) + loopType = BasicRenderLoop; + else if (qmlForceThreadedRenderer()) + loopType = ThreadedRenderLoop; + + const QByteArray loopName = qgetenv("QSG_RENDER_LOOP"); + if (loopName == QByteArrayLiteral("windows")) + loopType = WindowsRenderLoop; + else if (loopName == QByteArrayLiteral("basic")) + loopType = BasicRenderLoop; + else if (loopName == QByteArrayLiteral("threaded")) + loopType = ThreadedRenderLoop; + + switch (loopType) { + case ThreadedRenderLoop: + s_instance = new QSGThreadedRenderLoop(); + break; + case WindowsRenderLoop: + s_instance = new QSGWindowsRenderLoop(); + break; + default: + s_instance = new QSGGuiThreadRenderLoop(); + break; + } } } return s_instance; diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp new file mode 100644 index 0000000000..3e21af6ac0 --- /dev/null +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -0,0 +1,435 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml 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 "qsgwindowsrenderloop_p.h" + +#include + +#include +#include + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); + +// #define QSG_RENDER_LOOP_DEBUG + +#ifdef QSG_RENDER_LOOP_DEBUG +static QElapsedTimer qsg_debug_timer; +# define RLDEBUG(x) printf("(%6d) %s : %4d - %s\n", (int) qsg_debug_timer.elapsed(), __FILE__, __LINE__, x) +#else +# define RLDEBUG(x) +#endif + +#ifndef QSG_NO_RENDER_TIMING +static bool qsg_render_timing = !qgetenv("QSG_RENDER_TIMING").isEmpty(); +static QElapsedTimer qsg_render_timer; +#define QSG_RENDER_TIMING_SAMPLE(sampleName) int sampleName = 0; if (qsg_render_timing) sampleName = qsg_render_timer.elapsed() +#else +#define QSG_RENDER_TIMING_SAMPLE(sampleName) +#endif + + +QSGWindowsRenderLoop::QSGWindowsRenderLoop() + : m_gl(0) + , m_sg(QSGContext::createDefaultContext()) + , m_updateTimer(0) + , m_animationTimer(0) +{ +#ifdef QSG_RENDER_LOOP_DEBUG + qsg_debug_timer.start(); +#endif + + m_animationDriver = m_sg->createAnimationDriver(m_sg); + m_animationDriver->install(); + + connect(m_animationDriver, SIGNAL(started()), this, SLOT(started())); + connect(m_animationDriver, SIGNAL(stopped()), this, SLOT(stopped())); + + m_vsyncDelta = 1000 / QGuiApplication::primaryScreen()->refreshRate(); + if (m_vsyncDelta <= 0) + m_vsyncDelta = 16; + + RLDEBUG("Windows Render Loop created"); + +#ifndef QSG_NO_RENDER_TIMIMG + qsg_render_timer.start(); +#endif +} + +QSGWindowsRenderLoop::WindowData *QSGWindowsRenderLoop::windowData(QQuickWindow *window) +{ + for (int i=0; isetFormat(window->requestedFormat()); + m_gl->create(); + QSG_RENDER_TIMING_SAMPLE(time_created); + RLDEBUG(" - making current"); + m_gl->makeCurrent(window); + RLDEBUG(" - initializing SG"); + QSG_RENDER_TIMING_SAMPLE(time_current); + m_sg->initialize(m_gl); + +#ifndef QSG_NO_RENDER_TIMING + if (qsg_render_timing) { + qDebug("WindowsRenderLoop: GL=%d ms, makeCurrent=%d ms, SG=%d ms", + int(time_created - time_start), + int(time_current - time_created), + int(qsg_render_timer.elapsed() - time_current)); + } +#endif + + } + + WindowData data; + data.window = window; + data.pendingUpdate = false; + m_windows << data; + + RLDEBUG(" - done with show"); +} + +void QSGWindowsRenderLoop::hide(QQuickWindow *window) +{ + RLDEBUG("hide"); + + for (int i=0; iisExposed()) + handleObscurity(); + + QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); + cd->cleanupNodesOnShutdown(); + + // If this is the last tracked window, check for persistent SG and GL and + // potentially clean up. + if (m_windows.size() == 0) { + if (!cd->persistentSceneGraph) { + m_sg->invalidate(); + if (!cd->persistentGLContext) { + delete m_gl; + m_gl = 0; + } + } + } +} + +void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window) +{ + RLDEBUG("windowDestroyed"); + hide(window); + + // If this is the last tracked window, clean up SG and GL. + if (m_windows.size() == 0) { + m_sg->invalidate(); + delete m_gl; + m_gl = 0; + } +} + +bool QSGWindowsRenderLoop::anyoneShowing() const +{ + foreach (const WindowData &wd, m_windows) + if (wd.window->isExposed() && wd.window->size().isValid()) + return true; + return false; +} + +void QSGWindowsRenderLoop::exposureChanged(QQuickWindow *window) +{ + + if (windowData(window) == 0) + return; + + if (window->isExposed()) { + + // Stop non-visual animation timer as we now have a window rendering + if (m_animationTimer && anyoneShowing()) { + RLDEBUG(" - stopping non-visual animation timer"); + killTimer(m_animationTimer); + m_animationTimer = 0; + } + + RLDEBUG("exposureChanged - exposed"); + WindowData *wd = windowData(window); + wd->pendingUpdate = true; + + // If we have a pending timer and we get an expose, we need to stop it. + // Otherwise we get two frames and two animation ticks in the same time-interval. + if (m_updateTimer) { + RLDEBUG(" - killing pending update timer"); + killTimer(m_updateTimer); + m_updateTimer = 0; + } + render(); + } else { + handleObscurity(); + } +} + +void QSGWindowsRenderLoop::handleObscurity() +{ + RLDEBUG("handleObscurity"); + // Potentially start the non-visual animation timer if nobody is rendering + if (m_animationDriver->isRunning() && !anyoneShowing() && !m_animationTimer) { + RLDEBUG(" - starting non-visual animation timer"); + m_animationTimer = startTimer(m_vsyncDelta); + } +} + +QImage QSGWindowsRenderLoop::grab(QQuickWindow *window) +{ + RLDEBUG("grab"); + if (!m_gl) + return QImage(); + + m_gl->makeCurrent(window); + + QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); + d->polishItems(); + d->syncSceneGraph(); + d->renderSceneGraph(window->size()); + + QImage image = qt_gl_read_framebuffer(window->size(), false, false); + return image; +} + +void QSGWindowsRenderLoop::update(QQuickWindow *window) +{ + RLDEBUG("update"); + maybeUpdate(window); +} + +void QSGWindowsRenderLoop::maybeUpdate(QQuickWindow *window) +{ + RLDEBUG("maybeUpdate"); + + WindowData *wd = windowData(window); + if (!wd || !anyoneShowing()) + return; + + wd->pendingUpdate = true; + maybePostUpdateTimer(); +} + +bool QSGWindowsRenderLoop::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::Timer: { + QTimerEvent *te = static_cast(event); + if (te->timerId() == m_animationTimer) { + RLDEBUG("event : animation tick while nothing is showing"); + m_animationDriver->advance(); + } else if (te->timerId() == m_updateTimer) { + RLDEBUG("event : update"); + killTimer(m_updateTimer); + m_updateTimer = 0; + render(); + } + return true; } + default: + break; + } + + return QObject::event(event); +} + +/* + * Go through all windows we control and render them in turn. + * Then tick animations if active. + */ +void QSGWindowsRenderLoop::render() +{ + RLDEBUG("render"); + foreach (const WindowData &wd, m_windows) { + if (wd.pendingUpdate) { + const_cast(wd).pendingUpdate = false; + renderWindow(wd.window); + } + } + + if (m_animationDriver->isRunning()) { + RLDEBUG("advancing animations"); + QSG_RENDER_TIMING_SAMPLE(time_start); + m_animationDriver->advance(); + RLDEBUG("animations advanced"); + +#ifndef QSG_NO_RENDER_TIMING + if (qsg_render_timing) { + qDebug("WindowsRenderLoop: animations=%d ms", + int(qsg_render_timer.elapsed() - time_start)); + } +#endif + + // It is not given that animations triggered another maybeUpdate() + // and thus another render pass, so to keep things running, + // make sure there is another frame pending. + maybePostUpdateTimer(); + } +} + +/* + * Render the contents of this window. First polish, then sync, render + * then finally swap. + * + * Note: This render function does not implement aborting + * the render call when sync step results in no scene graph changes, + * like the threaded renderer does. + */ +void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window) +{ + RLDEBUG("renderWindow"); + QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); + + if (!d->isRenderable()) + return; + + if (!m_gl->makeCurrent(window)) + return; + + QSG_RENDER_TIMING_SAMPLE(time_start); + + RLDEBUG(" - polishing"); + d->polishItems(); + QSG_RENDER_TIMING_SAMPLE(time_polished); + + RLDEBUG(" - syncing"); + d->syncSceneGraph(); + QSG_RENDER_TIMING_SAMPLE(time_synced); + + RLDEBUG(" - rendering"); + d->renderSceneGraph(window->size()); + QSG_RENDER_TIMING_SAMPLE(time_rendered); + + RLDEBUG(" - swapping"); + m_gl->swapBuffers(window); + QSG_RENDER_TIMING_SAMPLE(time_swapped); + + RLDEBUG(" - frameDone"); + d->fireFrameSwapped(); + +#ifndef QSG_NO_RENDER_TIMING + if (qsg_render_timing) { + qDebug("WindowsRenderLoop(t=%d): window=%p, polish=%d ms, sync=%d ms, render=%d ms, swap=%d ms", + int(qsg_render_timer.elapsed()), + window, + int(time_polished - time_start), + int(time_synced - time_polished), + int(time_rendered - time_synced), + int(time_swapped - time_rendered)); + } +#endif +} + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/qsgwindowsrenderloop_p.h b/src/quick/scenegraph/qsgwindowsrenderloop_p.h new file mode 100644 index 0000000000..dc3a409cd5 --- /dev/null +++ b/src/quick/scenegraph/qsgwindowsrenderloop_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml 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 QSGWINDOWSRENDERLOOP_P_H +#define QSGWINDOWSRENDERLOOP_P_H + +#include +#include + +#include + +#include "qsgrenderloop_p.h" + +QT_BEGIN_NAMESPACE + +class QSGWindowsRenderLoop : public QObject, public QSGRenderLoop +{ + Q_OBJECT +public: + explicit QSGWindowsRenderLoop(); + + void show(QQuickWindow *window); + void hide(QQuickWindow *window); + + void windowDestroyed(QQuickWindow *window); + + void exposureChanged(QQuickWindow *window); + QImage grab(QQuickWindow *window); + + void update(QQuickWindow *window); + void maybeUpdate(QQuickWindow *window); + + QAnimationDriver *animationDriver() const { return m_animationDriver; } + + QSGContext *sceneGraphContext() const { return m_sg; } + + void releaseResources(QQuickWindow *) { } + + void render(); + void renderWindow(QQuickWindow *window); + + void resize(QQuickWindow *, const QSize &) { } + + bool event(QEvent *event); + +public slots: + void started(); + void stopped(); + +private: + struct WindowData { + QQuickWindow *window; + bool pendingUpdate; + }; + + void handleObscurity(); + void maybePostUpdateTimer(); + bool anyoneShowing() const; + WindowData *windowData(QQuickWindow *window); + + QList m_windows; + + QOpenGLContext *m_gl; + QSGContext *m_sg; + + QAnimationDriver *m_animationDriver; + + int m_updateTimer; + int m_animationTimer; + + int m_vsyncDelta; +}; + +QT_END_NAMESPACE + +#endif // QSGWINDOWSRENDERLOOP_P_H diff --git a/src/quick/scenegraph/scenegraph.pri b/src/quick/scenegraph/scenegraph.pri index 8c87e23ac9..c002a81451 100644 --- a/src/quick/scenegraph/scenegraph.pri +++ b/src/quick/scenegraph/scenegraph.pri @@ -51,7 +51,6 @@ SOURCES += \ $$PWD/util/qsgpainternode.cpp \ $$PWD/util/qsgdistancefieldutil.cpp - # QML / Adaptations API HEADERS += \ $$PWD/qsgadaptationlayer_p.h \ @@ -67,8 +66,8 @@ HEADERS += \ $$PWD/qsgflashnode_p.h \ $$PWD/qsgshareddistancefieldglyphcache_p.h \ $$PWD/qsgrenderloop_p.h \ - $$PWD/qsgthreadedrenderloop_p.h - + $$PWD/qsgthreadedrenderloop_p.h \ + $$PWD/qsgwindowsrenderloop_p.h SOURCES += \ $$PWD/qsgadaptationlayer.cpp \ @@ -84,12 +83,5 @@ SOURCES += \ $$PWD/qsgflashnode.cpp \ $$PWD/qsgshareddistancefieldglyphcache.cpp \ $$PWD/qsgrenderloop.cpp \ - $$PWD/qsgthreadedrenderloop.cpp - - - - - - - - + $$PWD/qsgthreadedrenderloop.cpp \ + $$PWD/qsgwindowsrenderloop.cpp -- cgit v1.2.3 From 4d54326fece7fe915902e3bbac34aa0e2569f219 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 25 Apr 2013 15:17:40 +0200 Subject: Disable native glyph rendering on embedded Change-Id: I71769affe8f0138dd65f3b94fb27176bd069ab8d Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/qsgcontext.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 8d36fce481..5d894e5236 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -354,7 +354,11 @@ QSGDistanceFieldGlyphCache *QSGContext::distanceFieldGlyphCache(const QRawFont & */ QSGGlyphNode *QSGContext::createNativeGlyphNode() { +#if defined(QT_OPENGL_ES) && !defined(QT_OPENGL_ES_2_ANGLE) + return createGlyphNode(); +#else return new QSGDefaultGlyphNode; +#endif } /*! -- cgit v1.2.3 From 49ef011e33b9ef977679b3d30f883fccea0d8748 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Wed, 17 Apr 2013 16:46:12 +0200 Subject: QmlProfiler: SceneGraph profiling Change-Id: Ide71b330b13fc3816ed191bd9af84e0fce0d9587 Reviewed-by: Kai Koehne --- src/quick/scenegraph/coreapi/qsgrenderer.cpp | 52 ++++++++++------- src/quick/scenegraph/qsgadaptationlayer.cpp | 21 +++++-- src/quick/scenegraph/qsgcontext.cpp | 10 +++- src/quick/scenegraph/qsgrenderloop.cpp | 36 ++++++++---- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 77 +++++++++++++++++--------- src/quick/scenegraph/qsgwindowsrenderloop.cpp | 45 ++++++++++++--- src/quick/scenegraph/util/qsgtexture.cpp | 58 ++++++++++++------- 7 files changed, 208 insertions(+), 91 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp index b46d45be57..805cfaad0d 100644 --- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp @@ -53,6 +53,8 @@ #include +#include + QT_BEGIN_NAMESPACE //#define RENDERER_DEBUG @@ -62,9 +64,9 @@ QT_BEGIN_NAMESPACE #ifndef QSG_NO_RENDER_TIMING static bool qsg_render_timing = !qgetenv("QSG_RENDER_TIMING").isEmpty(); -static QTime frameTimer; -static int preprocessTime; -static int updatePassTime; +static QElapsedTimer frameTimer; +static qint64 preprocessTime; +static qint64 updatePassTime; #endif void QSGBindable::clear(QSGRenderer::ClearMode mode) const @@ -238,10 +240,11 @@ void QSGRenderer::renderScene(const QSGBindable &bindable) #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) + bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled; + if (profileFrames) frameTimer.start(); - int bindTime = 0; - int renderTime = 0; + qint64 bindTime = 0; + qint64 renderTime = 0; #endif m_bindable = &bindable; @@ -249,8 +252,8 @@ void QSGRenderer::renderScene(const QSGBindable &bindable) bindable.bind(); #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) - bindTime = frameTimer.elapsed(); + if (profileFrames) + bindTime = frameTimer.nsecsElapsed(); #endif #ifndef QT_NO_DEBUG @@ -270,8 +273,8 @@ void QSGRenderer::renderScene(const QSGBindable &bindable) render(); #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) - renderTime = frameTimer.elapsed(); + if (profileFrames) + renderTime = frameTimer.nsecsElapsed(); #endif glDisable(GL_SCISSOR_TEST); @@ -292,12 +295,22 @@ void QSGRenderer::renderScene(const QSGBindable &bindable) #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) { printf(" - Breakdown of render time: preprocess=%d, updates=%d, binding=%d, render=%d, total=%d\n", - preprocessTime, - updatePassTime - preprocessTime, - bindTime - updatePassTime, - renderTime - bindTime, - renderTime); + int(preprocessTime / 1000000), + int((updatePassTime - preprocessTime) / 1000000), + int((bindTime - updatePassTime) / 1000000), + int((renderTime - bindTime) / 1000000), + int(renderTime / 1000000)); + } + + if (QQmlProfilerService::enabled) { + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphRendererFrame, + preprocessTime, + updatePassTime - preprocessTime, + bindTime - updatePassTime, + renderTime - bindTime); } + #endif } @@ -380,16 +393,17 @@ void QSGRenderer::preprocess() } #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) - preprocessTime = frameTimer.elapsed(); + bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled; + if (profileFrames) + preprocessTime = frameTimer.nsecsElapsed(); #endif nodeUpdater()->setToplevelOpacity(context()->renderAlpha()); nodeUpdater()->updateStates(m_root_node); #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) - updatePassTime = frameTimer.elapsed(); + if (profileFrames) + updatePassTime = frameTimer.nsecsElapsed(); #endif } diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index 1d534e3563..3536975e94 100644 --- a/src/quick/scenegraph/qsgadaptationlayer.cpp +++ b/src/quick/scenegraph/qsgadaptationlayer.cpp @@ -48,6 +48,7 @@ #include #include +#include #include QT_BEGIN_NAMESPACE @@ -162,7 +163,8 @@ void QSGDistanceFieldGlyphCache::update() return; #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) + bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled; + if (profileFrames) qsg_render_timer.start(); #endif @@ -176,10 +178,10 @@ void QSGDistanceFieldGlyphCache::update() } #ifndef QSG_NO_RENDER_TIMING - int renderTime = 0; + qint64 renderTime = 0; int count = m_pendingGlyphs.size(); - if (qsg_render_timing) - renderTime = qsg_render_timer.elapsed(); + if (profileFrames) + renderTime = qsg_render_timer.nsecsElapsed(); #endif m_pendingGlyphs.reset(); @@ -190,11 +192,18 @@ void QSGDistanceFieldGlyphCache::update() if (qsg_render_timing) { printf(" - glyphs: count=%d, render=%d, store=%d, total=%d\n", count, - renderTime, - (int) qsg_render_timer.elapsed() - renderTime, + int(renderTime/1000000), + (int) qsg_render_timer.elapsed() - int(renderTime/1000000), (int) qsg_render_timer.elapsed()); } + if (QQmlProfilerService::enabled) { + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphAdaptationLayerFrame, + count, + renderTime, + qsg_render_timer.nsecsElapsed() - renderTime); + } #endif } diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 5d894e5236..14f0fabbdd 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -67,6 +67,8 @@ #include #include +#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) @@ -482,7 +484,7 @@ QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material) return shader; #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) + if (qsg_render_timing || QQmlProfilerService::enabled) qsg_renderer_timer.start(); #endif @@ -494,6 +496,12 @@ QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material) #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) printf(" - compiling material: %dms\n", (int) qsg_renderer_timer.elapsed()); + + if (QQmlProfilerService::enabled) { + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphContextFrame, + qsg_renderer_timer.nsecsElapsed()); + } #endif return shader; diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index f71ccea294..3a608a911d 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -56,6 +56,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -273,20 +274,21 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); cd->polishItems(); - int renderTime = 0, syncTime = 0; - QTime renderTimer; - if (qsg_render_timing()) + qint64 renderTime = 0, syncTime = 0; + QElapsedTimer renderTimer; + bool profileFrames = qsg_render_timing() || QQmlProfilerService::enabled; + if (profileFrames) renderTimer.start(); cd->syncSceneGraph(); - if (qsg_render_timing()) - syncTime = renderTimer.elapsed(); + if (profileFrames) + syncTime = renderTimer.nsecsElapsed(); cd->renderSceneGraph(window->size()); - if (qsg_render_timing()) - renderTime = renderTimer.elapsed() - syncTime; + if (profileFrames) + renderTime = renderTimer.nsecsElapsed() - syncTime; if (data.grabOnly) { grabContent = qt_gl_read_framebuffer(window->size(), false, false); @@ -298,17 +300,29 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) cd->fireFrameSwapped(); } + qint64 swapTime = 0; + if (profileFrames) { + swapTime = renderTimer.nsecsElapsed() - renderTime - syncTime; + } + if (qsg_render_timing()) { static QTime lastFrameTime = QTime::currentTime(); - const int swapTime = renderTimer.elapsed() - renderTime - syncTime; - qDebug() << "- Breakdown of frame time; sync:" << syncTime - << "ms render:" << renderTime << "ms swap:" << swapTime - << "ms total:" << swapTime + renderTime + syncTime + qDebug() << "- Breakdown of frame time; sync:" << syncTime/1000000 + << "ms render:" << renderTime/1000000 << "ms swap:" << swapTime/1000000 + << "ms total:" << (swapTime + renderTime + syncTime)/1000000 << "ms time since last frame:" << (lastFrameTime.msecsTo(QTime::currentTime())) << "ms"; lastFrameTime = QTime::currentTime(); } + if (QQmlProfilerService::enabled) { + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphRenderLoopFrame, + syncTime, + renderTime, + swapTime); + } + // Might have been set during syncSceneGraph() if (data.updatePending) maybeUpdate(window); diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index de1e2517db..c4a9328ceb 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -55,6 +55,8 @@ #include "qsgthreadedrenderloop_p.h" +#include + /* Overall design: @@ -138,10 +140,10 @@ static inline int qsgrl_animation_interval() { #ifndef QSG_NO_RENDER_TIMING static bool qsg_render_timing = !qgetenv("QSG_RENDER_TIMING").isEmpty(); -static QTime threadTimer; -static int syncTime; -static int renderTime; -static int sinceLastTime; +static QElapsedTimer threadTimer; +static qint64 syncTime; +static qint64 renderTime; +static qint64 sinceLastTime; #endif extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); @@ -545,8 +547,11 @@ void QSGRenderThread::sync() void QSGRenderThread::syncAndRender() { #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) - sinceLastTime = threadTimer.restart(); + bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled; + if (profileFrames) { + sinceLastTime = threadTimer.nsecsElapsed(); + threadTimer.start(); + } #endif QElapsedTimer waitTimer; waitTimer.start(); @@ -573,8 +578,8 @@ void QSGRenderThread::syncAndRender() } #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) - syncTime = threadTimer.elapsed(); + if (profileFrames) + syncTime = threadTimer.nsecsElapsed(); #endif RLDEBUG(" Render: - rendering starting"); @@ -588,8 +593,8 @@ void QSGRenderThread::syncAndRender() gl->makeCurrent(w.window); d->renderSceneGraph(w.size); #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing && i == 0) - renderTime = threadTimer.elapsed(); + if (profileFrames && i == 0) + renderTime = threadTimer.nsecsElapsed(); #endif gl->swapBuffers(w.window); d->fireFrameSwapped(); @@ -599,10 +604,18 @@ void QSGRenderThread::syncAndRender() #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) qDebug("window Time: sinceLast=%d, sync=%d, first render=%d, after final swap=%d", - sinceLastTime, - syncTime, - renderTime - syncTime, - threadTimer.elapsed() - renderTime); + int(sinceLastTime/1000000), + int(syncTime/1000000), + int((renderTime - syncTime)/1000000), + int(threadTimer.elapsed() - renderTime/1000000)); + + if (QQmlProfilerService::enabled) { + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphRenderLoopFrame, + syncTime, + renderTime - syncTime, + threadTimer.nsecsElapsed() - renderTime); + } #endif } @@ -950,10 +963,11 @@ void QSGThreadedRenderLoop::polishAndSync() #ifndef QSG_NO_RENDER_TIMING QElapsedTimer timer; - int polishTime = 0; - int waitTime = 0; - int syncTime; - if (qsg_render_timing) + qint64 polishTime = 0; + qint64 waitTime = 0; + qint64 syncTime = 0; + bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled; + if (profileFrames) timer.start(); #endif @@ -964,8 +978,8 @@ void QSGThreadedRenderLoop::polishAndSync() d->polishItems(); } #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) - polishTime = timer.elapsed(); + if (profileFrames) + polishTime = timer.nsecsElapsed(); #endif m_sync_triggered_update = false; @@ -977,8 +991,8 @@ void QSGThreadedRenderLoop::polishAndSync() RLDEBUG("GUI: - wait for sync..."); #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) - waitTime = timer.elapsed(); + if (profileFrames) + waitTime = timer.nsecsElapsed(); #endif m_thread->waitCondition.wait(&m_thread->mutex); m_thread->guiIsLocked = false; @@ -986,8 +1000,8 @@ void QSGThreadedRenderLoop::polishAndSync() RLDEBUG("GUI: - unlocked after sync..."); #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) - syncTime = timer.elapsed(); + if (profileFrames) + syncTime = timer.nsecsElapsed(); #endif killTimer(m_update_timer); @@ -1006,7 +1020,20 @@ void QSGThreadedRenderLoop::polishAndSync() #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) - qDebug(" - polish=%d, wait=%d, sync=%d -- animations=%d", polishTime, waitTime - polishTime, syncTime - waitTime, int(timer.elapsed() - syncTime)); + qDebug(" - polish=%d, wait=%d, sync=%d -- animations=%d", + int(polishTime/1000000), + int((waitTime - polishTime)/1000000), + int((syncTime - waitTime)/1000000), + int((timer.nsecsElapsed() - syncTime)/1000000)); + + if (QQmlProfilerService::enabled) { + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphPolishAndSync, + polishTime, + waitTime - polishTime, + syncTime - waitTime, + timer.elapsed() - syncTime); + } #endif } diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index 3e21af6ac0..ce43ccf531 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -51,6 +51,8 @@ #include +#include + QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); @@ -67,7 +69,7 @@ static QElapsedTimer qsg_debug_timer; #ifndef QSG_NO_RENDER_TIMING static bool qsg_render_timing = !qgetenv("QSG_RENDER_TIMING").isEmpty(); static QElapsedTimer qsg_render_timer; -#define QSG_RENDER_TIMING_SAMPLE(sampleName) int sampleName = 0; if (qsg_render_timing) sampleName = qsg_render_timer.elapsed() +#define QSG_RENDER_TIMING_SAMPLE(sampleName) qint64 sampleName = 0; if (qsg_render_timing || QQmlProfilerService::enabled) sampleName = qsg_render_timer.nsecsElapsed() #else #define QSG_RENDER_TIMING_SAMPLE(sampleName) #endif @@ -174,9 +176,16 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window) #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) { qDebug("WindowsRenderLoop: GL=%d ms, makeCurrent=%d ms, SG=%d ms", - int(time_created - time_start), - int(time_current - time_created), - int(qsg_render_timer.elapsed() - time_current)); + int((time_created - time_start)/1000000), + int((time_current - time_created)/1000000), + int((qsg_render_timer.nsecsElapsed() - time_current)/1000000)); + } + if (QQmlProfilerService::enabled) { + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphWindowsRenderShow, + time_created - time_start, + time_current - time_created, + qsg_render_timer.nsecsElapsed() - time_current); } #endif @@ -368,7 +377,12 @@ void QSGWindowsRenderLoop::render() #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) { qDebug("WindowsRenderLoop: animations=%d ms", - int(qsg_render_timer.elapsed() - time_start)); + int((qsg_render_timer.nsecsElapsed() - time_start)/1000000)); + } + if (QQmlProfilerService::Enabled) { + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphWindowsAnimations, + qsg_render_timer.nsecsElapsed() - time_start); } #endif @@ -424,10 +438,23 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window) qDebug("WindowsRenderLoop(t=%d): window=%p, polish=%d ms, sync=%d ms, render=%d ms, swap=%d ms", int(qsg_render_timer.elapsed()), window, - int(time_polished - time_start), - int(time_synced - time_polished), - int(time_rendered - time_synced), - int(time_swapped - time_rendered)); + int((time_polished - time_start)/1000000), + int((time_synced - time_polished)/1000000), + int((time_rendered - time_synced)/1000000), + int((time_swapped - time_rendered)/1000000)); + } + if (QQmlProfilerService::enabled) { + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphWindowsPolishFrame, + time_polished - time_start + ); + + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphRenderLoopFrame, + time_synced - time_polished, + time_rendered - time_synced, + time_swapped - time_rendered + ); } #endif } diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index ad98fe9d47..a104e4af2f 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -614,7 +614,8 @@ void QSGPlainTexture::bind() m_dirty_texture = false; #ifndef QSG_NO_RENDER_TIMING - if (qsg_render_timing) + bool profileFrames = qsg_render_timing || QQmlProfilerService::enabled; + if (profileFrames) qsg_renderer_timer.start(); #endif @@ -628,6 +629,11 @@ void QSGPlainTexture::bind() m_texture_size.width(), m_texture_size.height()); } + if (QQmlProfilerService::enabled) { + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphTextureDeletion, + qsg_renderer_timer.nsecsElapsed()); + } #endif } m_texture_id = 0; @@ -645,9 +651,9 @@ void QSGPlainTexture::bind() glBindTexture(GL_TEXTURE_2D, m_texture_id); #ifndef QSG_NO_RENDER_TIMING - int bindTime = 0; - if (qsg_render_timing) - bindTime = qsg_renderer_timer.elapsed(); + qint64 bindTime = 0; + if (profileFrames) + bindTime = qsg_renderer_timer.nsecsElapsed(); #endif // ### TODO: check for out-of-memory situations... @@ -659,9 +665,9 @@ void QSGPlainTexture::bind() : m_image.convertToFormat(QImage::Format_ARGB32_Premultiplied); #ifndef QSG_NO_RENDER_TIMING - int convertTime = 0; - if (qsg_render_timing) - convertTime = qsg_renderer_timer.elapsed(); + qint64 convertTime = 0; + if (profileFrames) + convertTime = qsg_renderer_timer.nsecsElapsed(); #endif updateBindOptions(m_dirty_bind_options); @@ -684,16 +690,16 @@ void QSGPlainTexture::bind() } #ifndef QSG_NO_RENDER_TIMING - int swizzleTime = 0; - if (qsg_render_timing) - swizzleTime = qsg_renderer_timer.elapsed(); + qint64 swizzleTime = 0; + if (profileFrames) + swizzleTime = qsg_renderer_timer.nsecsElapsed(); #endif glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, externalFormat, GL_UNSIGNED_BYTE, tmp.constBits()); #ifndef QSG_NO_RENDER_TIMING - int uploadTime = 0; - if (qsg_render_timing) - uploadTime = qsg_renderer_timer.elapsed(); + qint64 uploadTime = 0; + if (profileFrames) + uploadTime = qsg_renderer_timer.nsecsElapsed(); #endif @@ -704,23 +710,35 @@ void QSGPlainTexture::bind() } #ifndef QSG_NO_RENDER_TIMING - int mipmapTime = 0; + qint64 mipmapTime = 0; if (qsg_render_timing) { - mipmapTime = qsg_renderer_timer.elapsed(); + mipmapTime = qsg_renderer_timer.nsecsElapsed(); printf(" - plaintexture(%dx%d) bind=%d, convert=%d, swizzle=%d (%s->%s), upload=%d, mipmap=%d, total=%d\n", m_texture_size.width(), m_texture_size.height(), - bindTime, - convertTime - bindTime, - swizzleTime - convertTime, + int(bindTime/1000000), + int((convertTime - bindTime)/1000000), + int((swizzleTime - convertTime)/1000000), externalFormat == GL_BGRA ? "BGRA" : "RGBA", internalFormat == GL_BGRA ? "BGRA" : "RGBA", - uploadTime - swizzleTime, - mipmapTime - uploadTime, + int((uploadTime - swizzleTime)/1000000), + int((mipmapTime - uploadTime)/1000000), (int) qsg_renderer_timer.elapsed()); } + if (QQmlProfilerService::enabled) { + mipmapTime = qsg_renderer_timer.nsecsElapsed(); + + QQmlProfilerService::sceneGraphFrame( + QQmlProfilerService::SceneGraphTexturePrepare, + bindTime, + convertTime - bindTime, + swizzleTime - convertTime, + uploadTime - swizzleTime, + mipmapTime - uploadTime); + } + #endif -- cgit v1.2.3 From e12ebce572ff5dd624477bf5d3dff84242f2e175 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 13 May 2013 16:02:30 +0200 Subject: Fix sorting of QSGTextMaskMaterial (native glyph drawing). It seems we were hitting the bool operator rather than the pointer values so all text materials, regardless of size or style would return equal. Change-Id: I8773e5aa965035f6737920747c2cf073929ff799 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/qsgdefaultglyphnode_p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp index 3df11532e4..f5a461f19e 100644 --- a/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.cpp @@ -521,7 +521,7 @@ int QSGTextMaskMaterial::compare(const QSGMaterial *o) const Q_ASSERT(o && type() == o->type()); const QSGTextMaskMaterial *other = static_cast(o); if (m_glyphCache != other->m_glyphCache) - return m_glyphCache - other->m_glyphCache; + return m_glyphCache.data() < other->m_glyphCache.data() ? -1 : 1; QRgb c1 = m_color.rgba(); QRgb c2 = other->m_color.rgba(); return int(c2 < c1) - int(c1 < c2); -- cgit v1.2.3 From 3b5173b82635141ae0fc805ecbdbef6194f480be Mon Sep 17 00:00:00 2001 From: David Fries Date: Wed, 8 May 2013 00:14:25 -0500 Subject: Doc: corrections, spelling, and ListView requirements comments From the ListView comment I thought the model had to be derived from QAbstractListModel, but that's not the case, QAbstractListModel will work just fine, it just doesn't support specific cases such as trees. Change-Id: I59305006540ddc049e276cf412571373cbfa6c67 Reviewed-by: Jerome Pasion Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/coreapi/qsggeometry.cpp | 12 ++++++------ src/quick/scenegraph/coreapi/qsgnode.cpp | 6 +++--- src/quick/scenegraph/util/qsgtexturematerial.cpp | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp index 818b9b26aa..a82c8570e5 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.cpp +++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp @@ -332,42 +332,42 @@ const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D() /*! \fn const QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D() const - Convenience function to access the vertex data as an immuatble + Convenience function to access the vertex data as an immutable array of QSGGeometry::ColoredPoint2D. */ /*! \fn QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D() - Convenience function to access the vertex data as a muatble + Convenience function to access the vertex data as a mutable array of QSGGeometry::ColoredPoint2D. */ /*! \fn const QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D() const - Convenience function to access the vertex data as an immuatble + Convenience function to access the vertex data as an immutable array of QSGGeometry::TexturedPoint2D. */ /*! \fn QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D() - Convenience function to access the vertex data as a muatble + Convenience function to access the vertex data as a mutable array of QSGGeometry::TexturedPoint2D. */ /*! \fn const QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D() const - Convenience function to access the vertex data as an immuatble + Convenience function to access the vertex data as an immutable array of QSGGeometry::Point2D. */ /*! \fn QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D() - Convenience function to access the vertex data as a muatble + Convenience function to access the vertex data as a mutable array of QSGGeometry::Point2D. */ diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp index 6a22e0e7f9..f30e95deb7 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.cpp +++ b/src/quick/scenegraph/coreapi/qsgnode.cpp @@ -128,12 +128,12 @@ static void qt_print_node_count() before rendering starts. \value OwnsGeometry Only valid for QSGGeometryNode and QSGClipNode. The node has ownership over the QSGGeometry instance and will - delete it when the node is destroyed. + delete it when the node is destroyed or a geometry is assigned. \value OwnsMaterial Only valid for QSGGeometryNode. The node has ownership - over the material and will delete it when the node is destroyed. + over the material and will delete it when the node is destroyed or a material is assigned. \value OwnsOpaqueMaterial Only valid for QSGGeometryNode. The node has ownership over the opaque material and will delete it when the node is - destroyed. + destroyed or a material is assigned. */ /*! diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp index ff91109a2a..87414766e3 100644 --- a/src/quick/scenegraph/util/qsgtexturematerial.cpp +++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp @@ -145,7 +145,7 @@ void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMa tuple. The QSGGeometry::defaultAttributes_TexturedPoint2D returns an attribute set compatible with this material. - The texture to be rendered is can be set using setTexture(). How the + The texture to be rendered can be set using setTexture(). How the texture should be rendered can be specified using setMipmapFiltering(), setFiltering(), setHorizontalWrapMode() and setVerticalWrapMode(). The rendering state is set on the texture instance just before it @@ -208,7 +208,7 @@ QSGMaterialShader *QSGOpaqueTextureMaterial::createShader() const /*! Sets the texture of this material to \a texture. - The material does not take ownership over the texture. + The material does not take ownership of the texture. */ void QSGOpaqueTextureMaterial::setTexture(QSGTexture *texture) @@ -337,7 +337,7 @@ int QSGOpaqueTextureMaterial::compare(const QSGMaterial *o) const tuple. The QSGGeometry::defaultAttributes_TexturedPoint2D returns an attribute set compatible with this material. - The texture to be rendered is set using setTexture(). How the + The texture to be rendered can be set using setTexture(). How the texture should be rendered can be specified using setMipmapFiltering(), setFiltering(), setHorizontalWrapMode() and setVerticalWrapMode(). The rendering state is set on the texture instance just before it -- cgit v1.2.3 From 392e8e1558f18ae07a0c05ace948ef732a66375e Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 16 May 2013 09:56:01 +0200 Subject: improve docs of QSGGeometry::set[Vertex|Index]DataPattern Change-Id: I6ca0d8549891302cc9d71bdfac11704752caaf60 Reviewed-by: Yoann Lopes --- src/quick/scenegraph/coreapi/qsggeometry.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp index a82c8570e5..7f09af4da3 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.cpp +++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp @@ -705,7 +705,8 @@ void QSGGeometry::updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, The default is AlwaysUploadPattern. When set to anything other than the default, the user must call markIndexDataDirty() after changing - the index data. + the index data, in addition to calling QSGNode::markDirty() with + QSGNode::DirtyGeometry. */ void QSGGeometry::setIndexDataPattern(DataPattern p) @@ -728,7 +729,8 @@ void QSGGeometry::setIndexDataPattern(DataPattern p) The default is AlwaysUploadPattern. When set to anything other than the default, the user must call markVertexDataDirty() after changing - the vertex data. + the vertex data, in addition to calling QSGNode::markDirty() with + QSGNode::DirtyGeometry. */ void QSGGeometry::setVertexDataPattern(DataPattern p) -- cgit v1.2.3 From 81a9dd71b9ce60ab4cae629b67d6f26ebdeb19db Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Sat, 18 May 2013 08:24:45 +0200 Subject: Avoid using QColor::xxxF functions. In our usecase, the color is always used as a float so using QColor (which is ushort) internally adds a lot of pointless conversion. Enough so that it shows up in profiles as 1-2% each. Not a lot, but easy to fix. The compare function is also somewhat simplified. For colors we're primarily searching for equallity. If that fails, we just need to provide consistent values, so use the address instead of doing any fancy calculation. Change-Id: Icae7e78ed767e802c137bab7fcacff66e9a4bc66 Reviewed-by: Yoann Lopes --- .../scenegraph/qsgdistancefieldglyphnode_p.cpp | 39 +++++++++------------- .../scenegraph/qsgdistancefieldglyphnode_p_p.h | 12 +++---- 2 files changed, 22 insertions(+), 29 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp index 86c3356d58..bdbce6165b 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp @@ -144,8 +144,7 @@ void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, Q if (oldMaterial == 0 || material->color() != oldMaterial->color() || state.isOpacityDirty()) { - QColor c = material->color(); - QVector4D color(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + QVector4D color = material->color(); color *= state.opacity(); program()->setUniformValue(m_color_id, color); } @@ -206,10 +205,10 @@ QSGMaterialType *QSGDistanceFieldTextMaterial::type() const void QSGDistanceFieldTextMaterial::setColor(const QColor &color) { - m_color = QColor::fromRgbF(color.redF() * color.alphaF(), - color.greenF() * color.alphaF(), - color.blueF() * color.alphaF(), - color.alphaF()); + m_color = QVector4D(color.redF() * color.alphaF(), + color.greenF() * color.alphaF(), + color.blueF() * color.alphaF(), + color.alphaF()); } QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader() const @@ -239,10 +238,8 @@ int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const if (m_fontScale != other->m_fontScale) { return int(other->m_fontScale < m_fontScale) - int(m_fontScale < other->m_fontScale); } - QRgb c1 = m_color.rgba(); - QRgb c2 = other->m_color.rgba(); - if (c1 != c2) - return int(c2 < c1) - int(c1 < c2); + if (m_color != other->m_color) + return &m_color < &other->m_color ? -1 : 1; int t0 = m_texture ? m_texture->textureId : -1; int t1 = other->m_texture ? other->m_texture->textureId : -1; return t0 - t1; @@ -284,8 +281,7 @@ void DistanceFieldStyledTextMaterialShader::updateState(const RenderState &state if (oldMaterial == 0 || material->styleColor() != oldMaterial->styleColor() || (state.isOpacityDirty())) { - QColor c = material->styleColor(); - QVector4D color(c.redF(), c.greenF(), c.blueF(), c.alphaF()); + QVector4D color = material->styleColor(); color *= state.opacity(); program()->setUniformValue(m_styleColor_id, color); } @@ -302,21 +298,18 @@ QSGDistanceFieldStyledTextMaterial::~QSGDistanceFieldStyledTextMaterial() void QSGDistanceFieldStyledTextMaterial::setStyleColor(const QColor &color) { - m_styleColor = QColor::fromRgbF(color.redF() * color.alphaF(), - color.greenF() * color.alphaF(), - color.blueF() * color.alphaF(), - color.alphaF()); + m_styleColor = QVector4D(color.redF() * color.alphaF(), + color.greenF() * color.alphaF(), + color.blueF() * color.alphaF(), + color.alphaF()); } int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const { Q_ASSERT(o && type() == o->type()); const QSGDistanceFieldStyledTextMaterial *other = static_cast(o); - if (m_styleColor != other->m_styleColor) { - QRgb c1 = m_styleColor.rgba(); - QRgb c2 = other->m_styleColor.rgba(); - return int(c2 < c1) - int(c1 < c2); - } + if (m_styleColor != other->m_color) + return &m_styleColor < &other->m_styleColor ? -1 : 1; return QSGDistanceFieldTextMaterial::compare(o); } @@ -657,8 +650,8 @@ void QSGHiQSubPixelDistanceFieldTextMaterialShader::updateState(const RenderStat QSGDistanceFieldTextMaterial *oldMaterial = static_cast(oldEffect); if (oldMaterial == 0 || material->color() != oldMaterial->color()) { - QColor c = material->color(); - state.context()->functions()->glBlendColor(c.redF(), c.greenF(), c.blueF(), 1.0f); + QVector4D c = material->color(); + state.context()->functions()->glBlendColor(c.x(), c.y(), c.z(), 1.0f); } if (oldMaterial == 0 || material->fontScale() != oldMaterial->fontScale()) diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h index 7fea8f65dc..54d4146ddb 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p_p.h @@ -59,7 +59,7 @@ public: virtual int compare(const QSGMaterial *other) const; virtual void setColor(const QColor &color); - const QColor &color() const { return m_color; } + const QVector4D &color() const { return m_color; } void setGlyphCache(QSGDistanceFieldGlyphCache *a) { m_glyph_cache = a; } QSGDistanceFieldGlyphCache *glyphCache() const { return m_glyph_cache; } @@ -76,7 +76,7 @@ public: protected: QSize m_size; - QColor m_color; + QVector4D m_color; QSGDistanceFieldGlyphCache *m_glyph_cache; const QSGDistanceFieldGlyphCache::Texture *m_texture; qreal m_fontScale; @@ -93,10 +93,10 @@ public: virtual int compare(const QSGMaterial *other) const; void setStyleColor(const QColor &color); - const QColor &styleColor() const { return m_styleColor; } + const QVector4D &styleColor() const { return m_styleColor; } protected: - QColor m_styleColor; + QVector4D m_styleColor; }; class Q_QUICK_PRIVATE_EXPORT QSGDistanceFieldOutlineTextMaterial : public QSGDistanceFieldStyledTextMaterial @@ -130,7 +130,7 @@ class Q_QUICK_PRIVATE_EXPORT QSGHiQSubPixelDistanceFieldTextMaterial : public QS public: virtual QSGMaterialType *type() const; virtual QSGMaterialShader *createShader() const; - void setColor(const QColor &color) { m_color = color; } + void setColor(const QColor &color) { m_color = QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF()); } }; class Q_QUICK_PRIVATE_EXPORT QSGLoQSubPixelDistanceFieldTextMaterial : public QSGDistanceFieldTextMaterial @@ -138,7 +138,7 @@ class Q_QUICK_PRIVATE_EXPORT QSGLoQSubPixelDistanceFieldTextMaterial : public QS public: virtual QSGMaterialType *type() const; virtual QSGMaterialShader *createShader() const; - void setColor(const QColor &color) { m_color = color; } + void setColor(const QColor &color) { m_color = QVector4D(color.redF(), color.greenF(), color.blueF(), color.alphaF()); } }; QT_END_NAMESPACE -- cgit v1.2.3 From b528809fc46ae80b291b62a9da45ea3147977dd2 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Sat, 18 May 2013 08:31:54 +0200 Subject: Avoid redundant QColor::alphaF() calls. Change-Id: I3694b075e98eab9f3eacf7758881a9473999b46e Reviewed-by: Yoann Lopes --- src/quick/scenegraph/util/qsgflatcolormaterial.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp index 307201277c..09e2a7da27 100644 --- a/src/quick/scenegraph/util/qsgflatcolormaterial.cpp +++ b/src/quick/scenegraph/util/qsgflatcolormaterial.cpp @@ -74,11 +74,11 @@ void FlatColorMaterialShader::updateState(const RenderState &state, QSGMaterial const QColor &c = newMaterial->color(); if (oldMaterial == 0 || c != oldMaterial->color() || state.isOpacityDirty()) { - float opacity = state.opacity(); - QVector4D v(c.redF() * c.alphaF() * opacity, - c.greenF() * c.alphaF() * opacity, - c.blueF() * c.alphaF() * opacity, - c.alphaF() * opacity); + float opacity = state.opacity() * c.alphaF(); + QVector4D v(c.redF() * opacity, + c.greenF() * opacity, + c.blueF() * opacity, + opacity); program()->setUniformValue(m_color_id, v); } -- cgit v1.2.3 From c23dfece55e12c18a19a72ccf8ea617eaea50ba6 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 22 May 2013 21:04:04 +0200 Subject: add private export to image and rectangle nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I15aea1b1dc3d41c9efe0a38f53d6858bae273566 Reviewed-by: Samuel Rødal --- src/quick/scenegraph/qsgdefaultimagenode_p.h | 2 +- src/quick/scenegraph/qsgdefaultrectanglenode_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgdefaultimagenode_p.h b/src/quick/scenegraph/qsgdefaultimagenode_p.h index 7d299faee3..d7be5f7c14 100644 --- a/src/quick/scenegraph/qsgdefaultimagenode_p.h +++ b/src/quick/scenegraph/qsgdefaultimagenode_p.h @@ -60,7 +60,7 @@ protected: virtual QSGMaterialShader *createShader() const; }; -class QSGDefaultImageNode : public QSGImageNode +class Q_QUICK_PRIVATE_EXPORT QSGDefaultImageNode : public QSGImageNode { public: QSGDefaultImageNode(); diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode_p.h b/src/quick/scenegraph/qsgdefaultrectanglenode_p.h index 24bdbb3d34..9ca8a96de5 100644 --- a/src/quick/scenegraph/qsgdefaultrectanglenode_p.h +++ b/src/quick/scenegraph/qsgdefaultrectanglenode_p.h @@ -63,7 +63,7 @@ protected: virtual QSGMaterialShader *createShader() const; }; -class QSGDefaultRectangleNode : public QSGRectangleNode +class Q_QUICK_PRIVATE_EXPORT QSGDefaultRectangleNode : public QSGRectangleNode { public: QSGDefaultRectangleNode(); -- cgit v1.2.3 From 0e9cd8b4098661bf611fa73a787c58c85e7d7338 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Sat, 18 May 2013 08:20:30 +0200 Subject: Cut performance cost in QSGContext::prepareMaterial() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hash-lookup in this function is costing us a lot, and since we're looking up the same materials again and again, and the material has a place holder for it, we can store it directly in the material at no extra cost. This was a 10% gain in this particular benchmark. Change-Id: I46b67791ce39f453fa86d1ee82f6f5c7785b46a1 Reviewed-by: Yoann Lopes Reviewed-by: Samuel Rødal --- src/quick/scenegraph/coreapi/qsgmaterial.cpp | 1 + src/quick/scenegraph/coreapi/qsgmaterial.h | 1 + src/quick/scenegraph/qsgcontext.cpp | 9 ++++++++- 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp index c0794d0d69..9346236db9 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp +++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp @@ -556,6 +556,7 @@ static void qt_print_material_count() QSGMaterial::QSGMaterial() : m_flags(0) + , m_reserved(0) { #ifndef QT_NO_DEBUG if (qsg_leak_check) { diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.h b/src/quick/scenegraph/coreapi/qsgmaterial.h index ee8889deac..20ab21ad28 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterial.h +++ b/src/quick/scenegraph/coreapi/qsgmaterial.h @@ -133,6 +133,7 @@ public: void setFlag(Flags flags, bool on = true); private: + friend class QSGContext; Flags m_flags; void *m_reserved; Q_DISABLE_COPY(QSGMaterial) diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 14f0fabbdd..d3710c7bd5 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -478,10 +478,16 @@ QSGDepthStencilBufferManager *QSGContext::depthStencilBufferManager() QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material) { Q_D(QSGContext); + + if (material->m_reserved) + return reinterpret_cast(material->m_reserved); + QSGMaterialType *type = material->type(); QSGMaterialShader *shader = d->materials.value(type); - if (shader) + if (shader) { + material->m_reserved = shader; return shader; + } #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing || QQmlProfilerService::enabled) @@ -489,6 +495,7 @@ QSGMaterialShader *QSGContext::prepareMaterial(QSGMaterial *material) #endif shader = material->createShader(); + material->m_reserved = shader; shader->compile(); shader->initialize(); d->materials[type] = shader; -- cgit v1.2.3 From 8f8d8dde3cde7ed2bcf6af9e85f40ee551eaafce Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Fri, 24 May 2013 16:07:13 +0200 Subject: QmlProfiler: fix SceneGraph profiling Change-Id: I54c960f0b0da061816223a51795c83a9f9dd3f66 Reviewed-by: Kai Koehne --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index c4a9328ceb..bd69fd5464 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -1032,7 +1032,7 @@ void QSGThreadedRenderLoop::polishAndSync() polishTime, waitTime - polishTime, syncTime - waitTime, - timer.elapsed() - syncTime); + timer.nsecsElapsed() - syncTime); } #endif } -- cgit v1.2.3 From 84adf4ff5b6b459c5dfc084b12f8ce6b58e5f5b7 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 29 May 2013 10:29:08 +0200 Subject: Added QQuickWindow::setDefaultAlphaBuffer() All QQuickWindows will render using the same OpenGL context, so for a window to support transparency, the OpenGL context needs to be created with support for transparency from the very start. Therefore the application needs to call setDefaultAlphaBuffer() before creating windows. There are some relevant comments in QTBUG-20768 although the bug itself is not the same use case (it was already OK as long as the first window had a translucent color, because of setAlphaBufferSize in QQuickWindow::setColor()). Change-Id: I92e111c1a62c0d510821b646fd334e52254f8f57 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgcontext.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index d3710c7bd5..4ebae38699 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -54,6 +54,7 @@ #include #include +#include #include #include @@ -398,6 +399,8 @@ QSurfaceFormat QSGContext::defaultSurfaceFormat() const QSurfaceFormat format; format.setDepthBufferSize(24); format.setStencilBufferSize(8); + if (QQuickWindow::hasDefaultAlphaBuffer()) + format.setAlphaBufferSize(8); format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); return format; } -- cgit v1.2.3 From 9f9330c524092e63cf5b490d193fd9172938526f Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 31 May 2013 09:29:48 +0200 Subject: Do not use QApp::arguments() to select antialiasing mode. This selection typically interfers with an application's command line arguments. Creator's qml2puppet needs to set this mode to avoid getting subpixel antialiased text from DesignerSupport. Change-Id: Iabf2bece211b897c58e2933d5502fdcf7c360c55 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/qsgcontext.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index d3710c7bd5..1c7f9cd800 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -159,15 +159,13 @@ QSGContext::QSGContext(QObject *parent) : QObject(*(new QSGContextPrivate), parent) { Q_D(QSGContext); - static bool doSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing")); - static bool doLowQualSubpixel = qApp->arguments().contains(QLatin1String("--text-subpixel-antialiasing-lowq")); - static bool doGray = qApp->arguments().contains(QLatin1String("--text-gray-antialiasing")); - if (doSubpixel) + QByteArray mode = qgetenv("QSG_DISTANCEFIELD_ANTIALIASING"); + if (mode == "subpixel") d->distanceFieldAntialiasing = QSGGlyphNode::HighQualitySubPixelAntialiasing; - else if (doLowQualSubpixel) + else if (mode == "subpixel-lowq") d->distanceFieldAntialiasing = QSGGlyphNode::LowQualitySubPixelAntialiasing; - else if (doGray) - d->distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing; + else if (mode == "gray") + d->distanceFieldAntialiasing = QSGGlyphNode::GrayAntialiasing; } -- cgit v1.2.3 From 4ddeb6e460eba94bfc65b07559160c441545a8d4 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 19 Apr 2013 15:30:41 +0200 Subject: Precompile the most common materials Change-Id: Idfa76f9fcdbac61a248b38e1f793a6628af12552 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/scenegraph/qsgcontext.cpp | 28 ++++++++++++++++++++++++++++ src/quick/scenegraph/qsgcontext_p.h | 1 + 2 files changed, 29 insertions(+) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 4ebae38699..61fb1bc5b9 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -47,7 +47,9 @@ #include #include #include +#include #include +#include #include #include @@ -263,9 +265,35 @@ void QSGContext::initialize(QOpenGLContext *context) Q_ASSERT(!d->gl); d->gl = context; + precompileMaterials(); + emit initialized(); } +#define QSG_PRECOMPILE_MATERIAL(name) { name m; prepareMaterial(&m); } + +/* + * Some glsl compilers take their time compiling materials, and + * the way the scene graph is being processed, these materials + * get compiled when they are first taken into use. This can + * easily lead to skipped frames. By precompiling the most + * common materials, we potentially add a few milliseconds to the + * start up, and reduce the chance of avoiding skipped frames + * later on. + */ +void QSGContext::precompileMaterials() +{ + if (qEnvironmentVariableIsEmpty("QSG_NO_MATERIAL_PRELOADING")) { + QSG_PRECOMPILE_MATERIAL(QSGVertexColorMaterial); + QSG_PRECOMPILE_MATERIAL(QSGFlatColorMaterial); + QSG_PRECOMPILE_MATERIAL(QSGOpaqueTextureMaterial); + QSG_PRECOMPILE_MATERIAL(QSGTextureMaterial); + QSG_PRECOMPILE_MATERIAL(SmoothTextureMaterial); + QSG_PRECOMPILE_MATERIAL(SmoothColorMaterial); + QSG_PRECOMPILE_MATERIAL(QSGDistanceFieldTextMaterial); + } +} + /*! Returns if the scene graph context is ready or not, meaning that it has a valid diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index b069c53dd3..bbc42674c6 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -90,6 +90,7 @@ public: bool isReady() const; + virtual void precompileMaterials(); QSGMaterialShader *prepareMaterial(QSGMaterial *material); virtual void renderNextFrame(QSGRenderer *renderer, GLuint fboId); -- cgit v1.2.3 From 9d75626b1073113d77988bcb52e99215d5af4787 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Fri, 31 May 2013 10:38:33 -0700 Subject: Set incubation controller when a Window{} is loaded via QQmlApplicationEngine This was the one convenience that was lost when transitioning templates from QQuickView + Item{} to QQmlApplicationEngine + Window{}. As the default window incubation controller was tied to the first window's frameSwapped, we could easily run into a situation where a secondary window required incubation while the first window was idle. This would then starve the incubation controller. Instead make it so that the renderloop emits "timeToIncubate" once it is done with a renderpass over all windows, so the incubator gets to run once and exactly once per vsync when animating. The incubator logic was also flawed in that it could post a lot of events to itself as a result of incubatingObjectCountChanged and thus starve system events while processing incubation requests. Now we start a timer and don't start it again until we have completed an incubation pass. Task-number: QTBUG-31203 Change-Id: Iea9e2c81efb46bb7875c70ccda0cdc4b3b3e58e7 Reviewed-by: Alan Alpert Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgrenderloop.cpp | 2 +- src/quick/scenegraph/qsgrenderloop_p.h | 9 ++++++++- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 10 ++++++++-- src/quick/scenegraph/qsgthreadedrenderloop_p.h | 6 +++--- src/quick/scenegraph/qsgwindowsrenderloop.cpp | 7 +++++++ src/quick/scenegraph/qsgwindowsrenderloop_p.h | 6 ++++-- 6 files changed, 31 insertions(+), 9 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 3a608a911d..e099d94a53 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -82,7 +82,7 @@ QSGRenderLoop::~QSGRenderLoop() { } -class QSGGuiThreadRenderLoop : public QObject, public QSGRenderLoop +class QSGGuiThreadRenderLoop : public QSGRenderLoop { Q_OBJECT public: diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h index b18e6f00ad..6ff9c4c5f9 100644 --- a/src/quick/scenegraph/qsgrenderloop_p.h +++ b/src/quick/scenegraph/qsgrenderloop_p.h @@ -51,8 +51,10 @@ class QQuickWindow; class QSGContext; class QAnimationDriver; -class Q_QUICK_PRIVATE_EXPORT QSGRenderLoop +class Q_QUICK_PRIVATE_EXPORT QSGRenderLoop : public QObject { + Q_OBJECT + public: virtual ~QSGRenderLoop(); @@ -77,6 +79,11 @@ public: static QSGRenderLoop *instance(); static void setInstance(QSGRenderLoop *instance); + virtual bool interleaveIncubation() const { return false; } + +signals: + void timeToIncubate(); + private: static QSGRenderLoop *s_instance; }; diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index bd69fd5464..bfd9a2fb20 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -574,6 +574,7 @@ void QSGRenderThread::syncAndRender() int waitTime = vsyncDelta - (int) waitTimer.elapsed(); if (waitTime > 0) msleep(waitTime); + emit wm->timeToIncubate(); return; } @@ -600,6 +601,7 @@ void QSGRenderThread::syncAndRender() d->fireFrameSwapped(); } RLDEBUG(" Render: - rendering done"); + emit wm->timeToIncubate(); #ifndef QSG_NO_RENDER_TIMING if (qsg_render_timing) @@ -723,7 +725,7 @@ QSGContext *QSGThreadedRenderLoop::sceneGraphContext() const return m_thread->sg; } -bool QSGThreadedRenderLoop::anyoneShowing() +bool QSGThreadedRenderLoop::anyoneShowing() const { for (int i=0; iisRunning() && anyoneShowing(); +} + void QSGThreadedRenderLoop::animationStarted() { RLDEBUG("GUI: animationStarted()"); @@ -1011,7 +1018,6 @@ void QSGThreadedRenderLoop::polishAndSync() 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) { diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h index aab0e8726f..6ff5cabf43 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h +++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE class QSGRenderThread; -class QSGThreadedRenderLoop : public QObject, public QSGRenderLoop +class QSGThreadedRenderLoop : public QSGRenderLoop { Q_OBJECT public: @@ -79,7 +79,7 @@ public: bool event(QEvent *); - void wakeup(); + bool interleaveIncubation() const; public slots: void animationStarted(); @@ -91,7 +91,7 @@ private: void releaseResources(QQuickWindow *window, bool inDestructor); bool checkAndResetForceUpdate(QQuickWindow *window); - bool anyoneShowing(); + bool anyoneShowing() const; void initialize(); void maybePostPolishRequest(); diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index ce43ccf531..8e97f65ea5 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -102,6 +102,11 @@ QSGWindowsRenderLoop::QSGWindowsRenderLoop() #endif } +bool QSGWindowsRenderLoop::interleaveIncubation() const +{ + return m_animationDriver->isRunning() && anyoneShowing(); +} + QSGWindowsRenderLoop::WindowData *QSGWindowsRenderLoop::windowData(QQuickWindow *window) { for (int i=0; i m_windows; -- cgit v1.2.3 From 1261b75a36fc330f182dd1c3b34a2b4a0d439a80 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Tue, 11 Jun 2013 16:47:57 +0200 Subject: Fix -Wpedantic warnings Don't need these extra ; and give warnings with -Wpedantic Change-Id: I877fee2a6421b1aaa97ca3845a09d70f3b2b302b Reviewed-by: Alan Alpert Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/util/qsgtexture_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h index 6430a93ed8..7282d4051f 100644 --- a/src/quick/scenegraph/util/qsgtexture_p.h +++ b/src/quick/scenegraph/util/qsgtexture_p.h @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE class QSGTexturePrivate : public QObjectPrivate { - Q_DECLARE_PUBLIC(QSGTexture); + Q_DECLARE_PUBLIC(QSGTexture) public: QSGTexturePrivate(); -- cgit v1.2.3 From e99cb6767b54aa9b082c4fd8bef93760c563da59 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Wed, 12 Jun 2013 10:11:06 +0300 Subject: Support unaligned QImage strides in QSGTexture If a QImage has a different stride than its width, copy the image to relayout the memory for compatibility with glTexImage2D(). Change-Id: I74338da97d785ffb9e00820caff36466dfa46838 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/util/qsgtexture.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp index a104e4af2f..a69f43f8d6 100644 --- a/src/quick/scenegraph/util/qsgtexture.cpp +++ b/src/quick/scenegraph/util/qsgtexture.cpp @@ -663,6 +663,8 @@ void QSGPlainTexture::bind() QImage tmp = (m_image.format() == QImage::Format_RGB32 || m_image.format() == QImage::Format_ARGB32_Premultiplied) ? m_image : m_image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + if (tmp.width() * 4 != tmp.bytesPerLine()) + tmp = tmp.copy(); #ifndef QSG_NO_RENDER_TIMING qint64 convertTime = 0; -- cgit v1.2.3 From 70cf8ffcf9e32f44740fe717a0811bc905fdb6a1 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 14 Jun 2013 19:27:01 +0200 Subject: Prefix internal classes properly and private export them. Without the private export on these classes, the private export on the QSGDefaultImageNode and QSGDefaultTextureNode is useless, as the symbols fail to resolve Change-Id: I25a265a7669e5f5015c482aa24fe154c2c9a1062 Reviewed-by: Alan Alpert --- src/quick/scenegraph/qsgcontext.cpp | 4 ++-- src/quick/scenegraph/qsgdefaultimagenode.cpp | 8 ++++---- src/quick/scenegraph/qsgdefaultimagenode_p.h | 6 +++--- src/quick/scenegraph/qsgdefaultrectanglenode.cpp | 8 ++++---- src/quick/scenegraph/qsgdefaultrectanglenode_p.h | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src/quick/scenegraph') diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 6d327b8d80..866d678412 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -286,8 +286,8 @@ void QSGContext::precompileMaterials() QSG_PRECOMPILE_MATERIAL(QSGFlatColorMaterial); QSG_PRECOMPILE_MATERIAL(QSGOpaqueTextureMaterial); QSG_PRECOMPILE_MATERIAL(QSGTextureMaterial); - QSG_PRECOMPILE_MATERIAL(SmoothTextureMaterial); - QSG_PRECOMPILE_MATERIAL(SmoothColorMaterial); + QSG_PRECOMPILE_MATERIAL(QSGSmoothTextureMaterial); + QSG_PRECOMPILE_MATERIAL(QSGSmoothColorMaterial); QSG_PRECOMPILE_MATERIAL(QSGDistanceFieldTextMaterial); } } diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp index cadd18e833..aed69913fa 100644 --- a/src/quick/scenegraph/qsgdefaultimagenode.cpp +++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp @@ -87,24 +87,24 @@ protected: }; -SmoothTextureMaterial::SmoothTextureMaterial() +QSGSmoothTextureMaterial::QSGSmoothTextureMaterial() { setFlag(RequiresFullMatrixExceptTranslate, true); setFlag(Blending, true); } -void SmoothTextureMaterial::setTexture(QSGTexture *texture) +void QSGSmoothTextureMaterial::setTexture(QSGTexture *texture) { m_texture = texture; } -QSGMaterialType *SmoothTextureMaterial::type() const +QSGMaterialType *QSGSmoothTextureMaterial::type() const { static QSGMaterialType type; return &type; } -QSGMaterialShader *SmoothTextureMaterial::createShader() const +QSGMaterialShader *QSGSmoothTextureMaterial::createShader() const { return new SmoothTextureMaterialShader; } diff --git a/src/quick/scenegraph/qsgdefaultimagenode_p.h b/src/quick/scenegraph/qsgdefaultimagenode_p.h index d7be5f7c14..723943fd71 100644 --- a/src/quick/scenegraph/qsgdefaultimagenode_p.h +++ b/src/quick/scenegraph/qsgdefaultimagenode_p.h @@ -48,10 +48,10 @@ QT_BEGIN_NAMESPACE -class SmoothTextureMaterial : public QSGTextureMaterial +class Q_QUICK_PRIVATE_EXPORT QSGSmoothTextureMaterial : public QSGTextureMaterial { public: - SmoothTextureMaterial(); + QSGSmoothTextureMaterial(); void setTexture(QSGTexture *texture); @@ -90,7 +90,7 @@ private: QSGOpaqueTextureMaterial m_material; QSGTextureMaterial m_materialO; - SmoothTextureMaterial m_smoothMaterial; + QSGSmoothTextureMaterial m_smoothMaterial; uint m_antialiasing : 1; uint m_mirror : 1; diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp index f642ca8d16..76fbbb4209 100644 --- a/src/quick/scenegraph/qsgdefaultrectanglenode.cpp +++ b/src/quick/scenegraph/qsgdefaultrectanglenode.cpp @@ -211,24 +211,24 @@ const char *SmoothColorMaterialShader::fragmentShader() const "}"; } -SmoothColorMaterial::SmoothColorMaterial() +QSGSmoothColorMaterial::QSGSmoothColorMaterial() { setFlag(RequiresFullMatrixExceptTranslate, true); setFlag(Blending, true); } -int SmoothColorMaterial::compare(const QSGMaterial *) const +int QSGSmoothColorMaterial::compare(const QSGMaterial *) const { return 0; } -QSGMaterialType *SmoothColorMaterial::type() const +QSGMaterialType *QSGSmoothColorMaterial::type() const { static QSGMaterialType type; return &type; } -QSGMaterialShader *SmoothColorMaterial::createShader() const +QSGMaterialShader *QSGSmoothColorMaterial::createShader() const { return new SmoothColorMaterialShader; } diff --git a/src/quick/scenegraph/qsgdefaultrectanglenode_p.h b/src/quick/scenegraph/qsgdefaultrectanglenode_p.h index 9ca8a96de5..1994e015e9 100644 --- a/src/quick/scenegraph/qsgdefaultrectanglenode_p.h +++ b/src/quick/scenegraph/qsgdefaultrectanglenode_p.h @@ -51,10 +51,10 @@ QT_BEGIN_NAMESPACE class QSGContext; -class SmoothColorMaterial : public QSGMaterial +class Q_QUICK_PRIVATE_EXPORT QSGSmoothColorMaterial : public QSGMaterial { public: - SmoothColorMaterial(); + QSGSmoothColorMaterial(); int compare(const QSGMaterial *other) const; @@ -83,7 +83,7 @@ private: void updateGradientTexture(); QSGVertexColorMaterial m_material; - SmoothColorMaterial m_smoothMaterial; + QSGSmoothColorMaterial m_smoothMaterial; QRectF m_rect; QGradientStops m_gradient_stops; -- cgit v1.2.3