Route ShaderEffect through the old GL impl

Register the common QQuickShaderEffect class as ShaderEffect to QML.
In case of GL this will route to QQuickOpenGLShaderEffect. For others
the default no-op implementation is used (at least for now). Later this
new implementation will route to a backend-specific scenegraph node via
the adaptation layer.

This also means that QQuickOpenGLShaderEffect is no longer a QQuickItem
and QQuickShaderEffect must handle everything item-related and forward.

Change-Id: I1ff4b674253543a04978a69f4a3b67f3a44dd983
Reviewed-by: Andy Nichols <andy.nichols@theqtcompany.com>
This commit is contained in:
Laszlo Agocs 2016-04-11 16:06:39 +02:00
parent e188a3d864
commit 96a7afec18
12 changed files with 257 additions and 92 deletions

View File

@ -75,12 +75,12 @@
#include <QtQuick/private/qquickcontext2d_p.h>
#ifndef QT_NO_OPENGL
# include "qquickitemgrabresult.h"
# include <private/qquickopenglshadereffect_p.h>
# include "qquicksprite_p.h"
# include "qquickspritesequence_p.h"
# include "qquickanimatedsprite_p.h"
# include "qquickopenglinfo_p.h"
#endif
#include "qquickshadereffect_p.h"
#include "qquickshadereffectmesh_p.h"
#include "qquickdrag_p.h"
#include "qquickdroparea_p.h"
@ -214,9 +214,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickShaderEffectSource>("QtQuick", 2, 0, "ShaderEffectSource");
qmlRegisterUncreatableType<QQuickShaderEffectMesh>("QtQuick", 2, 0, "ShaderEffectMesh", QQuickShaderEffectMesh::tr("Cannot create instance of abstract class ShaderEffectMesh."));
qmlRegisterType<QQuickGridMesh>("QtQuick", 2, 0, "GridMesh");
#ifndef QT_NO_OPENGL
qmlRegisterType<QQuickOpenGLShaderEffect>("QtQuick", 2, 0, "ShaderEffect");
#endif
qmlRegisterType<QQuickShaderEffect>("QtQuick", 2, 0, "ShaderEffect");
qmlRegisterUncreatableType<QQuickPaintedItem>("QtQuick", 2, 0, "PaintedItem", QQuickPaintedItem::tr("Cannot create instance of abstract class PaintedItem"));
@ -267,8 +265,9 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QQuickItem, 2>(uri, 2, 4, "Item");
qmlRegisterType<QQuickListView, 2>(uri, 2, 4, "ListView");
qmlRegisterType<QQuickMouseArea, 1>(uri, 2, 4, "MouseArea");
qmlRegisterType<QQuickShaderEffect, 1>(uri, 2, 4, "ShaderEffect");
#ifndef QT_NO_OPENGL
qmlRegisterType<QQuickOpenGLShaderEffect, 1>(uri, 2, 4, "ShaderEffect");
qmlRegisterUncreatableType<QQuickOpenGLInfo>(uri, 2, 4,"OpenGLInfo", QQuickOpenGLInfo::tr("OpenGLInfo is only available via attached properties"));
#endif
qmlRegisterType<QQuickPinchArea, 1>(uri, 2, 5,"PinchArea");

View File

