diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2016-06-27 17:13:37 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2016-06-29 11:59:54 +0000 |
commit | 5ee02242d72ac9a536584b36ba549480a97303f7 (patch) | |
tree | c898b2eedad203ee0536d7b40cab6c1c08234056 /src/quick/items/qquickgenericshadereffect.cpp | |
parent | 12bff27aa6f1caac9bfacf365c542cf5da6e3148 (diff) |
Unify ShaderEffect property setting
rendererInterface() should not require isSceneGraphInitialized() to be
true - the API and language queries like graphicsApi() have no need for the
scenegraph, they only need the plugin to be loaded, i.e. that the QQuickWindow
is constructed.
This is the key to be able to make GraphicsInfo report graphicsApi and
shaderType with the correct values as early as possible - meaning as soon
as the item is associated with a window. The initialization of the
scenegraph (the exact timing of which varies backend to backend) does not
matter here.
The fragment and vertex shader property setting is now unified in the two
ShaderEffect implementations:
- If the component is complete, the shader is attempted to be processed
right from the setter.
- Otherwise the item will trigger processing once the component is
complete.
- If there is no window when processing is trigerred, it is deferred via
polish.
To implement item polish handling we need a new virtual in
QQuickItemPrivate since we cannot intrdouce virtuals into the public
classes.
This way one can write a condition (and later potentially use file
selectors) like this:
fragmentShader: GraphicsInfo.shaderType == GraphicsInfo.GLSL ? "..." : ...
without having to worry about getting an unintended value processed due to
GraphicsInfo not yet reporting an up-to-date value.
parseLog() forces, for GL at least, shader processing to prevent autotests
from breaking.
Change-Id: If55c69d746c29cd07348ddad2d6b0f2b5dd7f3a2
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/quick/items/qquickgenericshadereffect.cpp')
-rw-r--r-- | src/quick/items/qquickgenericshadereffect.cpp | 65 |
1 files changed, 28 insertions, 37 deletions
diff --git a/src/quick/items/qquickgenericshadereffect.cpp b/src/quick/items/qquickgenericshadereffect.cpp index 11259a588a..683453d4ee 100644 --- a/src/quick/items/qquickgenericshadereffect.cpp +++ b/src/quick/items/qquickgenericshadereffect.cpp @@ -59,10 +59,11 @@ QQuickGenericShaderEffect::QQuickGenericShaderEffect(QQuickShaderEffect *item, Q , m_blending(true) , m_supportsAtlasTextures(false) , m_mgr(nullptr) + , m_fragNeedsUpdate(true) + , m_vertNeedsUpdate(true) , m_dirty(0) { qRegisterMetaType<QSGGuiThreadShaderEffectManager::ShaderInfo::Type>("ShaderInfo::Type"); - connect(m_item, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(itemWindowChanged(QQuickWindow*))); for (int i = 0; i < NShader; ++i) m_inProgress[i] = nullptr; } @@ -88,12 +89,11 @@ void QQuickGenericShaderEffect::setFragmentShader(const QByteArray &src) return; m_fragShader = src; - m_dirty |= QSGShaderEffectNode::DirtyShaders; + m_fragNeedsUpdate = true; if (m_item->isComponentComplete()) - updateShader(Fragment, src); + maybeUpdateShaders(); - m_item->update(); emit m_item->fragmentShaderChanged(); } @@ -103,12 +103,11 @@ void QQuickGenericShaderEffect::setVertexShader(const QByteArray &src) return; m_vertShader = src; - m_dirty |= QSGShaderEffectNode::DirtyShaders; + m_vertNeedsUpdate = true; if (m_item->isComponentComplete()) - updateShader(Vertex, src); + maybeUpdateShaders(); - m_item->update(); emit m_item->vertexShaderChanged(); } @@ -187,6 +186,12 @@ void QQuickGenericShaderEffect::setSupportsAtlasTextures(bool supports) emit m_item->supportsAtlasTexturesChanged(); } +QString QQuickGenericShaderEffect::parseLog() +{ + maybeUpdateShaders(); + return log(); +} + QString QQuickGenericShaderEffect::log() const { QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); @@ -294,10 +299,14 @@ QSGNode *QQuickGenericShaderEffect::handleUpdatePaintNode(QSGNode *oldNode, QQui return node; } -void QQuickGenericShaderEffect::handleComponentComplete() +void QQuickGenericShaderEffect::maybeUpdateShaders() { - updateShader(Vertex, m_vertShader); - updateShader(Fragment, m_fragShader); + if (m_vertNeedsUpdate) + m_vertNeedsUpdate = !updateShader(Vertex, m_vertShader); + if (m_fragNeedsUpdate) + m_fragNeedsUpdate = !updateShader(Fragment, m_fragShader); + if (m_vertNeedsUpdate || m_fragNeedsUpdate) + m_item->polish(); } void QQuickGenericShaderEffect::handleItemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) @@ -326,9 +335,8 @@ QSGGuiThreadShaderEffectManager *QQuickGenericShaderEffect::shaderEffectManager( // return null if this is not the gui thread and not already created if (QThread::currentThread() != m_item->thread()) return m_mgr; - // need a window and a rendercontext (i.e. the scenegraph backend is ready) QQuickWindow *w = m_item->window(); - if (w && w->isSceneGraphInitialized()) { + if (w) { // note: just the window, don't care about isSceneGraphInitialized() here m_mgr = QQuickWindowPrivate::get(w)->context->sceneGraphContext()->createGuiThreadShaderEffectManager(); if (m_mgr) { connect(m_mgr, SIGNAL(logAndStatusChanged()), m_item, SIGNAL(logChanged())); @@ -336,34 +344,12 @@ QSGGuiThreadShaderEffectManager *QQuickGenericShaderEffect::shaderEffectManager( connect(m_mgr, SIGNAL(textureChanged()), this, SLOT(markGeometryDirtyAndUpdateIfSupportsAtlas())); connect(m_mgr, &QSGGuiThreadShaderEffectManager::shaderCodePrepared, this, &QQuickGenericShaderEffect::shaderCodePrepared); } - } else if (!w) { - // Wait until itemWindowChanged() gets called. Return null for now. - } else { - // Have window, but no scenegraph -> ensure the signal is connected. Return null for now. - const_cast<QQuickGenericShaderEffect *>(this)->itemWindowChanged(w); } } return m_mgr; } -void QQuickGenericShaderEffect::itemWindowChanged(QQuickWindow *w) -{ - if (w) { - if (w->isSceneGraphInitialized()) - backendChanged(); - else - connect(w, SIGNAL(sceneGraphInitialized()), this, SLOT(backendChanged()), Qt::UniqueConnection); - } -} - -void QQuickGenericShaderEffect::backendChanged() -{ - disconnect(m_item->window(), SIGNAL(sceneGraphInitialized()), this, SLOT(backendChanged())); - emit m_item->logChanged(); - emit m_item->statusChanged(); -} - void QQuickGenericShaderEffect::disconnectSignals(Shader shaderType) { for (auto &sm : m_signalMappers[shaderType]) { @@ -407,11 +393,11 @@ struct ShaderInfoCache Q_GLOBAL_STATIC(ShaderInfoCache, shaderInfoCache) -void QQuickGenericShaderEffect::updateShader(Shader shaderType, const QByteArray &src) +bool QQuickGenericShaderEffect::updateShader(Shader shaderType, const QByteArray &src) { QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); if (!mgr) - return; + return false; const bool texturesSeparate = mgr->hasSeparateSamplerAndTextureObjects(); @@ -439,7 +425,7 @@ void QQuickGenericShaderEffect::updateShader(Shader shaderType, const QByteArray // source->bytecode compilation as well in this step. mgr->prepareShaderCode(typeHint, src, m_inProgress[shaderType]); // the rest is handled in shaderCodePrepared() - return; + return true; } } else { m_shaders[shaderType].hasShaderCode = false; @@ -459,6 +445,9 @@ void QQuickGenericShaderEffect::updateShader(Shader shaderType, const QByteArray } updateShaderVars(shaderType); + m_dirty |= QSGShaderEffectNode::DirtyShaders; + m_item->update(); + return true; } void QQuickGenericShaderEffect::shaderCodePrepared(bool ok, QSGGuiThreadShaderEffectManager::ShaderInfo::Type typeHint, @@ -486,6 +475,8 @@ void QQuickGenericShaderEffect::shaderCodePrepared(bool ok, QSGGuiThreadShaderEf m_shaders[shaderType].hasShaderCode = true; shaderInfoCache()->insert(src, m_shaders[shaderType].shaderInfo); updateShaderVars(shaderType); + m_dirty |= QSGShaderEffectNode::DirtyShaders; + m_item->update(); } void QQuickGenericShaderEffect::updateShaderVars(Shader shaderType) |