{
Q_D(const QSGImage);
if (!d->provider) {
- Q_ASSERT(d->sceneGraphContext());
// Make sure it gets thread affinity on the rendering thread so deletion works properly..
- Q_ASSERT_X(QThread::currentThread() == d->sceneGraphContext()->thread(),
+ Q_ASSERT_X(d->canvas
+ && d->sceneGraphContext()
+ && QThread::currentThread() == d->sceneGraphContext()->thread(),
"QSGImage::textureProvider",
"Cannot be used outside the GUI thread");
const_cast<QSGImagePrivate *>(d)->provider = new QSGImageTextureProvider(this);
VAlignment verticalAlignment() const;
void setVerticalAlignment(VAlignment align);
+ bool isTextureProvider() const { return true; }
QSGTextureProvider *textureProvider() const;
Q_SIGNALS:
return ((QElapsedTimerConsistentTimeHack*)&t)->restart();
}
+/*!
+ \fn bool QSGItem::isTextureProvider() const
+
+ Returns true if this item is a texture provider. The default
+ implementation returns false.
+
+ This function can be called from any thread.
+ */
+
+/*!
+ \fn QSGTextureProvider *QSGItem::textureProvider() const
+
+ Returns the texture provider for an item. The default implementation
+ returns 0.
+
+ This function may only be called on the rendering thread.
+ */
+
QT_END_NAMESPACE
#include <moc_qsgitem.cpp>
class QTouchEvent;
class QSGNode;
class QSGTransformNode;
+class QSGTextureProvider;
+
class Q_DECLARATIVE_EXPORT QSGItem : public QObject, public QDeclarativeParserStatus
{
Q_OBJECT
UpdatePaintNodeData();
};
+ virtual bool isTextureProvider() const { return false; }
+ virtual QSGTextureProvider *textureProvider() const { return 0; }
+
public Q_SLOTS:
void update();
void updateMicroFocus();
}
QObject *obj = qVariantValue<QObject *>(var);
- if (!QSGTextureProvider::from(obj)) {
+ QSGItem *item = qobject_cast<QSGItem *>(obj);
+ if (!item || !item->isTextureProvider()) {
qWarning("ShaderEffect: source uniform [%s] is not assigned a valid texture provider: %s [%s]",
qPrintable(source.name), qPrintable(obj->objectName()), obj->metaObject()->className());
return;
}
- source.sourceObject = obj;
+ source.sourceObject = item;
- QSGItem *item = qobject_cast<QSGItem *>(obj);
// TODO: Find better solution.
// 'item' needs a canvas to get a scenegraph node.
}
for (int i = 0; i < m_sources.size(); ++i) {
const SourceData &source = m_sources.at(i);
- QSGTextureProvider *t = QSGTextureProvider::from(source.sourceObject);
+ QSGTextureProvider *t = source.sourceObject->textureProvider();
textures.append(qMakePair(source.name, t));
if (t)
connect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()), Qt::DirectConnection);
struct SourceData
{
QSignalMapper *mapper;
- QPointer<QObject> sourceObject;
+ QPointer<QSGItem> sourceObject;
QByteArray name;
};
QVector<SourceData> m_sources;
QSGTextureProvider *QSGShaderEffectSource::textureProvider() const
{
if (!m_provider) {
- Q_ASSERT(QSGItemPrivate::get(this)->sceneGraphContext());
// Make sure it gets thread affinity on the rendering thread so deletion works properly..
- Q_ASSERT_X(QThread::currentThread() == QSGItemPrivate::get(this)->sceneGraphContext()->thread(),
+ Q_ASSERT_X(QSGItemPrivate::get(this)->canvas
+ && QSGItemPrivate::get(this)->sceneGraphContext()
+ && QThread::currentThread() == QSGItemPrivate::get(this)->sceneGraphContext()->thread(),
"QSGShaderEffectSource::textureProvider",
"Cannot be used outside the GUI thread");
const_cast<QSGShaderEffectSource *>(this)->m_provider = new QSGShaderEffectSourceTextureProvider();
bool recursive() const;
void setRecursive(bool enabled);
+ bool isTextureProvider() const { return true; }
QSGTextureProvider *textureProvider() const;
Q_INVOKABLE void scheduleUpdate();
: QSGParticlePainter(parent)
, m_pleaseReset(true)
, m_dirtyData(true)
+ , m_material(0)
, m_rootNode(0)
{
setFlag(QSGItem::ItemHasContents);
}
+class QSGShaderEffectMaterialObject : public QObject, public QSGShaderEffectMaterial { };
+
+QSGCustomParticle::~QSGCustomParticle()
+{
+ if (m_material)
+ m_material->deleteLater();
+}
+
void QSGCustomParticle::componentComplete()
{
reset();
}
QObject *obj = qVariantValue<QObject *>(var);
-
- QSGTextureProvider *int3rface = QSGTextureProvider::from(obj);
- if (!int3rface) {
- qWarning("Could not assign property '%s', did not implement QSGTextureProvider.", source.name.constData());
- }
-
source.item = qobject_cast<QSGItem *>(obj);
+ if (!source.item || !source.item->isTextureProvider()) {
+ qWarning("ShaderEffect: source uniform [%s] is not assigned a valid texture provider: %s [%s]",
+ qPrintable(source.name), qPrintable(obj->objectName()), obj->metaObject()->className());
+ return;
+ }
// TODO: Copy better solution in QSGShaderEffect when they find it.
// 'source.item' needs a canvas to get a scenegraph node.
s.fragmentCode = qt_particles_default_fragment_code;
if (s.vertexCode.isEmpty())
s.vertexCode = qt_particles_default_vertex_code;
- m_material.setProgramSource(s);
+
+ if (!m_material) {
+ m_material = new QSGShaderEffectMaterialObject;
+ }
+
+ m_material->setProgramSource(s);
foreach (const QString &str, m_particles){
int gIdx = m_system->m_groupIds[str];
int count = m_system->m_groupData[gIdx]->size();
QSGShaderEffectNode* node = new QSGShaderEffectNode();
node->setGeometry(g);
- node->setMaterial(&m_material);
+ node->setMaterial(m_material);
node->markDirty(QSGNode::DirtyMaterial);
m_nodes.insert(gIdx, node);
return;
QVector<QPair<QByteArray, QVariant> > values;
QVector<QPair<QByteArray, QSGTextureProvider *> > textures;
- const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = m_material.textureProviders();
+ const QVector<QPair<QByteArray, QSGTextureProvider *> > &oldTextures = m_material->textureProviders();
for (int i = 0; i < oldTextures.size(); ++i) {
QSGTextureProvider *t = oldTextures.at(i).second;
if (t)
}
for (int i = 0; i < m_sources.size(); ++i) {
const SourceData &source = m_sources.at(i);
- QSGTextureProvider *t = QSGTextureProvider::from(source.item);
+ QSGTextureProvider *t = source.item->textureProvider();
textures.append(qMakePair(source.name, t));
if (t)
foreach (QSGShaderEffectNode* node, m_nodes)
values.append(qMakePair(*it, property(*it)));
}
values.append(qMakePair(timestampName, QVariant(m_lastTime)));
- m_material.setUniforms(values);
- m_material.setTextureProviders(textures);
+ m_material->setUniforms(values);
+ m_material->setTextureProviders(textures);
m_dirtyData = false;
foreach (QSGShaderEffectNode* node, m_nodes)
node->markDirty(QSGNode::DirtyMaterial);
class QSGNode;
struct PlainVertices;
+
+class QSGShaderEffectMaterialObject;
+
//Genealogy: Hybrid of UltraParticle and ShaderEffect
class QSGCustomParticle : public QSGParticlePainter
{
public:
explicit QSGCustomParticle(QSGItem* parent=0);
+ ~QSGCustomParticle();
QByteArray fragmentShader() const { return m_source.fragmentCode; }
void setFragmentShader(const QByteArray &code);
QByteArray name;
};
QVector<SourceData> m_sources;
- QSGShaderEffectMaterial m_material;
+ QSGShaderEffectMaterialObject *m_material;
QSGShaderEffectNode* m_rootNode;
QHash<int, QSGShaderEffectNode*> m_nodes;
qreal m_lastTime;
*/
-/*!
- Convenience function for casting a QObject to a QSGTextureProvider
- */
-QSGTextureProvider *QSGTextureProvider::from(QObject *object)
-{
- if (QSGImage *image = qobject_cast<QSGImage*>(object))
- return image->textureProvider();
- else if (QSGShaderEffectSource *source = qobject_cast<QSGShaderEffectSource *>(object))
- return source->textureProvider();
- else if (QSGTextureProvider *provider = qobject_cast<QSGTextureProvider *>(object))
- return provider;
-
- qDebug() << "QSGTextureProvider::from() not a texture provider" << object;
- return 0;
-}
-
QT_END_NAMESPACE
public:
virtual QSGTexture *texture() const = 0;
- static QSGTextureProvider *from(QObject *object);
-
Q_SIGNALS:
void textureChanged();
};