@ -523,12 +523,13 @@ void QQuickOpenGLShaderEffectCommon::propertyChanged(QQuickItem *item, int mappe
}
}
QQuickOpenGLShaderEffect::QQuickOpenGLShaderEffect(QQuickItem *parent)
: QQuickItem(parent)
QQuickOpenGLShaderEffect::QQuickOpenGLShaderEffect(QQuickShaderEffect *item, QObject *parent)
: QObject(parent)
, m_item(item)
, m_meshResolution(1, 1)
, m_mesh(0)
, m_cullMode(NoCulling)
, m_status(Uncompiled)
, m_cullMode(QQuickShaderEffect::NoCulling)
, m_status(QQuickShaderEffect::Uncompiled)
, m_blending(true)
, m_dirtyUniforms(true)
, m_dirtyUniformValues(true)
@ -540,13 +541,12 @@ QQuickOpenGLShaderEffect::QQuickOpenGLShaderEffect(QQuickItem *parent)
, m_customVertexShader(false)
, m_supportsAtlasTextures(false)
{
setFlag(QQuickItem::ItemHasContents);
}
QQuickOpenGLShaderEffect::~QQuickOpenGLShaderEffect()
{
for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType)
m_common.disconnectPropertySignals(this, Key::ShaderType(shaderType));
m_common.disconnectPropertySignals(m_item, Key::ShaderType(shaderType));
}
void QQuickOpenGLShaderEffect::setFragmentShader(const QByteArray &code)
@ -557,12 +557,12 @@ void QQuickOpenGLShaderEffect::setFragmentShader(const QByteArray &code)
m_dirtyProgram = true;
m_dirtyParseLog = true;
if (isComponentComplete())
m_common.updateShader(this, Key::FragmentShader);
if (m_item->isComponentComplete())
m_common.updateShader(m_item, Key::FragmentShader);
update();
if (m_status != Uncompiled) {
m_status = Uncompiled;
m_item->update();
if (m_status != QQuickShaderEffect::Uncompiled) {
m_status = QQuickShaderEffect::Uncompiled;
emit statusChanged();
}
emit fragmentShaderChanged();
@ -577,12 +577,12 @@ void QQuickOpenGLShaderEffect::setVertexShader(const QByteArray &code)
m_dirtyParseLog = true;
m_customVertexShader = true;
if (isComponentComplete())
m_common.updateShader(this, Key::VertexShader);
if (m_item->isComponentComplete())
m_common.updateShader(m_item, Key::VertexShader);
update();
if (m_status != Uncompiled) {
m_status = Uncompiled;
m_item->update();
if (m_status != QQuickShaderEffect::Uncompiled) {
m_status = QQuickShaderEffect::Uncompiled;
emit statusChanged();
}
emit vertexShaderChanged();
@ -594,7 +594,7 @@ void QQuickOpenGLShaderEffect::setBlending(bool enable)
return;
m_blending = enable;
update();
m_item->update();
emit blendingChanged();
}
@ -637,16 +637,16 @@ void QQuickOpenGLShaderEffect::setMesh(const QVariant &mesh)
m_dirtyMesh = true;
m_dirtyParseLog = true;
update();
m_item->update();
emit meshChanged();
}
void QQuickOpenGLShaderEffect::setCullMode(CullMode face)
void QQuickOpenGLShaderEffect::setCullMode(QQuickShaderEffect::CullMode face)
{
if (face == m_cullMode)
return;
m_cullMode = face;
update();
m_item->update();
emit cullModeChanged();
}
@ -668,7 +668,7 @@ QString QQuickOpenGLShaderEffect::parseLog()
return m_common.parseLog;
}
bool QQuickOpenGLShaderEffect::event(QEvent *event)
void QQuickOpenGLShaderEffect::handleEvent(QEvent *event)
{
if (event->type() == QEvent::DynamicPropertyChange) {
QDynamicPropertyChangeEvent *e = static_cast<QDynamicPropertyChangeEvent *>(event);
@ -676,21 +676,20 @@ bool QQuickOpenGLShaderEffect::event(QEvent *event)
for (int i = 0; i < m_common.uniformData[shaderType].size(); ++i) {
if (m_common.uniformData[shaderType].at(i).name == e->propertyName()) {
bool textureProviderChanged;
m_common.propertyChanged(this, (shaderType << 16) | i, &textureProviderChanged);
m_common.propertyChanged(m_item, (shaderType << 16) | i, &textureProviderChanged);
m_dirtyTextureProviders |= textureProviderChanged;
m_dirtyUniformValues = true;
update();
m_item->update();
}
}
}
}
return QQuickItem::event(event);
}
void QQuickOpenGLShaderEffect::updateGeometry()
{
m_dirtyGeometry = true;
update();
m_item->update();
}
void QQuickOpenGLShaderEffect::updateGeometryIfAtlased()
@ -702,38 +701,36 @@ void QQuickOpenGLShaderEffect::updateGeometryIfAtlased()
void QQuickOpenGLShaderEffect::updateLogAndStatus(const QString &log, int status)
{
m_log = parseLog() + log;
m_status = Status(status);
m_status = QQuickShaderEffect::Status(status);
emit logChanged();
emit statusChanged();
}
void QQuickOpenGLShaderEffect::sourceDestroyed(QObject *object)
void QQuickOpenGLShaderEffect::handleSourceDestroyed(QObject *object)
{
m_common.sourceDestroyed(object);
}
void QQuickOpenGLShaderEffect::propertyChanged(int mappedId)
void QQuickOpenGLShaderEffect::handlePropertyChanged(int mappedId)
{
bool textureProviderChanged;
m_common.propertyChanged(this, mappedId, &textureProviderChanged);
m_common.propertyChanged(m_item, mappedId, &textureProviderChanged);
m_dirtyTextureProviders |= textureProviderChanged;
m_dirtyUniformValues = true;
update();
m_item->update();
}
void QQuickOpenGLShaderEffect::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
void QQuickOpenGLShaderEffect::handleGeometryChanged(const QRectF &, const QRectF &)
{
m_dirtyGeometry = true;
QQuickItem::geometryChanged(newGeometry, oldGeometry);
}
QSGNode *QQuickOpenGLShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
QSGNode *QQuickOpenGLShaderEffect::handleUpdatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
QQuickOpenGLShaderEffectNode *node = static_cast<QQuickOpenGLShaderEffectNode *>(oldNode);
// In the case of zero-size or a bad vertex shader, don't try to create a node...
if (m_common.attributes.isEmpty() || width() <= 0 || height() <= 0) {
if (m_common.attributes.isEmpty() || m_item->width() <= 0 || m_item->height() <= 0) {
if (node)
delete node;
return 0;
@ -821,7 +818,7 @@ QSGNode *QQuickOpenGLShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaint
if (m_dirtyGeometry) {
node->setFlag(QSGNode::OwnsGeometry, false);
QSGGeometry *geometry = node->geometry();
QRectF rect(0, 0, width(), height());
QRectF rect(0, 0, m_item->width(), m_item->height());
QQuickShaderEffectMesh *mesh = m_mesh ? m_mesh : &m_defaultMesh;
geometry = mesh->updateGeometry(geometry, m_common.attributes, srcRect, rect);
@ -831,7 +828,7 @@ QSGNode *QQuickOpenGLShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaint
m_log = parseLog();
m_log += QLatin1String("*** Mesh ***\n");
m_log += log;
m_status = Error;
m_status = QQuickShaderEffect::Error;
emit logChanged();
emit statusChanged();
}
@ -848,18 +845,16 @@ QSGNode *QQuickOpenGLShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaint
return node;
}
void QQuickOpenGLShaderEffect::componentComplete()
void QQuickOpenGLShaderEffect::handleComponentComplete()
{
m_common.updateShader(this, Key::VertexShader);
m_common.updateShader(this, Key::FragmentShader);
QQuickItem::componentComplete();
m_common.updateShader(m_item, Key::VertexShader);
m_common.updateShader(m_item, Key::FragmentShader);
}
void QQuickOpenGLShaderEffect::itemChange(ItemChange change, const ItemChangeData &value)
void QQuickOpenGLShaderEffect::handleItemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
{
if (change == QQuickItem::ItemSceneChange)
m_common.updateWindow(value.window);
QQuickItem::itemChange(change, value);
}
QT_END_NAMESPACE

View File

@ -96,36 +96,12 @@ struct Q_QUICK_PRIVATE_EXPORT QQuickOpenGLShaderEffectCommon
};
class Q_QUICK_PRIVATE_EXPORT QQuickOpenGLShaderEffect : public QQuickItem
class Q_QUICK_PRIVATE_EXPORT QQuickOpenGLShaderEffect : public QObject
{
Q_OBJECT
Q_PROPERTY(QByteArray fragmentShader READ fragmentShader WRITE setFragmentShader NOTIFY fragmentShaderChanged)
Q_PROPERTY(QByteArray vertexShader READ vertexShader WRITE setVertexShader NOTIFY vertexShaderChanged)
Q_PROPERTY(bool blending READ blending WRITE setBlending NOTIFY blendingChanged)
Q_PROPERTY(QVariant mesh READ mesh WRITE setMesh NOTIFY meshChanged)
Q_PROPERTY(CullMode cullMode READ cullMode WRITE setCullMode NOTIFY cullModeChanged)
Q_PROPERTY(QString log READ log NOTIFY logChanged)
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(bool supportsAtlasTextures READ supportsAtlasTextures WRITE setSupportsAtlasTextures NOTIFY supportsAtlasTexturesChanged REVISION 1)
public:
enum CullMode
{
NoCulling = QQuickShaderEffect::NoCulling,
BackFaceCulling = QQuickShaderEffect::BackFaceCulling,
FrontFaceCulling = QQuickShaderEffect::FrontFaceCulling
};
Q_ENUM(CullMode)
enum Status
{
Compiled,
Uncompiled,
Error
};
Q_ENUM(Status)
QQuickOpenGLShaderEffect(QQuickItem *parent = 0);
QQuickOpenGLShaderEffect(QQuickShaderEffect *item, QObject *parent = 0);
~QQuickOpenGLShaderEffect();
QByteArray fragmentShader() const { return m_common.source.sourceCode[Key::FragmentShader]; }
@ -140,19 +116,17 @@ public:
QVariant mesh() const;
void setMesh(const QVariant &mesh);
CullMode cullMode() const { return m_cullMode; }
void setCullMode(CullMode face);
QQuickShaderEffect::CullMode cullMode() const { return m_cullMode; }
void setCullMode(QQuickShaderEffect::CullMode face);
QString log() const { return m_log; }
Status status() const { return m_status; }
QQuickShaderEffect::Status status() const { return m_status; }
bool supportsAtlasTextures() const { return m_supportsAtlasTextures; }
void setSupportsAtlasTextures(bool supports);
QString parseLog();
bool event(QEvent *) Q_DECL_OVERRIDE;
Q_SIGNALS:
void fragmentShaderChanged();
void vertexShaderChanged();
@ -164,17 +138,18 @@ Q_SIGNALS:
void supportsAtlasTexturesChanged();
protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
void componentComplete() Q_DECL_OVERRIDE;
void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
void handleEvent(QEvent *);
void handleGeometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
QSGNode *handleUpdatePaintNode(QSGNode *, QQuickItem::UpdatePaintNodeData *);
void handleComponentComplete();
void handleItemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value);
void handleSourceDestroyed(QObject *object);
void handlePropertyChanged(int mappedId);
private Q_SLOTS:
void updateGeometry();
void updateGeometryIfAtlased();
void updateLogAndStatus(const QString &log, int status);
void sourceDestroyed(QObject *object);
void propertyChanged(int mappedId);
private:
friend class QQuickCustomMaterialShader;
@ -183,12 +158,13 @@ private:
typedef QQuickOpenGLShaderEffectMaterialKey Key;
typedef QQuickOpenGLShaderEffectMaterial::UniformData UniformData;
QQuickShaderEffect *m_item;
QSize m_meshResolution;
QQuickShaderEffectMesh *m_mesh;
QQuickGridMesh m_defaultMesh;
CullMode m_cullMode;
QQuickShaderEffect::CullMode m_cullMode;
QString m_log;
Status m_status;
QQuickShaderEffect::Status m_status;
QQuickOpenGLShaderEffectCommon m_common;
@ -202,6 +178,8 @@ private:
uint m_dirtyGeometry : 1;
uint m_customVertexShader : 1;
uint m_supportsAtlasTextures : 1;
friend class QQuickShaderEffect;
};
QT_END_NAMESPACE

