Example #1
0
/*!
 * Copies command data to execute queue. GUI thread must be locked when this
 * method is called.
 */
void CanvasGlCommandQueue::transferCommands(QVector<GlCommand> &executeQueue)
{
    memcpy(executeQueue.data(), m_queue.data(), m_queuedCount * sizeof(GlCommand));

    m_queuedCount = 0;

    // Grab texture providers from quick items and cache them
    const int quickItemCount = m_quickItemsAsTextureList.size();
    if (quickItemCount) {
        for (int i = 0; i < quickItemCount; i++) {
            const ItemAndId *itemAndId = m_quickItemsAsTextureList.at(i);
            if (!itemAndId->itemPtr.isNull()) {
                QQuickItem *quickItem = itemAndId->itemPtr.data();
                QSGTextureProvider *texProvider = quickItem->textureProvider();
                if (texProvider) {
                    // Make sure the old provider, if any, gets cleared up before inserting a new one
                    delete m_providerCache.take(itemAndId->id);
                    m_providerCache.insert(itemAndId->id,
                                           new ProviderCacheItem(texProvider, quickItem));
                    // Reset the mapped glId so it gets resolved at render time
                    setGlIdToMap(itemAndId->id, 0,
                                 CanvasGlCommandQueue::internalClearQuickItemAsTexture);
                } else {
                    qCWarning(canvas3drendering).nospace() << "CanvasGlCommandQueue::"
                                                           << __FUNCTION__
                                                           << ": The Quick item doesn't implement a texture provider: "
                                                           << quickItem;
                }
            }
        }
        clearQuickItemAsTextureList();
    }
}
void QQuickShaderEffectCommon::updateMaterial(QQuickShaderEffectNode *node,
                                              QQuickShaderEffectMaterial *material,
                                              bool updateUniforms, bool updateUniformValues,
                                              bool updateTextureProviders)
{
    if (updateUniforms) {
        for (int i = 0; i < material->textureProviders.size(); ++i) {
            QSGTextureProvider *t = material->textureProviders.at(i);
            if (t) {
                QObject::disconnect(t, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
                QObject::disconnect(t, SIGNAL(destroyed(QObject*)), node, SLOT(textureProviderDestroyed(QObject*)));
            }
        }

        // First make room in the textureProviders array. Set to proper value further down.
        int textureProviderCount = 0;
        for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
            for (int i = 0; i < uniformData[shaderType].size(); ++i) {
                if (uniformData[shaderType].at(i).specialType == UniformData::Sampler)
                    ++textureProviderCount;
            }
            material->uniforms[shaderType] = uniformData[shaderType];
        }
        material->textureProviders.fill(0, textureProviderCount);
        updateUniformValues = false;
        updateTextureProviders = true;
    }

    if (updateUniformValues) {
        for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
            Q_ASSERT(uniformData[shaderType].size() == material->uniforms[shaderType].size());
            for (int i = 0; i < uniformData[shaderType].size(); ++i)
                material->uniforms[shaderType][i].value = uniformData[shaderType].at(i).value;
        }
    }

    if (updateTextureProviders) {
        int index = 0;
        for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
            for (int i = 0; i < uniformData[shaderType].size(); ++i) {
                const UniformData &d = uniformData[shaderType].at(i);
                if (d.specialType != UniformData::Sampler)
                    continue;
                QSGTextureProvider *oldProvider = material->textureProviders.at(index);
                QSGTextureProvider *newProvider = 0;
                QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(d.value));
                if (source && source->isTextureProvider())
                    newProvider = source->textureProvider();
                if (newProvider != oldProvider) {
                    if (oldProvider) {
                        QObject::disconnect(oldProvider, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
                        QObject::disconnect(oldProvider, SIGNAL(destroyed(QObject*)), node, SLOT(textureProviderDestroyed(QObject*)));
                    }
                    if (newProvider) {
                        Q_ASSERT_X(newProvider->thread() == QThread::currentThread(),
                                   "QQuickShaderEffect::updatePaintNode",
                                   "Texture provider must belong to the rendering thread");
                        QObject::connect(newProvider, SIGNAL(textureChanged()), node, SLOT(markDirtyTexture()));
                        QObject::connect(newProvider, SIGNAL(destroyed(QObject*)), node, SLOT(textureProviderDestroyed(QObject*)));
                    } else {
                        const char *typeName = source ? source->metaObject()->className() : d.value.typeName();
                        qWarning("ShaderEffect: Property '%s' is not assigned a valid texture provider (%s).",
                                 d.name.constData(), typeName);
                    }
                    material->textureProviders[index] = newProvider;
                }
                ++index;
            }
        }
        Q_ASSERT(index == material->textureProviders.size());
    }
}