diff options
Diffstat (limited to 'src/quick/scenegraph/coreapi')
19 files changed, 1061 insertions, 226 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgabstractrenderer.h b/src/quick/scenegraph/coreapi/qsgabstractrenderer.h index d0a22c8c10..eb9e7cea7c 100644 --- a/src/quick/scenegraph/coreapi/qsgabstractrenderer.h +++ b/src/quick/scenegraph/coreapi/qsgabstractrenderer.h @@ -42,6 +42,10 @@ #include <QtQuick/qsgnode.h> +#ifndef GLuint +#define GLuint uint +#endif + QT_BEGIN_NAMESPACE class QSGAbstractRendererPrivate; diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index d91004fbee..49bbbf0ba8 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -154,8 +154,8 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material) p->bindAttributeLocation(attr[i], i); } p->bindAttributeLocation("_qt_order", i); - context->compile(s, material, qsgShaderRewriter_insertZAttributes(s->vertexShader(), profile), 0); - context->initialize(s); + context->compileShader(s, material, qsgShaderRewriter_insertZAttributes(s->vertexShader(), profile), 0); + context->initializeShader(s); if (!p->isLinked()) return 0; @@ -188,8 +188,8 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphContextFrame); QSGMaterialShader *s = static_cast<QSGMaterialShader *>(material->createShader()); - context->compile(s, material); - context->initialize(s); + context->compileShader(s, material); + context->initializeShader(s); shader = new Shader(); shader->program = s; @@ -356,17 +356,17 @@ void Updater::visitClipNode(Node *n) if (m_roots.last() && m_added > 0) renderer->registerBatchRoot(n, m_roots.last()); - cn->m_clip_list = m_current_clip; + cn->setRendererClipList(m_current_clip); m_current_clip = cn; m_roots << n; m_rootMatrices.add(m_rootMatrices.last() * *m_combined_matrix_stack.last()); extra->matrix = m_rootMatrices.last(); - cn->m_matrix = &extra->matrix; + cn->setRendererMatrix(&extra->matrix); m_combined_matrix_stack << &m_identityMatrix; SHADOWNODE_TRAVERSE(n) visitNode(child); - m_current_clip = cn->m_clip_list; + m_current_clip = cn->clipList(); m_rootMatrices.pop_back(); m_combined_matrix_stack.pop_back(); m_roots.pop_back(); @@ -459,8 +459,8 @@ void Updater::visitGeometryNode(Node *n) { QSGGeometryNode *gn = static_cast<QSGGeometryNode *>(n->sgNode); - gn->m_matrix = m_combined_matrix_stack.last(); - gn->m_clip_list = m_current_clip; + gn->setRendererMatrix(m_combined_matrix_stack.last()); + gn->setRendererClipList(m_current_clip); gn->setInheritedOpacity(m_opacity_stack.last()); if (m_added) { @@ -746,8 +746,9 @@ static int qsg_countNodesInBatches(const QDataBuffer<Batch *> &batches) return sum; } -Renderer::Renderer(QSGRenderContext *ctx) +Renderer::Renderer(QSGDefaultRenderContext *ctx) : QSGRenderer(ctx) + , m_context(ctx) , m_opaqueRenderList(64) , m_alphaRenderList(64) , m_nextRenderOrder(0) @@ -807,7 +808,7 @@ Renderer::Renderer(QSGRenderContext *ctx) // If rendering with an OpenGL Core profile context, we need to create a VAO // to hold our vertex specification state. - if (context()->openglContext()->format().profile() == QSurfaceFormat::CoreProfile) { + if (m_context->openglContext()->format().profile() == QSurfaceFormat::CoreProfile) { m_vao = new QOpenGLVertexArrayObject(this); m_vao->create(); } @@ -845,7 +846,7 @@ Renderer::~Renderer() for (int i=0; i<m_batchPool.size(); ++i) qsg_wipeBatch(m_batchPool.at(i), this); } - foreach (Node *n, m_nodes.values()) + for (Node *n : qAsConst(m_nodes)) m_nodeAllocator.release(n); // Remaining elements... @@ -1032,11 +1033,13 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent) m_rebuild |= FullRebuild; } else if (node->type() == QSGNode::RenderNodeType) { - RenderNodeElement *e = new RenderNodeElement(static_cast<QSGRenderNode *>(node)); + QSGRenderNode *rn = static_cast<QSGRenderNode *>(node); + RenderNodeElement *e = new RenderNodeElement(rn); snode->data = e; - Q_ASSERT(!m_renderNodeElements.contains(static_cast<QSGRenderNode *>(node))); + Q_ASSERT(!m_renderNodeElements.contains(rn)); m_renderNodeElements.insert(e->renderNode, e); - m_useDepthBuffer = false; + if (!rn->flags().testFlag(QSGRenderNode::DepthAwareRendering)) + m_useDepthBuffer = false; m_rebuild |= FullRebuild; } @@ -1101,7 +1104,7 @@ void Renderer::nodeWasRemoved(Node *node) if (m_renderNodeElements.isEmpty()) { static bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER"); - m_useDepthBuffer = useDepth && context()->openglContext()->format().depthBufferSize() > 0; + m_useDepthBuffer = useDepth && m_context->openglContext()->format().depthBufferSize() > 0; } } } @@ -2760,6 +2763,22 @@ void Renderer::render() m_vao->release(); } +struct RenderNodeState : public QSGRenderNode::RenderState +{ + const QMatrix4x4 *projectionMatrix() const override { return m_projectionMatrix; } + QRect scissorRect() const override { return m_scissorRect; } + bool scissorEnabled() const override { return m_scissorEnabled; } + int stencilValue() const override { return m_stencilValue; } + bool stencilEnabled() const override { return m_stencilEnabled; } + const QRegion *clipRegion() const override { return nullptr; } + + const QMatrix4x4 *m_projectionMatrix; + QRect m_scissorRect; + int m_stencilValue; + bool m_scissorEnabled; + bool m_stencilEnabled; +}; + void Renderer::renderRenderNode(Batch *batch) { if (Q_UNLIKELY(debug_render())) @@ -2771,24 +2790,25 @@ void Renderer::renderRenderNode(Batch *batch) setActiveShader(0, 0); QSGNode *clip = e->renderNode->parent(); - e->renderNode->m_clip_list = 0; + QSGRenderNodePrivate *rd = QSGRenderNodePrivate::get(e->renderNode); + rd->m_clip_list = 0; while (clip != rootNode()) { if (clip->type() == QSGNode::ClipNodeType) { - e->renderNode->m_clip_list = static_cast<QSGClipNode *>(clip); + rd->m_clip_list = static_cast<QSGClipNode *>(clip); break; } clip = clip->parent(); } - updateClip(e->renderNode->m_clip_list, batch); + updateClip(rd->m_clip_list, batch); - QSGRenderNode::RenderState state; + RenderNodeState state; QMatrix4x4 pm = projectionMatrix(); - state.projectionMatrix = ± - state.scissorEnabled = m_currentClipType & ScissorClip; - state.stencilEnabled = m_currentClipType & StencilClip; - state.scissorRect = m_currentScissorRect; - state.stencilValue = m_currentStencilValue; + state.m_projectionMatrix = ± + state.m_scissorEnabled = m_currentClipType & ScissorClip; + state.m_stencilEnabled = m_currentClipType & StencilClip; + state.m_scissorRect = m_currentScissorRect; + state.m_stencilValue = m_currentStencilValue; QSGNode *xform = e->renderNode->parent(); QMatrix4x4 matrix; @@ -2804,13 +2824,13 @@ void Renderer::renderRenderNode(Batch *batch) } xform = xform->parent(); } - e->renderNode->m_matrix = &matrix; + rd->m_matrix = &matrix; QSGNode *opacity = e->renderNode->parent(); - e->renderNode->m_opacity = 1.0; + rd->m_opacity = 1.0; while (opacity != rootNode()) { if (opacity->type() == QSGNode::OpacityNodeType) { - e->renderNode->m_opacity = static_cast<QSGOpacityNode *>(opacity)->combinedOpacity(); + rd->m_opacity = static_cast<QSGOpacityNode *>(opacity)->combinedOpacity(); break; } opacity = opacity->parent(); @@ -2822,12 +2842,17 @@ void Renderer::renderRenderNode(Batch *batch) glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - e->renderNode->render(state); + QSGRenderNode::StateFlags changes = e->renderNode->changedStates(); - e->renderNode->m_matrix = 0; - e->renderNode->m_clip_list = 0; + GLuint prevFbo = 0; + if (changes & QSGRenderNode::RenderTargetState) + glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &prevFbo); + + e->renderNode->render(&state); + + rd->m_matrix = 0; + rd->m_clip_list = 0; - QSGRenderNode::StateFlags changes = e->renderNode->changedStates(); if (changes & QSGRenderNode::ViewportState) { QRect r = viewportRect(); glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height()); @@ -2861,6 +2886,8 @@ void Renderer::renderRenderNode(Batch *batch) glDisable(GL_CULL_FACE); } + if (changes & QSGRenderNode::RenderTargetState) + glBindFramebuffer(GL_FRAMEBUFFER, prevFbo); } class VisualizeShader : public QOpenGLShaderProgram diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 8bf4a13af6..01e517e65b 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -54,13 +54,15 @@ // #include <private/qsgrenderer_p.h> +#include <private/qsgdefaultrendercontext_p.h> #include <private/qsgnodeupdater_p.h> -#include <private/qdatabuffer_p.h> - #include <private/qsgrendernode_p.h> +#include <private/qdatabuffer_p.h> #include <QtCore/QBitArray> +#include <QtGui/QOpenGLFunctions> + QT_BEGIN_NAMESPACE class QOpenGLVertexArrayObject; @@ -527,7 +529,7 @@ public: float lastOpacity; }; - ShaderManager(QSGRenderContext *ctx) : visualizeProgram(0), blitProgram(0), context(ctx) { } + ShaderManager(QSGDefaultRenderContext *ctx) : visualizeProgram(0), blitProgram(0), context(ctx) { } ~ShaderManager() { qDeleteAll(rewrittenShaders); qDeleteAll(stockShaders); @@ -547,13 +549,13 @@ private: QHash<QSGMaterialType *, Shader *> stockShaders; QOpenGLShaderProgram *blitProgram; - QSGRenderContext *context; + QSGDefaultRenderContext *context; }; class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer, public QOpenGLFunctions { public: - Renderer(QSGRenderContext *); + Renderer(QSGDefaultRenderContext *); ~Renderer(); enum VisualizeMode { @@ -637,6 +639,7 @@ private: void visualizeDrawGeometry(const QSGGeometry *g); void setCustomRenderMode(const QByteArray &mode) Q_DECL_OVERRIDE; + QSGDefaultRenderContext *m_context; QSet<Node *> m_taggedRoots; QDataBuffer<Element *> m_opaqueRenderList; QDataBuffer<Element *> m_alphaRenderList; diff --git a/src/quick/scenegraph/coreapi/qsggeometry.cpp b/src/quick/scenegraph/coreapi/qsggeometry.cpp index 5012f6a31b..b43a2bc2ba 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.cpp +++ b/src/quick/scenegraph/coreapi/qsggeometry.cpp @@ -39,10 +39,11 @@ #include "qsggeometry.h" #include "qsggeometry_p.h" - -#include <qopenglcontext.h> -#include <qopenglfunctions.h> -#include <private/qopenglextensions_p.h> +#ifndef QT_NO_OPENGL +# include <qopenglcontext.h> +# include <qopenglfunctions.h> +# include <private/qopenglextensions_p.h> +#endif #ifdef Q_OS_QNX #include <malloc.h> @@ -53,10 +54,21 @@ QT_BEGIN_NAMESPACE QSGGeometry::Attribute QSGGeometry::Attribute::create(int attributeIndex, int tupleSize, int primitiveType, bool isPrimitive) { - Attribute a = { attributeIndex, tupleSize, primitiveType, isPrimitive, 0 }; + Attribute a = { attributeIndex, tupleSize, primitiveType, isPrimitive, UnknownAttribute, 0 }; return a; } +QSGGeometry::Attribute QSGGeometry::Attribute::createWithAttributeType(int pos, int tupleSize, int primitiveType, AttributeType attributeType) +{ + Attribute a; + a.position = pos; + a.tupleSize = tupleSize; + a.type = primitiveType; + a.isVertexCoordinate = attributeType == PositionAttribute; + a.attributeType = attributeType; + a.reserved = 0; + return a; +} /*! Convenience function which returns attributes to be used for 2D solid @@ -66,7 +78,7 @@ QSGGeometry::Attribute QSGGeometry::Attribute::create(int attributeIndex, int tu const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_Point2D() { static Attribute data[] = { - QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true) + Attribute::createWithAttributeType(0, 2, FloatType, PositionAttribute) }; static AttributeSet attrs = { 1, sizeof(float) * 2, data }; return attrs; @@ -79,8 +91,8 @@ const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_Point2D() const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_TexturedPoint2D() { static Attribute data[] = { - QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), - QSGGeometry::Attribute::create(1, 2, GL_FLOAT) + Attribute::createWithAttributeType(0, 2, FloatType, PositionAttribute), + Attribute::createWithAttributeType(1, 2, FloatType, TexCoordAttribute) }; static AttributeSet attrs = { 2, sizeof(float) * 4, data }; return attrs; @@ -93,8 +105,8 @@ const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_TexturedPoint2D( const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D() { static Attribute data[] = { - QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), - QSGGeometry::Attribute::create(1, 4, GL_UNSIGNED_BYTE) + Attribute::createWithAttributeType(0, 2, FloatType, PositionAttribute), + Attribute::createWithAttributeType(1, 4, UnsignedByteType, ColorAttribute) }; static AttributeSet attrs = { 2, 2 * sizeof(float) + 4 * sizeof(char), data }; return attrs; @@ -122,12 +134,31 @@ const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D() \fn QSGGeometry::Attribute QSGGeometry::Attribute::create(int pos, int tupleSize, int primitiveType, bool isPosition) Creates a new QSGGeometry::Attribute for attribute register \a pos with \a - tupleSize. The \a primitiveType can be any of the supported OpenGL types, - such as \c GL_FLOAT or \c GL_UNSIGNED_BYTE. + tupleSize. The \a primitiveType can be any of the supported types from + QSGGeometry::Type, such as QSGGeometry::FloatType or + QSGGeometry::UnsignedByteType. - If the attribute describes the position for the vertex, the \a isPosition hint - should be set to \c true. The scene graph renderer may use this information - to perform optimizations. + If the attribute describes the position for the vertex, the \a isPosition + hint should be set to \c true. The scene graph renderer may use this + information to perform optimizations. + + \note Scene graph backends for APIs other than OpenGL may require an + accurate description of attributes' usage, and therefore it is recommended + to use createWithAttributeType() instead. + + Use the create function to construct the attribute, rather than an + initialization list, to ensure that all fields are initialized. + */ + +/*! + \fn QSGGeometry::Attribute QSGGeometry::Attribute::createWithAttributeType(int pos, int tupleSize, int primitiveType, AttributeType attributeType) + + Creates a new QSGGeometry::Attribute for attribute register \a pos with \a + tupleSize. The \a primitiveType can be any of the supported types from + QSGGeometry::Type, such as QSGGeometry::FloatType or + QSGGeometry::UnsignedByteType. + + \a attributeType describes the intended use of the attribute. Use the create function to construct the attribute, rather than an initialization list, to ensure that all fields are initialized. @@ -206,9 +237,9 @@ const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D() The QSGGeometry class stores the geometry of the primitives rendered with the scene graph. It contains vertex data and optionally index data. The mode used to draw the geometry is - specified with setDrawingMode(), which maps directly to the OpenGL + specified with setDrawingMode(), which maps directly to the graphics API's drawing mode, such as \c GL_TRIANGLE_STRIP, \c GL_TRIANGLES, or - \c GL_POINTS. + \c GL_POINTS in case of OpenGL. Vertices can be as simple as points defined by x and y values or can be more complex where each vertex contains a normal, texture @@ -394,7 +425,7 @@ QSGGeometry::QSGGeometry(const QSGGeometry::AttributeSet &attributes, int vertexCount, int indexCount, int indexType) - : m_drawing_mode(GL_TRIANGLE_STRIP) + : m_drawing_mode(DrawTriangleStrip) , m_vertex_count(0) , m_index_count(0) , m_index_type(indexType) @@ -410,21 +441,20 @@ QSGGeometry::QSGGeometry(const QSGGeometry::AttributeSet &attributes, Q_UNUSED(m_reserved_bits); Q_ASSERT(m_attributes.count > 0); Q_ASSERT(m_attributes.stride > 0); - +#ifndef QT_NO_OPENGL Q_ASSERT_X(indexType != GL_UNSIGNED_INT || static_cast<QOpenGLExtensions *>(QOpenGLContext::currentContext()->functions()) ->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint), "QSGGeometry::QSGGeometry", "GL_UNSIGNED_INT is not supported, geometry will not render" ); - - if (indexType != GL_UNSIGNED_BYTE - && indexType != GL_UNSIGNED_SHORT - && indexType != GL_UNSIGNED_INT) { +#endif + if (indexType != UnsignedByteType + && indexType != UnsignedShortType + && indexType != UnsignedIntType) { qFatal("QSGGeometry: Unsupported index type, %x.\n", indexType); } - // Because allocate reads m_vertex_count, m_index_count and m_owns_data, these // need to be set before calling allocate... allocate(vertexCount, indexCount); @@ -516,23 +546,63 @@ const void *QSGGeometry::indexData() const } /*! + \enum QSGGeometry::DrawingMode + + The values correspond to OpenGL enum values like \c GL_POINTS, \c GL_LINES, + etc. QSGGeometry provies its own type in order to be able to provide the + same API with non-OpenGL backends as well. + + \value DrawPoints + \value DrawLines + \value DrawLineLoop + \value DrawLineStrip + \value DrawTriangles + \value DrawTriangleStrip + \value DrawTriangleFan + */ + +/*! + \enum QSGGeometry::Type + + The values correspond to OpenGL type constants like \c GL_BYTE, \c + GL_UNSIGNED_BYTE, etc. QSGGeometry provies its own type in order to be able + to provide the same API with non-OpenGL backends as well. + + \value ByteType + \value UnsignedByteType + \value ShortType + \value UnsignedShortType + \value IntType + \value UnsignedIntType + \value FloatType + */ + +/*! Sets the \a mode to be used for drawing this geometry. - The default value is \c GL_TRIANGLE_STRIP. + The default value is QSGGeometry::DrawTriangleStrip. + + \sa DrawingMode */ -void QSGGeometry::setDrawingMode(GLenum mode) +void QSGGeometry::setDrawingMode(unsigned int mode) { m_drawing_mode = mode; } /*! - Gets the current line or point width or to be used for this geometry. This property - only applies to line width when the drawingMode is \c GL_LINES, \c GL_LINE_STRIP, or - \c GL_LINE_LOOP. For desktop OpenGL, it also applies to point size when the drawingMode - is \c GL_POINTS. + Gets the current line or point width or to be used for this geometry. This + property only applies to line width when the drawingMode is DrawLines, + DarwLineStrip, or DrawLineLoop. For desktop OpenGL, it also applies to + point size when the drawingMode is DrawPoints. The default value is \c 1.0 + \note When not using OpenGL, support for point and line drawing may be + limited. For example, some APIs do not support point sprites and so setting + a size other than 1 is not possible. Some backends may be able implement + support via geometry shaders, but this is not guaranteed to be always + available. + \sa setLineWidth(), drawingMode() */ float QSGGeometry::lineWidth() const @@ -541,14 +611,15 @@ float QSGGeometry::lineWidth() const } /*! - Sets the line or point width to be used for this geometry to \a width. This property - only applies to line width when the drawingMode is \c GL_LINES, \c GL_LINE_STRIP, or - \c GL_LINE_LOOP. For Desktop OpenGL, it also applies to point size when the drawingMode - is \c GL_POINTS. + Sets the line or point width to be used for this geometry to \a width. This + property only applies to line width when the drawingMode is DrawLines, + DrawLineStrip, or DrawLineLoop. For Desktop OpenGL, it also applies to + point size when the drawingMode is DrawPoints. - \note How line width and point size are treated is implementation dependent: The application - should not rely on these, but rather create triangles or similar to draw areas. On OpenGL ES, - line width support is limited and point size is unsupported. + \note How line width and point size are treated is implementation + dependent: The application should not rely on these, but rather create + triangles or similar to draw areas. On OpenGL ES, line width support is + limited and point size is unsupported. \sa lineWidth(), drawingMode() */ @@ -601,8 +672,8 @@ void QSGGeometry::allocate(int vertexCount, int indexCount) m_index_data_offset = -1; m_owns_data = false; } else { - Q_ASSERT(m_index_type == GL_UNSIGNED_INT || m_index_type == GL_UNSIGNED_SHORT); - int indexByteSize = indexCount * (m_index_type == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32)); + Q_ASSERT(m_index_type == UnsignedIntType || m_index_type == UnsignedShortType); + int indexByteSize = indexCount * (m_index_type == UnsignedShortType ? sizeof(quint16) : sizeof(quint32)); m_data = (void *) malloc(vertexByteSize + indexByteSize); m_index_data_offset = vertexByteSize; m_owns_data = true; @@ -674,6 +745,27 @@ void QSGGeometry::updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, v[3].ty = textureRect.bottom(); } +/*! + Updates the geometry \a g with the coordinates in \a rect. + + The function assumes the geometry object contains a single triangle strip + of QSGGeometry::ColoredPoint2D vertices + */ +void QSGGeometry::updateColoredRectGeometry(QSGGeometry *g, const QRectF &rect) +{ + ColoredPoint2D *v = g->vertexDataAsColoredPoint2D(); + v[0].x = rect.left(); + v[0].y = rect.top(); + + v[1].x = rect.left(); + v[1].y = rect.bottom(); + + v[2].x = rect.right(); + v[2].y = rect.top(); + + v[3].x = rect.right(); + v[3].y = rect.bottom(); +} /*! diff --git a/src/quick/scenegraph/coreapi/qsggeometry.h b/src/quick/scenegraph/coreapi/qsggeometry.h index 5773b6abd1..7a916610e3 100644 --- a/src/quick/scenegraph/coreapi/qsggeometry.h +++ b/src/quick/scenegraph/coreapi/qsggeometry.h @@ -51,6 +51,45 @@ class QSGGeometryData; class Q_QUICK_EXPORT QSGGeometry { public: + enum AttributeType { + UnknownAttribute, + PositionAttribute, + ColorAttribute, + TexCoordAttribute, + TexCoord1Attribute, + TexCoord2Attribute + }; + + enum DataPattern { + AlwaysUploadPattern = 0, + StreamPattern = 1, + DynamicPattern = 2, + StaticPattern = 3 + }; + + // Equivalents to GL_* drawing modes. + // Keep in sync with GL headers. + enum DrawingMode { + DrawPoints = 0x0000, + DrawLines = 0x0001, + DrawLineLoop = 0x0002, + DrawLineStrip = 0x0003, + DrawTriangles = 0x0004, + DrawTriangleStrip = 0x0005, + DrawTriangleFan = 0x0006 + }; + + // Equivalents to GL_BYTE and similar type constants. + // Keep in sync with GL headers. + enum Type { + ByteType = 0x1400, + UnsignedByteType = 0x1401, + ShortType = 0x1402, + UnsignedShortType = 0x1403, + IntType = 0x1404, + UnsignedIntType = 0x1405, + FloatType = 0x1406 + }; struct Q_QUICK_EXPORT Attribute { @@ -60,9 +99,12 @@ public: uint isVertexCoordinate : 1; - uint reserved : 31; + AttributeType attributeType : 4; + + uint reserved : 27; static Attribute create(int pos, int tupleSize, int primitiveType, bool isPosition = false); + static Attribute createWithAttributeType(int pos, int tupleSize, int primitiveType, AttributeType attributeType); }; struct AttributeSet { @@ -97,21 +139,15 @@ public: static const AttributeSet &defaultAttributes_TexturedPoint2D(); static const AttributeSet &defaultAttributes_ColoredPoint2D(); - enum DataPattern { - AlwaysUploadPattern = 0, - StreamPattern = 1, - DynamicPattern = 2, - StaticPattern = 3 - }; - QSGGeometry(const QSGGeometry::AttributeSet &attribs, int vertexCount, int indexCount = 0, - int indexType = GL_UNSIGNED_SHORT); + int indexType = UnsignedShortType); virtual ~QSGGeometry(); - void setDrawingMode(GLenum mode); - inline GLenum drawingMode() const { return m_drawing_mode; } + // must use unsigned int to be compatible with the old GLenum to keep BC + void setDrawingMode(unsigned int mode); + inline unsigned int drawingMode() const { return m_drawing_mode; } void allocate(int vertexCount, int indexCount = 0); @@ -147,6 +183,7 @@ public: static void updateRectGeometry(QSGGeometry *g, const QRectF &rect); static void updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &sourceRect); + static void updateColoredRectGeometry(QSGGeometry *g, const QRectF &rect); void setIndexDataPattern(DataPattern p); DataPattern indexDataPattern() const { return DataPattern(m_index_usage_pattern); } @@ -187,25 +224,25 @@ private: inline uint *QSGGeometry::indexDataAsUInt() { - Q_ASSERT(m_index_type == GL_UNSIGNED_INT); + Q_ASSERT(m_index_type == UnsignedIntType); return static_cast<uint *>(indexData()); } inline quint16 *QSGGeometry::indexDataAsUShort() { - Q_ASSERT(m_index_type == GL_UNSIGNED_SHORT); + Q_ASSERT(m_index_type == UnsignedShortType); return static_cast<quint16 *>(indexData()); } inline const uint *QSGGeometry::indexDataAsUInt() const { - Q_ASSERT(m_index_type == GL_UNSIGNED_INT); + Q_ASSERT(m_index_type == UnsignedIntType); return static_cast<const uint *>(indexData()); } inline const quint16 *QSGGeometry::indexDataAsUShort() const { - Q_ASSERT(m_index_type == GL_UNSIGNED_SHORT); + Q_ASSERT(m_index_type == UnsignedShortType); return static_cast<const quint16 *>(indexData()); } @@ -214,7 +251,7 @@ inline QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D() Q_ASSERT(m_attributes.count == 1); Q_ASSERT(m_attributes.stride == 2 * sizeof(float)); Q_ASSERT(m_attributes.attributes[0].tupleSize == 2); - Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT); + Q_ASSERT(m_attributes.attributes[0].type == FloatType); Q_ASSERT(m_attributes.attributes[0].position == 0); return static_cast<Point2D *>(m_data); } @@ -225,10 +262,10 @@ inline QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D() Q_ASSERT(m_attributes.stride == 4 * sizeof(float)); Q_ASSERT(m_attributes.attributes[0].position == 0); Q_ASSERT(m_attributes.attributes[0].tupleSize == 2); - Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT); + Q_ASSERT(m_attributes.attributes[0].type == FloatType); Q_ASSERT(m_attributes.attributes[1].position == 1); Q_ASSERT(m_attributes.attributes[1].tupleSize == 2); - Q_ASSERT(m_attributes.attributes[1].type == GL_FLOAT); + Q_ASSERT(m_attributes.attributes[1].type == FloatType); return static_cast<TexturedPoint2D *>(m_data); } @@ -238,10 +275,10 @@ inline QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D() Q_ASSERT(m_attributes.stride == 2 * sizeof(float) + 4 * sizeof(char)); Q_ASSERT(m_attributes.attributes[0].position == 0); Q_ASSERT(m_attributes.attributes[0].tupleSize == 2); - Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT); + Q_ASSERT(m_attributes.attributes[0].type == FloatType); Q_ASSERT(m_attributes.attributes[1].position == 1); Q_ASSERT(m_attributes.attributes[1].tupleSize == 4); - Q_ASSERT(m_attributes.attributes[1].type == GL_UNSIGNED_BYTE); + Q_ASSERT(m_attributes.attributes[1].type == UnsignedByteType); return static_cast<ColoredPoint2D *>(m_data); } @@ -250,7 +287,7 @@ inline const QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D() const Q_ASSERT(m_attributes.count == 1); Q_ASSERT(m_attributes.stride == 2 * sizeof(float)); Q_ASSERT(m_attributes.attributes[0].tupleSize == 2); - Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT); + Q_ASSERT(m_attributes.attributes[0].type == FloatType); Q_ASSERT(m_attributes.attributes[0].position == 0); return static_cast<const Point2D *>(m_data); } @@ -261,10 +298,10 @@ inline const QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoin Q_ASSERT(m_attributes.stride == 4 * sizeof(float)); Q_ASSERT(m_attributes.attributes[0].position == 0); Q_ASSERT(m_attributes.attributes[0].tupleSize == 2); - Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT); + Q_ASSERT(m_attributes.attributes[0].type == FloatType); Q_ASSERT(m_attributes.attributes[1].position == 1); Q_ASSERT(m_attributes.attributes[1].tupleSize == 2); - Q_ASSERT(m_attributes.attributes[1].type == GL_FLOAT); + Q_ASSERT(m_attributes.attributes[1].type == FloatType); return static_cast<const TexturedPoint2D *>(m_data); } @@ -274,18 +311,18 @@ inline const QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2 Q_ASSERT(m_attributes.stride == 2 * sizeof(float) + 4 * sizeof(char)); Q_ASSERT(m_attributes.attributes[0].position == 0); Q_ASSERT(m_attributes.attributes[0].tupleSize == 2); - Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT); + Q_ASSERT(m_attributes.attributes[0].type == FloatType); Q_ASSERT(m_attributes.attributes[1].position == 1); Q_ASSERT(m_attributes.attributes[1].tupleSize == 4); - Q_ASSERT(m_attributes.attributes[1].type == GL_UNSIGNED_BYTE); + Q_ASSERT(m_attributes.attributes[1].type == UnsignedByteType); return static_cast<const ColoredPoint2D *>(m_data); } int QSGGeometry::sizeOfIndex() const { - if (m_index_type == GL_UNSIGNED_SHORT) return 2; - else if (m_index_type == GL_UNSIGNED_BYTE) return 1; - else if (m_index_type == GL_UNSIGNED_INT) return 4; + if (m_index_type == UnsignedShortType) return 2; + else if (m_index_type == UnsignedByteType) return 1; + else if (m_index_type == UnsignedIntType) return 4; return 0; } diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.cpp b/src/quick/scenegraph/coreapi/qsgmaterial.cpp index ceb53d0d14..13598bbe1d 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterial.cpp +++ b/src/quick/scenegraph/coreapi/qsgmaterial.cpp @@ -40,7 +40,13 @@ #include "qsgmaterial.h" #include "qsgrenderer_p.h" #include "qsgmaterialshader_p.h" -#include <private/qsgshadersourcebuilder_p.h> +#ifndef QT_NO_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 @@ -58,16 +64,17 @@ void qsg_set_material_failure() qsg_material_failure = true; } #endif - +#ifndef QT_NO_OPENGL const char *QSGMaterialShaderPrivate::loadShaderSource(QOpenGLShader::ShaderType type) const { - QStringList files = m_sourceFiles[type]; + const QStringList files = m_sourceFiles[type]; QSGShaderSourceBuilder builder; - Q_FOREACH (const QString &file, files) + 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"); @@ -220,7 +227,7 @@ QSGMaterialShader::~QSGMaterialShader() defines the attribute register position in the vertex shader. */ - +#ifndef QT_NO_OPENGL /*! \fn const char *QSGMaterialShader::vertexShader() const @@ -256,7 +263,7 @@ const char *QSGMaterialShader::fragmentShader() const Returns the shader program used by this QSGMaterialShader. */ - +#endif /*! \fn void QSGMaterialShader::initialize() @@ -313,6 +320,7 @@ void QSGMaterialShader::updateState(const RenderState & /* state */, QSGMaterial { } +#ifndef QT_NO_OPENGL /*! Sets the GLSL source file for the shader stage \a type to \a sourceFile. The default implementation of the vertexShader() and fragmentShader() functions @@ -388,7 +396,7 @@ void QSGMaterialShader::compile() } } - +#endif /*! \class QSGMaterialShader::RenderState @@ -542,7 +550,7 @@ QRect QSGMaterialShader::RenderState::deviceRect() const return static_cast<const QSGRenderer *>(m_data)->deviceRect(); } - +#ifndef QT_NO_OPENGL /*! Returns the QOpenGLContext that is being used for rendering @@ -550,9 +558,15 @@ QRect QSGMaterialShader::RenderState::deviceRect() const QOpenGLContext *QSGMaterialShader::RenderState::context() const { - return static_cast<const QSGRenderer *>(m_data)->context()->openglContext(); + // 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; @@ -667,7 +681,6 @@ QSGMaterial::~QSGMaterial() the full matrix of the geometry nodes for rendering. \value CustomCompileStep Starting with Qt 5.2, the scene graph will not always call - QSGMaterialShader::compile() when its shader program is compiled and linked. Set this flag to enforce that the function is called. diff --git a/src/quick/scenegraph/coreapi/qsgmaterial.h b/src/quick/scenegraph/coreapi/qsgmaterial.h index 0a6a340092..114651653f 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterial.h +++ b/src/quick/scenegraph/coreapi/qsgmaterial.h @@ -41,7 +41,11 @@ #define QSGMATERIAL_H #include <QtQuick/qtquickglobal.h> -#include <QtGui/qopenglshaderprogram.h> +#ifndef QT_NO_OPENGL +# include <QtGui/qopenglshaderprogram.h> +#endif +#include <QtGui/QMatrix4x4> +#include <QtCore/QRect> QT_BEGIN_NAMESPACE @@ -59,8 +63,10 @@ public: public: enum DirtyState { - DirtyMatrix = 0x0001, - DirtyOpacity = 0x0002 + DirtyMatrix = 0x0001, + DirtyOpacity = 0x0002, + DirtyCachedMaterialData = 0x0004, + DirtyAll = 0xFFFF }; Q_DECLARE_FLAGS(DirtyStates, DirtyState) @@ -68,6 +74,7 @@ public: inline bool isMatrixDirty() const { return m_dirty & DirtyMatrix; } inline bool isOpacityDirty() const { return m_dirty & DirtyOpacity; } + bool isCachedMaterialDataDirty() const { return m_dirty & DirtyCachedMaterialData; } float opacity() const; QMatrix4x4 combinedMatrix() const; @@ -77,9 +84,9 @@ public: QRect deviceRect() const; float determinant() const; float devicePixelRatio() const; - +#ifndef QT_NO_OPENGL QOpenGLContext *context() const; - +#endif private: friend class QSGRenderer; DirtyStates m_dirty; @@ -94,27 +101,30 @@ public: // First time a material is used, oldMaterial is null. virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); virtual char const *const *attributeNames() const = 0; // Array must end with null. - +#ifndef QT_NO_OPENGL inline QOpenGLShaderProgram *program() { return &m_program; } - +#endif protected: Q_DECLARE_PRIVATE(QSGMaterialShader) QSGMaterialShader(QSGMaterialShaderPrivate &dd); - friend class QSGRenderContext; + friend class QSGDefaultRenderContext; friend class QSGBatchRenderer::ShaderManager; - +#ifndef QT_NO_OPENGL void setShaderSourceFile(QOpenGLShader::ShaderType type, const QString &sourceFile); void setShaderSourceFiles(QOpenGLShader::ShaderType type, const QStringList &sourceFiles); virtual void compile(); +#endif virtual void initialize() { } - +#ifndef QT_NO_OPENGL virtual const char *vertexShader() const; virtual const char *fragmentShader() const; - +#endif private: +#ifndef QT_NO_OPENGL QOpenGLShaderProgram m_program; +#endif QScopedPointer<QSGMaterialShaderPrivate> d_ptr; }; diff --git a/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h index 291c0cc57c..0dbce010db 100644 --- a/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h +++ b/src/quick/scenegraph/coreapi/qsgmaterialshader_p.h @@ -59,10 +59,12 @@ QT_BEGIN_NAMESPACE class Q_QUICK_PRIVATE_EXPORT QSGMaterialShaderPrivate { public: +#ifndef QT_NO_OPENGL const char *loadShaderSource(QOpenGLShader::ShaderType type) const; QHash<QOpenGLShader::ShaderType, QStringList> m_sourceFiles; mutable QHash<QOpenGLShader::ShaderType, QByteArray> m_sources; +#endif }; #ifndef QT_NO_DEBUG diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp index 53798f0e07..a1e1ef8c27 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.cpp +++ b/src/quick/scenegraph/coreapi/qsgnode.cpp @@ -778,6 +778,18 @@ QSGBasicGeometryNode::~QSGBasicGeometryNode() \internal */ +/*! + \fn void QSGBasicGeometryNode::setRendererMatrix(const QMatrix4x4 *m) + + \internal + */ + +/*! + \fn void QSGBasicGeometryNode::setRendererClipList(const QSGClipNode *c) + + \internal + */ + /*! Sets the geometry of this node to \a geometry. @@ -1256,7 +1268,7 @@ QSGRootNode::QSGRootNode() QSGRootNode::~QSGRootNode() { while (!m_renderers.isEmpty()) - m_renderers.last()->setRootNode(0); + m_renderers.constLast()->setRootNode(0); destroy(); // Must call destroy() here because markDirty() casts this to QSGRootNode. } @@ -1454,8 +1466,6 @@ void QSGNodeVisitor::visitChildren(QSGNode *n) visitNode(c); } - - #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const QSGGeometryNode *n) { @@ -1472,15 +1482,15 @@ QDebug operator<<(QDebug d, const QSGGeometryNode *n) } else { switch (g->drawingMode()) { - case GL_TRIANGLE_STRIP: d << "strip"; break; - case GL_TRIANGLE_FAN: d << "fan"; break; - case GL_TRIANGLES: d << "triangles"; break; + case QSGGeometry::DrawTriangleStrip: d << "strip"; break; + case QSGGeometry::DrawTriangleFan: d << "fan"; break; + case QSGGeometry::DrawTriangles: d << "triangles"; break; default: break; } d << "#V:" << g->vertexCount() << "#I:" << g->indexCount(); - if (g->attributeCount() > 0 && g->attributes()->type == GL_FLOAT) { + if (g->attributeCount() > 0 && g->attributes()->type == QSGGeometry::FloatType) { float x1 = 1e10, x2 = -1e10, y1=1e10, y2=-1e10; int stride = g->sizeOfVertex(); for (int i = 0; i < g->vertexCount(); ++i) { diff --git a/src/quick/scenegraph/coreapi/qsgnode.h b/src/quick/scenegraph/coreapi/qsgnode.h index 9d14ae04df..f7ea6dbe23 100644 --- a/src/quick/scenegraph/coreapi/qsgnode.h +++ b/src/quick/scenegraph/coreapi/qsgnode.h @@ -79,8 +79,8 @@ public: OpacityNodeType, #ifndef qdoc RootNodeType, - RenderNodeType #endif + RenderNodeType }; enum Flag { @@ -204,13 +204,15 @@ public: const QMatrix4x4 *matrix() const { return m_matrix; } const QSGClipNode *clipList() const { return m_clip_list; } + void setRendererMatrix(const QMatrix4x4 *m) { m_matrix = m; } + void setRendererClipList(const QSGClipNode *c) { m_clip_list = c; } + protected: QSGBasicGeometryNode(NodeType type); QSGBasicGeometryNode(QSGBasicGeometryNodePrivate &dd, NodeType type); private: friend class QSGNodeUpdater; - friend class QSGBatchRenderer::Updater; QSGGeometry *m_geometry; diff --git a/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp index 372ffce9d6..d6d533307e 100644 --- a/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp +++ b/src/quick/scenegraph/coreapi/qsgnodeupdater.cpp @@ -175,9 +175,10 @@ void QSGNodeUpdater::enterRenderNode(QSGRenderNode *r) qDebug() << "enter render:" << r; #endif - r->m_matrix = m_combined_matrix_stack.isEmpty() ? 0 : m_combined_matrix_stack.last(); - r->m_clip_list = m_current_clip; - r->setInheritedOpacity(m_opacity_stack.last()); + QSGRenderNodePrivate *rd = QSGRenderNodePrivate::get(r); + rd->m_matrix = m_combined_matrix_stack.isEmpty() ? 0 : m_combined_matrix_stack.last(); + rd->m_clip_list = m_current_clip; + rd->m_opacity = m_opacity_stack.last(); } void QSGNodeUpdater::leaveRenderNode(QSGRenderNode *r) diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp index ace10661c0..220e6ab212 100644 --- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp @@ -39,11 +39,15 @@ #include "qsgrenderer_p.h" #include "qsgnodeupdater_p.h" - -#include <qopenglframebufferobject.h> - +#ifndef QT_NO_OPENGL +# include <QtGui/QOpenGLFramebufferObject> +# include <QtGui/QOpenGLContext> +# include <QtGui/QOpenGLFunctions> +#endif #include <private/qquickprofiler_p.h> +#include <QtCore/QElapsedTimer> + QT_BEGIN_NAMESPACE static const bool qsg_sanity_check = qEnvironmentVariableIntValue("QSG_SANITY_CHECK"); @@ -63,19 +67,25 @@ int qt_sg_envInt(const char *name, int defaultValue) void QSGBindable::clear(QSGAbstractRenderer::ClearMode mode) const { +#ifndef QT_NO_OPENGL GLuint bits = 0; if (mode & QSGAbstractRenderer::ClearColorBuffer) bits |= GL_COLOR_BUFFER_BIT; if (mode & QSGAbstractRenderer::ClearDepthBuffer) bits |= GL_DEPTH_BUFFER_BIT; if (mode & QSGAbstractRenderer::ClearStencilBuffer) bits |= GL_STENCIL_BUFFER_BIT; QOpenGLContext::currentContext()->functions()->glClear(bits); +#else + Q_UNUSED(mode) +#endif } // Reactivate the color buffer after switching to the stencil. void QSGBindable::reactivate() const { +#ifndef QT_NO_OPENGL QOpenGLContext::currentContext()->functions()->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); +#endif } - +#ifndef QT_NO_OPENGL QSGBindableFboId::QSGBindableFboId(GLuint id) : m_id(id) { @@ -86,7 +96,7 @@ void QSGBindableFboId::bind() const { QOpenGLContext::currentContext()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_id); } - +#endif /*! \class QSGRenderer \brief The renderer class is the abstract baseclass use for rendering the @@ -169,8 +179,9 @@ bool QSGRenderer::isMirrored() const return matrix(0, 0) * matrix(1, 1) - matrix(0, 1) * matrix(1, 0) > 0; } -void QSGRenderer::renderScene(GLuint fboId) +void QSGRenderer::renderScene(uint fboId) { +#ifndef QT_NO_OPENGL if (fboId) { QSGBindableFboId bindable(fboId); renderScene(bindable); @@ -182,7 +193,11 @@ void QSGRenderer::renderScene(GLuint fboId) } bindable; renderScene(bindable); } +#else + Q_UNUSED(fboId) +#endif } + void QSGRenderer::renderScene(const QSGBindable &bindable) { if (!rootNode()) @@ -207,6 +222,7 @@ void QSGRenderer::renderScene(const QSGBindable &bindable) bindTime = frameTimer.nsecsElapsed(); Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame); +#ifndef QT_NO_OPENGL // Sanity check that attribute registers are disabled if (qsg_sanity_check) { GLint count = 0; @@ -219,6 +235,7 @@ void QSGRenderer::renderScene(const QSGBindable &bindable) } } } +#endif render(); if (profileFrames) diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h index 5c7a32c161..94b78a85b4 100644 --- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h @@ -86,14 +86,12 @@ public: bool isMirrored() const; void renderScene(const QSGBindable &bindable); - virtual void renderScene(GLuint fboId = 0) Q_DECL_OVERRIDE; + virtual void renderScene(uint fboId = 0) Q_DECL_OVERRIDE; virtual void nodeChanged(QSGNode *node, QSGNode::DirtyState state) Q_DECL_OVERRIDE; QSGNodeUpdater *nodeUpdater() const; void setNodeUpdater(QSGNodeUpdater *updater); - inline QSGMaterialShader::RenderState state(QSGMaterialShader::RenderState::DirtyStates dirty) const; - virtual void setCustomRenderMode(const QByteArray &) { }; void clearChangedFlag() { m_changed_emitted = false; } @@ -135,7 +133,7 @@ public: virtual void clear(QSGAbstractRenderer::ClearMode mode) const; virtual void reactivate() const; }; - +#ifndef QT_NO_OPENGL class QSGBindableFboId : public QSGBindable { public: @@ -144,7 +142,7 @@ public: private: GLuint m_id; }; - +#endif QSGMaterialShader::RenderState QSGRenderer::state(QSGMaterialShader::RenderState::DirtyStates dirty) const diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp new file mode 100644 index 0000000000..fa543aecad --- /dev/null +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.cpp @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgrendererinterface.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QSGRendererInterface + \brief An interface providing access to some of the graphics API specific internals + of the scenegraph. + \inmodule QtQuick + \since 5.8 + + Renderer interfaces allow accessing graphics API specific functionality in + the scenegraph. Such internals are not typically exposed. However, when + integrating custom rendering via QSGRenderNode for example, it may become + necessary to query certain values, for instance the graphics device (e.g. + the Direct3D or Vulkan device) that is used by the scenegraph. + + QSGRendererInterface's functions have varying availability. API and + language queries, like graphicsApi() or shaderType() are always available, + meaning it is sufficient to construct a QQuickWindow or QQuickView, and the + graphics API or shading language in use can be queried right after via + QQuickWindow::rendererInterface(). This guarantees that utilities like the + GraphicsInfo QML type are able to report the correct values as early as + possible, without having conditional property values - depending on for + instance shaderType() - evaluate to unexpected values. + + Engine-specific accessors, like getResource(), are however available only + after the scenegraph is initialized. Additionally, there may be + backend-specific limitations on when such functions can be called. The only + way that is guaranteed to succeed is calling them when the rendering of a + node (i.e. the preparation of the command list for the next frame) is + active. In practice this typically means QSGRenderNode::render(). + */ + +/*! + \enum QSGRendererInterface::GraphicsApi + \value Unknown An unknown graphics API is in use + \value Software The Qt Quick 2D Renderer is in use + \value OpenGL OpenGL ES 2.0 or higher + \value Direct3D12 Direct3D 12 + */ + +/*! + \enum QSGRendererInterface::Resource + \value Device The graphics device, when applicable. + \value CommandQueue The graphics command queue used by the scenegraph, when applicable. + \value CommandList The command list or buffer used by the scenegraph, when applicable. + \value Painter The active QPainter used by the scenegraph, when running with the software backend. + */ + +/*! + \enum QSGRendererInterface::ShaderType + \value UnknownShadingLanguage Not yet known due to no window and scenegraph associated + \value GLSL GLSL or GLSL ES + \value HLSL HLSL + */ + +/*! + \enum QSGRendererInterface::ShaderCompilationType + \value RuntimeCompilation Runtime compilation of shader source code is supported + \value OfflineCompilation Pre-compiled bytecode supported + */ + +/*! + \enum QSGRendererInterface::ShaderSourceType + + \value ShaderSourceString Shader source can be provided as a string in + the corresponding properties of ShaderEffect + + \value ShaderSourceFile Local or resource files containing shader source + code are supported + + \value ShaderByteCode Local or resource files containing shader bytecode are + supported + */ + +QSGRendererInterface::~QSGRendererInterface() +{ +} + +/*! + \fn QSGRendererInterface::GraphicsApi QSGRendererInterface::graphicsApi() const + + Returns the graphics API that is in use by the Qt Quick scenegraph. + + \note This function can be called on any thread. + */ + +/*! + Queries a graphics \a resource. Returns null when the resource in question is + not supported or not available. + + When successful, the returned pointer is either a direct pointer to an + interface (and can be cast, for example, to \c{ID3D12Device *}) or a + pointer to an opaque handle that needs to be dereferenced first (for + example, \c{VkDevice dev = *static_cast<VkDevice *>(result)}). The latter + is necessary since such handles may have sizes different from a pointer. + + \note The ownership of the returned pointer is never transferred to the caller. + + \note This function must only be called on the render thread. + */ +void *QSGRendererInterface::getResource(QQuickWindow *window, Resource resource) const +{ + Q_UNUSED(window); + Q_UNUSED(resource); + return nullptr; +} + +/*! + Queries a graphics resource. \a resource is a backend-specific key. This + allows supporting any future resources that are not listed in the + Resource enum. + + \note The ownership of the returned pointer is never transferred to the caller. + + \note This function must only be called on the render thread. + */ +void *QSGRendererInterface::getResource(QQuickWindow *window, const char *resource) const +{ + Q_UNUSED(window); + Q_UNUSED(resource); + return nullptr; +} + +/*! + \fn QSGRendererInterface::ShaderType QSGRendererInterface::shaderType() const + + \return the shading language supported by the Qt Quick backend the + application is using. + + \note This function can be called on any thread. + + \sa QtQuick::GraphicsInfo + */ + +/*! + \fn QSGRendererInterface::ShaderCompilationTypes QSGRendererInterface::shaderCompilationType() const + + \return a bitmask of the shader compilation approaches supported by the Qt + Quick backend the application is using. + + \note This function can be called on any thread. + + \sa QtQuick::GraphicsInfo + */ + +/*! + \fn QSGRendererInterface::ShaderSourceTypes QSGRendererInterface::shaderSourceType() const + + \return a bitmask of the supported ways of providing shader sources in ShaderEffect items. + + \note This function can be called on any thread. + + \sa QtQuick::GraphicsInfo + */ + +QT_END_NAMESPACE diff --git a/src/quick/scenegraph/coreapi/qsgrendererinterface.h b/src/quick/scenegraph/coreapi/qsgrendererinterface.h new file mode 100644 index 0000000000..a50b362aeb --- /dev/null +++ b/src/quick/scenegraph/coreapi/qsgrendererinterface.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGRENDERERINTERFACE_H +#define QSGRENDERERINTERFACE_H + +#include <QtQuick/qsgnode.h> + +QT_BEGIN_NAMESPACE + +class QQuickWindow; + +class Q_QUICK_EXPORT QSGRendererInterface +{ +public: + enum GraphicsApi { + Unknown, + Software, + OpenGL, + Direct3D12 + }; + + enum Resource { + Device, + CommandQueue, + CommandList, + Painter + }; + + enum ShaderType { + UnknownShadingLanguage, + GLSL, + HLSL + }; + + enum ShaderCompilationType { + RuntimeCompilation = 0x01, + OfflineCompilation = 0x02 + }; + Q_DECLARE_FLAGS(ShaderCompilationTypes, ShaderCompilationType) + + enum ShaderSourceType { + ShaderSourceString = 0x01, + ShaderSourceFile = 0x02, + ShaderByteCode = 0x04 + }; + Q_DECLARE_FLAGS(ShaderSourceTypes, ShaderSourceType) + + virtual ~QSGRendererInterface(); + + virtual GraphicsApi graphicsApi() const = 0; + + virtual void *getResource(QQuickWindow *window, Resource resource) const; + virtual void *getResource(QQuickWindow *window, const char *resource) const; + + virtual ShaderType shaderType() const = 0; + virtual ShaderCompilationTypes shaderCompilationType() const = 0; + virtual ShaderSourceTypes shaderSourceType() const = 0; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRendererInterface::ShaderCompilationTypes) +Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRendererInterface::ShaderSourceTypes) + +QT_END_NAMESPACE + +#endif diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.cpp b/src/quick/scenegraph/coreapi/qsgrendernode.cpp index 1a38f6495e..5915d51f2b 100644 --- a/src/quick/scenegraph/coreapi/qsgrendernode.cpp +++ b/src/quick/scenegraph/coreapi/qsgrendernode.cpp @@ -37,28 +37,51 @@ ** ****************************************************************************/ +#include "qsgrendernode.h" #include "qsgrendernode_p.h" QT_BEGIN_NAMESPACE +/*! + \class QSGRenderNode + \brief The QSGRenderNode class represents a set of custom rendering commands + targeting the graphics API that is in use by the scenegraph. + \inmodule QtQuick + \since 5.8 + */ + QSGRenderNode::QSGRenderNode() - : QSGNode(RenderNodeType) - , m_matrix(0) - , m_clip_list(0) - , m_opacity(1) + : QSGNode(RenderNodeType), + d(new QSGRenderNodePrivate) { } -void QSGRenderNode::setInheritedOpacity(qreal opacity) +/*! + Destructs the render node. Derived classes are expected to perform cleanup + similar to releaseResources() in here. + + When a low-level graphics API is in use, the scenegraph will make sure + there is a CPU-side wait for the GPU to complete all work submitted to the + scenegraph's graphics command queue before the scenegraph's nodes are + deleted. Therefore there is no need to issue additional waits here, unless + the render() implementation is using additional command queues. + + \sa releaseResources() + */ +QSGRenderNode::~QSGRenderNode() { - Q_ASSERT(opacity >= 0 && opacity <= 1); - m_opacity = opacity; + delete d; } -/*! - \fn QSGRenderNode::StateFlags QSGRenderNode::changedStates() +QSGRenderNodePrivate::QSGRenderNodePrivate() + : m_matrix(0) + , m_clip_list(0) + , m_opacity(1) +{ +} - This function should return a mask where each bit represents OpenGL states changed by +/*! + This function should return a mask where each bit represents graphics states changed by the \l render() function: \list \li DepthState - depth write mask, depth test enabled, depth comparison function @@ -69,30 +92,71 @@ void QSGRenderNode::setInheritedOpacity(qreal opacity) \li BlendState - blend enabled, blend function \li CullState - front face, cull face enabled \li ViewportState - viewport + \li RenderTargetState - render target \endlist - The function is called by the renderer so it can reset the OpenGL states after rendering this - node. + The function is called by the renderer so it can reset the states after + rendering this node. This makes the implementation of render() simpler + since it does not have to query and restore these states. + + The default implementation returns 0, meaning no relevant state was changed + in render(). + + With APIs other than OpenGL the relevant states are only those that are set + via the command list (for example, OMSetRenderTargets, RSSetViewports, + RSSetScissorRects, OMSetBlendFactor, OMSetStencilRef in case of D3D12), and + only when such commands were added to the scenegraph's command list queried + via the QSGRendererInterface::CommandList resource enum. States set in + pipeline state objects do not need to be reported here. Similarly, draw + call related settings (root signature, descriptor heaps, etc.) are always + set again by the scenegraph so render() can freely change them. - \internal + The software backend exposes its QPainter and saves and restores before and + after invoking render(). Therefore reporting any changed states from here + is not necessary. + + \note This function may be called before render(). */ +QSGRenderNode::StateFlags QSGRenderNode::changedStates() const +{ + return 0; +} /*! - \fn void QSGRenderNode::render(const RenderState &state) + \fn void QSGRenderNode::render(const RenderState *state) - This function is called by the renderer and should paint this node with OpenGL commands. - - The states necessary for clipping has already been set before the function is called. - The clip is a combination of a stencil clip and scissor clip. Information about the clip is - found in \a state. + This function is called by the renderer and should paint this node with + directly invoking commands in the graphics API (OpenGL, Direct3D, etc.) + currently in use. The effective opacity can be retrieved with \l inheritedOpacity(). - The projection matrix is available through \a state, while the model-view matrix can be - fetched with \l matrix(). The combined matrix is then the projection matrix times the - model-view matrix. + The projection matrix is available through \a state, while the model-view + matrix can be fetched with \l matrix(). The combined matrix is then the + projection matrix times the model-view matrix. The correct stacking of the + items in the scene is ensured by the projection matrix. + + When using the provided matrices, the coordinate system for vertex data + follows the usual QQuickItem conventions: top-left is (0, 0), bottom-right + is the corresponding QQuickItem's width() and height() minus one. For + example, assuming a two float (x-y) per vertex coordinate layout, a + triangle covering half of the item can be specified as (width - 1, height - 1), + (0, 0), (0, height - 1) using counter-clockwise direction. + + \note QSGRenderNode is provided as a means to implement custom 2D or 2.5D + Qt Quick items. It is not intended for integrating true 3D content into the + Qt Quick scene. That use case is better supported by + QQuickFramebufferObject, QQuickWindow::beforeRendering(), or the + equivalents of those for APIs other than OpenGL. - The following states are set before this function is called: + Clip information is calculated before the function is called, it is however + not enabled. Implementations wishing to take clipping into account can set + up scissoring or stencil based on the information in \a state. Some + scenegraph backends, software in particular, use no scissor or stencil. + There the clip region is provided as an ordinary QRegion. + + For OpenGL the following states are set on the render thread's context + before this function is called: \list \li glDepthMask(false) \li glDisable(GL_DEPTH_TEST) @@ -107,14 +171,209 @@ void QSGRenderNode::setInheritedOpacity(qreal opacity) \li glDisable(GL_CULL_FACE) \endlist - States that are not listed above, but are included in \l StateFlags, can have arbitrary - values. + States that are not listed above, but are included in \l StateFlags, can + have arbitrary values. + + \l changedStates() should return which states this function changes. If a + state is not covered by \l StateFlags, the state should be set to the + default value according to the OpenGL specification. For other APIs, see + the documentation for changedStates() for more information. + + \note Depth writes are disabled when this function is called (for example, + glDepthMask(false) in case of OpenGL). Enabling depth writes can lead to + unexpected results, depending on the scenegraph backend in use, so nodes + should avoid this. - \l changedStates() should return which states this function has changed. If a state is not - covered by \l StateFlags, the state should be set to the default value according to the - OpenGL specification. + For APIs other than OpenGL, it will likely be necessary to query certain + API-specific resources (for example, the graphics device or the command + list/buffer to add the commands to). This is done via QSGRendererInterface. - \internal + \sa QSGRendererInterface, QQuickWindow::rendererInterface() */ +/*! + This function is called when all custom graphics resources allocated by + this node have to be freed immediately. In case the node does not directly + allocate graphics resources (buffers, textures, render targets, fences, + etc.) through the graphics API that is in use, there is nothing to do here. + + Failing to release all custom resources can lead to incorrect behavior in + graphics device loss scenarios on some systems since subsequent + reinitialization of the graphics system may fail. + + \note Some scenegraph backends may choose not to call this function. + Therefore it is expected that QSGRenderNode implementations perform cleanup + both in their destructor and in releaseResources(). + + Unlike with the destructor, it is expected that render() can reinitialize + all resources it needs when called after a call to releaseResources(). + + With OpenGL, the scenegraph's OpenGL context will be current both when + calling the destructor and this function. + */ +void QSGRenderNode::releaseResources() +{ +} + +/*! + \enum QSGRenderNode::RenderingFlag + + Possible values for the bitmask returned from flags(). + + \value BoundedRectRendering Indicates that the implementation of render() + does not render outside the area reported from rect() in item + coordinates. Such node implementations can lead to more efficient rendering, + depending on the scenegraph backend. For example, the software backend can + continue to use the more optimal partial update path when all render nodes + in the scene have this flag set. + + \value DepthAwareRendering Indicates that the implementations of render() + conforms to scenegraph expectations by only generating a Z value of 0 in + scene coordinates which is then transformed by the matrices retrieved from + RenderState::projectionMatrix() and matrix(), as described in the notes for + render(). Such node implementations can lead to more efficient rendering, + depending on the scenegraph backend. For example, the batching OpenGL + renderer can continue to use a more optimal path when all render nodes in + the scene have this flag set. + + \value OpaqueRendering Indicates that the implementation of render() writes + out opaque pixels for the entire area reported from rect(). By default the + renderers must assume that render() can also output semi or fully + transparent pixels. Setting this flag can improve performance in some + cases. + + \sa render(), rect() + */ + +/*! + \return flags describing the behavior of this render node. + + The default implementation returns 0. + + \sa RenderingFlag, rect() + */ +QSGRenderNode::RenderingFlags QSGRenderNode::flags() const +{ + return 0; +} + +/*! + \return the bounding rectangle in item coordinates for the area render() + touches. The value is only in use when flags() includes + BoundedRectRendering, ignored otherwise. + + Reporting the rectangle in combination with BoundedRectRendering is + particularly important with the \c software backend because otherwise + having a rendernode in the scene would trigger fullscreen updates, skipping + all partial update optimizations. + + For rendernodes covering the entire area of a corresponding QQuickItem the + return value will be (0, 0, item->width(), item->height()). + + \sa flags() +*/ +QRectF QSGRenderNode::rect() const +{ + return QRectF(); +} + +/*! + \return pointer to the current model-view matrix. + */ +const QMatrix4x4 *QSGRenderNode::matrix() const +{ + return d->m_matrix; +} + +/*! + \return the current clip list. + */ +const QSGClipNode *QSGRenderNode::clipList() const +{ + return d->m_clip_list; +} + +/*! + \return the current effective opacity. + */ +qreal QSGRenderNode::inheritedOpacity() const +{ + return d->m_opacity; +} + +QSGRenderNode::RenderState::~RenderState() +{ +} + +/*! + \fn const QMatrix4x4 *QSGRenderNode::RenderState::projectionMatrix() const + + \return pointer to the current projection matrix. + + The model-view matrix can be retrieved with QSGRenderNode::matrix(). + Typically \c{projection * modelview} is the matrix that is then used in the + vertex shader to transform the vertices. + */ + +/*! + \fn const QMatrix4x4 *QSGRenderNode::RenderState::scissorRect() const + + \return the current scissor rectangle when clipping is active. + + \note Be aware of the differences between graphics APIs: for some the + scissor rect is only active when scissoring is enabled (for example, + OpenGL), while for others the scissor rect is equal to the viewport rect + when there is no need to scissor away anything (for example, Direct3D 12). + */ + +/*! + \fn const QMatrix4x4 *QSGRenderNode::RenderState::scissorEnabled() const + + \return the current state of scissoring. + + \note Only relevant for graphics APIs that have a dedicated on/off state of + scissoring. + */ + +/*! + \fn const QMatrix4x4 *QSGRenderNode::RenderState::stencilValue() const + + \return the current stencil reference value when clipping is active. + */ + +/*! + \fn const QMatrix4x4 *QSGRenderNode::RenderState::stencilEnabled() const + + \return the current state of stencil testing. + + \note With graphics APIs where stencil testing is enabled in pipeline state + objects, instead of individual state-setting commands, it is up to the + implementation of render() to enable stencil testing with operations + \c KEEP, comparison function \c EQUAL, and a read and write mask of \c 0xFF. + */ + +/*! + \fn const QRegion *QSGRenderNode::clipRegion() const + + \return the current clip region or null for backends where clipping is + implemented via stencil or scissoring. + + The software backend uses no projection, scissor or stencil, meaning most + of the render state is not in use. However, the clip region that can be set + on the QPainter still has to be communicated since reconstructing this + manually in render() is not reasonable. It can therefore be queried via + this function. + */ + +/*! + \return pointer to a \a state value. + + Reserved for future use. + */ +void *QSGRenderNode::RenderState::get(const char *state) const +{ + Q_UNUSED(state); + return nullptr; +} + QT_END_NAMESPACE diff --git a/src/quick/scenegraph/coreapi/qsgrendernode.h b/src/quick/scenegraph/coreapi/qsgrendernode.h new file mode 100644 index 0000000000..f6bc40d3ee --- /dev/null +++ b/src/quick/scenegraph/coreapi/qsgrendernode.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGRENDERNODE_H +#define QSGRENDERNODE_H + +#include <QtQuick/qsgnode.h> + +QT_BEGIN_NAMESPACE + +class QSGRenderNodePrivate; + +class Q_QUICK_EXPORT QSGRenderNode : public QSGNode +{ +public: + enum StateFlag { + DepthState = 0x01, + StencilState = 0x02, + ScissorState = 0x04, + ColorState = 0x08, + BlendState = 0x10, + CullState = 0x20, + ViewportState = 0x40, + RenderTargetState = 0x80 + }; + Q_DECLARE_FLAGS(StateFlags, StateFlag) + + enum RenderingFlag { + BoundedRectRendering = 0x01, + DepthAwareRendering = 0x02, + OpaqueRendering = 0x04 + }; + Q_DECLARE_FLAGS(RenderingFlags, RenderingFlag) + + struct Q_QUICK_EXPORT RenderState { + virtual ~RenderState(); + virtual const QMatrix4x4 *projectionMatrix() const = 0; + virtual QRect scissorRect() const = 0; + virtual bool scissorEnabled() const = 0; + virtual int stencilValue() const = 0; + virtual bool stencilEnabled() const = 0; + virtual const QRegion *clipRegion() const = 0; + virtual void *get(const char *state) const; + }; + + QSGRenderNode(); + ~QSGRenderNode(); + + virtual StateFlags changedStates() const; + virtual void render(const RenderState *state) = 0; + virtual void releaseResources(); + virtual RenderingFlags flags() const; + virtual QRectF rect() const; + + const QMatrix4x4 *matrix() const; + const QSGClipNode *clipList() const; + qreal inheritedOpacity() const; + +private: + QSGRenderNodePrivate *d; + friend class QSGRenderNodePrivate; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderNode::StateFlags) +Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderNode::RenderingFlags) + +QT_END_NAMESPACE + +#endif diff --git a/src/quick/scenegraph/coreapi/qsgrendernode_p.h b/src/quick/scenegraph/coreapi/qsgrendernode_p.h index 8659b0e62c..5c42e55689 100644 --- a/src/quick/scenegraph/coreapi/qsgrendernode_p.h +++ b/src/quick/scenegraph/coreapi/qsgrendernode_p.h @@ -51,64 +51,23 @@ // We mean it. // -#include "qsgnode.h" -#include <private/qtquickglobal_p.h> +#include <QtQuick/qsgnode.h> +#include <QtQuick/qsgrendernode.h> QT_BEGIN_NAMESPACE -namespace QSGBatchRenderer { - class Renderer; -} - -class Q_QUICK_PRIVATE_EXPORT QSGRenderNode : public QSGNode +class QSGRenderNodePrivate { public: - enum StateFlag - { - DepthState = 0x01, // depth mask, depth test enable, depth func, clear depth - StencilState = 0x02, // stencil mask, stencil test enable, stencil op, stencil func, clear stencil - ScissorState = 0x04, // scissor enable, scissor test enable - ColorState = 0x08, // clear color, color mask - BlendState = 0x10, // blend enable, blend func - CullState = 0x20, // front face, cull face enable - ViewportState = 0x40 // viewport - }; - Q_DECLARE_FLAGS(StateFlags, StateFlag) - - struct RenderState - { - // The model-view matrix can be retrieved with matrix(). - // The opacity can be retrieved with inheritedOpacity(). - const QMatrix4x4 *projectionMatrix; - QRect scissorRect; - int stencilValue; - - bool stencilEnabled; - bool scissorEnabled; - }; - - QSGRenderNode(); + QSGRenderNodePrivate(); - virtual StateFlags changedStates() = 0; - virtual void render(const RenderState &state) = 0; - - const QMatrix4x4 *matrix() const { return m_matrix; } - const QSGClipNode *clipList() const { return m_clip_list; } - - void setInheritedOpacity(qreal opacity); - qreal inheritedOpacity() const { return m_opacity; } - -private: - friend class QSGNodeUpdater; - friend class QSGBatchRenderer::Renderer; + static QSGRenderNodePrivate *get(QSGRenderNode *node) { return node->d; } const QMatrix4x4 *m_matrix; const QSGClipNode *m_clip_list; qreal m_opacity; }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderNode::StateFlags) - QT_END_NAMESPACE #endif diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp index 97d7e69407..3a35632d5c 100644 --- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp +++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp @@ -89,9 +89,6 @@ void Tokenizer::initialize(const char *input) identifier = input; } -#define foo - - Tokenizer::Token Tokenizer::next() { while (*pos != 0) { |