View File

@ -111,8 +111,8 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
QQuickOpenGLShaderEffectMaterial *material = static_cast<QQuickOpenGLShaderEffectMaterial *>(newEffect);
if (!material->m_emittedLogChanged && material->m_node) {
material->m_emittedLogChanged = true;
emit material->m_node->logAndStatusChanged(m_log, m_compiled ? QQuickOpenGLShaderEffect::Compiled
: QQuickOpenGLShaderEffect::Error);
emit material->m_node->logAndStatusChanged(m_log, m_compiled ? QQuickShaderEffect::Compiled
: QQuickShaderEffect::Error);
}
int textureProviderIndex = 0;

View File

@ -38,6 +38,10 @@
****************************************************************************/
#include <private/qquickshadereffect_p.h>
#include <private/qsgcontextplugin_p.h>
#ifndef QT_NO_OPENGL
#include <private/qquickopenglshadereffect_p.h>
#endif
QT_BEGIN_NAMESPACE
@ -189,10 +193,19 @@ QT_BEGIN_NAMESPACE
\sa {Item Layers}
*/
QSGContextFactoryInterface::Flags qsg_backend_flags();
QQuickShaderEffect::QQuickShaderEffect(QQuickItem *parent)
: QQuickItem(parent)
{
setFlag(QQuickItem::ItemHasContents);
#ifndef QT_NO_OPENGL
if (!qsg_backend_flags().testFlag(QSGContextFactoryInterface::SupportsShaderEffectV2))
m_glImpl = new QQuickOpenGLShaderEffect(this, this);
else
m_glImpl = nullptr;
#endif
}
/*!
@ -206,11 +219,19 @@ QQuickShaderEffect::QQuickShaderEffect(QQuickItem *parent)
QByteArray QQuickShaderEffect::fragmentShader() const
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
return m_glImpl->fragmentShader();
#endif
return QByteArray();
}
void QQuickShaderEffect::setFragmentShader(const QByteArray &code)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->setFragmentShader(code);
#endif
Q_UNUSED(code);
}
@ -224,11 +245,19 @@ void QQuickShaderEffect::setFragmentShader(const QByteArray &code)
QByteArray QQuickShaderEffect::vertexShader() const
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
return m_glImpl->vertexShader();
#endif
return QByteArray();
}
void QQuickShaderEffect::setVertexShader(const QByteArray &code)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->setVertexShader(code);
#endif
Q_UNUSED(code);
}
@ -243,11 +272,19 @@ void QQuickShaderEffect::setVertexShader(const QByteArray &code)
bool QQuickShaderEffect::blending() const
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
return m_glImpl->blending();
#endif
return true;
}
void QQuickShaderEffect::setBlending(bool enable)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->setBlending(enable);
#endif
Q_UNUSED(enable);
}
@ -266,11 +303,19 @@ void QQuickShaderEffect::setBlending(bool enable)
QVariant QQuickShaderEffect::mesh() const
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
return m_glImpl->mesh();
#endif
return QVariant();
}
void QQuickShaderEffect::setMesh(const QVariant &mesh)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->setMesh(mesh);
#endif
Q_UNUSED(mesh);
}
@ -290,11 +335,19 @@ void QQuickShaderEffect::setMesh(const QVariant &mesh)
QQuickShaderEffect::CullMode QQuickShaderEffect::cullMode() const
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
return m_glImpl->cullMode();
#endif
return NoCulling;
}
void QQuickShaderEffect::setCullMode(CullMode face)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->setCullMode(face);
#endif
Q_UNUSED(face);
}
@ -321,11 +374,19 @@ void QQuickShaderEffect::setCullMode(CullMode face)
bool QQuickShaderEffect::supportsAtlasTextures() const
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
return m_glImpl->supportsAtlasTextures();
#endif
return false;
}
void QQuickShaderEffect::setSupportsAtlasTextures(bool supports)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->setSupportsAtlasTextures(supports);
#endif
Q_UNUSED(supports);
}
@ -359,12 +420,88 @@ void QQuickShaderEffect::setSupportsAtlasTextures(bool supports)
QString QQuickShaderEffect::log() const
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
return m_glImpl->log();
#endif
return QString();
}
QQuickShaderEffect::Status QQuickShaderEffect::status() const
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
return m_glImpl->status();
#endif
return Uncompiled;
}
bool QQuickShaderEffect::event(QEvent *e)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->handleEvent(e);
#endif
return QQuickItem::event(e);
}
void QQuickShaderEffect::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->handleGeometryChanged(newGeometry, oldGeometry);
#endif
QQuickItem::geometryChanged(newGeometry, oldGeometry);
}
QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
return m_glImpl->handleUpdatePaintNode(oldNode, updatePaintNodeData);
#endif
return nullptr;
}
void QQuickShaderEffect::componentComplete()
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->handleComponentComplete();
#endif
QQuickItem::componentComplete();
}
void QQuickShaderEffect::itemChange(ItemChange change, const ItemChangeData &value)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->handleItemChange(change, value);
#endif
QQuickItem::itemChange(change, value);
}
bool QQuickShaderEffect::isComponentComplete() const
{
return QQuickItem::isComponentComplete();
}
void QQuickShaderEffect::sourceDestroyed(QObject *object)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->handleSourceDestroyed(object);
#endif
Q_UNUSED(object);
}
void QQuickShaderEffect::propertyChanged(int mappedId)
{
#ifndef QT_NO_OPENGL
if (m_glImpl)
m_glImpl->handlePropertyChanged(mappedId);
#endif
Q_UNUSED(mappedId);
}
QT_END_NAMESPACE

View File

@ -56,6 +56,8 @@
QT_BEGIN_NAMESPACE
class QQuickOpenGLShaderEffect;
class Q_QUICK_PRIVATE_EXPORT QQuickShaderEffect : public QQuickItem
{
Q_OBJECT
@ -106,6 +108,8 @@ public:
QString log() const;
Status status() const;
bool isComponentComplete() const;
Q_SIGNALS:
void fragmentShaderChanged();
void vertexShaderChanged();
@ -115,6 +119,22 @@ Q_SIGNALS:
void logChanged();
void statusChanged();
void supportsAtlasTexturesChanged();
protected:
bool event(QEvent *e) override;
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) override;
void componentComplete() override;
void itemChange(ItemChange change, const ItemChangeData &value) override;
private Q_SLOTS:
void sourceDestroyed(QObject *object);
void propertyChanged(int mappedId);
private:
#ifndef QT_NO_OPENGL
QQuickOpenGLShaderEffect *m_glImpl;
#endif
};
QT_END_NAMESPACE

View File

@ -61,6 +61,11 @@ QSGContext *QSGD3D12Adaptation::create(const QString &) const
return contextInstance;
}
QSGContextFactoryInterface::Flags QSGD3D12Adaptation::flags(const QString &) const
{
return QSGContextFactoryInterface::SupportsShaderEffectV2;
}
QSGRenderLoop *QSGD3D12Adaptation::createWindowManager()
{
return new QSGD3D12RenderLoop;

View File

@ -66,6 +66,7 @@ public:
QStringList keys() const override;
QSGContext *create(const QString &key) const override;
QSGContextFactoryInterface::Flags flags(const QString &key) const override;
QSGRenderLoop *createWindowManager() override;
private:

View File

@ -63,6 +63,11 @@ QSGContext *QSGSoftwareAdaptation::create(const QString &) const
return instance;
}
QSGContextFactoryInterface::Flags QSGSoftwareAdaptation::flags(const QString &) const
{
return QSGContextFactoryInterface::SupportsShaderEffectV2;
}
QSGRenderLoop *QSGSoftwareAdaptation::createWindowManager()
{
return new QSGSoftwareRenderLoop();

View File

@ -55,6 +55,7 @@ public:
QStringList keys() const override;
QSGContext *create(const QString &key) const override;
QSGContextFactoryInterface::Flags flags(const QString &key) const override;
QSGRenderLoop *createWindowManager() override;
private:
static QSGSoftwareContext *instance;

View File

@ -77,13 +77,15 @@ struct QSGAdaptionBackendData
bool tried;
QSGContextFactoryInterface *factory;
QString name;
QSGContextFactoryInterface::Flags flags;
QVector<QSGContextFactoryInterface *> builtIns;
};
QSGAdaptionBackendData::QSGAdaptionBackendData()
: tried(false)
, factory(0)
, factory(nullptr)
, flags(0)
{
// Fill in the table with the built-in adaptations.
builtIns.append(new QSGSoftwareAdaptation);
@ -94,6 +96,16 @@ QSGAdaptionBackendData::QSGAdaptionBackendData()
Q_GLOBAL_STATIC(QSGAdaptionBackendData, qsg_adaptation_data)
// This only works when the backend is loaded (contextFactory() was called),
// otherwise the return value is 0.
//
// Note that the default (OpenGL) implementation always results in 0, custom flags
// can only be returned from the other (either compiled-in or plugin-based) backends.
QSGContextFactoryInterface::Flags qsg_backend_flags()
{
return qsg_adaptation_data()->flags;
}
QSGAdaptionBackendData *contextFactory()
{
QSGAdaptionBackendData *backendData = qsg_adaptation_data();
@ -136,6 +148,8 @@ QSGAdaptionBackendData *contextFactory()
for (QSGContextFactoryInterface *builtInBackend : qAsConst(backendData->builtIns)) {
if (builtInBackend->keys().contains(requestedBackend)) {
backendData->factory = builtInBackend;
backendData->name = requestedBackend;
backendData->flags = backendData->factory->flags(requestedBackend);
break;
}
}
@ -146,7 +160,10 @@ QSGAdaptionBackendData *contextFactory()
const int index = loader()->indexOf(requestedBackend);
if (index != -1)
backendData->factory = qobject_cast<QSGContextFactoryInterface*>(loader()->instance(index));
backendData->name = requestedBackend;
if (backendData->factory) {
backendData->name = requestedBackend;
backendData->flags = backendData->factory->flags(requestedBackend);
}
#ifndef QT_NO_DEBUG
if (!backendData->factory) {
qWarning("Could not create scene graph context for backend '%s'"

View File

@ -64,12 +64,20 @@ class QSGRenderLoop;
struct Q_QUICK_PRIVATE_EXPORT QSGContextFactoryInterface : public QFactoryInterface
{
enum Flag {
SupportsShaderEffectV2 = 0x01
};
Q_DECLARE_FLAGS(Flags, Flag)
virtual QSGContext *create(const QString &key) const = 0;
virtual Flags flags(const QString &key) const = 0;
virtual QQuickTextureFactory *createTextureFactoryFromImage(const QImage &image) = 0;
virtual QSGRenderLoop *createWindowManager() = 0;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QSGContextFactoryInterface::Flags)
#define QSGContextFactoryInterface_iid \
"org.qt-project.Qt.QSGContextFactoryInterface"
Q_DECLARE_INTERFACE(QSGContextFactoryInterface, QSGContextFactoryInterface_iid)
@ -83,7 +91,6 @@ public:
virtual ~QSGContextPlugin();
virtual QStringList keys() const = 0;
virtual QSGContext *create(const QString &key) const = 0;
virtual QQuickTextureFactory *createTextureFactoryFromImage(const QImage &) { return 0; }
virtual QSGRenderLoop *createWindowManager() { return 0; }