void QQuickShaderEffectCommon::updateShader(QQuickItem *item, Key::ShaderType shaderType)
{
    disconnectPropertySignals(item, shaderType);
    qDeleteAll(signalMappers[shaderType]);
    uniformData[shaderType].clear();
    signalMappers[shaderType].clear();
    if (shaderType == Key::VertexShader)
        attributes.clear();

    const QByteArray &code = source.sourceCode[shaderType];
    if (code.isEmpty()) {
        // Optimize for default code.
        if (shaderType == Key::VertexShader) {
            attributes.append(QByteArray(qt_position_attribute_name));
            attributes.append(QByteArray(qt_texcoord_attribute_name));
            UniformData d;
            d.name = "qt_Matrix";
            d.specialType = UniformData::Matrix;
            uniformData[Key::VertexShader].append(d);
            signalMappers[Key::VertexShader].append(0);
        } else if (shaderType == Key::FragmentShader) {
            UniformData d;
            d.name = "qt_Opacity";
            d.specialType = UniformData::Opacity;
            uniformData[Key::FragmentShader].append(d);
            signalMappers[Key::FragmentShader].append(0);
            QSignalMapper *mapper = new QSignalMapper;
            mapper->setMapping(item, 1 | (Key::FragmentShader << 16));
            const char *sourceName = "source";
            d.name = sourceName;
            d.value = item->property(sourceName);
            d.specialType = UniformData::Sampler;
            uniformData[Key::FragmentShader].append(d);
            signalMappers[Key::FragmentShader].append(mapper);
        }
    } else {
        lookThroughShaderCode(item, shaderType, code);
    }

    connectPropertySignals(item, shaderType);
}
Example #2
0
void QQuickOpenGLShaderEffectCommon::updateShader(QQuickItem *item,
                                                  const QMetaObject *itemMetaObject,
                                                  Key::ShaderType shaderType)
{
    disconnectPropertySignals(item, shaderType);
    uniformData[shaderType].clear();
    clearSignalMappers(shaderType);
    if (shaderType == Key::VertexShader)
        attributes.clear();

    // A qrc or file URL means the shader source is to be read from the specified file.
    QUrl srcUrl(QString::fromUtf8(source.sourceCode[shaderType]));
    if (!srcUrl.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) || srcUrl.isLocalFile()) {
        if (!fileSelector) {
            fileSelector = new QFileSelector(item);
            // There may not be an OpenGL context accessible here. So rely on
            // the window's requestedFormat().
            if (item->window()
                    && item->window()->requestedFormat().profile() == QSurfaceFormat::CoreProfile) {
                fileSelector->setExtraSelectors(QStringList() << QStringLiteral("glslcore"));
            }
        }
        const QString fn = fileSelector->select(QQmlFile::urlToLocalFileOrQrc(srcUrl));
        QFile f(fn);
        if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
            source.sourceCode[shaderType] = f.readAll();
            f.close();
        } else {
            qWarning("ShaderEffect: Failed to read %s", qPrintable(fn));
            source.sourceCode[shaderType] = QByteArray();
        }
    }

    const QByteArray &code = source.sourceCode[shaderType];
    if (code.isEmpty()) {
        // Optimize for default code.
        if (shaderType == Key::VertexShader) {
            attributes.append(QByteArray(qtPositionAttributeName()));
            attributes.append(QByteArray(qtTexCoordAttributeName()));
            UniformData d;
            d.name = "qt_Matrix";
            d.specialType = UniformData::Matrix;
            uniformData[Key::VertexShader].append(d);
            signalMappers[Key::VertexShader].append(0);
        } else if (shaderType == Key::FragmentShader) {
            UniformData d;
            d.name = "qt_Opacity";
            d.specialType = UniformData::Opacity;
            uniformData[Key::FragmentShader].append(d);
            signalMappers[Key::FragmentShader].append(0);
            const int mappedId = 1 | (Key::FragmentShader << 16);
            auto mapper = new QtPrivate::MappedSlotObject([this, mappedId](){mappedPropertyChanged(mappedId);});
            const char *sourceName = "source";
            d.name = sourceName;
            d.setValueFromProperty(item, itemMetaObject);
            d.specialType = UniformData::Sampler;
            uniformData[Key::FragmentShader].append(d);
            signalMappers[Key::FragmentShader].append(mapper);
        }
    } else {
        lookThroughShaderCode(item, itemMetaObject, shaderType, code);
    }

    connectPropertySignals(item, itemMetaObject, shaderType);
}