aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-11-28 12:16:17 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2016-11-28 12:16:17 +0000
commit4e1463c20aa6ec52f23e1e5f6426b68edb2255f0 (patch)
treedf3d8f65f0c8df1990c48931c4c0b5063ff6f8c6
parentea9d6955f4c1c1141d0909ddb32abb59c032ac3c (diff)
parent9044800083ccffe4d0b732f8b3b60512f32d8f8a (diff)
Merge "Merge remote-tracking branch 'origin/5.7' into 5.8" into refs/staging/5.8
-rw-r--r--dist/changes-5.7.164
-rw-r--r--src/imports/folderlistmodel/qquickfolderlistmodel.cpp6
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp12
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp24
-rw-r--r--src/qml/compiler/qv4ssa.cpp15
-rw-r--r--src/qml/doc/src/javascript/resources.qdoc8
-rw-r--r--src/qml/jit/qv4isel_masm.cpp4
-rw-r--r--src/qml/parser/qqmljsmemorypool_p.h5
-rw-r--r--src/qml/qml/qqmlnotifier.cpp6
-rw-r--r--src/qml/qml/qqmlnotifier_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp1
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp2
-rw-r--r--src/qml/types/qqmllistmodel.cpp44
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h2
-rw-r--r--src/quick/items/qquicktextnode.cpp8
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp12
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp24
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp6
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp12
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp4
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp12
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp24
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp21
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp17
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp18
-rw-r--r--src/quick/util/qquickprofiler_p.h141
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp8
-rw-r--r--tests/auto/qml/qqmllistmodel/data/bindingsOnGetResult.qml27
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp13
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp34
-rw-r--r--tests/benchmarks/qml/creation/tst_creation.cpp8
31 files changed, 449 insertions, 135 deletions
diff --git a/dist/changes-5.7.1 b/dist/changes-5.7.1
new file mode 100644
index 0000000000..b9bdaedca3
--- /dev/null
+++ b/dist/changes-5.7.1
@@ -0,0 +1,64 @@
+Qt 5.7.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.7.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+http://doc.qt.io/qt-5/index.html
+
+The Qt version 5.7 series is binary compatible with the 5.6.x series.
+Applications compiled for 5.6 will continue to run with 5.7.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Important Behavior Changes *
+****************************************************************************
+
+ - [QTBUG-55935] AnimatedSprite will no longer cause scenegraph updates when not
+ visible
+ - [QTBUG-46263] Fix QObjects becoming undefined when used in multiple QML
+ engines
+ - [QTBUG-54238] qt.scenegraph.info logging category got renamed to
+ qt.scenegraph.general.
+ - [QTBUG-50592] QVariants (e.g. QUrl) will now be better handled by
+ JSON.stringify
+ - [QTBUG-37095] Canvas now properly supports high-DPI screens
+ - QQuickWidget now properly repaints text on high-DPI screen changes.
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+QtQml
+-----
+
+ - [QTBUG-53412] Fix mapping of null JS values to null SQL values instead
+ of empty strings.
+ - [QTBUG-53794] Fix crash when using the "with" statement with an
+ expression that throws an exception.
+ - [QTBUG-54589] Fix assertion when deleting properties of JS objects
+ - [QTBUG-56658] Fix a crash in the QML compiler
+ - [QTBUG-53672] Fix crash caused by passing 0 to Array.join
+
+QtQuick
+-------
+
+ - The relevant child item is now sent a hover event when the window
+ receives a QEnterEvent, making sure hovering is recognized without
+ waiting for mouse movement.
+ - The threaded scene graph renderer does not sleep up to one vsync
+ interval before the first frame anymore.
+ - [QTBUG-56056] Fix crash when cancelling a QQuickImageResponse
+ - [QTBUG-39888] Fix crash with QQuickItems created via JavaScript being
+ garbage collected sometimes when they're not assigned to a window.
+ - [QTBUG-31861] Item: Fixed issue with mouse button events being sent even
+ when they were disabled by setAcceptedMouseButtons.
+ - [QTBUG-52389] Text: Fixed clipping of glyphs that extend beyond font's em
+ square.
diff --git a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
index 1c94fddecf..fdcce9c685 100644
--- a/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
+++ b/src/imports/folderlistmodel/qquickfolderlistmodel.cpp
@@ -447,9 +447,9 @@ void QQuickFolderListModel::setFolder(const QUrl &folder)
/*!
\qmlproperty url FolderListModel::rootFolder
- When the rootFolder is set, then this folder will
- be threated as the root in the file system, so that
- you can only travers sub folders from this rootFolder.
+ When this property is set, the given folder will
+ be treated as the root in the file system, so that
+ you can only traverse subfolders within it.
*/
QUrl QQuickFolderListModel::rootFolder() const
{
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
index c53a1fa6c1..60b76deb2e 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
@@ -421,7 +421,8 @@ void QSGD3D12RenderLoop::renderWindow(QQuickWindow *window)
if (profileFrames)
polishTime = renderTimer.nsecsElapsed();
Q_QUICK_SG_PROFILE_SWITCH(QQuickProfiler::SceneGraphPolishFrame,
- QQuickProfiler::SceneGraphRenderLoopFrame);
+ QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphPolishPolish);
emit window->afterAnimating();
@@ -463,13 +464,15 @@ void QSGD3D12RenderLoop::renderWindow(QQuickWindow *window)
if (profileFrames)
syncTime = renderTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSync);
wd->renderSceneGraph(window->size());
if (profileFrames)
renderTime = renderTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopRender);
if (!data.grabOnly) {
// The engine is able to have multiple frames in flight. This in effect is
@@ -496,7 +499,8 @@ void QSGD3D12RenderLoop::renderWindow(QQuickWindow *window)
qint64 swapTime = 0;
if (profileFrames)
swapTime = renderTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSwap);
if (Q_UNLIKELY(debug_time())) {
static QTime lastFrameTime = QTime::currentTime();
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp
index a803f67380..317471eeec 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12threadedrenderloop.cpp
@@ -597,7 +597,8 @@ void QSGD3D12RenderThread::syncAndRender()
if (Q_UNLIKELY(debug_time()))
syncTime = threadTimer.nsecsElapsed();
#endif
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSync);
if (!syncResultedInChanges && !repaintRequested) {
if (Q_UNLIKELY(debug_loop()))
@@ -632,7 +633,8 @@ void QSGD3D12RenderThread::syncAndRender()
wd->renderSceneGraph(engine->windowSize());
if (Q_UNLIKELY(debug_time()))
renderTime = threadTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopRender);
// The engine is able to have multiple frames in flight. This in effect is
// similar to BufferQueueingOpenGL. Provide an env var to force the
@@ -649,7 +651,8 @@ void QSGD3D12RenderThread::syncAndRender()
// blockOnEachFrame is not used, but emit it for compatibility.
wd->fireFrameSwapped();
} else {
- Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame, 1);
+ Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSync, 1);
if (Q_UNLIKELY(debug_loop()))
qDebug("RT - window not ready, skipping render");
}
@@ -671,7 +674,8 @@ void QSGD3D12RenderThread::syncAndRender()
int((renderTime - syncTime) / 1000000),
int(threadTimer.elapsed() - renderTime / 1000000));
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSwap);
static int devLossTest = qEnvironmentVariableIntValue("QT_D3D_TEST_DEVICE_LOSS");
if (devLossTest > 0) {
@@ -1127,7 +1131,8 @@ void QSGD3D12ThreadedRenderLoop::polishAndSync(WindowData *w, bool inExpose)
if (Q_UNLIKELY(debug_time()))
polishTime = timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncPolish);
w->updateDuringSync = false;
@@ -1144,7 +1149,8 @@ void QSGD3D12ThreadedRenderLoop::polishAndSync(WindowData *w, bool inExpose)
qDebug("polishAndSync - wait for sync");
if (Q_UNLIKELY(debug_time()))
waitTime = timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncWait);
w->thread->waitCondition.wait(&w->thread->mutex);
lockedForSync = false;
w->thread->mutex.unlock();
@@ -1153,7 +1159,8 @@ void QSGD3D12ThreadedRenderLoop::polishAndSync(WindowData *w, bool inExpose)
if (Q_UNLIKELY(debug_time()))
syncTime = timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncSync);
if (!animationTimer && anim->isRunning()) {
if (Q_UNLIKELY(debug_loop()))
@@ -1175,7 +1182,8 @@ void QSGD3D12ThreadedRenderLoop::polishAndSync(WindowData *w, bool inExpose)
<< ", animations=" << (timer.nsecsElapsed() - syncTime) / 1000000
<< " - (on gui thread) " << window;
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncAnimations);
}
#include "qsgd3d12threadedrenderloop.moc"
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 3bcc231696..deba41ef9d 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -1838,11 +1838,6 @@ public:
return *this;
}
- bool isEmpty() const
- {
- return worklistSize == 0;
- }
-
unsigned size() const
{
return worklistSize;
@@ -1850,7 +1845,7 @@ public:
Stmt *takeNext(Stmt *last)
{
- if (isEmpty())
+ if (worklistSize == 0)
return 0;
const int startAt = last ? last->id() + 1 : 0;
@@ -1866,6 +1861,10 @@ public:
--worklistSize;
Stmt *s = stmts.at(pos);
Q_ASSERT(s);
+
+ if (removed.at(s->id()))
+ return takeNext(s);
+
return s;
}
@@ -3991,9 +3990,7 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df)
ExprReplacer replaceUses(defUses, function);
Stmt *s = 0;
- while (!W.isEmpty()) {
- s = W.takeNext(s);
- Q_ASSERT(s);
+ while ((s = W.takeNext(s))) {
if (Phi *phi = s->asPhi()) {
// dead code elimination:
diff --git a/src/qml/doc/src/javascript/resources.qdoc b/src/qml/doc/src/javascript/resources.qdoc
index b831e2ba70..4f9b40f1d7 100644
--- a/src/qml/doc/src/javascript/resources.qdoc
+++ b/src/qml/doc/src/javascript/resources.qdoc
@@ -78,13 +78,13 @@ Rectangle {
\code
// my_button_impl.js
-property var clickCount = 0; // this state is separate for each instance of MyButton
-function onClicked(btn) {
+var clickCount = 0; // this state is separate for each instance of MyButton
+function onClicked(button) {
clickCount += 1;
if ((clickCount % 5) == 0) {
- obj.color = Qt.rgba(1,0,0,1);
+ button.color = Qt.rgba(1,0,0,1);
} else {
- obj.color = Qt.rgba(0,1,0,1);
+ button.color = Qt.rgba(0,1,0,1);
}
}
\endcode
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 71069d64a5..ed1455b086 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -1838,7 +1838,7 @@ bool InstructionSelection::visitCJumpStrictUndefined(IR::Binop *binop,
Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal
: Assembler::NotEqual;
- const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
+ const Assembler::RegisterID tagReg = Assembler::ReturnValueRegister;
#ifdef QV4_USE_64_BIT_VALUE_ENCODING
Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
_as->load64(addr, tagReg);
@@ -1937,7 +1937,7 @@ bool InstructionSelection::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Bin
Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
tagAddr.offset += 4;
- const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
+ const Assembler::RegisterID tagReg = Assembler::ReturnValueRegister;
_as->load32(tagAddr, tagReg);
if (binop->op == IR::OpNotEqual)
diff --git a/src/qml/parser/qqmljsmemorypool_p.h b/src/qml/parser/qqmljsmemorypool_p.h
index 08609e2961..536f5d4239 100644
--- a/src/qml/parser/qqmljsmemorypool_p.h
+++ b/src/qml/parser/qqmljsmemorypool_p.h
@@ -122,6 +122,7 @@ private:
_allocatedBlocks *= 2;
_blocks = (char **) realloc(_blocks, sizeof(char *) * _allocatedBlocks);
+ Q_CHECK_PTR(_blocks);
for (int index = _blockCount; index < _allocatedBlocks; ++index)
_blocks[index] = 0;
@@ -129,8 +130,10 @@ private:
char *&block = _blocks[_blockCount];
- if (! block)
+ if (! block) {
block = (char *) malloc(BLOCK_SIZE);
+ Q_CHECK_PTR(block);
+ }
_ptr = block;
_end = _ptr + BLOCK_SIZE;
diff --git a/src/qml/qml/qqmlnotifier.cpp b/src/qml/qml/qqmlnotifier.cpp
index 19f03eae80..185f9687fb 100644
--- a/src/qml/qml/qqmlnotifier.cpp
+++ b/src/qml/qml/qqmlnotifier.cpp
@@ -71,6 +71,12 @@ namespace {
};
}
+void QQmlNotifier::notify(QQmlData *ddata, int notifierIndex)
+{
+ if (QQmlNotifierEndpoint *ep = ddata->notify(notifierIndex))
+ emitNotify(ep, Q_NULLPTR);
+}
+
void QQmlNotifier::emitNotify(QQmlNotifierEndpoint *endpoint, void **a)
{
QVarLengthArray<NotifyListTraversalData> stack;
diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h
index eff9684558..14024c0113 100644
--- a/src/qml/qml/qqmlnotifier_p.h
+++ b/src/qml/qml/qqmlnotifier_p.h
@@ -65,6 +65,8 @@ public:
inline ~QQmlNotifier();
inline void notify();
+ static void notify(QQmlData *ddata, int notifierIndex);
+
private:
friend class QQmlData;
friend class QQmlNotifierEndpoint;
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index b23bc033d1..be93baf9f6 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -390,6 +390,7 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
// These four types are the most common used by the value type wrappers
VALUE_TYPE_LOAD(QMetaType::QReal, qreal, qreal);
+ VALUE_TYPE_LOAD(QMetaType::Int || result->isEnum(), int, int);
VALUE_TYPE_LOAD(QMetaType::Int, int, int);
VALUE_TYPE_LOAD(QMetaType::QString, QString, v4->newString);
VALUE_TYPE_LOAD(QMetaType::Bool, bool, bool);
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index cf0fd57773..c8a0463a2d 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -1031,7 +1031,7 @@ ReturnedValue QtObject::method_exit(CallContext *ctx)
/*!
\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
-Returns a new object created from the given \a string of QML which will have the specified \a parent,
+Returns a new object created from the given \a qml string which will have the specified \a parent,
or \c null if there was an error in creating the object.
If \a filepath is specified, it will be used for error reporting for the created object.
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index f7fdbf0d80..2ba164f721 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -45,10 +45,12 @@
#include <private/qqmlcustomparser_p.h>
#include <private/qqmlengine_p.h>
+#include <private/qqmlnotifier_p.h>
#include <private/qv4object_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4objectiterator_p.h>
+#include <private/qv4alloca_p.h>
#include <qqmlcontext.h>
#include <qqmlinfo.h>
@@ -57,6 +59,7 @@
#include <QtCore/qstack.h>
#include <QXmlStreamReader>
#include <QtCore/qdatetime.h>
+#include <QScopedValueRollback>
QT_BEGIN_NAMESPACE
@@ -1265,9 +1268,14 @@ ModelNodeMetaObject *ModelNodeMetaObject::get(QObject *obj)
void ModelNodeMetaObject::updateValues()
{
- if (!m_initialized)
+ const int roleCount = m_model->m_listModel->roleCount();
+ if (!m_initialized) {
+ int *changedRoles = reinterpret_cast<int *>(alloca(roleCount * sizeof(int)));
+ for (int i = 0; i < roleCount; ++i)
+ changedRoles[i] = i;
+ emitDirectNotifies(changedRoles, roleCount);
return;
- int roleCount = m_model->m_listModel->roleCount();
+ }
for (int i=0 ; i < roleCount ; ++i) {
const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
QByteArray name = role.name.toUtf8();
@@ -1278,8 +1286,10 @@ void ModelNodeMetaObject::updateValues()
void ModelNodeMetaObject::updateValues(const QVector<int> &roles)
{
- if (!m_initialized)
+ if (!m_initialized) {
+ emitDirectNotifies(roles.constData(), roles.count());
return;
+ }
int roleCount = roles.count();
for (int i=0 ; i < roleCount ; ++i) {
int roleIndex = roles.at(i);
@@ -1309,6 +1319,22 @@ void ModelNodeMetaObject::propertyWritten(int index)
}
}
+// Does the emission of the notifiers when we haven't created the meta-object yet
+void ModelNodeMetaObject::emitDirectNotifies(const int *changedRoles, int roleCount)
+{
+ Q_ASSERT(!m_initialized);
+ QQmlData *ddata = QQmlData::get(object(), /*create*/false);
+ if (!ddata)
+ return;
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlEngine(m_model));
+ if (!ep)
+ return;
+ for (int i = 0; i < roleCount; ++i) {
+ const int changedRole = changedRoles[i];
+ QQmlNotifier::notify(ddata, changedRole);
+ }
+}
+
namespace QV4 {
void ModelObject::put(Managed *m, String *name, const Value &value)
@@ -1338,6 +1364,18 @@ ReturnedValue ModelObject::get(const Managed *m, String *name, bool *hasProperty
return QObjectWrapper::get(m, name, hasProperty);
if (hasProperty)
*hasProperty = true;
+
+ if (QQmlEngine *qmlEngine = that->engine()->qmlEngine()) {
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlEngine);
+ if (ep && ep->propertyCapture) {
+ QObjectPrivate *op = QObjectPrivate::get(that->object());
+ // Temporarily hide the dynamic meta-object, to prevent it from being created when the capture
+ // triggers a QObject::connectNotify() by calling obj->metaObject().
+ QScopedValueRollback<QDynamicMetaObjectData*> metaObjectBlocker(op->metaObject, 0);
+ ep->propertyCapture->captureProperty(that->object(), -1, role->index);
+ }
+ }
+
const int elementIndex = that->d()->m_elementIndex;
QVariant value = that->d()->m_model->data(elementIndex, role->index);
return that->engine()->fromVariant(value);
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index 6e17b55e79..5ff8b9671f 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -153,6 +153,8 @@ private:
setValue(name, val);
}
+ void emitDirectNotifies(const int *changedRoles, int roleCount);
+
void initialize();
bool m_initialized;
};
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
index 6cfc1d0313..e6ac9b603e 100644
--- a/src/quick/items/qquicktextnode.cpp
+++ b/src/quick/items/qquicktextnode.cpp
@@ -99,10 +99,12 @@ QSGGlyphNode *QQuickTextNode::addGlyphs(const QPointF &position, const QGlyphRun
bool preferNativeGlyphNode = m_useNativeRenderer;
if (!preferNativeGlyphNode) {
QRawFontPrivate *fontPriv = QRawFontPrivate::get(font);
- if (fontPriv->fontEngine->hasUnreliableGlyphOutline())
+ if (fontPriv->fontEngine->hasUnreliableGlyphOutline()) {
preferNativeGlyphNode = true;
- else
- preferNativeGlyphNode = !QFontDatabase().isSmoothlyScalable(font.familyName(), font.styleName());
+ } else {
+ QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine;
+ preferNativeGlyphNode = !fe->isSmoothlyScalable;
+ }
}
QSGGlyphNode *node = sg->sceneGraphContext()->createGlyphNode(sg, preferNativeGlyphNode);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
index 19a963b403..6856d34616 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
@@ -143,7 +143,8 @@ void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
if (profileFrames)
polishTime = renderTimer.nsecsElapsed();
Q_QUICK_SG_PROFILE_SWITCH(QQuickProfiler::SceneGraphPolishFrame,
- QQuickProfiler::SceneGraphRenderLoopFrame);
+ QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphPolishPolish);
emit window->afterAnimating();
@@ -151,7 +152,8 @@ void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
if (profileFrames)
syncTime = renderTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSync);
//Tell the renderer about the windows backing store
auto softwareRenderer = static_cast<QSGSoftwareRenderer*>(cd->renderer);
@@ -162,7 +164,8 @@ void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
if (profileFrames)
renderTime = renderTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopRender);
if (data.grabOnly) {
grabContent = m_backingStores[window]->handle()->toImage();
@@ -178,7 +181,8 @@ void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
qint64 swapTime = 0;
if (profileFrames)
swapTime = renderTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSwap);
if (QSG_RASTER_LOG_TIME_RENDERLOOP().isDebugEnabled()) {
static QTime lastFrameTime = QTime::currentTime();
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
index 5d5485ed8f..df5ec9b745 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp
@@ -484,7 +484,8 @@ void QSGSoftwareRenderThread::syncAndRender()
if (syncRequested)
sync(exposeRequested);
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSync);
if (!syncResultedInChanges && !repaintRequested) {
qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - no changes, render aborted");
@@ -510,7 +511,8 @@ void QSGSoftwareRenderThread::syncAndRender()
softwareRenderer->setBackingStore(backingStore);
wd->renderSceneGraph(exposedWindow->size());
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopRender);
if (softwareRenderer && (!wd->customRenderStage || !wd->customRenderStage->swap()))
backingStore->flush(softwareRenderer->flushRegion());
@@ -526,7 +528,8 @@ void QSGSoftwareRenderThread::syncAndRender()
wd->fireFrameSwapped();
} else {
- Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame, 1);
+ Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSync, 1);
qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - window not ready, skipping render");
}
@@ -538,7 +541,8 @@ void QSGSoftwareRenderThread::syncAndRender()
mutex.unlock();
}
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSwap);
}
template<class T> T *windowFor(const QVector<T> &list, QQuickWindow *window)
@@ -951,7 +955,8 @@ void QSGSoftwareThreadedRenderLoop::polishAndSync(QSGSoftwareThreadedRenderLoop:
QQuickWindowPrivate *wd = QQuickWindowPrivate::get(window);
wd->polishItems();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncPolish);
w->updateDuringSync = false;
@@ -965,13 +970,15 @@ void QSGSoftwareThreadedRenderLoop::polishAndSync(QSGSoftwareThreadedRenderLoop:
qCDebug(QSG_RASTER_LOG_RENDERLOOP, "polishAndSync - wait for sync");
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncWait);
w->thread->waitCondition.wait(&w->thread->mutex);
lockedForSync = false;
w->thread->mutex.unlock();
qCDebug(QSG_RASTER_LOG_RENDERLOOP, "polishAndSync - unlock after sync");
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncSync);
if (!animationTimer && m_anim->isRunning()) {
qCDebug(QSG_RASTER_LOG_RENDERLOOP, "polishAndSync - advancing animations");
@@ -983,7 +990,8 @@ void QSGSoftwareThreadedRenderLoop::polishAndSync(QSGSoftwareThreadedRenderLoop:
w->window->requestUpdate();
}
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncAnimations);
}
#include "qsgsoftwarethreadedrenderloop.moc"
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 81aa641e03..6771c0e940 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -170,7 +170,8 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
qCDebug(QSG_LOG_TIME_COMPILATION, "shader compiled in %dms", (int) qsg_renderer_timer.elapsed());
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphContextFrame);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphContextFrame,
+ QQuickProfiler::SceneGraphContextMaterialCompile);
rewrittenShaders[type] = shader;
return shader;
@@ -201,7 +202,8 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
qCDebug(QSG_LOG_TIME_COMPILATION, "shader compiled in %dms (no rewrite)", (int) qsg_renderer_timer.elapsed());
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphContextFrame);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphContextFrame,
+ QQuickProfiler::SceneGraphContextMaterialCompile);
return shader;
}
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index 220e6ab212..34cdfc0a6d 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -220,7 +220,8 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
bindable.bind();
if (profileFrames)
bindTime = frameTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame,
+ QQuickProfiler::SceneGraphRendererBinding);
#ifndef QT_NO_OPENGL
// Sanity check that attribute registers are disabled
@@ -240,7 +241,8 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
render();
if (profileFrames)
renderTime = frameTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRendererFrame);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRendererFrame,
+ QQuickProfiler::SceneGraphRendererRender);
m_is_rendering = false;
m_changed_emitted = false;
@@ -304,13 +306,15 @@ void QSGRenderer::preprocess()
bool profileFrames = QSG_LOG_TIME_RENDERER().isDebugEnabled();
if (profileFrames)
preprocessTime = frameTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame,
+ QQuickProfiler::SceneGraphRendererPreprocess);
nodeUpdater()->updateStates(root);
if (profileFrames)
updatePassTime = frameTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame,
+ QQuickProfiler::SceneGraphRendererUpdate);
}
void QSGRenderer::addNodesToPreprocess(QSGNode *node)
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index 9923fa6e24..84ca09285a 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -189,7 +189,8 @@ void QSGDistanceFieldGlyphCache::update()
int count = m_pendingGlyphs.size();
if (profileFrames)
renderTime = qsg_render_timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphAdaptationLayerFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphAdaptationLayerFrame,
+ QQuickProfiler::SceneGraphAdaptationLayerGlyphRender);
m_pendingGlyphs.reset();
@@ -210,6 +211,7 @@ void QSGDistanceFieldGlyphCache::update()
int((now - (renderTime / 1000000))));
}
Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(QQuickProfiler::SceneGraphAdaptationLayerFrame,
+ QQuickProfiler::SceneGraphAdaptationLayerGlyphStore,
(qint64)count);
}
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index df7bbe6ceb..5bd1adc1f7 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -401,7 +401,8 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
if (profileFrames)
polishTime = renderTimer.nsecsElapsed();
Q_QUICK_SG_PROFILE_SWITCH(QQuickProfiler::SceneGraphPolishFrame,
- QQuickProfiler::SceneGraphRenderLoopFrame);
+ QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphPolishPolish);
emit window->afterAnimating();
@@ -409,13 +410,15 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
if (profileFrames)
syncTime = renderTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSync);
cd->renderSceneGraph(window->size());
if (profileFrames)
renderTime = renderTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopRender);
if (data.grabOnly) {
bool alpha = window->format().alphaBufferSize() > 0 && window->color().alpha() != 255;
@@ -432,7 +435,8 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
qint64 swapTime = 0;
if (profileFrames)
swapTime = renderTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSwap);
if (QSG_LOG_TIME_RENDERLOOP().isDebugEnabled()) {
static QTime lastFrameTime = QTime::currentTime();
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 693012154e..4543782d5b 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -602,7 +602,8 @@ void QSGRenderThread::syncAndRender()
if (profileFrames)
syncTime = threadTimer.nsecsElapsed();
#endif
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSync);
if (!syncResultedInChanges && !repaintRequested && sgrc->isValid()) {
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- no changes, render aborted";
@@ -634,12 +635,14 @@ void QSGRenderThread::syncAndRender()
d->renderSceneGraph(windowSize);
if (profileFrames)
renderTime = threadTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopRender);
if (!d->customRenderStage || !d->customRenderStage->swap())
gl->swapBuffers(window);
d->fireFrameSwapped();
} else {
- Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame, 1);
+ Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSync, 1);
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window not ready, skipping render";
}
@@ -664,7 +667,8 @@ void QSGRenderThread::syncAndRender()
int(threadTimer.elapsed() - renderTime / 1000000));
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSwap);
}
@@ -1169,7 +1173,8 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
if (profileFrames)
polishTime = timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncPolish);
w->updateDuringSync = false;
@@ -1184,7 +1189,8 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
qCDebug(QSG_LOG_RENDERLOOP) << "- wait for sync";
if (profileFrames)
waitTime = timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncWait);
w->thread->waitCondition.wait(&w->thread->mutex);
m_lockedForSync = false;
w->thread->mutex.unlock();
@@ -1192,7 +1198,8 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
if (profileFrames)
syncTime = timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncSync);
if (m_animation_timer == 0 && m_animation_driver->isRunning()) {
qCDebug(QSG_LOG_RENDERLOOP) << "- advancing animations";
@@ -1213,7 +1220,8 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
<< ", animations=" << (timer.nsecsElapsed() - syncTime) / 1000000
<< " - (on Gui thread) " << window;
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync,
+ QQuickProfiler::SceneGraphPolishAndSyncAnimations);
}
bool QSGThreadedRenderLoop::event(QEvent *e)
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index 941a7b3f3c..13388c0841 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -71,9 +71,9 @@ static QElapsedTimer qsg_render_timer;
if (QSG_LOG_TIME_RENDERLOOP().isDebugEnabled()) \
sampleName = qsg_render_timer.nsecsElapsed(); \
-#define QSG_RENDER_TIMING_SAMPLE(frameType, sampleName) \
+#define QSG_RENDER_TIMING_SAMPLE(frameType, sampleName, position) \
QSG_LOG_TIME_SAMPLE(sampleName) \
- Q_QUICK_SG_PROFILE_RECORD(frameType);
+ Q_QUICK_SG_PROFILE_RECORD(frameType, position);
QSGWindowsRenderLoop::QSGWindowsRenderLoop()
@@ -406,7 +406,7 @@ void QSGWindowsRenderLoop::render()
"animations ticked in %dms",
int((qsg_render_timer.nsecsElapsed() - time_start)/1000000));
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphWindowsAnimations);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphWindowsAnimations, 1);
// It is not given that animations triggered another maybeUpdate()
// and thus another render pass, so to keep things running,
@@ -457,22 +457,26 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window)
d->polishItems();
QSG_LOG_TIME_SAMPLE(time_polished);
Q_QUICK_SG_PROFILE_SWITCH(QQuickProfiler::SceneGraphPolishFrame,
- QQuickProfiler::SceneGraphRenderLoopFrame);
+ QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphPolishPolish);
emit window->afterAnimating();
RLDEBUG(" - syncing");
d->syncSceneGraph();
- QSG_RENDER_TIMING_SAMPLE(QQuickProfiler::SceneGraphRenderLoopFrame, time_synced);
+ QSG_RENDER_TIMING_SAMPLE(QQuickProfiler::SceneGraphRenderLoopFrame, time_synced,
+ QQuickProfiler::SceneGraphRenderLoopSync);
RLDEBUG(" - rendering");
d->renderSceneGraph(window->size());
- QSG_RENDER_TIMING_SAMPLE(QQuickProfiler::SceneGraphRenderLoopFrame, time_rendered);
+ QSG_RENDER_TIMING_SAMPLE(QQuickProfiler::SceneGraphRenderLoopFrame, time_rendered,
+ QQuickProfiler::SceneGraphRenderLoopRender);
RLDEBUG(" - swapping");
if (!d->customRenderStage || !d->customRenderStage->swap())
m_gl->swapBuffers(window);
- QSG_RENDER_TIMING_SAMPLE(QQuickProfiler::SceneGraphRenderLoopFrame, time_swapped);
+ QSG_RENDER_TIMING_SAMPLE(QQuickProfiler::SceneGraphRenderLoopFrame, time_swapped,
+ QQuickProfiler::SceneGraphRenderLoopSwap);
RLDEBUG(" - frameDone");
d->fireFrameSwapped();
@@ -485,7 +489,8 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window)
<< ", swap=" << (time_swapped - time_rendered) / 1000000
<< " - " << window;
- Q_QUICK_SG_PROFILE_REPORT(QQuickProfiler::SceneGraphRenderLoopFrame);
+ Q_QUICK_SG_PROFILE_REPORT(QQuickProfiler::SceneGraphRenderLoopFrame,
+ QQuickProfiler::SceneGraphRenderLoopSwap);
}
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index b6abb55bd3..c864ea9496 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -395,9 +395,12 @@ void Atlas::bind(QSGTexture::Filtering filtering)
bool profileFrames = QSG_LOG_TIME_TEXTURE().isDebugEnabled();
if (profileFrames)
qsg_renderer_timer.start();
- // Skip bind, convert, swizzle; they're irrelevant
+
Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphTexturePrepare);
- Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, 3);
+
+ // Skip bind, convert, swizzle; they're irrelevant
+ Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare,
+ QQuickProfiler::SceneGraphTexturePrepareStart, 3);
Texture *t = m_pending_uploads.at(i);
if (m_externalFormat == GL_BGRA &&
@@ -415,10 +418,14 @@ void Atlas::bind(QSGTexture::Filtering filtering)
<< "ms (" << t->textureSize().width() << "x"
<< t->textureSize().height() << ")";
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare,
+ QQuickProfiler::SceneGraphTexturePrepareUpload);
+
// Skip mipmap; unused
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
- Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, 1);
- Q_QUICK_SG_PROFILE_REPORT(QQuickProfiler::SceneGraphTexturePrepare);
+ Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare,
+ QQuickProfiler::SceneGraphTexturePrepareUpload, 1);
+ Q_QUICK_SG_PROFILE_REPORT(QQuickProfiler::SceneGraphTexturePrepare,
+ QQuickProfiler::SceneGraphTexturePrepareMipmap);
}
GLenum f = filtering == QSGTexture::Nearest ? GL_NEAREST : GL_LINEAR;
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index 4cf339aeb8..436f97b1ff 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -673,7 +673,8 @@ void QSGPlainTexture::bind()
(int) qsg_renderer_timer.elapsed(),
m_texture_size.width(),
m_texture_size.height());
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphTextureDeletion);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphTextureDeletion,
+ QQuickProfiler::SceneGraphTextureDeletionDelete);
}
m_texture_id = 0;
m_texture_size = QSize();
@@ -689,7 +690,8 @@ void QSGPlainTexture::bind()
qint64 bindTime = 0;
if (profileFrames)
bindTime = qsg_renderer_timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare,
+ QQuickProfiler::SceneGraphTexturePrepareBind);
// ### TODO: check for out-of-memory situations...
@@ -730,7 +732,8 @@ void QSGPlainTexture::bind()
qint64 convertTime = 0;
if (profileFrames)
convertTime = qsg_renderer_timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare,
+ QQuickProfiler::SceneGraphTexturePrepareConvert);
updateBindOptions(m_dirty_bind_options);
@@ -773,14 +776,16 @@ void QSGPlainTexture::bind()
qint64 swizzleTime = 0;
if (profileFrames)
swizzleTime = qsg_renderer_timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare,
+ QQuickProfiler::SceneGraphTexturePrepareSwizzle);
funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_texture_size.width(), m_texture_size.height(), 0, externalFormat, GL_UNSIGNED_BYTE, tmp.constBits());
qint64 uploadTime = 0;
if (profileFrames)
uploadTime = qsg_renderer_timer.nsecsElapsed();
- Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare,
+ QQuickProfiler::SceneGraphTexturePrepareUpload);
if (mipmapFiltering() != QSGTexture::None) {
funcs->glGenerateMipmap(GL_TEXTURE_2D);
@@ -803,7 +808,8 @@ void QSGPlainTexture::bind()
int((mipmapTime - uploadTime)/1000000),
m_texture_size != m_image.size() ? " (scaled to GL_MAX_TEXTURE_SIZE)" : "");
}
- Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphTexturePrepare);
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphTexturePrepare,
+ QQuickProfiler::SceneGraphTexturePrepareMipmap);
m_texture_rect = QRectF(0, 0, 1, 1);
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
index 66ed212722..d2fa935ad4 100644
--- a/src/quick/util/qquickprofiler_p.h
+++ b/src/quick/util/qquickprofiler_p.h
@@ -152,7 +152,6 @@ private:
template<uint size>
struct TimingData {
qint64 values[size][s_numSceneGraphTimings + 1];
- int offsets[size];
};
QThreadStorage<TimingData<NumRenderThreadFrameTypes> > renderThreadTimings;
@@ -167,15 +166,6 @@ public:
else
return guiThreadTimings.values[type - NumRenderThreadFrameTypes];
}
-
- template<SceneGraphFrameType type>
- int &offset()
- {
- if (type < NumRenderThreadFrameTypes)
- return renderThreadTimings.localData().offsets[type];
- else
- return guiThreadTimings.offsets[type - NumRenderThreadFrameTypes];
- }
};
class Q_QUICK_PRIVATE_EXPORT QQuickProfiler : public QObject, public QQmlProfilerDefinitions {
@@ -187,6 +177,59 @@ public:
RenderThread
};
+ enum SceneGraphContextStage {
+ SceneGraphContextStart,
+ SceneGraphContextMaterialCompile
+ };
+
+ enum SceneGraphRendererStage {
+ SceneGraphRendererStart,
+ SceneGraphRendererPreprocess,
+ SceneGraphRendererUpdate,
+ SceneGraphRendererBinding,
+ SceneGraphRendererRender
+ };
+
+ enum SceneGraphAdaptationLayerStage {
+ SceneGraphAdaptationLayerStart,
+ SceneGraphAdaptationLayerGlyphRender,
+ SceneGraphAdaptationLayerGlyphStore
+ };
+
+ enum SceneGraphRenderLoopStage {
+ SceneGraphRenderLoopStart,
+ SceneGraphRenderLoopSync,
+ SceneGraphRenderLoopRender,
+ SceneGraphRenderLoopSwap
+ };
+
+ enum SceneGraphPolishStage {
+ SceneGraphPolishStart,
+ SceneGraphPolishPolish
+ };
+
+ enum SceneGraphPolishAndSyncStage {
+ SceneGraphPolishAndSyncStart,
+ SceneGraphPolishAndSyncPolish,
+ SceneGraphPolishAndSyncWait,
+ SceneGraphPolishAndSyncSync,
+ SceneGraphPolishAndSyncAnimations
+ };
+
+ enum SceneGraphTexturePrepareStage {
+ SceneGraphTexturePrepareStart,
+ SceneGraphTexturePrepareBind,
+ SceneGraphTexturePrepareConvert,
+ SceneGraphTexturePrepareSwizzle,
+ SceneGraphTexturePrepareUpload,
+ SceneGraphTexturePrepareMipmap
+ };
+
+ enum SceneGraphTextureDeletionStage {
+ SceneGraphTextureDeletionStart,
+ SceneGraphTextureDeletionDelete
+ };
+
template<EventType DetailType, InputEventType InputType>
static void inputEvent(int x, int y = 0)
{
@@ -209,7 +252,6 @@ public:
static void startSceneGraphFrame()
{
startSceneGraphFrame<FrameType1>();
- s_instance->m_sceneGraphData.offset<FrameType2>() = 0;
s_instance->m_sceneGraphData.timings<FrameType2>()[0] =
s_instance->m_sceneGraphData.timings<FrameType1>()[0];
}
@@ -217,50 +259,45 @@ public:
template<SceneGraphFrameType FrameType>
static void startSceneGraphFrame()
{
- s_instance->m_sceneGraphData.offset<FrameType>() = 0;
s_instance->m_sceneGraphData.timings<FrameType>()[0] = s_instance->timestamp();
}
template<SceneGraphFrameType FrameType>
- static void recordSceneGraphTimestamp()
+ static void recordSceneGraphTimestamp(uint position)
{
- s_instance->m_sceneGraphData.timings<FrameType>()
- [++s_instance->m_sceneGraphData.offset<FrameType>()] = s_instance->timestamp();
+ s_instance->m_sceneGraphData.timings<FrameType>()[position] = s_instance->timestamp();
}
template<SceneGraphFrameType FrameType, uint Skip>
- static void skipSceneGraphTimestamps()
+ static void skipSceneGraphTimestamps(uint position)
{
qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType>();
- const qint64 last = timings[s_instance->m_sceneGraphData.offset<FrameType>()];
+ const qint64 last = timings[position];
for (uint i = 0; i < Skip; ++i)
- timings[++s_instance->m_sceneGraphData.offset<FrameType>()] = last;
+ timings[++position] = last;
}
template<SceneGraphFrameType FrameType, bool Record>
- static void reportSceneGraphFrame(quint64 payload = ~0)
+ static void reportSceneGraphFrame(uint position, quint64 payload = ~0)
{
qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType>();
- int &offset = s_instance->m_sceneGraphData.offset<FrameType>();
if (Record)
- timings[++offset] = s_instance->timestamp();
+ timings[position] = s_instance->timestamp();
s_instance->processMessage(QQuickProfilerData(
- timings[offset], 1 << SceneGraphFrame, 1 << FrameType,
- offset > 0 ? timings[1] - timings[0] : payload,
- offset > 1 ? timings[2] - timings[1] : payload,
- offset > 2 ? timings[3] - timings[2] : payload,
- offset > 3 ? timings[4] - timings[3] : payload,
- offset > 4 ? timings[5] - timings[4] : payload));
+ timings[position], 1 << SceneGraphFrame, 1 << FrameType,
+ position > 0 ? timings[1] - timings[0] : payload,
+ position > 1 ? timings[2] - timings[1] : payload,
+ position > 2 ? timings[3] - timings[2] : payload,
+ position > 3 ? timings[4] - timings[3] : payload,
+ position > 4 ? timings[5] - timings[4] : payload));
}
template<SceneGraphFrameType FrameType, bool Record, SceneGraphFrameType SwitchTo>
- static void reportSceneGraphFrame(quint64 payload = ~0)
+ static void reportSceneGraphFrame(uint position, quint64 payload = ~0)
{
- reportSceneGraphFrame<FrameType, Record>(payload);
- s_instance->m_sceneGraphData.offset<SwitchTo>() = 0;
+ reportSceneGraphFrame<FrameType, Record>(position, payload);
s_instance->m_sceneGraphData.timings<SwitchTo>()[0] =
- s_instance->m_sceneGraphData.timings<FrameType>()
- [s_instance->m_sceneGraphData.offset<FrameType>()];
+ s_instance->m_sceneGraphData.timings<FrameType>()[position];
}
template<PixmapEventType PixmapState>
@@ -326,38 +363,52 @@ protected:
#define Q_QUICK_PROFILE(feature, Method)\
Q_QUICK_PROFILE_IF_ENABLED(feature, QQuickProfiler::Method)
+// Record current timestamp for \a Type at position 0.
#define Q_QUICK_SG_PROFILE_START(Type)\
Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
(QQuickProfiler::startSceneGraphFrame<Type>()))
-#define Q_QUICK_SG_PROFILE_RECORD(Type)\
+// Record current timestamp for \a Type at \a position.
+#define Q_QUICK_SG_PROFILE_RECORD(Type, position)\
Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::recordSceneGraphTimestamp<Type>()))
+ (QQuickProfiler::recordSceneGraphTimestamp<Type>(position)))
-#define Q_QUICK_SG_PROFILE_SKIP(Type, Skip)\
+// Use the timestamp for \a Type at position \a position and repeat it \a Skip times in subsequent
+// positions.
+#define Q_QUICK_SG_PROFILE_SKIP(Type, position, Skip)\
Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::skipSceneGraphTimestamps<Type, Skip>()))
+ (QQuickProfiler::skipSceneGraphTimestamps<Type, Skip>(position)))
+// Record current timestamp for both \a Type1 and \a Type2 at position 0.
#define Q_QUICK_SG_PROFILE_START_SYNCHRONIZED(Type1, Type2)\
Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
(QQuickProfiler::startSceneGraphFrame<Type1, Type2>()))
-#define Q_QUICK_SG_PROFILE_SWITCH(Type1, Type2) \
+// report \a Type1, using the current timestamp at \a position, and switch to \a Typ2, using
+// the current timestamp at position 0.
+#define Q_QUICK_SG_PROFILE_SWITCH(Type1, Type2, position)\
Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::reportSceneGraphFrame<Type1, true, Type2>()))
+ (QQuickProfiler::reportSceneGraphFrame<Type1, true, Type2>(\
+ position)))
-#define Q_QUICK_SG_PROFILE_REPORT(Type)\
+// report \a Type, using data points 0 to \a position, including \a position.
+#define Q_QUICK_SG_PROFILE_REPORT(Type, position)\
Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::reportSceneGraphFrame<Type, false>()))
+ (QQuickProfiler::reportSceneGraphFrame<Type, false>(position)))
-#define Q_QUICK_SG_PROFILE_END(Type)\
+// report \a Type, using data points 0 to \a position, including \a position, and setting the
+// timestamp at \a position to the current one.
+#define Q_QUICK_SG_PROFILE_END(Type, position)\
Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::reportSceneGraphFrame<Type, true>()))
+ (QQuickProfiler::reportSceneGraphFrame<Type, true>(position)))
-#define Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(Type, Payload)\
+// report \a Type, using data points 0 to \a position, including \a position, and setting the
+// timestamp at \a position to the current one. Remaining data points up to position 5 are filled
+// with \a Payload.
+#define Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(Type, position, Payload)\
Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::reportSceneGraphFrame<Type, true>(Payload)))
-
+ (QQuickProfiler::reportSceneGraphFrame<Type, true>(position,\
+ Payload)))
#define Q_QUICK_INPUT_PROFILE(Type, DetailType, A, B)\
Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileInputEvents,\
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index c20f0888d8..52df4c0642 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -196,6 +196,8 @@ private slots:
void basicBlockMergeAfterLoopPeeling();
+ void malformedExpression();
+
signals:
void testSignal();
};
@@ -4062,6 +4064,12 @@ void tst_QJSEngine::basicBlockMergeAfterLoopPeeling()
}
+void tst_QJSEngine::malformedExpression()
+{
+ QJSEngine engine;
+ engine.evaluate("5%55555&&5555555\n7-0");
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/qml/qqmllistmodel/data/bindingsOnGetResult.qml b/tests/auto/qml/qqmllistmodel/data/bindingsOnGetResult.qml
new file mode 100644
index 0000000000..6bf750dcda
--- /dev/null
+++ b/tests/auto/qml/qqmllistmodel/data/bindingsOnGetResult.qml
@@ -0,0 +1,27 @@
+import QtQuick 2.0
+
+QtObject {
+ property ListModel model: ListModel {
+ ListElement { modified: false }
+ ListElement { modified: false }
+ ListElement { modified: false }
+ ListElement { modified: false }
+ ListElement { modified: false }
+ }
+
+ property bool isModified: {
+ for (var i = 0; i < model.count; ++i) {
+ if (model.get(i).modified)
+ return true;
+ }
+ return false;
+ }
+
+ property bool success: false
+ Component.onCompleted: {
+ // trigger read and setup of property captures
+ success = isModified
+ model.setProperty(0, "modified", true)
+ success = isModified
+ }
+}
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index cd497cbd79..555ca5713e 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -122,6 +122,7 @@ private slots:
void datetime_data();
void about_to_be_signals();
void modify_through_delegate();
+ void bindingsOnGetResult();
};
bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object)
@@ -1469,6 +1470,18 @@ void tst_qqmllistmodel::modify_through_delegate()
QCOMPARE(model->data(model->index(1, 0, QModelIndex()), roleNames.key("age")).toInt(), 18);
}
+void tst_qqmllistmodel::bindingsOnGetResult()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("bindingsOnGetResult.qml"));
+ QVERIFY2(!component.isError(), qPrintable(component.errorString()));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+
+ QVERIFY(obj->property("success").toBool());
+}
+
QTEST_MAIN(tst_qqmllistmodel)
#include "tst_qqmllistmodel.moc"
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 803bad197a..9e915ac451 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -91,6 +91,7 @@ private slots:
void gadgetInheritance();
void toStringConversion();
void enumerableProperties();
+ void enumProperties();
private:
QQmlEngine engine;
@@ -1703,6 +1704,39 @@ void tst_qqmlvaluetypes::enumerableProperties()
QVERIFY(names.contains(QStringLiteral("derivedProperty")));
}
+struct GadgetWithEnum
+{
+ Q_GADGET
+public:
+
+ enum MyEnum { FirstValue, SecondValue };
+
+ Q_ENUM(MyEnum)
+ Q_PROPERTY(MyEnum enumProperty READ enumProperty)
+
+ MyEnum enumProperty() const { return SecondValue; }
+};
+
+void tst_qqmlvaluetypes::enumProperties()
+{
+ QJSEngine engine;
+
+ // When creating the property cache for the gadget when MyEnum is _not_ a registered
+ // meta-type, then QMetaProperty::type() will return QMetaType::Int and consequently
+ // property-read meta-calls will return an int (as expected in this test). However if we
+ // explicitly register the gadget, then QMetaProperty::type() will return the user-type
+ // and QQmlValueTypeWrapper should still handle that and return an integer/number for the
+ // enum property when it is read.
+ qRegisterMetaType<GadgetWithEnum::MyEnum>();
+
+ GadgetWithEnum g;
+ QJSValue value = engine.toScriptValue(g);
+
+ QJSValue enumValue = value.property("enumProperty");
+ QVERIFY(enumValue.isNumber());
+ QCOMPARE(enumValue.toInt(), int(g.enumProperty()));
+}
+
QTEST_MAIN(tst_qqmlvaluetypes)
diff --git a/tests/benchmarks/qml/creation/tst_creation.cpp b/tests/benchmarks/qml/creation/tst_creation.cpp
index a1c09db158..9fc67ada71 100644
--- a/tests/benchmarks/qml/creation/tst_creation.cpp
+++ b/tests/benchmarks/qml/creation/tst_creation.cpp
@@ -221,12 +221,15 @@ inline void QQmlGraphics_setParent_noEvent(QObject *object, QObject *parent)
void tst_creation::itemtree_notree_cpp()
{
+ std::vector<QQuickItem *> kids;
+ kids.resize(30);
QBENCHMARK {
QQuickItem *item = new QQuickItem;
for (int i = 0; i < 30; ++i) {
QQuickItem *child = new QQuickItem;
- Q_UNUSED(child);
+ kids[i] = child;
}
+ qDeleteAll(kids);
delete item;
}
}
@@ -258,12 +261,13 @@ void tst_creation::itemtree_cpp()
void tst_creation::itemtree_data_cpp()
{
+ QQmlEngine engine;
QBENCHMARK {
QQuickItem *item = new QQuickItem;
for (int i = 0; i < 30; ++i) {
QQuickItem *child = new QQuickItem;
QQmlGraphics_setParent_noEvent(child,item);
- QQmlListReference ref(item, "data");
+ QQmlListReference ref(item, "data", &engine);
ref.append(child);
}
delete item;