void QQuickOpenGLShaderEffectCommon::updateParseLog(bool ignoreAttributes) { parseLog.clear(); if (!ignoreAttributes) { if (!attributes.contains(qtPositionAttributeName())) { parseLog += QLatin1String("Warning: Missing reference to \'") + QLatin1String(qtPositionAttributeName()) + QLatin1String("\'.\n"); } if (!attributes.contains(qtTexCoordAttributeName())) { parseLog += QLatin1String("Warning: Missing reference to \'") + QLatin1String(qtTexCoordAttributeName()) + QLatin1String("\'.\n"); } } bool respectsMatrix = false; bool respectsOpacity = false; for (int i = 0; i < uniformData[Key::VertexShader].size(); ++i) respectsMatrix |= uniformData[Key::VertexShader].at(i).specialType == UniformData::Matrix; for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) { for (int i = 0; i < uniformData[shaderType].size(); ++i) respectsOpacity |= uniformData[shaderType].at(i).specialType == UniformData::Opacity; } if (!respectsMatrix) parseLog += QLatin1String("Warning: Vertex shader is missing reference to \'qt_Matrix\'.\n"); if (!respectsOpacity) parseLog += QLatin1String("Warning: Shaders are missing reference to \'qt_Opacity\'.\n"); }
QSGGeometry *QQuickGridMesh::updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &dstRect) { int vmesh = m_resolution.height(); int hmesh = m_resolution.width(); int attrCount = attributes.count(); int positionIndex = attributes.indexOf(qtPositionAttributeName()); int texCoordIndex = attributes.indexOf(qtTexCoordAttributeName()); if (!geometry) { switch (attrCount) { case 0: m_log = QLatin1String("Error: No attributes specified."); return 0; case 1: if (positionIndex != 0) { m_log = QLatin1String("Error: Missing \'"); m_log += QLatin1String(qtPositionAttributeName()); m_log += QLatin1String("\' attribute.\n"); return 0; } break; case 2: if (positionIndex == -1 || texCoordIndex == -1) { m_log.clear(); if (positionIndex == -1) { m_log = QLatin1String("Error: Missing \'"); m_log += QLatin1String(qtPositionAttributeName()); m_log += QLatin1String("\' attribute.\n"); } if (texCoordIndex == -1) { m_log += QLatin1String("Error: Missing \'"); m_log += QLatin1String(qtTexCoordAttributeName()); m_log += QLatin1String("\' attribute.\n"); } return 0; } break; default: m_log = QLatin1String("Error: Too many attributes specified."); return 0; } geometry = new QSGGeometry(attrCount == 1 ? QSGGeometry::defaultAttributes_Point2D() : QSGGeometry::defaultAttributes_TexturedPoint2D(), (vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2), GL_UNSIGNED_SHORT); } else { geometry->allocate((vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2)); } QSGGeometry::Point2D *vdata = static_cast<QSGGeometry::Point2D *>(geometry->vertexData()); QRectF srcRect(0, 0, 1, 1); for (int iy = 0; iy <= vmesh; ++iy) { float fy = iy / float(vmesh); float y = float(dstRect.top()) + fy * float(dstRect.height()); float ty = float(srcRect.top()) + fy * float(srcRect.height()); for (int ix = 0; ix <= hmesh; ++ix) { float fx = ix / float(hmesh); for (int ia = 0; ia < attrCount; ++ia) { if (ia == positionIndex) { vdata->x = float(dstRect.left()) + fx * float(dstRect.width()); vdata->y = y; ++vdata; } else { vdata->x = float(srcRect.left()) + fx * float(srcRect.width()); vdata->y = ty; ++vdata; } } } } quint16 *indices = (quint16 *)geometry->indexDataAsUShort(); int i = 0; for (int iy = 0; iy < vmesh; ++iy) { *(indices++) = i + hmesh + 1; for (int ix = 0; ix <= hmesh; ++ix, ++i) { *(indices++) = i + hmesh + 1; *(indices++) = i; } *(indices++) = i - 1; } return geometry; }
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); }