diff options
30 files changed, 251 insertions, 145 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 86cdb3eade..86200d7df7 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -84,8 +84,10 @@ static QString cacheFilePath(const QUrl &url) { const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url); const QString localCachePath = localSourcePath + QLatin1Char('c'); +#ifndef Q_OS_ANDROID if (QFile::exists(localCachePath) || QFileInfo(QFileInfo(localSourcePath).dir().absolutePath()).isWritable()) return localCachePath; +#endif QCryptographicHash fileNameHash(QCryptographicHash::Sha1); fileNameHash.addData(localSourcePath.toUtf8()); QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/"); diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index d03882f233..048c5856ce 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -552,7 +552,7 @@ QJSValue QJSEngine::newQMetaObject(const QMetaObject* metaObject) { return QJSValue(v4, v->asReturnedValue()); } -/*! \fn QJSValue QJSEngine::newQMetaObject<T>() +/*! \fn template <typename T> QJSValue QJSEngine::newQMetaObject() \since 5.8 Creates a JavaScript object that wraps the static QMetaObject associated @@ -710,14 +710,14 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr) } } -/*! \fn QJSValue QJSEngine::toScriptValue(const T &value) +/*! \fn template <typename T> QJSValue QJSEngine::toScriptValue(const T &value) Creates a QJSValue with the given \a value. \sa fromScriptValue() */ -/*! \fn T QJSEngine::fromScriptValue(const QJSValue &value) +/*! \fn template <typename T> T QJSEngine::fromScriptValue(const QJSValue &value) Returns the given \a value converted to the template type \c{T}. diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index c1a135c835..adfa98bd46 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -232,7 +232,7 @@ QJSValue::QJSValue(const QJSValue& other) */ /*! - \fn QJSValue &operator=(QJSValue && other) + \fn QJSValue &QJSValue::operator=(QJSValue && other) Move-assigns \a other to this QJSValue object. */ diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 15c6e98ea7..c033a7d805 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -124,6 +124,9 @@ QQmlEngine *ExecutionEngine::qmlEngine() const #endif // V4_BOOTSTRAP qint32 ExecutionEngine::maxCallDepth = -1; +#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP) +const bool ExecutionEngine::canAllocateExecutableMemory = OSAllocator::canAllocateExecutableMemory(); +#endif ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) : executableAllocator(new QV4::ExecutableAllocator) diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 61154d89a3..c955d1ab9e 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -488,10 +488,14 @@ public: bool checkStackLimits(); - bool canJIT(Function *f) + bool canJIT(Function *f = nullptr) { #if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP) - return f->interpreterCallCount >= jitCallCountThreshold; + if (!canAllocateExecutableMemory) + return false; + if (f) + return f->interpreterCallCount >= jitCallCountThreshold; + return true; #else Q_UNUSED(f); return false; @@ -506,6 +510,9 @@ private: QScopedPointer<QV4::Profiling::Profiler> m_profiler; #endif int jitCallCountThreshold; +#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP) + static const bool canAllocateExecutableMemory; +#endif }; // This is a trick to tell the code generators that functions taking a NoThrowContext won't diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 4e72539c1d..33298f5d98 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1194,7 +1194,7 @@ static QV4::ReturnedValue CallMethod(const QQmlObjectOrGadget &object, int index } } -/*! +/* Returns the match score for converting \a actual to be of type \a conversionType. A zero score means "perfect match" whereas a higher score is worse. @@ -1351,7 +1351,7 @@ static inline int QMetaObject_methods(const QMetaObject *metaObject) return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount; } -/*! +/* Returns the next related method, if one, or 0. */ static const QQmlPropertyData * RelatedMethod(const QQmlObjectOrGadget &object, @@ -1441,7 +1441,7 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ } } -/*! +/* Resolve the overloaded method to call. The algorithm works conceptually like this: 1. Resolve the set of overloads it is *possible* to call. Impossible overloads include those that have too many parameters or have parameters diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index fb49def317..36616bc024 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -82,7 +82,7 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo return result->d(); Scope scope(engine); - Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(pattern, ignoreCase, multiline, global)); + Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline, global)); result->d()->cache = cache; cachedValue.set(engine, result); @@ -90,7 +90,7 @@ Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bo return result->d(); } -void Heap::RegExp::init(const QString &pattern, bool ignoreCase, bool multiline, bool global) +void Heap::RegExp::init(ExecutionEngine *engine, const QString &pattern, bool ignoreCase, bool multiline, bool global) { Base::init(); this->pattern = new QString(pattern); @@ -106,7 +106,7 @@ void Heap::RegExp::init(const QString &pattern, bool ignoreCase, bool multiline, return; subPatternCount = yarrPattern.m_numSubpatterns; #if ENABLE(YARR_JIT) - if (!yarrPattern.m_containsBackreferences) { + if (!yarrPattern.m_containsBackreferences && engine->canJIT()) { jitCode = new JSC::Yarr::YarrCodeBlock; JSC::JSGlobalData dummy(internalClass->engine->regExpAllocator); JSC::Yarr::jitCompile(yarrPattern, JSC::Yarr::Char16, &dummy, *jitCode); diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h index 94bebbd931..56454f73d3 100644 --- a/src/qml/jsruntime/qv4regexp_p.h +++ b/src/qml/jsruntime/qv4regexp_p.h @@ -76,7 +76,7 @@ struct RegExpCacheKey; namespace Heap { struct RegExp : Base { - void init(const QString& pattern, bool ignoreCase, bool multiline, bool global); + void init(ExecutionEngine *engine, const QString& pattern, bool ignoreCase, bool multiline, bool global); void destroy(); QString *pattern; diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index e6e2be91f6..de43108312 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -365,6 +365,7 @@ void QQmlContext::setContextProperties(const QVector<PropertyPair> &properties) \since 5.11 \class QQmlContext::PropertyPair + \inmodule QtQml This struct contains a property name and a property value. It is used as a parameter for the \c setContextProperties function. diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 8b0bd9d6ec..f2757c34be 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -981,7 +981,7 @@ QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStr return 0; } -/*! +/* Returns the list of possible versioned URI combinations. For example, if \a uri is QtQml.Models, \a vmaj is 2, and \a vmin is 0, this method returns the following: [QtQml.Models.2.0, QtQml.2.0.Models, QtQml.Models.2, QtQml.2.Models, QtQml.Models] @@ -1017,7 +1017,7 @@ static QVector<QStaticPlugin> makePlugins() return plugins; } -/*! +/* Get all static plugins that are QML plugins and has a meta data URI that matches with one of \a versionUris, which is a list of all possible versioned URI combinations - see versionUriList() above. @@ -1059,7 +1059,7 @@ static inline QString msgCannotLoadPlugin(const QString &uri, const QString &why } #endif -/*! +/* Import an extension defined by a qmldir file. \a qmldirFilePath is a raw file path. diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp index 71be2e82a3..9bfdd3da35 100644 --- a/src/qml/qml/qqmllist.cpp +++ b/src/qml/qml/qqmllist.cpp @@ -374,12 +374,12 @@ The \l {Qt Quick 1} version of this class is named QDeclarativeListProperty. */ /*! -\fn QQmlListProperty::QQmlListProperty() +\fn template<typename T> QQmlListProperty<T>::QQmlListProperty() \internal */ /*! -\fn QQmlListProperty::QQmlListProperty(QObject *object, QList<T *> &list) +\fn template<typename T> QQmlListProperty<T>::QQmlListProperty(QObject *object, QList<T *> &list) Convenience constructor for making a QQmlListProperty value from an existing QList \a list. The \a list reference must remain valid for as long as \a object @@ -391,7 +391,7 @@ can be very useful while prototyping. */ /*! -\fn QQmlListProperty::QQmlListProperty(QObject *object, void *data, +\fn template<typename T> QQmlListProperty<T>::QQmlListProperty(QObject *object, void *data, CountFunction count, AtFunction at) Construct a readonly QQmlListProperty from a set of operation functions @@ -401,7 +401,7 @@ remains valid while \a object exists. */ /*! -\fn QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append, +\fn template<typename T> QQmlListProperty<T>::QQmlListProperty(QObject *object, void *data, AppendFunction append, CountFunction count, AtFunction at, ClearFunction clear) @@ -432,7 +432,7 @@ Return the number of elements in the list \a property. */ /*! -\fn bool QQmlListProperty::operator==(const QQmlListProperty &other) const +\fn template<typename T> bool QQmlListProperty<T>::operator==(const QQmlListProperty &other) const Returns true if this QQmlListProperty is equal to \a other, otherwise false. */ diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 299de8de70..b5c45d3aa4 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -265,7 +265,12 @@ QObject *ListModel::getOrCreateModelObject(QQmlListModel *model, int elementInde { ListElement *e = elements[elementIndex]; if (e->m_objectCache == 0) { - e->m_objectCache = new QObject; + void *memory = operator new(sizeof(QObject) + sizeof(QQmlData)); + void *ddataMemory = ((char *)memory) + sizeof(QObject); + e->m_objectCache = new (memory) QObject; + QQmlData *ddata = new (ddataMemory) QQmlData; + ddata->ownMemory = false; + QObjectPrivate::get(e->m_objectCache)->declarativeData = ddata; (void)new ModelNodeMetaObject(e->m_objectCache, model, elementIndex); } return e->m_objectCache; @@ -2428,8 +2433,7 @@ QQmlV4Handle QQmlListModel::get(int index) const QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index); result = scope.engine->memoryManager->allocObject<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this), index); // Keep track of the QObjectWrapper in persistent value storage - QV4::Value *val = scope.engine->memoryManager->m_weakValues->allocate(); - *val = result; + QQmlData::get(object)->jsWrapper.set(scope.engine, result); } } diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp index b54e8d901a..578c05086f 100644 --- a/src/qml/util/qqmlpropertymap.cpp +++ b/src/qml/util/qqmlpropertymap.cpp @@ -355,7 +355,7 @@ QQmlPropertyMap::QQmlPropertyMap(const QMetaObject *staticMetaObject, QObject *p */ /*! - \fn QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent) + \fn template<class DerivedType> QQmlPropertyMap::QQmlPropertyMap(DerivedType *derived, QObject *parent) Constructs a bindable map with parent object \a parent. Use this constructor in classes derived from QQmlPropertyMap. diff --git a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp index 4cec84646e..d715d900ba 100644 --- a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp @@ -255,14 +255,14 @@ QRect QSGAbstractSoftwareRenderer::backgroundRect() void QSGAbstractSoftwareRenderer::nodeAdded(QSGNode *node) { - qCDebug(lc2DRender) << "nodeAdded" << (void*)node; + qCDebug(lc2DRender, "nodeAdded %p", (void*)node); m_nodeUpdater->updateNodes(node); } void QSGAbstractSoftwareRenderer::nodeRemoved(QSGNode *node) { - qCDebug(lc2DRender) << "nodeRemoved" << (void*)node; + qCDebug(lc2DRender, "nodeRemoved %p", (void*)node); auto renderable = renderableNode(node); // remove mapping @@ -286,7 +286,7 @@ void QSGAbstractSoftwareRenderer::nodeRemoved(QSGNode *node) void QSGAbstractSoftwareRenderer::nodeGeometryUpdated(QSGNode *node) { - qCDebug(lc2DRender) << "nodeGeometryUpdated"; + qCDebug(lc2DRender, "nodeGeometryUpdated"); // Mark node as dirty auto renderable = renderableNode(node); @@ -299,7 +299,7 @@ void QSGAbstractSoftwareRenderer::nodeGeometryUpdated(QSGNode *node) void QSGAbstractSoftwareRenderer::nodeMaterialUpdated(QSGNode *node) { - qCDebug(lc2DRender) << "nodeMaterialUpdated"; + qCDebug(lc2DRender, "nodeMaterialUpdated"); // Mark node as dirty auto renderable = renderableNode(node); @@ -312,7 +312,7 @@ void QSGAbstractSoftwareRenderer::nodeMaterialUpdated(QSGNode *node) void QSGAbstractSoftwareRenderer::nodeMatrixUpdated(QSGNode *node) { - qCDebug(lc2DRender) << "nodeMaterialUpdated"; + qCDebug(lc2DRender, "nodeMaterialUpdated"); // Update children nodes m_nodeUpdater->updateNodes(node); @@ -320,7 +320,7 @@ void QSGAbstractSoftwareRenderer::nodeMatrixUpdated(QSGNode *node) void QSGAbstractSoftwareRenderer::nodeOpacityUpdated(QSGNode *node) { - qCDebug(lc2DRender) << "nodeOpacityUpdated"; + qCDebug(lc2DRender, "nodeOpacityUpdated"); // Update children nodes m_nodeUpdater->updateNodes(node); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp index 832b69d0cc..a7485a90eb 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarethreadedrenderloop.cpp @@ -523,7 +523,7 @@ void QSGSoftwareRenderThread::syncAndRender() // rate of the current screen the window is on. int blockTime = vsyncDelta - (int) renderThrottleTimer.elapsed(); if (blockTime > 0) { - qCDebug(QSG_RASTER_LOG_RENDERLOOP) << "RT - blocking for " << blockTime << "ms"; + qCDebug(QSG_RASTER_LOG_RENDERLOOP, "RT - blocking for %d ms", blockTime); msleep(blockTime); } renderThrottleTimer.restart(); diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 7531ae7604..87ecf3e5ad 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -226,7 +226,7 @@ void qsg_dumpShadowRoots(BatchRootInfo *i, int indent) QByteArray ind(indent + extraIndent + 10, ' '); if (!i) { - qDebug() << ind.constData() << "- no info"; + qDebug("%s - no info", ind.constData()); } else { qDebug() << ind.constData() << "- parent:" << i->parentRoot << "orders" << i->firstOrder << "->" << i->lastOrder << ", avail:" << i->availableOrders; for (QSet<Node *>::const_iterator it = i->subRoots.constBegin(); @@ -293,15 +293,15 @@ void Updater::updateStates(QSGNode *n) qsg_dumpShadowRoots(sn); if (Q_UNLIKELY(debug_build())) { - qDebug() << "Updater::updateStates()"; + qDebug("Updater::updateStates()"); if (sn->dirtyState & (QSGNode::DirtyNodeAdded << 16)) - qDebug() << " - nodes have been added"; + qDebug(" - nodes have been added"); if (sn->dirtyState & (QSGNode::DirtyMatrix << 16)) - qDebug() << " - transforms have changed"; + qDebug(" - transforms have changed"); if (sn->dirtyState & (QSGNode::DirtyOpacity << 16)) - qDebug() << " - opacity has changed"; + qDebug(" - opacity has changed"); if (uint(sn->dirtyState) & uint(QSGNode::DirtyForceUpdate << 16)) - qDebug() << " - forceupdate"; + qDebug(" - forceupdate"); } if (Q_UNLIKELY(renderer->m_visualizeMode == Renderer::VisualizeChanges)) @@ -805,8 +805,11 @@ Renderer::Renderer(QSGDefaultRenderContext *ctx) m_batchVertexThreshold = qt_sg_envInt("QSG_RENDERER_BATCH_VERTEX_THRESHOLD", 1024); if (Q_UNLIKELY(debug_build() || debug_render())) { - qDebug() << "Batch thresholds: nodes:" << m_batchNodeThreshold << " vertices:" << m_batchVertexThreshold; - qDebug() << "Using buffer strategy:" << (m_bufferStrategy == GL_STATIC_DRAW ? "static" : (m_bufferStrategy == GL_DYNAMIC_DRAW ? "dynamic" : "stream")); + qDebug("Batch thresholds: nodes: %d vertices: %d", + m_batchNodeThreshold, m_batchVertexThreshold); + qDebug("Using buffer strategy: %s", + (m_bufferStrategy == GL_STATIC_DRAW + ? "static" : (m_bufferStrategy == GL_DYNAMIC_DRAW ? "dynamic" : "stream"))); } // If rendering with an OpenGL Core profile context, we need to create a VAO @@ -1112,7 +1115,7 @@ void Renderer::nodeWasRemoved(Node *node) void Renderer::turnNodeIntoBatchRoot(Node *node) { - if (Q_UNLIKELY(debug_change())) qDebug() << " - new batch root"; + if (Q_UNLIKELY(debug_change())) qDebug(" - new batch root"); m_rebuild |= FullRebuild; node->isBatchRoot = true; node->becameBatchRoot = true; @@ -2328,7 +2331,7 @@ void Renderer::renderMergedBatch(const Batch *batch) #ifndef QT_NO_DEBUG if (qsg_test_and_clear_material_failure()) { - qDebug() << "QSGMaterial::updateState triggered an error (merged), batch will be skipped:"; + qDebug("QSGMaterial::updateState triggered an error (merged), batch will be skipped:"); Element *ee = e; while (ee) { qDebug() << " -" << ee->node; @@ -2449,7 +2452,7 @@ void Renderer::renderUnmergedBatch(const Batch *batch) #ifndef QT_NO_DEBUG if (qsg_test_and_clear_material_failure()) { - qDebug() << "QSGMaterial::updateState() triggered an error (unmerged), batch will be skipped:"; + qDebug("QSGMaterial::updateState() triggered an error (unmerged), batch will be skipped:"); qDebug() << " - offending node is" << e->node; QSGNodeDumper::dump(rootNode()); qFatal("Aborting: scene graph is invalid..."); @@ -2655,12 +2658,12 @@ void Renderer::render() m_rebuild |= BuildBatches; if (Q_UNLIKELY(debug_build())) { - qDebug() << "Opaque render lists" << (complete ? "(complete)" : "(partial)") << ":"; + qDebug("Opaque render lists %s:", (complete ? "(complete)" : "(partial)")); for (int i=0; i<m_opaqueRenderList.size(); ++i) { Element *e = m_opaqueRenderList.at(i); qDebug() << " - element:" << e << " batch:" << e->batch << " node:" << e->node << " order:" << e->order; } - qDebug() << "Alpha render list:" << (complete ? "(complete)" : "(partial)") << ":"; + qDebug("Alpha render list %s:", complete ? "(complete)" : "(partial)"); for (int i=0; i<m_alphaRenderList.size(); ++i) { Element *e = m_alphaRenderList.at(i); qDebug() << " - element:" << e << " batch:" << e->batch << " node:" << e->node << " order:" << e->order; @@ -2685,7 +2688,7 @@ void Renderer::render() if (Q_UNLIKELY(debug_render())) timePrepareAlpha = timer.restart(); if (Q_UNLIKELY(debug_build())) { - qDebug() << "Opaque Batches:"; + qDebug("Opaque Batches:"); for (int i=0; i<m_opaqueBatches.size(); ++i) { Batch *b = m_opaqueBatches.at(i); qDebug() << " - Batch " << i << b << (b->needsUpload ? "upload" : "") << " root:" << b->root; @@ -2693,7 +2696,7 @@ void Renderer::render() qDebug() << " - element:" << e << " node:" << e->node << e->order; } } - qDebug() << "Alpha Batches:"; + qDebug("Alpha Batches:"); for (int i=0; i<m_alphaBatches.size(); ++i) { Batch *b = m_alphaBatches.at(i); qDebug() << " - Batch " << i << b << (b->needsUpload ? "upload" : "") << " root:" << b->root; @@ -2731,7 +2734,7 @@ void Renderer::render() int largestIBO = 0; #endif - if (Q_UNLIKELY(debug_upload())) qDebug() << "Uploading Opaque Batches:"; + if (Q_UNLIKELY(debug_upload())) qDebug("Uploading Opaque Batches:"); for (int i=0; i<m_opaqueBatches.size(); ++i) { Batch *b = m_opaqueBatches.at(i); largestVBO = qMax(b->vbo.size, largestVBO); @@ -2743,7 +2746,7 @@ void Renderer::render() if (Q_UNLIKELY(debug_render())) timeUploadOpaque = timer.restart(); - if (Q_UNLIKELY(debug_upload())) qDebug() << "Uploading Alpha Batches:"; + if (Q_UNLIKELY(debug_upload())) qDebug("Uploading Alpha Batches:"); for (int i=0; i<m_alphaBatches.size(); ++i) { Batch *b = m_alphaBatches.at(i); uploadBatch(b); diff --git a/src/quick/scenegraph/qsgcontextplugin.cpp b/src/quick/scenegraph/qsgcontextplugin.cpp index 6583883d0c..634a492aa3 100644 --- a/src/quick/scenegraph/qsgcontextplugin.cpp +++ b/src/quick/scenegraph/qsgcontextplugin.cpp @@ -139,7 +139,7 @@ QSGAdaptationBackendData *contextFactory() } if (!requestedBackend.isEmpty()) { - qCDebug(QSG_LOG_INFO) << "Loading backend" << requestedBackend; + qCDebug(QSG_LOG_INFO, "Loading backend %s", qUtf8Printable(requestedBackend)); // First look for a built-in adaptation. for (QSGContextFactoryInterface *builtInBackend : qAsConst(backendData->builtIns)) { diff --git a/src/quick/scenegraph/qsgdefaultcontext.cpp b/src/quick/scenegraph/qsgdefaultcontext.cpp index be5fec9dab..9a0ac66690 100644 --- a/src/quick/scenegraph/qsgdefaultcontext.cpp +++ b/src/quick/scenegraph/qsgdefaultcontext.cpp @@ -149,20 +149,23 @@ void QSGDefaultContext::renderContextInitialized(QSGRenderContext *renderContext dumped = true; QSurfaceFormat format = openglRenderContext->openglContext()->format(); QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - qCDebug(QSG_LOG_INFO) << "R/G/B/A Buffers: " << format.redBufferSize() << format.greenBufferSize() << format.blueBufferSize() << format.alphaBufferSize(); - qCDebug(QSG_LOG_INFO) << "Depth Buffer: " << format.depthBufferSize(); - qCDebug(QSG_LOG_INFO) << "Stencil Buffer: " << format.stencilBufferSize(); - qCDebug(QSG_LOG_INFO) << "Samples: " << format.samples(); - qCDebug(QSG_LOG_INFO) << "GL_VENDOR: " << (const char *) funcs->glGetString(GL_VENDOR); - qCDebug(QSG_LOG_INFO) << "GL_RENDERER: " << (const char *) funcs->glGetString(GL_RENDERER); - qCDebug(QSG_LOG_INFO) << "GL_VERSION: " << (const char *) funcs->glGetString(GL_VERSION); + qCDebug(QSG_LOG_INFO, "R/G/B/A Buffers: %d %d %d %d", format.redBufferSize(), + format.greenBufferSize(), format.blueBufferSize(), format.alphaBufferSize()); + qCDebug(QSG_LOG_INFO, "Depth Buffer: %d", format.depthBufferSize()); + qCDebug(QSG_LOG_INFO, "Stencil Buffer: %d", format.stencilBufferSize()); + qCDebug(QSG_LOG_INFO, "Samples: %d", format.samples()); + qCDebug(QSG_LOG_INFO, "GL_VENDOR: %s", (const char*)funcs->glGetString(GL_VENDOR)); + qCDebug(QSG_LOG_INFO, "GL_RENDERER: %s", + (const char*)funcs->glGetString(GL_RENDERER)); + qCDebug(QSG_LOG_INFO, "GL_VERSION: %s", (const char*)funcs->glGetString(GL_VERSION)); QSet<QByteArray> exts = openglRenderContext->openglContext()->extensions(); QByteArray all; for (const QByteArray &e : qAsConst(exts)) all += ' ' + e; - qCDebug(QSG_LOG_INFO) << "GL_EXTENSIONS: " << all.constData(); - qCDebug(QSG_LOG_INFO) << "Max Texture Size: " << openglRenderContext->maxTextureSize(); - qCDebug(QSG_LOG_INFO) << "Debug context: " << format.testOption(QSurfaceFormat::DebugContext); + qCDebug(QSG_LOG_INFO, "GL_EXTENSIONS: %s", all.constData()); + qCDebug(QSG_LOG_INFO, "Max Texture Size: %d", openglRenderContext->maxTextureSize()); + qCDebug(QSG_LOG_INFO, "Debug context: %s", + format.testOption(QSurfaceFormat::DebugContext) ? "true" : "false"); } m_mutex.unlock(); diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 88899c400c..ca1fb9ba5c 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -327,7 +327,7 @@ void QSGGuiThreadRenderLoop::windowDestroyed(QQuickWindow *window) current = gl->makeCurrent(surface); } if (Q_UNLIKELY(!current)) - qCDebug(QSG_LOG_RENDERLOOP) << "cleanup without an OpenGL context"; + qCDebug(QSG_LOG_RENDERLOOP, "cleanup without an OpenGL context"); #if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl) QQuickOpenGLShaderEffectMaterial::cleanupMaterialCache(); diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 4a712d3cdd..971694db42 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -115,7 +115,7 @@ QT_BEGIN_NAMESPACE -#define QSG_RT_PAD " (RT)" +#define QSG_RT_PAD " (RT) %s" static inline int qsgrl_animation_interval() { qreal refreshRate = QGuiApplication::primaryScreen()->refreshRate(); @@ -315,7 +315,7 @@ public: public slots: void sceneGraphChanged() { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "sceneGraphChanged"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "sceneGraphChanged"); syncResultedInChanges = true; } @@ -358,14 +358,14 @@ bool QSGRenderThread::event(QEvent *e) switch ((int) e->type()) { case WM_Obscure: { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_Obscure"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "WM_Obscure"); Q_ASSERT(!window || window == static_cast<WMWindowEvent *>(e)->window); mutex.lock(); if (window) { QQuickWindowPrivate::get(window)->fireAboutToStop(); - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window removed"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- window removed"); window = 0; } waitCondition.wakeOne(); @@ -374,7 +374,7 @@ bool QSGRenderThread::event(QEvent *e) return true; } case WM_RequestSync: { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_RequestSync"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "WM_RequestSync"); WMSyncEvent *se = static_cast<WMSyncEvent *>(e); if (sleeping) stopEventProcessing = true; @@ -383,33 +383,33 @@ bool QSGRenderThread::event(QEvent *e) pendingUpdate |= SyncRequest; if (se->syncInExpose) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- triggered from expose"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- triggered from expose"); pendingUpdate |= ExposeRequest; } if (se->forceRenderPass) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- repaint regardless"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- repaint regardless"); pendingUpdate |= RepaintRequest; } return true; } case WM_TryRelease: { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_TryRelease"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "WM_TryRelease"); mutex.lock(); wm->m_lockedForSync = true; WMTryReleaseEvent *wme = static_cast<WMTryReleaseEvent *>(e); if (!window || wme->inDestructor) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- setting exit flag and invalidating OpenGL"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- setting exit flag and invalidating OpenGL"); invalidateOpenGL(wme->window, wme->inDestructor, wme->fallbackSurface); active = gl; Q_ASSERT_X(!wme->inDestructor || !active, "QSGRenderThread::invalidateOpenGL()", "Thread's active state is not set to false when shutting down"); if (sleeping) stopEventProcessing = true; } else { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- not releasing because window is still active"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- not releasing because window is still active"); if (window) { QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); if (d->renderer) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- requesting renderer to release cached resources"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- requesting renderer to release cached resources"); d->renderer->releaseCachedResources(); } } @@ -421,7 +421,7 @@ bool QSGRenderThread::event(QEvent *e) } case WM_Grab: { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_Grab"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "WM_Grab"); WMGrabEvent *ce = static_cast<WMGrabEvent *>(e); Q_ASSERT(ce->window); Q_ASSERT(ce->window == window || !window); @@ -429,27 +429,27 @@ bool QSGRenderThread::event(QEvent *e) if (ce->window) { gl->makeCurrent(ce->window); - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- sync scene graph"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- sync scene graph"); QQuickWindowPrivate *d = QQuickWindowPrivate::get(ce->window); d->syncSceneGraph(); sgrc->endSync(); - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering scene graph"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- rendering scene graph"); QQuickWindowPrivate::get(ce->window)->renderSceneGraph(ce->window->size()); - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- grabbing result"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- grabbing result"); bool alpha = ce->window->format().alphaBufferSize() > 0 && ce->window->color().alpha() != 255; *ce->image = qt_gl_read_framebuffer(windowSize * ce->window->effectiveDevicePixelRatio(), alpha, alpha); ce->image->setDevicePixelRatio(ce->window->effectiveDevicePixelRatio()); } - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- waking gui to handle result"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- waking gui to handle result"); waitCondition.wakeOne(); mutex.unlock(); return true; } case WM_PostJob: { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_PostJob"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "WM_PostJob"); WMJobEvent *ce = static_cast<WMJobEvent *>(e); Q_ASSERT(ce->window == window); if (window) { @@ -457,13 +457,13 @@ bool QSGRenderThread::event(QEvent *e) ce->job->run(); delete ce->job; ce->job = 0; - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- job done"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- job done"); } return true; } case WM_RequestRepaint: - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "WM_RequestPaint"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "WM_RequestPaint"); // When GUI posts this event, it is followed by a polishAndSync, so we mustn't // exit the event loop yet. pendingUpdate |= RepaintRequest; @@ -477,13 +477,13 @@ bool QSGRenderThread::event(QEvent *e) void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, QOffscreenSurface *fallback) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "invalidateOpenGL()"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "invalidateOpenGL()"); if (!gl) return; if (!window) { - qCWarning(QSG_LOG_RENDERLOOP()) << "QSGThreadedRenderLoop:QSGRenderThread: no window to make current..."; + qCWarning(QSG_LOG_RENDERLOOP, "QSGThreadedRenderLoop:QSGRenderThread: no window to make current..."); return; } @@ -493,7 +493,7 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, bool current = gl->makeCurrent(fallback ? static_cast<QSurface *>(fallback) : static_cast<QSurface *>(window)); if (Q_UNLIKELY(!current)) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- cleanup without an OpenGL context"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- cleanup without an OpenGL context"); } QQuickWindowPrivate *dd = QQuickWindowPrivate::get(window); @@ -506,7 +506,7 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, if (wipeSG) { dd->cleanupNodesOnShutdown(); } else { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- persistent SG, avoiding cleanup"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- persistent SG, avoiding cleanup"); if (current) gl->doneCurrent(); return; @@ -519,14 +519,14 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, delete dd->animationController; if (current) gl->doneCurrent(); - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- invalidating scene graph"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- invalidating scene graph"); if (wipeGL) { delete gl; gl = 0; - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- invalidated OpenGL"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- invalidated OpenGL"); } else { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- persistent GL, avoiding cleanup"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- persistent GL, avoiding cleanup"); } } @@ -536,7 +536,7 @@ void QSGRenderThread::invalidateOpenGL(QQuickWindow *window, bool inDestructor, */ void QSGRenderThread::sync(bool inExpose) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "sync()"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "sync()"); mutex.lock(); Q_ASSERT_X(wm->m_lockedForSync, "QSGRenderThread::sync()", "sync triggered on bad terms as gui is not already locked..."); @@ -562,7 +562,7 @@ void QSGRenderThread::sync(bool inExpose) d->syncSceneGraph(); sgrc->endSync(); if (!hadRenderer && d->renderer) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- renderer was created"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- renderer was created"); syncResultedInChanges = true; connect(d->renderer, SIGNAL(sceneGraphChanged()), this, SLOT(sceneGraphChanged()), Qt::DirectConnection); } @@ -572,11 +572,11 @@ void QSGRenderThread::sync(bool inExpose) // and the delete is a safe operation. QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); } else { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window has bad size, sync aborted"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- window has bad size, sync aborted"); } if (!inExpose) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- sync complete, waking Gui"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- sync complete, waking Gui"); waitCondition.wakeOne(); mutex.unlock(); } @@ -594,7 +594,7 @@ void QSGRenderThread::syncAndRender() QElapsedTimer waitTimer; waitTimer.start(); - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "syncAndRender()"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "syncAndRender()"); syncResultedInChanges = false; QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); @@ -605,7 +605,7 @@ void QSGRenderThread::syncAndRender() pendingUpdate = 0; if (syncRequested) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- updatePending, doing sync"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- updatePending, doing sync"); sync(exposeRequested); } #ifndef QSG_NO_RENDER_TIMING @@ -616,14 +616,14 @@ void QSGRenderThread::syncAndRender() QQuickProfiler::SceneGraphRenderLoopSync); if (!syncResultedInChanges && !repaintRequested && sgrc->isValid()) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- no changes, render aborted"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- no changes, render aborted"); int waitTime = vsyncDelta - (int) waitTimer.elapsed(); if (waitTime > 0) msleep(waitTime); return; } - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering started"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- rendering started"); if (animatorDriver->isRunning()) { @@ -653,10 +653,10 @@ void QSGRenderThread::syncAndRender() } else { Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame, QQuickProfiler::SceneGraphRenderLoopSync, 1); - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window not ready, skipping render"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- window not ready, skipping render"); } - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering done"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- rendering done"); // Though it would be more correct to put this block directly after // fireFrameSwapped in the if (current) branch above, we don't do @@ -664,7 +664,7 @@ void QSGRenderThread::syncAndRender() // has started rendering with a bad window, causing makeCurrent to // fail or if the window has a bad size. if (exposeRequested) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- wake Gui after initial expose"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "- wake Gui after initial expose"); waitCondition.wakeOne(); mutex.unlock(); } @@ -692,30 +692,30 @@ void QSGRenderThread::postEvent(QEvent *e) void QSGRenderThread::processEvents() { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "--- begin processEvents()"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "--- begin processEvents()"); while (eventQueue.hasMoreEvents()) { QEvent *e = eventQueue.takeEvent(false); event(e); delete e; } - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "--- done processEvents()"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "--- done processEvents()"); } void QSGRenderThread::processEventsAndWaitForMore() { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "--- begin processEventsAndWaitForMore()"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "--- begin processEventsAndWaitForMore()"); stopEventProcessing = false; while (!stopEventProcessing) { QEvent *e = eventQueue.takeEvent(true); event(e); delete e; } - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "--- done processEventsAndWaitForMore()"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "--- done processEventsAndWaitForMore()"); } void QSGRenderThread::run() { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "run()"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "run()"); animatorDriver = sgrc->sceneGraphContext()->createAnimationDriver(0); animatorDriver->install(); if (QQmlDebugConnector::service<QQmlProfilerService>()) @@ -733,7 +733,7 @@ void QSGRenderThread::run() QCoreApplication::processEvents(); if (active && (pendingUpdate == 0 || !window)) { - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "done drawing, sleep..."; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "done drawing, sleep..."); sleeping = true; processEventsAndWaitForMore(); sleeping = false; @@ -742,7 +742,7 @@ void QSGRenderThread::run() Q_ASSERT_X(!gl, "QSGRenderThread::run()", "The OpenGL context should be cleaned up before exiting the render thread..."); - qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "run() completed"; + qCDebug(QSG_LOG_RENDERLOOP, QSG_RT_PAD, "run() completed"); delete animatorDriver; animatorDriver = 0; @@ -809,7 +809,7 @@ bool QSGThreadedRenderLoop::interleaveIncubation() const void QSGThreadedRenderLoop::animationStarted() { - qCDebug(QSG_LOG_RENDERLOOP) << "- animationStarted()"; + qCDebug(QSG_LOG_RENDERLOOP, "- animationStarted()"); startOrStopAnimationTimer(); for (int i=0; i<m_windows.size(); ++i) @@ -818,7 +818,7 @@ void QSGThreadedRenderLoop::animationStarted() void QSGThreadedRenderLoop::animationStopped() { - qCDebug(QSG_LOG_RENDERLOOP) << "- animationStopped()"; + qCDebug(QSG_LOG_RENDERLOOP, "- animationStopped()"); startOrStopAnimationTimer(); } @@ -836,14 +836,14 @@ void QSGThreadedRenderLoop::startOrStopAnimationTimer() } if (m_animation_timer != 0 && (exposedWindows == 1 || !m_animation_driver->isRunning())) { - qCDebug(QSG_LOG_RENDERLOOP) << "*** Stopping animation timer"; + qCDebug(QSG_LOG_RENDERLOOP, "*** Stopping animation timer"); killTimer(m_animation_timer); m_animation_timer = 0; // If animations are running, make sure we keep on animating if (m_animation_driver->isRunning()) maybePostPolishRequest(const_cast<Window *>(theOne)); } else if (m_animation_timer == 0 && exposedWindows != 1 && m_animation_driver->isRunning()) { - qCDebug(QSG_LOG_RENDERLOOP) << "*** Starting animation timer"; + qCDebug(QSG_LOG_RENDERLOOP, "*** Starting animation timer"); m_animation_timer = startTimer(qsgrl_animation_interval()); } } @@ -930,7 +930,7 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window) Window *w = windowFor(m_windows, window); if (!w) { - qCDebug(QSG_LOG_RENDERLOOP) << "- adding window to list"; + qCDebug(QSG_LOG_RENDERLOOP, "- adding window to list"); Window win; win.window = window; win.actualWindowFormat = window->format(); @@ -962,7 +962,7 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window) // Start render thread if it is not running if (!w->thread->isRunning()) { - qCDebug(QSG_LOG_RENDERLOOP) << "- starting render thread"; + qCDebug(QSG_LOG_RENDERLOOP, "- starting render thread"); if (!w->thread->gl) { w->thread->gl = new QOpenGLContext(); @@ -981,7 +981,7 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window) QQuickWindowPrivate::get(w->window)->fireOpenGLContextCreated(w->thread->gl); w->thread->gl->moveToThread(w->thread); - qCDebug(QSG_LOG_RENDERLOOP) << "- OpenGL context created"; + qCDebug(QSG_LOG_RENDERLOOP, "- OpenGL context created"); } QQuickAnimatorController *controller = QQuickWindowPrivate::get(w->window)->animationController; @@ -998,11 +998,11 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window) qFatal("Render thread failed to start, aborting application."); } else { - qCDebug(QSG_LOG_RENDERLOOP) << "- render thread already running"; + qCDebug(QSG_LOG_RENDERLOOP, "- render thread already running"); } polishAndSync(w, true); - qCDebug(QSG_LOG_RENDERLOOP) << "- done with handleExposure()"; + qCDebug(QSG_LOG_RENDERLOOP, "- done with handleExposure()"); startOrStopAnimationTimer(); } @@ -1029,7 +1029,7 @@ void QSGThreadedRenderLoop::handleObscurity(Window *w) void QSGThreadedRenderLoop::handleUpdateRequest(QQuickWindow *window) { - qCDebug(QSG_LOG_RENDERLOOP) << "- polish and sync update request"; + qCDebug(QSG_LOG_RENDERLOOP, "- polish and sync update request"); Window *w = windowFor(m_windows, window); if (w) polishAndSync(w); @@ -1065,7 +1065,7 @@ void QSGThreadedRenderLoop::maybeUpdate(Window *w) // Call this function from the Gui thread later as startTimer cannot be // called from the render thread. if (current == w->thread) { - qCDebug(QSG_LOG_RENDERLOOP) << "- on render thread"; + qCDebug(QSG_LOG_RENDERLOOP, "- on render thread"); w->updateDuringSync = true; return; } @@ -1125,13 +1125,13 @@ void QSGThreadedRenderLoop::releaseResources(Window *w, bool inDestructor) // create it here and pass it on to QSGRenderThread::invalidateGL() QOffscreenSurface *fallback = 0; if (!window->handle()) { - qCDebug(QSG_LOG_RENDERLOOP) << "- using fallback surface"; + qCDebug(QSG_LOG_RENDERLOOP, "- using fallback surface"); fallback = new QOffscreenSurface(); fallback->setFormat(w->actualWindowFormat); fallback->create(); } - qCDebug(QSG_LOG_RENDERLOOP) << "- posting release request to render thread"; + qCDebug(QSG_LOG_RENDERLOOP, "- posting release request to render thread"); w->thread->postEvent(new WMTryReleaseEvent(window, inDestructor, fallback)); w->thread->waitCondition.wait(&w->thread->mutex); delete fallback; @@ -1161,7 +1161,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) QQuickWindow *window = w->window; if (!w->thread || !w->thread->window) { - qCDebug(QSG_LOG_RENDERLOOP) << "- not exposed, abort"; + qCDebug(QSG_LOG_RENDERLOOP, "- not exposed, abort"); return; } @@ -1170,7 +1170,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) // The delivery of the event might have caused the window to stop rendering w = windowFor(m_windows, window); if (!w || !w->thread || !w->thread->window) { - qCDebug(QSG_LOG_RENDERLOOP) << "- removed after event flushing, abort"; + qCDebug(QSG_LOG_RENDERLOOP, "- removed after event flushing, abort"); return; } @@ -1196,13 +1196,13 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) emit window->afterAnimating(); - qCDebug(QSG_LOG_RENDERLOOP) << "- lock for sync"; + qCDebug(QSG_LOG_RENDERLOOP, "- lock for sync"); w->thread->mutex.lock(); m_lockedForSync = true; w->thread->postEvent(new WMSyncEvent(window, inExpose, w->forceRenderPass)); w->forceRenderPass = false; - qCDebug(QSG_LOG_RENDERLOOP) << "- wait for sync"; + qCDebug(QSG_LOG_RENDERLOOP, "- wait for sync"); if (profileFrames) waitTime = timer.nsecsElapsed(); Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync, @@ -1210,7 +1210,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) w->thread->waitCondition.wait(&w->thread->mutex); m_lockedForSync = false; w->thread->mutex.unlock(); - qCDebug(QSG_LOG_RENDERLOOP) << "- unlock after sync"; + qCDebug(QSG_LOG_RENDERLOOP, "- unlock after sync"); if (profileFrames) syncTime = timer.nsecsElapsed(); @@ -1218,9 +1218,9 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose) QQuickProfiler::SceneGraphPolishAndSyncSync); if (m_animation_timer == 0 && m_animation_driver->isRunning()) { - qCDebug(QSG_LOG_RENDERLOOP) << "- advancing animations"; + qCDebug(QSG_LOG_RENDERLOOP, "- advancing animations"); m_animation_driver->advance(); - qCDebug(QSG_LOG_RENDERLOOP) << "- animations done.."; + qCDebug(QSG_LOG_RENDERLOOP, "- animations done.."); // We need to trigger another sync to keep animations running... maybePostPolishRequest(w); emit timeToIncubate(); @@ -1247,7 +1247,7 @@ bool QSGThreadedRenderLoop::event(QEvent *e) case QEvent::Timer: { QTimerEvent *te = static_cast<QTimerEvent *>(e); if (te->timerId() == m_animation_timer) { - qCDebug(QSG_LOG_RENDERLOOP) << "- ticking non-visual timer"; + qCDebug(QSG_LOG_RENDERLOOP, "- ticking non-visual timer"); m_animation_driver->advance(); emit timeToIncubate(); return true; @@ -1286,20 +1286,20 @@ QImage QSGThreadedRenderLoop::grab(QQuickWindow *window) if (!window->handle()) window->create(); - qCDebug(QSG_LOG_RENDERLOOP) << "- polishing items"; + qCDebug(QSG_LOG_RENDERLOOP, "- polishing items"); QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); d->polishItems(); QImage result; w->thread->mutex.lock(); m_lockedForSync = true; - qCDebug(QSG_LOG_RENDERLOOP) << "- posting grab event"; + qCDebug(QSG_LOG_RENDERLOOP, "- posting grab event"); w->thread->postEvent(new WMGrabEvent(window, &result)); w->thread->waitCondition.wait(&w->thread->mutex); m_lockedForSync = false; w->thread->mutex.unlock(); - qCDebug(QSG_LOG_RENDERLOOP) << "- grab complete"; + qCDebug(QSG_LOG_RENDERLOOP, "- grab complete"); return result; } diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index e33f31f2ac..8072359e11 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); -#define RLDEBUG(x) qCDebug(QSG_LOG_RENDERLOOP) << x; +#define RLDEBUG(x) qCDebug(QSG_LOG_RENDERLOOP, x) static QElapsedTimer qsg_render_timer; #define QSG_LOG_TIME_SAMPLE(sampleName) \ @@ -243,7 +243,7 @@ void QSGWindowsRenderLoop::windowDestroyed(QQuickWindow *window) current = m_gl->makeCurrent(surface); } if (Q_UNLIKELY(!current)) - qCDebug(QSG_LOG_RENDERLOOP) << "cleanup without an OpenGL context"; + RLDEBUG("cleanup without an OpenGL context"); #if QT_CONFIG(quick_shadereffect) && QT_CONFIG(opengl) QQuickOpenGLShaderEffectMaterial::cleanupMaterialCache(); diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index 9d37746fff..529cdaf070 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -501,9 +501,10 @@ void Atlas::uploadPendingTexture(int i) textureSize.height() > m_atlas_transient_image_threshold) t->releaseImage(); - qCDebug(QSG_LOG_TIME_TEXTURE).nospace() << "atlastexture uploaded in: " << qsg_renderer_timer.elapsed() - << "ms (" << t->textureSize().width() << "x" - << t->textureSize().height() << ")"; + qCDebug(QSG_LOG_TIME_TEXTURE, "atlastexture uploaded in: %lldms (%dx%d)", + qsg_renderer_timer.elapsed(), + t->textureSize().width(), + t->textureSize().height()); } TextureBase::TextureBase(AtlasBase *atlas, const QRect &textureRect) diff --git a/src/quick/scenegraph/util/qsgsimplematerial.cpp b/src/quick/scenegraph/util/qsgsimplematerial.cpp index f29c58ad9e..376f7dce5c 100644 --- a/src/quick/scenegraph/util/qsgsimplematerial.cpp +++ b/src/quick/scenegraph/util/qsgsimplematerial.cpp @@ -173,17 +173,17 @@ /*! - \fn char const *const *QSGSimpleMaterialShader::attributeNames() const + \fn template <typename State> char const *const *QSGSimpleMaterialShader<State>::attributeNames() const \internal */ /*! - \fn void QSGSimpleMaterialShader::initialize() + \fn template <typename State> void QSGSimpleMaterialShader<State>::initialize() \internal */ /*! - \fn void QSGSimpleMaterialShader::resolveUniforms() + \fn template <typename State> void QSGSimpleMaterialShader<State>::resolveUniforms() Reimplement this function to resolve the location of named uniforms in the shader program. @@ -192,34 +192,34 @@ */ /*! - \fn const char *QSGSimpleMaterialShader::uniformMatrixName() const + \fn template <typename State> const char *QSGSimpleMaterialShader<State>::uniformMatrixName() const Returns the name for the transform matrix uniform of this item. The default value is \c qt_Matrix. */ /*! - \fn const char *QSGSimpleMaterialShader::uniformOpacityName() const + \fn template <typename State> const char *QSGSimpleMaterialShader<State>::uniformOpacityName() const Returns the name for the opacity uniform of this item. The default value is \c qt_Opacity. */ /*! - \fn void QSGSimpleMaterialShader::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) + \fn template <typename State> void QSGSimpleMaterialShader<State>::updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) \internal */ /*! - \fn QList<QByteArray> QSGSimpleMaterialShader::attributes() const + \fn template <typename State> QList<QByteArray> QSGSimpleMaterialShader<State>::attributes() const Returns a list of names, declaring the vertex attributes in the vertex shader. */ /*! - \fn void QSGSimpleMaterialShader::updateState(const State *newState, const State *oldState) + \fn template <typename State> void QSGSimpleMaterialShader<State>::updateState(const State *newState, const State *oldState) Called whenever the state of this shader should be updated from \a oldState to \a newState, typical for each new set of diff --git a/src/quick/scenegraph/util/qsgtexturereader.cpp b/src/quick/scenegraph/util/qsgtexturereader.cpp index 168afb9e56..eb0caa59e4 100644 --- a/src/quick/scenegraph/util/qsgtexturereader.cpp +++ b/src/quick/scenegraph/util/qsgtexturereader.cpp @@ -92,6 +92,12 @@ bool QSGTextureReader::isTexture() #endif } +QList<QByteArray> QSGTextureReader::supportedFileFormats() +{ + // Hardcoded for now + return {QByteArrayLiteral("pkm"), QByteArrayLiteral("ktx")}; +} + bool QSGTextureReader::init() { if (!m_device) diff --git a/src/quick/scenegraph/util/qsgtexturereader_p.h b/src/quick/scenegraph/util/qsgtexturereader_p.h index 8251e4c696..1d874f840c 100644 --- a/src/quick/scenegraph/util/qsgtexturereader_p.h +++ b/src/quick/scenegraph/util/qsgtexturereader_p.h @@ -71,6 +71,8 @@ public: // TBD access function to params // TBD ask for identified fmt + static QList<QByteArray> supportedFileFormats(); + private: bool init(); QIODevice *m_device = nullptr; diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index 6712b01476..7097bcc156 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -414,6 +414,34 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e } } +static QStringList fromLatin1List(const QList<QByteArray> &list) +{ + QStringList res; + res.reserve(list.size()); + for (const QByteArray &item : list) + res.append(QString::fromLatin1(item)); + return res; +} + +static QString existingImageFileForPath(const QString &localFile) +{ + // Do nothing if given filepath exists or already has a suffix + QFileInfo fi(localFile); + if (!fi.suffix().isEmpty() || fi.exists()) + return localFile; + + static const QStringList suffixes = fromLatin1List(QSGTextureReader::supportedFileFormats() + + QImageReader::supportedImageFormats()); + QString tryFile = localFile + QStringLiteral(".xxxx"); + const int suffixIdx = localFile.length() + 1; + for (const QString &suffix : suffixes) { + tryFile.replace(suffixIdx, 10, suffix); + if (QFileInfo::exists(tryFile)) + return tryFile; + } + return localFile; +} + QQuickPixmapReader::QQuickPixmapReader(QQmlEngine *eng) : QThread(eng), engine(eng), threadObject(0) #if QT_CONFIG(qml_network) @@ -769,7 +797,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u QImage image; QQuickPixmapReply::ReadError errorCode = QQuickPixmapReply::NoError; QString errorStr; - QFile f(localFile); + QFile f(existingImageFileForPath(localFile)); QSize readSize; if (f.open(QIODevice::ReadOnly)) { QSGTextureReader texReader(&f, localFile); @@ -779,6 +807,8 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u readSize = factory->textureSize(); } else { errorStr = QQuickPixmap::tr("Error decoding: %1").arg(url.toString()); + if (f.fileName() != localFile) + errorStr += QString::fromLatin1(" (%1)").arg(f.fileName()); errorCode = QQuickPixmapReply::Decoding; } mutex.lock(); @@ -787,8 +817,11 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u mutex.unlock(); return; } else { - if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->requestSize, runningJob->providerOptions)) + if (!readImage(url, &f, &image, &errorStr, &readSize, runningJob->requestSize, runningJob->providerOptions)) { errorCode = QQuickPixmapReply::Loading; + if (f.fileName() != localFile) + errorStr += QString::fromLatin1(" (%1)").arg(f.fileName()); + } } } else { errorStr = QQuickPixmap::tr("Cannot open: %1").arg(url.toString()); @@ -1245,7 +1278,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q if (localFile.isEmpty()) return 0; - QFile f(localFile); + QFile f(existingImageFileForPath(localFile)); QSize readSize; QString errorString; @@ -1258,6 +1291,8 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q return new QQuickPixmapData(declarativePixmap, url, factory, factory->textureSize(), requestSize, providerOptions, QQuickImageProviderOptions::UsePluginDefaultTransform); } else { errorString = QQuickPixmap::tr("Error decoding: %1").arg(url.toString()); + if (f.fileName() != localFile) + errorString += QString::fromLatin1(" (%1)").arg(f.fileName()); } } else { QImage image; @@ -1265,6 +1300,8 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q if (readImage(url, &f, &image, &errorString, &readSize, requestSize, providerOptions, &appliedTransform)) { *ok = true; return new QQuickPixmapData(declarativePixmap, url, QQuickTextureFactory::textureFactoryForImage(image), readSize, requestSize, providerOptions, appliedTransform); + } else if (f.fileName() != localFile) { + errorString += QString::fromLatin1(" (%1)").arg(f.fileName()); } } } else { diff --git a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.pro b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.pro index 55a77d830d..a8eb4885d4 100644 --- a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.pro +++ b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.pro @@ -1,6 +1,7 @@ QT = core macos:CONFIG -= app_bundle CONFIG -= debug_and_release_target +CONFIG += console SOURCES += qqmldebugprocessprocess.cpp DESTDIR = ../qqmldebugprocess diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp index 4089673d68..73aec7c55b 100644 --- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp @@ -124,6 +124,7 @@ private slots: void modify_through_delegate(); void bindingsOnGetResult(); void stringifyModelEntry(); + void qobjectTrackerForDynamicModelObjects(); }; bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object) @@ -1505,6 +1506,33 @@ void tst_qqmllistmodel::stringifyModelEntry() QCOMPARE(v.toString(), expectedString); } +void tst_qqmllistmodel::qobjectTrackerForDynamicModelObjects() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData( + "import QtQuick 2.0\n" + "Item {\n" + " ListModel {\n" + " id: testModel\n" + " objectName: \"testModel\"\n" + " ListElement { name: \"Joe\"; age: 22 }\n" + " }\n" + "}\n", QUrl()); + QScopedPointer<QObject> scene(component.create()); + QQmlListModel *model = scene->findChild<QQmlListModel*>("testModel"); + QQmlExpression expr(engine.rootContext(), model, "get(0);"); + QVariant v = expr.evaluate(); + QVERIFY2(!expr.hasError(), QTest::toString(expr.error().toString())); + + QObject *obj = v.value<QObject*>(); + QVERIFY(obj); + + QQmlData *ddata = QQmlData::get(obj, /*create*/false); + QVERIFY(ddata); + QVERIFY(!ddata->jsWrapper.isNullOrUndefined()); +} + QTEST_MAIN(tst_qqmllistmodel) #include "tst_qqmllistmodel.moc" diff --git a/tests/auto/quick/qquickimage/data/pattern.pkm b/tests/auto/quick/qquickimage/data/pattern.pkm Binary files differnew file mode 100644 index 0000000000..d986e89b2d --- /dev/null +++ b/tests/auto/quick/qquickimage/data/pattern.pkm diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp index 256e667980..f458bdcf5b 100644 --- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp +++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp @@ -152,6 +152,14 @@ void tst_qquickimage::imageSource_data() QTest::newRow("remote svgz") << "/heart.svgz" << 595.0 << 841.0 << true << false << false << ""; QTest::newRow("remote not found") << "/no-such-file.png" << 0.0 << 0.0 << true << false << true << "<Unknown File>:2:1: QML Image: Error transferring {{ServerBaseUrl}}/no-such-file.png - server replied: Not found"; + QTest::newRow("extless") << testFileUrl("colors").toString() << 120.0 << 120.0 << false << false << true << ""; + QTest::newRow("extless no cache") << testFileUrl("colors").toString() << 120.0 << 120.0 << false << false << false << ""; + QTest::newRow("extless async") << testFileUrl("colors1").toString() << 120.0 << 120.0 << false << true << true << ""; + QTest::newRow("extless not found") << testFileUrl("no-such-file").toString() << 0.0 << 0.0 << false + << false << true << "<Unknown File>:2:1: QML Image: Cannot open: " + testFileUrl("no-such-file").toString(); + // Test that pkm is preferred over png. As pattern.pkm has different size than pattern.png, these tests verify that the right file has been loaded + QTest::newRow("extless prefer-tex") << testFileUrl("pattern").toString() << 64.0 << 64.0 << false << false << true << ""; + QTest::newRow("extless prefer-tex async") << testFileUrl("pattern").toString() << 64.0 << 64.0 << false << true << true << ""; } |