diff options
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgmaterial.cpp')
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgmaterial.cpp | 572 |
1 files changed, 49 insertions, 523 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp index 8557de1b1f..c8ae26311b 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp +++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp @@ -39,14 +39,6 @@ #include "qsgmaterial.h" #include "qsgrenderer_p.h" -#include "qsgmaterialshader_p.h" -#if QT_CONFIG(opengl) -# include <private/qsgshadersourcebuilder_p.h> -# include <private/qsgdefaultcontext_p.h> -# include <private/qsgdefaultrendercontext_p.h> -# include <QtGui/QOpenGLFunctions> -# include <QtGui/QOpenGLContext> -#endif QT_BEGIN_NAMESPACE @@ -64,17 +56,6 @@ void qsg_set_material_failure() qsg_material_failure = true; } #endif -#if QT_CONFIG(opengl) -const char *QSGMaterialShaderPrivate::loadShaderSource(QOpenGLShader::ShaderType type) const -{ - const QStringList files = m_sourceFiles[type]; - QSGShaderSourceBuilder builder; - for (const QString &file : files) - builder.appendSourceFile(file); - m_sources[type] = builder.source(); - return m_sources[type].constData(); -} -#endif #ifndef QT_NO_DEBUG static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK"); @@ -89,494 +70,6 @@ static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK" \l {scene graph}{Qt Quick Scene Graph}. */ -/*! - \class QSGMaterialShader - \brief The QSGMaterialShader class represents an OpenGL shader program - in the renderer. - \inmodule QtQuick - \ingroup qtquick-scenegraph-materials - - The QSGMaterialShader API is very low-level. A more convenient API, which - provides almost all the same features, is available through - QSGSimpleMaterialShader. - - The QSGMaterial and QSGMaterialShader form a tight relationship. For one - scene graph (including nested graphs), there is one unique QSGMaterialShader - instance which encapsulates the QOpenGLShaderProgram the scene graph uses - to render that material, such as a shader to flat coloring of geometry. - Each QSGGeometryNode can have a unique QSGMaterial containing the - how the shader should be configured when drawing that node, such as - the actual color used to render the geometry. - - An instance of QSGMaterialShader is never created explicitly by the user, - it will be created on demand by the scene graph through - QSGMaterial::createShader(). The scene graph will make sure that there - is only one instance of each shader implementation through a scene graph. - - The source code returned from vertexShader() is used to control what the - material does with the vertiex data that comes in from the geometry. - The source code returned from the fragmentShader() is used to control - what how the material should fill each individual pixel in the geometry. - The vertex and fragment source code is queried once during initialization, - changing what is returned from these functions later will not have - any effect. - - The activate() function is called by the scene graph when a shader is - is starting to be used. The deactivate function is called by the scene - graph when the shader is no longer going to be used. While active, - the scene graph may make one or more calls to updateState() which - will update the state of the shader for each individual geometry to - render. - - The attributeNames() returns the name of the attributes used in the - vertexShader(). These are used in the default implementation of - activate() and deactivate() to decide whice vertex registers are enabled. - - The initialize() function is called during program creation to allow - subclasses to prepare for use, such as resolve uniform names in the - vertexShader() and fragmentShader(). - - A minimal example: - \code - class Shader : public QSGMaterialShader - { - public: - const char *vertexShader() const { - return - "attribute highp vec4 vertex; \n" - "uniform highp mat4 matrix; \n" - "void main() { \n" - " gl_Position = matrix * vertex; \n" - "}"; - } - - const char *fragmentShader() const { - return - "uniform lowp float opacity; \n" - "void main() { \n" - " gl_FragColor = vec4(1, 0, 0, 1) * opacity; \n" - "}"; - } - - char const *const *attributeNames() const - { - static char const *const names[] = { "vertex", 0 }; - return names; - } - - void initialize() - { - QSGMaterialShader::initialize(); - m_id_matrix = program()->uniformLocation("matrix"); - m_id_opacity = program()->uniformLocation("opacity"); - } - - void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) - { - Q_ASSERT(program()->isLinked()); - if (state.isMatrixDirty()) - program()->setUniformValue(m_id_matrix, state.combinedMatrix()); - if (state.isOpacityDirty()) - program()->setUniformValue(m_id_opacity, state.opacity()); - } - - private: - int m_id_matrix; - int m_id_opacity; - }; - \endcode - - \note All classes with QSG prefix should be used solely on the scene graph's - rendering thread. See \l {Scene Graph and Rendering} for more information. - - */ - - - -/*! - Creates a new QSGMaterialShader. - */ -QSGMaterialShader::QSGMaterialShader() - : d_ptr(new QSGMaterialShaderPrivate) -{ -} - -/*! - \internal - */ -QSGMaterialShader::QSGMaterialShader(QSGMaterialShaderPrivate &dd) - : d_ptr(&dd) -{ -} - -/*! - \internal - */ -QSGMaterialShader::~QSGMaterialShader() -{ -} - -/*! - \fn char const *const *QSGMaterialShader::attributeNames() const - - Returns a zero-terminated array describing the names of the - attributes used in the vertex shader. - - This function is called when the shader is compiled to specify - which attributes exist. The order of the attribute names - defines the attribute register position in the vertex shader. - */ - -#if QT_CONFIG(opengl) -/*! - \fn const char *QSGMaterialShader::vertexShader() const - - Called when the shader is being initialized to get the vertex - shader source code. - - The contents returned from this function should never change. -*/ -const char *QSGMaterialShader::vertexShader() const -{ - Q_D(const QSGMaterialShader); - return d->loadShaderSource(QOpenGLShader::Vertex); -} - - -/*! - \fn const char *QSGMaterialShader::fragmentShader() const - - Called when the shader is being initialized to get the fragment - shader source code. - - The contents returned from this function should never change. -*/ -const char *QSGMaterialShader::fragmentShader() const -{ - Q_D(const QSGMaterialShader); - return d->loadShaderSource(QOpenGLShader::Fragment); -} - - -/*! - \fn QOpenGLShaderProgram *QSGMaterialShader::program() - - Returns the shader program used by this QSGMaterialShader. - */ -#endif - -/*! - \fn void QSGMaterialShader::initialize() - - Reimplement this function to do one-time initialization when the - shader program is compiled. The OpenGL shader program is compiled - and linked, but not bound, when this function is called. - */ - - -/*! - This function is called by the scene graph to indicate that geometry is - about to be rendered using this shader. - - State that is global for all uses of the shader, independent of the geometry - that is being drawn, can be setup in this function. - */ - -void QSGMaterialShader::activate() -{ -} - - - -/*! - This function is called by the scene graph to indicate that geometry will - no longer to be rendered using this shader. - */ - -void QSGMaterialShader::deactivate() -{ -} - - - -/*! - This function is called by the scene graph before geometry is rendered - to make sure the shader is in the right state. - - The current rendering \a state is passed from the scene graph. If the state - indicates that any state is dirty, the updateState implementation must - update accordingly for the geometry to render correctly. - - The subclass specific state, such as the color of a flat color material, should - be extracted from \a newMaterial to update the color uniforms accordingly. - - The \a oldMaterial can be used to minimze state changes when updating - material states. The \a oldMaterial is 0 if this shader was just activated. - - \sa activate(), deactivate() - */ - -void QSGMaterialShader::updateState(const RenderState & /* state */, QSGMaterial * /* newMaterial */, QSGMaterial * /* oldMaterial */) -{ -} - -#if QT_CONFIG(opengl) -/*! - Sets the GLSL source file for the shader stage \a type to \a sourceFile. The - default implementation of the vertexShader() and fragmentShader() functions - will load the source files set by this function. - - This function is useful when you have a single source file for a given shader - stage. If your shader consists of multiple source files then use - setShaderSourceFiles() - - \sa setShaderSourceFiles(), vertexShader(), fragmentShader() - */ -void QSGMaterialShader::setShaderSourceFile(QOpenGLShader::ShaderType type, const QString &sourceFile) -{ - Q_D(QSGMaterialShader); - d->m_sourceFiles[type] = (QStringList() << sourceFile); -} - -/*! - Sets the GLSL source files for the shader stage \a type to \a sourceFiles. The - default implementation of the vertexShader() and fragmentShader() functions - will load the source files set by this function in the order given. - - \sa setShaderSourceFile(), vertexShader(), fragmentShader() - */ -void QSGMaterialShader::setShaderSourceFiles(QOpenGLShader::ShaderType type, const QStringList &sourceFiles) -{ - Q_D(QSGMaterialShader); - d->m_sourceFiles[type] = sourceFiles; -} - -/*! - This function is called when the shader is initialized to compile the - actual QOpenGLShaderProgram. Do not call it explicitly. - - The default implementation will extract the vertexShader() and - fragmentShader() and bind the names returned from attributeNames() - to consecutive vertex attribute registers starting at 0. - */ - -void QSGMaterialShader::compile() -{ - Q_ASSERT_X(!m_program.isLinked(), "QSGSMaterialShader::compile()", "Compile called multiple times!"); - - program()->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader()); - program()->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader()); - - char const *const *attr = attributeNames(); -#ifndef QT_NO_DEBUG - int maxVertexAttribs = 0; - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - funcs->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); - for (int i = 0; attr[i]; ++i) { - if (i >= maxVertexAttribs) { - qFatal("List of attribute names is either too long or not null-terminated.\n" - "Maximum number of attributes on this hardware is %i.\n" - "Vertex shader:\n%s\n" - "Fragment shader:\n%s\n", - maxVertexAttribs, vertexShader(), fragmentShader()); - } - if (*attr[i]) - program()->bindAttributeLocation(attr[i], i); - } -#else - for (int i = 0; attr[i]; ++i) { - if (*attr[i]) - program()->bindAttributeLocation(attr[i], i); - } -#endif - - if (!program()->link()) { - qWarning("QSGMaterialShader: Shader compilation failed:"); - qWarning() << program()->log(); - } -} - -#endif - -/*! - \class QSGMaterialShader::RenderState - \brief The QSGMaterialShader::RenderState encapsulates the current rendering state - during a call to QSGMaterialShader::updateState(). - \inmodule QtQuick - - The render state contains a number of accessors that the shader needs to respect - in order to conform to the current state of the scene graph. - - The instance is only valid inside a call to QSGMaterialShader::updateState() and - should not be used outisde this function. - */ - - - -/*! - \enum QSGMaterialShader::RenderState::DirtyState - - \value DirtyMatrix Used to indicate that the matrix has changed and must be updated. - - \value DirtyOpacity Used to indicate that the opacity has changed and must be updated. - - \value DirtyCachedMaterialData Used to indicate that the cached material data have changed and must be updated. - - \value DirtyAll Used to indicate that everything needs to be updated. - */ - - - -/*! - \fn bool QSGMaterialShader::RenderState::isMatrixDirty() const - - Returns \c true if the dirtyStates() contain the dirty matrix state, - otherwise returns \c false. - */ - - - -/*! - \fn bool QSGMaterialShader::RenderState::isOpacityDirty() const - - Returns \c true if the dirtyStates() contains the dirty opacity state, - otherwise returns \c false. - */ - -/*! - \fn bool QSGMaterialShader::RenderState::isCachedMaterialDataDirty() const - - Returns \c true if the dirtyStates() contains the dirty cached material state, - otherwise returns \c false. - */ - -/*! - \fn QSGMaterialShader::RenderState::DirtyStates QSGMaterialShader::RenderState::dirtyStates() const - - Returns which rendering states that have changed and needs to be updated - for geometry rendered with this material to conform to the current - rendering state. - */ - - - -/*! - Returns the accumulated opacity to be used for rendering. - */ - -float QSGMaterialShader::RenderState::opacity() const -{ - Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->currentOpacity(); -} - -/*! - Returns the modelview determinant to be used for rendering. - */ - -float QSGMaterialShader::RenderState::determinant() const -{ - Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->determinant(); -} - -/*! - Returns the matrix combined of modelview matrix and project matrix. - */ - -QMatrix4x4 QSGMaterialShader::RenderState::combinedMatrix() const -{ - Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->currentCombinedMatrix(); -} -/*! - Returns the ratio between physical pixels and device-independent pixels - to be used for rendering. -*/ -float QSGMaterialShader::RenderState::devicePixelRatio() const -{ - Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->devicePixelRatio(); -} - - - -/*! - Returns the model view matrix. - - If the material has the RequiresFullMatrix flag - set, this is guaranteed to be the complete transform - matrix calculated from the scenegraph. - - However, if this flag is not set, the renderer may - choose to alter this matrix. For example, it may - pre-transform vertices on the CPU and set this matrix - to identity. - - In a situation such as the above, it is still possible - to retrieve the actual matrix determinant by setting - the RequiresDeterminant flag in the material and - calling the determinant() accessor. - */ - -QMatrix4x4 QSGMaterialShader::RenderState::modelViewMatrix() const -{ - Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->currentModelViewMatrix(); -} - -/*! - Returns the projection matrix. - */ - -QMatrix4x4 QSGMaterialShader::RenderState::projectionMatrix() const -{ - Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->currentProjectionMatrix(); -} - - - -/*! - Returns the viewport rect of the surface being rendered to. - */ - -QRect QSGMaterialShader::RenderState::viewportRect() const -{ - Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->viewportRect(); -} - - - -/*! - Returns the device rect of the surface being rendered to - */ - -QRect QSGMaterialShader::RenderState::deviceRect() const -{ - Q_ASSERT(m_data); - return static_cast<const QSGRenderer *>(m_data)->deviceRect(); -} - -#if QT_CONFIG(opengl) - -/*! - Returns the QOpenGLContext that is being used for rendering - */ - -QOpenGLContext *QSGMaterialShader::RenderState::context() const -{ - // Only the QSGDefaultRenderContext will have an OpenGL Context to query - auto openGLRenderContext = static_cast<const QSGDefaultRenderContext *>(static_cast<const QSGRenderer *>(m_data)->context()); - if (openGLRenderContext != nullptr) - return openGLRenderContext->openglContext(); - else - return nullptr; -} - -#endif - #ifndef QT_NO_DEBUG static int qt_material_count = 0; @@ -605,22 +98,20 @@ static void qt_print_material_count() \inmodule QtQuick \ingroup qtquick-scenegraph-materials - The QSGMaterial API is very low-level. A more convenient API, which - provides almost all the same features, is available through - QSGSimpleMaterialShader. - - The QSGMaterial and QSGMaterialShader subclasses form a tight relationship. For - one scene graph (including nested graphs), there is one unique QSGMaterialShader - instance which encapsulates the QOpenGLShaderProgram the scene graph uses - to render that material, such as a shader to flat coloring of geometry. - Each QSGGeometryNode can have a unique QSGMaterial containing the - how the shader should be configured when drawing that node, such as - the actual color to used to render the geometry. - - The QSGMaterial has two virtual functions that both need to be implemented. - The function type() should return a unique instance for all instances of a + The QSGMaterial, QSGMaterialShader and QSGMaterialRhiShader subclasses + form a tight relationship. For one scene graph (including nested graphs), + there is one unique QSGMaterialShader or QSGMaterialRhiShader instance + which encapsulates the shaders the scene graph uses to render that + material, such as a shader to flat coloring of geometry. Each + QSGGeometryNode can have a unique QSGMaterial containing the how the shader + should be configured when drawing that node, such as the actual color to + used to render the geometry. + + QSGMaterial has two virtual functions that both need to be implemented. The + function type() should return a unique instance for all instances of a specific subclass. The createShader() function should return a new instance - of QSGMaterialShader, specific to the subclass of QSGMaterial. + of QSGMaterialShader or QSGMaterialRhiShader, specific to that subclass of + QSGMaterial. A minimal QSGMaterial implementation could look like this: \code @@ -632,6 +123,27 @@ static void qt_print_material_count() }; \endcode + This is suitable only for the OpenGL-based, traditional renderer of the + scene graph. When using the new, graphics API abstracted renderer, + materials must create QSGMaterialRhiShader instances instead, or in + addition: + \code + class Material : public QSGMaterial + { + public: + Material() { setFlag(SupportsRhiShader, true); } + QSGMaterialType *type() const { static QSGMaterialType type; return &type; } + QSGMaterialShader *createShader() { + if (flags().testFlag(RhiShaderWanted)) { + return new RhiShader; + } else { + // this is optional, relevant for materials that intend to be usable with the legacy OpenGL renderer as well + return new Shader; + } + } + }; + \endcode + \note All classes with QSG prefix should be used solely on the scene graph's rendering thread. See \l {Scene Graph and Rendering} for more information. */ @@ -693,6 +205,16 @@ QSGMaterial::~QSGMaterial() QSGMaterialShader::compile() when its shader program is compiled and linked. Set this flag to enforce that the function is called. + \value SupportsRhiShader Starting with Qt 5.14, the scene graph supports + QSGMaterialRhiShader as an alternative to the OpenGL-specific + QSGMaterialShader. Set this flag to indicate createShader() is capable of + returning QSGMaterialRhiShader instances when the RhiShaderWanted flag is + set. + + \value RhiShaderWanted This flag is set by the scene graph, not by the + QSGMaterial. When set, and that can only happen when SupportsRhiShader was + set by the material, it indicates that createShader() must return a + QSGMaterialRhiShader instance instead of QSGMaterialShader. */ /*! @@ -757,7 +279,11 @@ int QSGMaterial::compare(const QSGMaterial *other) const The function will be called only once for each material type that exists in the scene graph and will be cached internally. -*/ + When the QSGMaterial reports SupportsRhiShader in flags(), the scene graph + may request a QSGMaterialRhiShader instead of QSGMaterialShader. This is + indicated by having the RhiShaderWanted flag set. In this case the return + value must be a QSGRhiMaterialShader subclass. +*/ QT_END_NAMESPACE |