aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/scenegraph/coreapi/qsgmaterial.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/scenegraph/coreapi/qsgmaterial.cpp')
-rw-r--r--src/quick/scenegraph/coreapi/qsgmaterial.cpp572
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