Merge remote-tracking branch 'origin/5.6' into 5.7

Conflicts:
	src/qml/compiler/qv4ssa.cpp
	src/qml/qml/v8/qqmlbuiltinfunctions.cpp
	src/quick/util/qquickprofiler_p.h

Change-Id: I11a89c2a166115d6697adfba09928805643e709e
This commit is contained in:
Liang Qi 2016-11-25 23:35:34 +01:00
commit cc1c3d0e2b
26 changed files with 337 additions and 110 deletions

View File

@ -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
{

View File

@ -1857,11 +1857,6 @@ public:
return *this;
}
bool isEmpty() const
{
return worklistSize == 0;
}
unsigned size() const
{
return worklistSize;
@ -1869,7 +1864,7 @@ public:
Stmt *takeNext(Stmt *last)
{
if (isEmpty())
if (worklistSize == 0)
return 0;
const int startAt = last ? last->id() + 1 : 0;
@ -1885,6 +1880,10 @@ public:
--worklistSize;
Stmt *s = stmts.at(pos);
Q_ASSERT(s);
if (removed.at(s->id()))
return takeNext(s);
return s;
}
@ -3857,9 +3856,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:

View File

@ -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

View File

@ -1877,7 +1877,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);
@ -1976,7 +1976,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)

View File

@ -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;

View File

@ -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;

View File

@ -65,6 +65,8 @@ public:
inline ~QQmlNotifier();
inline void notify();
static void notify(QQmlData *ddata, int notifierIndex);
private:
friend class QQmlData;
friend class QQmlNotifierEndpoint;

View File

@ -360,6 +360,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);

View File

@ -999,7 +999,7 @@ ReturnedValue QtObject::method_quit(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.

View File

@ -46,10 +46,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>
@ -58,6 +60,7 @@
#include <QtCore/qstack.h>
#include <QXmlStreamReader>
#include <QtCore/qdatetime.h>
#include <QScopedValueRollback>
QT_BEGIN_NAMESPACE
@ -1263,9 +1266,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();
@ -1276,8 +1284,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);
@ -1307,6 +1317,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)
@ -1336,6 +1362,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);

View File

@ -153,6 +153,8 @@ private:
setValue(name, val);
}
void emitDirectNotifies(const int *changedRoles, int roleCount);
void initialize();
bool m_initialized;
};

View File

@ -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);

View File

@ -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;
}

View File

@ -205,7 +205,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);
// Sanity check that attribute registers are disabled
if (qsg_sanity_check) {
@ -223,7 +224,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;
@ -287,13 +289,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)

View File

@ -185,7 +185,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();
@ -206,6 +207,7 @@ void QSGDistanceFieldGlyphCache::update()
int((now - (renderTime / 1000000))));
}
Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(QQuickProfiler::SceneGraphAdaptationLayerFrame,
QQuickProfiler::SceneGraphAdaptationLayerGlyphStore,
(qint64)count);
}

View File

@ -384,7 +384,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();
@ -392,13 +393,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;
@ -415,7 +418,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();

View File

@ -597,7 +597,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";
@ -629,12 +630,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";
}
@ -659,7 +662,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);
}
@ -1164,7 +1168,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;
@ -1179,7 +1184,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();
@ -1187,7 +1193,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";
@ -1208,7 +1215,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)

View File

@ -67,9 +67,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()
@ -395,7 +395,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,
@ -446,22 +446,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();
@ -474,7 +478,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

View File

@ -394,9 +394,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 &&
@ -414,10 +417,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;

View File

@ -652,7 +652,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();
@ -668,7 +669,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...
@ -709,7 +711,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);
@ -752,14 +755,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);
@ -782,7 +787,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);

View File

@ -71,37 +71,52 @@ QT_BEGIN_NAMESPACE
#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)\
@ -182,7 +197,6 @@ private:
template<uint size>
struct TimingData {
qint64 values[size][s_numSceneGraphTimings + 1];
int offsets[size];
};
QThreadStorage<TimingData<NumRenderThreadFrameTypes> > renderThreadTimings;
@ -197,15 +211,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 {
@ -217,6 +222,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)
{
@ -239,7 +297,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];
}
@ -247,50 +304,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>

View File

@ -192,6 +192,8 @@ private slots:
void withNoContext();
void holeInPropertyData();
void malformedExpression();
signals:
void testSignal();
};
@ -3876,6 +3878,12 @@ void tst_QJSEngine::holeInPropertyData()
QVERIFY(ok.toBool());
}
void tst_QJSEngine::malformedExpression()
{
QJSEngine engine;
engine.evaluate("5%55555&&5555555\n7-0");
}
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"

View File

@ -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
}
}

View File

@ -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"

View File

@ -89,6 +89,7 @@ private slots:
void customValueTypeInQml();
void gadgetInheritance();
void toStringConversion();
void enumProperties();
private:
QQmlEngine engine;
@ -1649,6 +1650,39 @@ void tst_qqmlvaluetypes::toStringConversion()
QCOMPARE(stringConversion.toString(), StringLessGadget_to_QString(g));
}
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)

View File

@ -215,12 +215,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;
}
}
@ -252,12 +255,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;