diff options
Diffstat (limited to 'src/declarative/scenegraph')
35 files changed, 780 insertions, 292 deletions
diff --git a/src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp b/src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp index 382ac37d2c..a215968e2b 100644 --- a/src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp +++ b/src/declarative/scenegraph/coreapi/qsgdefaultrenderer.cpp @@ -46,7 +46,7 @@ #include "qsgmaterial.h" #include <QtCore/qvarlengtharray.h> -#include <QtGui/qapplication.h> +#include <QtGui/qguiapplication.h> #include <QtCore/qpair.h> #include <QtCore/QElapsedTimer> @@ -510,8 +510,7 @@ void QSGDefaultRenderer::renderNodes(const QDataBuffer<QSGGeometryNode *> &list) //glDepthRange((geomNode->renderOrder() + 0.1) * scale, (geomNode->renderOrder() + 0.9) * scale); const QSGGeometry *g = geomNode->geometry(); - bindGeometry(program, g); - draw(geomNode); + draw(program, g); #ifdef RENDERER_DEBUG geometryNodesDrawn++; diff --git a/src/declarative/scenegraph/coreapi/qsggeometry.cpp b/src/declarative/scenegraph/coreapi/qsggeometry.cpp index 71b5cb63f1..8661c9af93 100644 --- a/src/declarative/scenegraph/coreapi/qsggeometry.cpp +++ b/src/declarative/scenegraph/coreapi/qsggeometry.cpp @@ -40,10 +40,22 @@ ****************************************************************************/ #include "qsggeometry.h" +#include "qsggeometry_p.h" + +#include <qopenglcontext.h> +#include <qopenglfunctions.h> +#include <private/qopenglextensions_p.h> QT_BEGIN_NAMESPACE +QSGGeometry::Attribute QSGGeometry::Attribute::create(int attributeIndex, int tupleSize, int primitiveType, bool isPrimitive) +{ + Attribute a = { attributeIndex, tupleSize, primitiveType, isPrimitive, 0 }; + return a; +} + + /*! Convenience function which returns attributes to be used for 2D solid color drawing. @@ -52,7 +64,7 @@ QT_BEGIN_NAMESPACE const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_Point2D() { static Attribute data[] = { - { 0, 2, GL_FLOAT } + QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true) }; static AttributeSet attrs = { 1, sizeof(float) * 2, data }; return attrs; @@ -65,8 +77,8 @@ const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_Point2D() const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_TexturedPoint2D() { static Attribute data[] = { - { 0, 2, GL_FLOAT }, - { 1, 2, GL_FLOAT } + QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), + QSGGeometry::Attribute::create(1, 2, GL_FLOAT) }; static AttributeSet attrs = { 2, sizeof(float) * 4, data }; return attrs; @@ -79,8 +91,8 @@ const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_TexturedPoint2D( const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D() { static Attribute data[] = { - { 0, 2, GL_FLOAT }, - { 1, 4, GL_UNSIGNED_BYTE } + QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), + QSGGeometry::Attribute::create(1, 4, GL_UNSIGNED_BYTE) }; static AttributeSet attrs = { 2, 2 * sizeof(float) + 4 * sizeof(char), data }; return attrs; @@ -122,20 +134,58 @@ QSGGeometry::QSGGeometry(const QSGGeometry::AttributeSet &attributes, , m_attributes(attributes) , m_data(0) , m_index_data_offset(-1) + , m_server_data(0) , m_owns_data(false) + , m_index_usage_pattern(AlwaysUploadPattern) + , m_vertex_usage_pattern(AlwaysUploadPattern) { Q_ASSERT(m_attributes.count > 0); Q_ASSERT(m_attributes.stride > 0); + 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) { + 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); } +/*! + \fn int QSGGeometry::sizeOfVertex() const + + Returns the size in bytes of one vertex. + + This value comes from the attributes. + */ + +/*! + \fn int QSGGeometry::sizeOfIndex() const + + Returns the byte size of the index type. + + This value is either 1 when index type is GL_UNSIGNED_BYTE or 2 when + index type is GL_UNSIGNED_SHORT. For Desktop OpenGL, GL_UNSIGNED_INT + with the value 4 is also supported. + */ + QSGGeometry::~QSGGeometry() { if (m_owns_data) qFree(m_data); + + if (m_server_data) + delete m_server_data; } /*! @@ -250,6 +300,15 @@ void QSGGeometry::allocate(int vertexCount, int indexCount) m_owns_data = true; } + // If we have associated vbo data we could potentially crash later if + // the old buffers are used with the new vertex and index count, so we force + // an update in the renderer in that case. This is really the users responsibility + // but it is cheap for us to enforce this, so why not... + if (m_server_data) { + markIndexDataDirty(); + markVertexDataDirty(); + } + } /*! @@ -307,4 +366,101 @@ void QSGGeometry::updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, v[3].ty = textureRect.bottom(); } + + +/*! + \enum QSGGeometry::DataPattern + + The DataPattern enum is used to specify the use pattern for the vertex + and index data in a geometry object. + + \value AlwaysUploadPattern The data is always uploaded. This means that + the user does not need to explicitly mark index and vertex data as + dirty after changing it. This is the default. + + \value DynamicPattern The data is modified repeatedly and drawn many times. + This is a hint that may provide better performance. When set + the user must make sure to mark the data as dirty after changing it. + + \value StaticPattern The data is modified once and drawn many times. This is + a hint that may provide better performance. When set the user must make sure + to mark the data as dirty after changing it. + */ + + +/*! + \fn QSGGeometry::DataPattern QSGGeometry::indexDataPattern() const + + Returns the usage pattern for indices in this geometry. The default + pattern is AlwaysUploadPattern. + */ + +/*! + Sets the usage pattern for indices to \a p. + + The default is AlwaysUploadPattern. When set to anything other than + the default, the user must call markIndexDataDirty() after changing + the index data. + */ + +void QSGGeometry::setIndexDataPattern(DataPattern p) +{ + m_index_usage_pattern = p; +} + + + + +/*! + \fn QSGGeometry::DataPattern QSGGeometry::vertexDataPattern() const + + Returns the usage pattern for vertices in this geometry. The default + pattern is AlwaysUploadPattern. + */ + +/*! + Sets the usage pattern for vertices to \a p. + + The default is AlwaysUploadPattern. When set to anything other than + the default, the user must call markVertexDataDirty() after changing + the vertex data. + */ + +void QSGGeometry::setVertexDataPattern(DataPattern p) +{ + m_vertex_usage_pattern = p; +} + + + + +/*! + Mark that the vertices in this geometry has changed and must be uploaded + again. + + This function only has an effect when the usage pattern for vertices is + StaticData and the renderer that renders this geometry uploads the geometry + into Vertex Buffer Objects (VBOs). + */ +void QSGGeometry::markIndexDataDirty() +{ + m_dirty_index_data = true; +} + + + +/*! + Mark that the vertices in this geometry has changed and must be uploaded + again. + + This function only has an effect when the usage pattern for vertices is + StaticData and the renderer that renders this geometry uploads the geometry + into Vertex Buffer Objects (VBOs). + */ +void QSGGeometry::markVertexDataDirty() +{ + m_dirty_vertex_data = true; +} + + QT_END_NAMESPACE diff --git a/src/declarative/scenegraph/coreapi/qsggeometry.h b/src/declarative/scenegraph/coreapi/qsggeometry.h index 432503085d..d7b343c108 100644 --- a/src/declarative/scenegraph/coreapi/qsggeometry.h +++ b/src/declarative/scenegraph/coreapi/qsggeometry.h @@ -42,7 +42,8 @@ #ifndef QSGGEOMETRY_H #define QSGGEOMETRY_H -#include <QtOpenGL/qgl.h> +#include <QtGui/qopengl.h> +#include <QRectF> QT_BEGIN_HEADER @@ -50,14 +51,22 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) +class QSGGeometryData; + class Q_DECLARATIVE_EXPORT QSGGeometry { public: + struct Attribute { int position; int tupleSize; int type; + + uint isVertexCoordinate : 1; + uint migrateYourCodeToUseTheCreateFunction: 31; // ### Remove before release + + static Attribute create(int pos, int tupleSize, int primitiveType, bool isPosition = false); }; struct AttributeSet { @@ -92,6 +101,13 @@ 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, @@ -123,18 +139,31 @@ public: inline uint *indexDataAsUInt(); inline quint16 *indexDataAsUShort(); + inline int sizeOfIndex() const; + const void *indexData() const; inline const uint *indexDataAsUInt() const; inline const quint16 *indexDataAsUShort() const; inline int attributeCount() const { return m_attributes.count; } inline const Attribute *attributes() const { return m_attributes.attributes; } - inline int stride() const { return m_attributes.stride; } + inline int sizeOfVertex() const { return m_attributes.stride; } static void updateRectGeometry(QSGGeometry *g, const QRectF &rect); static void updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &sourceRect); + void setIndexDataPattern(DataPattern p); + DataPattern indexDataPattern() const { return (DataPattern) m_index_usage_pattern; } + + void setVertexDataPattern(DataPattern p); + DataPattern vertexDataPattern() const { return (DataPattern) m_vertex_usage_pattern; } + + void markIndexDataDirty(); + void markVertexDataDirty(); + private: + friend class QSGGeometryData; + int m_drawing_mode; int m_vertex_count; int m_index_count; @@ -143,10 +172,14 @@ private: void *m_data; int m_index_data_offset; - void *m_reserved_pointer; + QSGGeometryData *m_server_data; uint m_owns_data : 1; - uint m_reserved_bits : 31; + uint m_index_usage_pattern : 2; + uint m_vertex_usage_pattern : 2; + uint m_dirty_index_data : 1; + uint m_dirty_vertex_data : 1; + uint m_reserved_bits : 27; float m_prealloc[16]; }; @@ -247,6 +280,14 @@ inline const QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2 return (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; + return 0; +} + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/declarative/scenegraph/coreapi/qsggeometry_p.h b/src/declarative/scenegraph/coreapi/qsggeometry_p.h new file mode 100644 index 0000000000..2fba155000 --- /dev/null +++ b/src/declarative/scenegraph/coreapi/qsggeometry_p.h @@ -0,0 +1,32 @@ +#ifndef QSGGEOMETRY_P_H +#define QSGGEOMETRY_P_H + +#include "qsggeometry.h" + +QT_BEGIN_NAMESPACE + +class QSGGeometryData +{ +public: + virtual ~QSGGeometryData() {} + + static inline QSGGeometryData *data(const QSGGeometry *g) { + return g->m_server_data; + } + + static inline void install(const QSGGeometry *g, QSGGeometryData *data) { + Q_ASSERT(!g->m_server_data); + const_cast<QSGGeometry *>(g)->m_server_data = data; + } + + static bool inline hasDirtyVertexData(const QSGGeometry *g) { return g->m_dirty_vertex_data; } + static void inline clearDirtyVertexData(const QSGGeometry *g) { const_cast<QSGGeometry *>(g)->m_dirty_vertex_data = false; } + + static bool inline hasDirtyIndexData(const QSGGeometry *g) { return g->m_dirty_vertex_data; } + static void inline clearDirtyIndexData(const QSGGeometry *g) { const_cast<QSGGeometry *>(g)->m_dirty_index_data = false; } + +}; + +QT_END_NAMESPACE + +#endif // QSGGEOMETRY_P_H diff --git a/src/declarative/scenegraph/coreapi/qsgmaterial.cpp b/src/declarative/scenegraph/coreapi/qsgmaterial.cpp index ca172d6f49..65ce9eec93 100644 --- a/src/declarative/scenegraph/coreapi/qsgmaterial.cpp +++ b/src/declarative/scenegraph/coreapi/qsgmaterial.cpp @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE The QSGMaterial and QSGMaterialShader form a tight relationship. For one scene graph (including nested graphs), there is one unique QSGMaterialShader - instance which encapsulates the QGLShaderProgram the scene graph uses + 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 @@ -152,7 +152,7 @@ QSGMaterialShader::QSGMaterialShader() /*! - \fn QGLShaderProgram *QSGMaterialShader::program() const + \fn QOpenGLShaderProgram *QSGMaterialShader::program() const Returns the shader program used by this QSGMaterialShader. */ @@ -228,7 +228,7 @@ void QSGMaterialShader::updateState(const RenderState &state, QSGMaterial *newMa /*! This function is called when the shader is initialized to compile the - actual QGLShaderProgram. Do not call it explicitely. + actual QOpenGLShaderProgram. Do not call it explicitely. The default implementation will extract the vertexShader() and fragmentShader() and bind the names returned from attributeNames() @@ -239,8 +239,8 @@ void QSGMaterialShader::compile() { Q_ASSERT_X(!m_program.isLinked(), "QSGSMaterialShader::compile()", "Compile called multiple times!"); - program()->addShaderFromSourceCode(QGLShader::Vertex, vertexShader()); - program()->addShaderFromSourceCode(QGLShader::Fragment, fragmentShader()); + program()->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader()); + program()->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader()); char const *const *attr = attributeNames(); #ifndef QT_NO_DEBUG @@ -385,10 +385,10 @@ QRect QSGMaterialShader::RenderState::deviceRect() const /*! - Returns the QGLContext that is being used for rendering + Returns the QOpenGLContext that is being used for rendering */ -const QGLContext *QSGMaterialShader::RenderState::context() const +QOpenGLContext *QSGMaterialShader::RenderState::context() const { return static_cast<const QSGRenderer *>(m_data)->glContext(); } @@ -417,7 +417,7 @@ static void qt_print_material_count() 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 QGLShaderProgram the scene graph uses + 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 diff --git a/src/declarative/scenegraph/coreapi/qsgmaterial.h b/src/declarative/scenegraph/coreapi/qsgmaterial.h index 7c6935899e..084219bfba 100644 --- a/src/declarative/scenegraph/coreapi/qsgmaterial.h +++ b/src/declarative/scenegraph/coreapi/qsgmaterial.h @@ -42,7 +42,7 @@ #ifndef MATERIAL_H #define MATERIAL_H -#include <qglshaderprogram.h> +#include <qopenglshaderprogram.h> QT_BEGIN_HEADER @@ -75,7 +75,7 @@ public: QRect viewportRect() const; QRect deviceRect() const; - const QGLContext *context() const; + QOpenGLContext *context() const; private: friend class QSGRenderer; @@ -91,7 +91,7 @@ public: virtual void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial); virtual char const *const *attributeNames() const = 0; // Array must end with null. - inline QGLShaderProgram *program() { return &m_program; } + inline QOpenGLShaderProgram *program() { return &m_program; } protected: @@ -104,7 +104,7 @@ protected: virtual const char *fragmentShader() const = 0; private: - QGLShaderProgram m_program; + QOpenGLShaderProgram m_program; void *m_reserved; }; diff --git a/src/declarative/scenegraph/coreapi/qsgnode.cpp b/src/declarative/scenegraph/coreapi/qsgnode.cpp index bff289b332..083b073301 100644 --- a/src/declarative/scenegraph/coreapi/qsgnode.cpp +++ b/src/declarative/scenegraph/coreapi/qsgnode.cpp @@ -1102,7 +1102,7 @@ QDebug operator<<(QDebug d, const QSGGeometryNode *n) if (g->attributeCount() > 0 && g->attributes()->type == GL_FLOAT) { float x1 = 1e10, x2 = -1e10, y1=1e10, y2=-1e10; - int stride = g->stride(); + int stride = g->sizeOfVertex(); for (int i = 0; i < g->vertexCount(); ++i) { float x = ((float *)((char *)const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[0]; float y = ((float *)((char *)const_cast<QSGGeometry *>(g)->vertexData() + i * stride))[1]; @@ -1235,7 +1235,8 @@ QDebug operator<<(QDebug d, const QSGNode *n) break; default: d << "QSGNode(" << hex << (void *) n << dec - << "dirty=" << hex << (int) n->dirtyFlags() << dec + << "dirty=" << hex << (int) n->dirtyFlags() + << "flags=" << (int) n->flags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); #ifdef QML_RUNTIME_TESTING d << n->description; @@ -1246,37 +1247,6 @@ QDebug operator<<(QDebug d, const QSGNode *n) return d; } - -/*! - \class QSGNodeDumper - \brief The QSGNodeDumper class provides a way of dumping a scene grahp to the console. - - This class is solely for debugging purposes. - - \internal - */ - -void QSGNodeDumper::dump(QSGNode *n) -{ - QSGNodeDumper dump; - dump.visitNode(n); -} - -void QSGNodeDumper::visitNode(QSGNode *n) -{ - if (n->isSubtreeBlocked()) - return; - qDebug() << QString(m_indent * 2, QLatin1Char(' ')) << n; - QSGNodeVisitor::visitNode(n); -} - -void QSGNodeDumper::visitChildren(QSGNode *n) -{ - ++m_indent; - QSGNodeVisitor::visitChildren(n); - --m_indent; -} - #endif QT_END_NAMESPACE diff --git a/src/declarative/scenegraph/coreapi/qsgnode.h b/src/declarative/scenegraph/coreapi/qsgnode.h index 95c89b996d..c4f4674a79 100644 --- a/src/declarative/scenegraph/coreapi/qsgnode.h +++ b/src/declarative/scenegraph/coreapi/qsgnode.h @@ -339,19 +339,6 @@ Q_DECLARATIVE_EXPORT QDebug operator<<(QDebug, const QSGTransformNode *n); Q_DECLARATIVE_EXPORT QDebug operator<<(QDebug, const QSGOpacityNode *n); Q_DECLARATIVE_EXPORT QDebug operator<<(QDebug, const QSGRootNode *n); -class QSGNodeDumper : public QSGNodeVisitor { - -public: - static void dump(QSGNode *n); - - QSGNodeDumper() : m_indent(0) {} - void visitNode(QSGNode *n); - void visitChildren(QSGNode *n); - -private: - int m_indent; -}; - #endif QT_END_NAMESPACE diff --git a/src/declarative/scenegraph/coreapi/qsgrenderer.cpp b/src/declarative/scenegraph/coreapi/qsgrenderer.cpp index 67575597ff..b81df008f7 100644 --- a/src/declarative/scenegraph/coreapi/qsgrenderer.cpp +++ b/src/declarative/scenegraph/coreapi/qsgrenderer.cpp @@ -43,12 +43,13 @@ #include "qsgnode.h" #include "qsgmaterial.h" #include "qsgnodeupdater_p.h" +#include "qsggeometry_p.h" #include "private/qsgadaptationlayer_p.h" -#include <QGLShaderProgram> -#include <qglframebufferobject.h> -#include <QtGui/qapplication.h> +#include <QOpenGLShaderProgram> +#include <qopenglframebufferobject.h> +#include <QtGui/qguiapplication.h> #include <qdatetime.h> @@ -57,12 +58,14 @@ QT_BEGIN_NAMESPACE //#define RENDERER_DEBUG //#define QT_GL_NO_SCISSOR_TEST -// #define QSG_RENDERER_TIMING + + +#define QSG_RENDERER_TIMING #ifdef QSG_RENDERER_TIMING +static bool qsg_render_timing = !qgetenv("QML_RENDERER_TIMING").isEmpty(); static QTime frameTimer; static int preprocessTime; static int updatePassTime; -static int frameNumber = 0; #endif void QSGBindable::clear(QSGRenderer::ClearMode mode) const @@ -80,7 +83,7 @@ void QSGBindable::reactivate() const glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } -QSGBindableFbo::QSGBindableFbo(QGLFramebufferObject *fbo) : m_fbo(fbo) +QSGBindableFbo::QSGBindableFbo(QOpenGLFramebufferObject *fbo) : m_fbo(fbo) { } @@ -130,6 +133,8 @@ QSGRenderer::QSGRenderer(QSGContext *context) , m_changed_emitted(false) , m_mirrored(false) , m_is_rendering(false) + , m_vertex_buffer_bound(false) + , m_index_buffer_bound(false) { initializeGLFunctions(); } @@ -206,7 +211,7 @@ void QSGRenderer::renderScene() class B : public QSGBindable { public: - void bind() const { QGLFramebufferObject::bindDefault(); } + void bind() const { QOpenGLFramebufferObject::bindDefault(); } } b; renderScene(b); } @@ -217,8 +222,13 @@ void QSGRenderer::renderScene(const QSGBindable &bindable) return; m_is_rendering = true; + + #ifdef QSG_RENDERER_TIMING - frameTimer.start(); + if (qsg_render_timing) + frameTimer.start(); + int bindTime; + int renderTime; #endif m_bindable = &bindable; @@ -226,7 +236,8 @@ void QSGRenderer::renderScene(const QSGBindable &bindable) bindable.bind(); #ifdef QSG_RENDERER_TIMING - int bindTime = frameTimer.elapsed(); + if (qsg_render_timing) + bindTime = frameTimer.elapsed(); #endif #ifndef QT_NO_DEBUG @@ -246,7 +257,8 @@ void QSGRenderer::renderScene(const QSGBindable &bindable) render(); #ifdef QSG_RENDERER_TIMING - int renderTime = frameTimer.elapsed(); + if (qsg_render_timing) + renderTime = frameTimer.elapsed(); #endif glDisable(GL_SCISSOR_TEST); @@ -254,13 +266,25 @@ void QSGRenderer::renderScene(const QSGBindable &bindable) m_changed_emitted = false; m_bindable = 0; + if (m_vertex_buffer_bound) { + glBindBuffer(GL_ARRAY_BUFFER, 0); + m_vertex_buffer_bound = false; + } + + if (m_index_buffer_bound) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + m_index_buffer_bound = false; + } + #ifdef QSG_RENDERER_TIMING - printf(" - Breakdown of frametime: preprocess=%d, updates=%d, binding=%d, render=%d, total=%d\n", - preprocessTime, - updatePassTime - preprocessTime, - bindTime - updatePassTime, - renderTime - bindTime, - renderTime); + if (qsg_render_timing) { + printf(" - Breakdown of frametime: preprocess=%d, updates=%d, binding=%d, render=%d, total=%d\n", + preprocessTime, + updatePassTime - preprocessTime, + bindTime - updatePassTime, + renderTime - bindTime, + renderTime); + } #endif } @@ -340,14 +364,16 @@ void QSGRenderer::preprocess() } #ifdef QSG_RENDERER_TIMING - preprocessTime = frameTimer.elapsed(); + if (qsg_render_timing) + preprocessTime = frameTimer.elapsed(); #endif nodeUpdater()->setToplevelOpacity(context()->renderAlpha()); nodeUpdater()->updateStates(m_root_node); #ifdef QSG_RENDERER_TIMING - updatePassTime = frameTimer.elapsed(); + if (qsg_render_timing) + updatePassTime = frameTimer.elapsed(); #endif } @@ -441,13 +467,13 @@ QSGRenderer::ClipType QSGRenderer::updateStencilClip(const QSGClipNode *clip) } else { if (!stencilEnabled) { if (!m_clip_program.isLinked()) { - m_clip_program.addShaderFromSourceCode(QGLShader::Vertex, + m_clip_program.addShaderFromSourceCode(QOpenGLShader::Vertex, "attribute highp vec4 vCoord; \n" "uniform highp mat4 matrix; \n" "void main() { \n" " gl_Position = matrix * vCoord; \n" "}"); - m_clip_program.addShaderFromSourceCode(QGLShader::Fragment, + m_clip_program.addShaderFromSourceCode(QOpenGLShader::Fragment, "void main() { \n" " gl_FragColor = vec4(0.81, 0.83, 0.12, 1.0); \n" // Trolltech green ftw! "}"); @@ -473,14 +499,17 @@ QSGRenderer::ClipType QSGRenderer::updateStencilClip(const QSGClipNode *clip) glStencilFunc(GL_EQUAL, clipDepth, 0xff); // stencil test, ref, test mask glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // stencil fail, z fail, z pass - const QSGGeometry *geometry = clip->geometry(); - Q_ASSERT(geometry->attributeCount() > 0); - const QSGGeometry::Attribute *a = geometry->attributes(); - - glVertexAttribPointer(0, a->tupleSize, a->type, GL_FALSE, geometry->stride(), geometry->vertexData()); + const QSGGeometry *g = clip->geometry(); + Q_ASSERT(g->attributeCount() > 0); + const QSGGeometry::Attribute *a = g->attributes(); + glVertexAttribPointer(0, a->tupleSize, a->type, GL_FALSE, g->sizeOfVertex(), g->vertexData()); m_clip_program.setUniformValue(m_clip_matrix_id, m); - draw(clip); + if (g->indexCount()) { + glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), g->indexData()); + } else { + glDrawArrays(g->drawingMode(), 0, g->vertexCount()); + } ++clipDepth; } @@ -507,25 +536,6 @@ QSGRenderer::ClipType QSGRenderer::updateStencilClip(const QSGClipNode *clip) } -/*! - Issues the GL draw call for \a geometryNode. - - The function assumes that attributes have been bound and set up prior - to making this call. - - \internal - */ - -void QSGRenderer::draw(const QSGBasicGeometryNode *node) -{ - const QSGGeometry *g = node->geometry(); - if (g->indexCount()) { - glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), g->indexData()); - } else { - glDrawArrays(g->drawingMode(), 0, g->vertexCount()); - } -} - static inline int size_of_type(GLenum type) { @@ -542,19 +552,102 @@ static inline int size_of_type(GLenum type) 4, sizeof(double) }; + Q_ASSERT(type >= GL_BYTE && type <= 0x140A); // the value of GL_DOUBLE return sizes[type - GL_BYTE]; } + +class QSGRendererVBOGeometryData : public QSGGeometryData +{ +public: + QSGRendererVBOGeometryData() + : vertexBuffer(0) + , indexBuffer(0) + { + } + + ~QSGRendererVBOGeometryData() + { + QOpenGLFunctions *func = QOpenGLContext::currentContext()->functions(); + if (vertexBuffer) + func->glDeleteBuffers(1, &vertexBuffer); + if (indexBuffer) + func->glDeleteBuffers(1, &indexBuffer); + } + + GLuint vertexBuffer; + GLuint indexBuffer; + + static QSGRendererVBOGeometryData *get(const QSGGeometry *g) { + QSGRendererVBOGeometryData *gd = static_cast<QSGRendererVBOGeometryData *>(QSGGeometryData::data(g)); + if (!gd) { + gd = new QSGRendererVBOGeometryData; + QSGGeometryData::install(g, gd); + } + return gd; + } + +}; + +static inline GLenum qt_drawTypeForPattern(QSGGeometry::DataPattern p) +{ + Q_ASSERT(p > 0 && p <= 3); + static GLenum drawTypes[] = { 0, + GL_STREAM_DRAW, + GL_DYNAMIC_DRAW, + GL_STATIC_DRAW + }; + return drawTypes[p]; +} + + /*! - Convenience function to set up and bind the vertex data in \a g to the - required attribute positions defined in \a material. + Issues the GL draw call for the geometry \a g using the material \a shader. + + The function assumes that attributes have been bound and set up prior + to making this call. \internal */ -void QSGRenderer::bindGeometry(QSGMaterialShader *material, const QSGGeometry *g) +void QSGRenderer::draw(const QSGMaterialShader *shader, const QSGGeometry *g) { - char const *const *attrNames = material->attributeNames(); + // ### remove before final release... + static bool use_vbo = !QGuiApplication::arguments().contains(QLatin1String("--no-vbo")); + + const void *vertexData; + int vertexByteSize = g->vertexCount() * g->sizeOfVertex(); + if (use_vbo && g->vertexDataPattern() != QSGGeometry::AlwaysUploadPattern && vertexByteSize > 1024) { + + // The base pointer for a VBO is 0 + vertexData = 0; + + bool updateData = QSGGeometryData::hasDirtyVertexData(g); + QSGRendererVBOGeometryData *gd = QSGRendererVBOGeometryData::get(g); + if (!gd->vertexBuffer) { + glGenBuffers(1, &gd->vertexBuffer); + updateData = true; + } + + glBindBuffer(GL_ARRAY_BUFFER, gd->vertexBuffer); + m_vertex_buffer_bound = true; + + if (updateData) { + glBufferData(GL_ARRAY_BUFFER, vertexByteSize, g->vertexData(), + qt_drawTypeForPattern(g->vertexDataPattern())); + QSGGeometryData::clearDirtyVertexData(g); + } + + } else { + if (m_vertex_buffer_bound) { + glBindBuffer(GL_ARRAY_BUFFER, 0); + m_vertex_buffer_bound = false; + } + vertexData = g->vertexData(); + } + + // Bind the vertices to attributes... + char const *const *attrNames = shader->attributeNames(); int offset = 0; for (int j = 0; attrNames[j]; ++j) { if (!*attrNames[j]) @@ -562,14 +655,88 @@ void QSGRenderer::bindGeometry(QSGMaterialShader *material, const QSGGeometry *g Q_ASSERT_X(j < g->attributeCount(), "QSGRenderer::bindGeometry()", "Geometry lacks attribute required by material"); const QSGGeometry::Attribute &a = g->attributes()[j]; Q_ASSERT_X(j == a.position, "QSGRenderer::bindGeometry()", "Geometry does not have continuous attribute positions"); + #if defined(QT_OPENGL_ES_2) GLboolean normalize = a.type != GL_FLOAT; #else GLboolean normalize = a.type != GL_FLOAT && a.type != GL_DOUBLE; #endif - glVertexAttribPointer(a.position, a.tupleSize, a.type, normalize, g->stride(), (char *) g->vertexData() + offset); + glVertexAttribPointer(a.position, a.tupleSize, a.type, normalize, g->sizeOfVertex(), (char *) vertexData + offset); offset += a.tupleSize * size_of_type(a.type); } + + // Set up the indices... + const void *indexData; + if (use_vbo && g->indexDataPattern() != QSGGeometry::AlwaysUploadPattern && g->indexCount() > 512) { + + // Base pointer for a VBO is 0 + indexData = 0; + + bool updateData = QSGGeometryData::hasDirtyIndexData(g); + QSGRendererVBOGeometryData *gd = QSGRendererVBOGeometryData::get(g); + if (!gd->indexBuffer) { + glGenBuffers(1, &gd->indexBuffer); + updateData = true; + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gd->indexBuffer); + m_index_buffer_bound = true; + + if (updateData) { + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + g->indexCount() * g->sizeOfIndex(), + g->indexData(), + qt_drawTypeForPattern(g->indexDataPattern())); + QSGGeometryData::clearDirtyIndexData(g); + } + + } else { + if (m_index_buffer_bound) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + m_index_buffer_bound = false; + } + indexData = g->indexData(); + } + + + // draw the stuff... + if (g->indexCount()) { + glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), indexData); + } else { + glDrawArrays(g->drawingMode(), 0, g->vertexCount()); + } + + // We leave buffers bound for now... They will be reset by bind on next draw() or + // set back to 0 if next draw is not using VBOs + +} + +/*! + \class QSGNodeDumper + \brief The QSGNodeDumper class provides a way of dumping a scene grahp to the console. + + This class is solely for debugging purposes. + + \internal + */ + +void QSGNodeDumper::dump(QSGNode *n) +{ + QSGNodeDumper dump; + dump.visitNode(n); +} + +void QSGNodeDumper::visitNode(QSGNode *n) +{ + qDebug() << QString(m_indent * 2, QLatin1Char(' ')) << n; + QSGNodeVisitor::visitNode(n); +} + +void QSGNodeDumper::visitChildren(QSGNode *n) +{ + ++m_indent; + QSGNodeVisitor::visitChildren(n); + --m_indent; } diff --git a/src/declarative/scenegraph/coreapi/qsgrenderer_p.h b/src/declarative/scenegraph/coreapi/qsgrenderer_p.h index 3fdcf06a08..05fb9b42fd 100644 --- a/src/declarative/scenegraph/coreapi/qsgrenderer_p.h +++ b/src/declarative/scenegraph/coreapi/qsgrenderer_p.h @@ -45,8 +45,9 @@ #include <qset.h> #include <qhash.h> -#include <qglfunctions.h> -#include <qglshaderprogram.h> +#include <qcolor.h> +#include <qopenglfunctions.h> +#include <qopenglshaderprogram.h> #include "qsgnode.h" #include "qsgmaterial.h" @@ -62,13 +63,12 @@ QT_MODULE(Declarative) class QSGMaterialShader; struct QSGMaterialType; -class QGLFramebufferObject; +class QOpenGLFramebufferObject; class TextureReference; class QSGBindable; class QSGNodeUpdater; - -class Q_DECLARATIVE_EXPORT QSGRenderer : public QObject, public QGLFunctions +class Q_DECLARATIVE_EXPORT QSGRenderer : public QObject, public QOpenGLFunctions { Q_OBJECT public: @@ -116,7 +116,7 @@ public: void setClearColor(const QColor &color); QColor clearColor() const { return m_clear_color; } - const QGLContext *glContext() const { Q_ASSERT(m_context); return m_context->glContext(); } + QOpenGLContext *glContext() const { Q_ASSERT(m_context); return m_context->glContext(); } QSGContext *context(); @@ -137,8 +137,7 @@ signals: void sceneGraphChanged(); // Add, remove, ChangeFlags changes... protected: - void draw(const QSGBasicGeometryNode *geometry); - void bindGeometry(QSGMaterialShader *material, const QSGGeometry *g); + void draw(const QSGMaterialShader *material, const QSGGeometry *g); virtual void render() = 0; QSGRenderer::ClipType updateStencilClip(const QSGClipNode *clip); @@ -169,14 +168,17 @@ private: QSet<QSGNode *> m_nodes_to_preprocess; QMatrix4x4 m_projection_matrix; - QGLShaderProgram m_clip_program; + QOpenGLShaderProgram m_clip_program; int m_clip_matrix_id; const QSGBindable *m_bindable; - bool m_changed_emitted : 1; - bool m_mirrored : 1; - bool m_is_rendering : 1; + uint m_changed_emitted : 1; + uint m_mirrored : 1; + uint m_is_rendering : 1; + + uint m_vertex_buffer_bound : 1; + uint m_index_buffer_bound : 1; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QSGRenderer::ClearMode) @@ -193,10 +195,10 @@ public: class QSGBindableFbo : public QSGBindable { public: - QSGBindableFbo(QGLFramebufferObject *fbo); + QSGBindableFbo(QOpenGLFramebufferObject *fbo); virtual void bind() const; private: - QGLFramebufferObject *m_fbo; + QOpenGLFramebufferObject *m_fbo; }; @@ -210,6 +212,21 @@ QSGMaterialShader::RenderState QSGRenderer::state(QSGMaterialShader::RenderState } +class Q_DECLARATIVE_EXPORT QSGNodeDumper : public QSGNodeVisitor { + +public: + static void dump(QSGNode *n); + + QSGNodeDumper() : m_indent(0) {} + void visitNode(QSGNode *n); + void visitChildren(QSGNode *n); + +private: + int m_indent; +}; + + + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/declarative/scenegraph/qsgadaptationlayer_p.h b/src/declarative/scenegraph/qsgadaptationlayer_p.h index f2c0cbe9ef..f1e9a89f43 100644 --- a/src/declarative/scenegraph/qsgadaptationlayer_p.h +++ b/src/declarative/scenegraph/qsgadaptationlayer_p.h @@ -47,6 +47,7 @@ #include <private/qsgtext_p.h> #include <QtCore/qobject.h> #include <QtCore/qrect.h> +#include <QtGui/qbrush.h> #include <QtGui/qcolor.h> #include <QtCore/qsharedpointer.h> #include <QtGui/qglyphrun.h> diff --git a/src/declarative/scenegraph/qsgcontext.cpp b/src/declarative/scenegraph/qsgcontext.cpp index 2a9e007264..7adbb32ec2 100644 --- a/src/declarative/scenegraph/qsgcontext.cpp +++ b/src/declarative/scenegraph/qsgcontext.cpp @@ -54,8 +54,8 @@ #include <private/qsgtexture_p.h> #include <qsgengine.h> -#include <QApplication> -#include <QGLContext> +#include <QGuiApplication> +#include <QOpenGLContext> #include <private/qobject_p.h> #include <qmutex.h> @@ -105,7 +105,7 @@ public: QSGRootNode *rootNode; QSGRenderer *renderer; - QGLContext *gl; + QOpenGLContext *gl; QSGEngine engine; @@ -127,7 +127,7 @@ public: \brief The QSGContext holds the scene graph entry points for one QML engine. - The context is not ready for use until it has a QGLContext. Once that happens, + The context is not ready for use until it has a QOpenGLContext. Once that happens, the scene graph population can start. \internal @@ -214,7 +214,7 @@ QSGRootNode *QSGContext::rootNode() const } -QGLContext *QSGContext::glContext() const +QOpenGLContext *QSGContext::glContext() const { Q_D(const QSGContext); return d->gl; @@ -224,7 +224,7 @@ QGLContext *QSGContext::glContext() const Initializes the scene graph context with the GL context \a context. This also emits the ready() signal so that the QML graph can start building scene graph nodes. */ -void QSGContext::initialize(QGLContext *context) +void QSGContext::initialize(QOpenGLContext *context) { Q_D(QSGContext); @@ -253,7 +253,7 @@ bool QSGContext::isReady() const } -void QSGContext::renderNextFrame(QGLFramebufferObject *fbo) +void QSGContext::renderNextFrame(QOpenGLFramebufferObject *fbo) { Q_D(QSGContext); diff --git a/src/declarative/scenegraph/qsgcontext_p.h b/src/declarative/scenegraph/qsgcontext_p.h index 29a5aac4b9..a05854ebe8 100644 --- a/src/declarative/scenegraph/qsgcontext_p.h +++ b/src/declarative/scenegraph/qsgcontext_p.h @@ -42,6 +42,7 @@ #ifndef QSGCONTEXT_H #define QSGCONTEXT_H +#include <QImage> #include <QObject> #include <qabstractanimation.h> @@ -64,8 +65,8 @@ class QSGMaterial; class QSGMaterialShader; class QSGEngine; -class QGLContext; -class QGLFramebufferObject; +class QOpenGLContext; +class QOpenGLFramebufferObject; class Q_DECLARATIVE_EXPORT QSGContext : public QObject { @@ -76,7 +77,7 @@ public: explicit QSGContext(QObject *parent = 0); ~QSGContext(); - virtual void initialize(QGLContext *context); + virtual void initialize(QOpenGLContext *context); QSGRenderer *renderer() const; @@ -84,13 +85,13 @@ public: QSGRootNode *rootNode() const; QSGEngine *engine() const; - QGLContext *glContext() const; + QOpenGLContext *glContext() const; bool isReady() const; QSGMaterialShader *prepareMaterial(QSGMaterial *material); - virtual void renderNextFrame(QGLFramebufferObject *fbo = 0); + virtual void renderNextFrame(QOpenGLFramebufferObject *fbo = 0); virtual QSGRectangleNode *createRectangleNode(); virtual QSGImageNode *createImageNode(); diff --git a/src/declarative/scenegraph/qsgcontextplugin.cpp b/src/declarative/scenegraph/qsgcontextplugin.cpp index b5e74e6cc3..79bcbf9c04 100644 --- a/src/declarative/scenegraph/qsgcontextplugin.cpp +++ b/src/declarative/scenegraph/qsgcontextplugin.cpp @@ -41,7 +41,7 @@ #include "qsgcontextplugin_p.h" #include <private/qsgcontext_p.h> -#include <QtGui/qapplication.h> +#include <QtGui/qguiapplication.h> #include <QtCore/private/qfactoryloader_p.h> #include <QtCore/qlibraryinfo.h> @@ -69,7 +69,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, */ QSGContext *QSGContext::createDefaultContext() { - const QStringList args = QApplication::arguments(); + const QStringList args = QGuiApplication::arguments(); QString device; for (int index = 0; index < args.count(); ++index) { if (args.at(index).startsWith(QLatin1String("--device="))) { diff --git a/src/declarative/scenegraph/qsgdefaultglyphnode.cpp b/src/declarative/scenegraph/qsgdefaultglyphnode.cpp index 3e8510e943..b8cd247908 100644 --- a/src/declarative/scenegraph/qsgdefaultglyphnode.cpp +++ b/src/declarative/scenegraph/qsgdefaultglyphnode.cpp @@ -42,7 +42,7 @@ #include "qsgdefaultglyphnode_p.h" #include "qsgdefaultglyphnode_p_p.h" -#include <qglshaderprogram.h> +#include <qopenglshaderprogram.h> #include <private/qfont_p.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/scenegraph/qsgdefaultglyphnode_p.cpp b/src/declarative/scenegraph/qsgdefaultglyphnode_p.cpp index b00c6f0937..e34a4e091f 100644 --- a/src/declarative/scenegraph/qsgdefaultglyphnode_p.cpp +++ b/src/declarative/scenegraph/qsgdefaultglyphnode_p.cpp @@ -41,11 +41,11 @@ #include "qsgdefaultglyphnode_p_p.h" -#include <qglshaderprogram.h> +#include <qopenglshaderprogram.h> -#include <private/qtextureglyphcache_gl_p.h> +#include <QtGui/private/qopengltextureglyphcache_p.h> #include <private/qfontengine_p.h> -#include <private/qglextensions_p.h> +#include <private/qopenglextensions_p.h> #include <private/qsgtexture_p.h> @@ -163,24 +163,17 @@ void QSGTextMaskMaterial::init() QFontEngineGlyphCache::Type type = QFontEngineGlyphCache::Raster_A8; setFlag(Blending, true); - QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext()); + QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext()); Q_ASSERT(ctx != 0); QRawFontPrivate *fontD = QRawFontPrivate::get(m_font); if (fontD->fontEngine != 0) { m_glyphCache = fontD->fontEngine->glyphCache(ctx, type, QTransform()); if (!m_glyphCache || m_glyphCache->cacheType() != type) { - m_glyphCache = new QGLTextureGlyphCache(ctx, type, QTransform()); + m_glyphCache = new QOpenGLTextureGlyphCache(type, QTransform()); fontD->fontEngine->setGlyphCache(ctx, m_glyphCache.data()); } } - -#if !defined(QT_OPENGL_ES_2) - bool success = qt_resolve_version_2_0_functions(ctx) - && qt_resolve_buffer_extensions(ctx); - Q_ASSERT(success); - Q_UNUSED(success); -#endif } void QSGTextMaskMaterial::populate(const QPointF &p, @@ -207,7 +200,7 @@ void QSGTextMaskMaterial::populate(const QPointF &p, Q_ASSERT(geometry->indexType() == GL_UNSIGNED_SHORT); geometry->allocate(glyphIndexes.size() * 4, glyphIndexes.size() * 6); QVector4D *vp = (QVector4D *)geometry->vertexDataAsTexturedPoint2D(); - Q_ASSERT(geometry->stride() == sizeof(QVector4D)); + Q_ASSERT(geometry->sizeOfVertex() == sizeof(QVector4D)); ushort *ip = geometry->indexDataAsUShort(); QPointF position(p.x(), p.y() - m_font.ascent()); @@ -260,9 +253,9 @@ QSGMaterialType *QSGTextMaskMaterial::type() const return &type; } -QGLTextureGlyphCache *QSGTextMaskMaterial::glyphCache() const +QOpenGLTextureGlyphCache *QSGTextMaskMaterial::glyphCache() const { - return static_cast<QGLTextureGlyphCache*>(m_glyphCache.data()); + return static_cast<QOpenGLTextureGlyphCache*>(m_glyphCache.data()); } QSGMaterialShader *QSGTextMaskMaterial::createShader() const diff --git a/src/declarative/scenegraph/qsgdefaultglyphnode_p_p.h b/src/declarative/scenegraph/qsgdefaultglyphnode_p_p.h index 19d5f9e6a6..d22bc33fea 100644 --- a/src/declarative/scenegraph/qsgdefaultglyphnode_p_p.h +++ b/src/declarative/scenegraph/qsgdefaultglyphnode_p_p.h @@ -42,6 +42,7 @@ #ifndef TEXTMASKMATERIAL_H #define TEXTMASKMATERIAL_H +#include <qcolor.h> #include <qsgmaterial.h> #include <qsgtexture.h> #include <qsggeometry.h> @@ -52,7 +53,7 @@ QT_BEGIN_NAMESPACE class QFontEngineGlyphCache; -class QGLTextureGlyphCache; +class QOpenGLTextureGlyphCache; class QFontEngine; class Geometry; class QSGTextMaskMaterial: public QSGMaterial @@ -75,7 +76,7 @@ public: bool ensureUpToDate(); - QGLTextureGlyphCache *glyphCache() const; + QOpenGLTextureGlyphCache *glyphCache() const; void populate(const QPointF &position, const QVector<quint32> &glyphIndexes, const QVector<QPointF> &glyphPositions, QSGGeometry *geometry, QRectF *boundingRect, QPointF *baseLine); diff --git a/src/declarative/scenegraph/qsgdefaultimagenode.cpp b/src/declarative/scenegraph/qsgdefaultimagenode.cpp index e60ebf2b84..657f8d0e7c 100644 --- a/src/declarative/scenegraph/qsgdefaultimagenode.cpp +++ b/src/declarative/scenegraph/qsgdefaultimagenode.cpp @@ -45,7 +45,7 @@ #include <QtCore/qvarlengtharray.h> #include <QtCore/qmath.h> -#include <QtOpenGL/qglfunctions.h> +#include <QtGui/qopenglfunctions.h> QT_BEGIN_NAMESPACE @@ -194,8 +194,8 @@ void QSGDefaultImageNode::updateGeometry() bool isRepeating = hCells > 1 || vCells > 1; #ifdef QT_OPENGL_ES_2 - const QGLContext *ctx = QGLContext::currentContext(); - bool npotSupported = ctx->functions()->hasOpenGLFeature(QGLFunctions::NPOTTextures); + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + bool npotSupported = ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures); QSize size = t->textureSize(); bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height()); diff --git a/src/declarative/scenegraph/qsgdefaultrectanglenode.cpp b/src/declarative/scenegraph/qsgdefaultrectanglenode.cpp index 4a742efa91..fbd8e0e7ed 100644 --- a/src/declarative/scenegraph/qsgdefaultrectanglenode.cpp +++ b/src/declarative/scenegraph/qsgdefaultrectanglenode.cpp @@ -44,7 +44,7 @@ #include "qsgdefaultrectanglenode_p.h" -#include <private/qsgvertexcolormaterial_p.h> +#include <qsgvertexcolormaterial.h> #include "qsgtexturematerial.h" #include <private/qsgcontext_p.h> @@ -174,7 +174,7 @@ void QSGDefaultRectangleNode::setGradientStops(const QGradientStops &stops) setGeometry(g); setFlag(OwnsGeometry); } - static_cast<QSGVertexColorMaterial *>(material())->setColorsAreOpaque(m_gradient_is_opaque); + static_cast<QSGVertexColorMaterial *>(material())->setFlag(QSGMaterial::Blending, !m_gradient_is_opaque); } m_dirty_geometry = true; @@ -248,13 +248,13 @@ void QSGDefaultRectangleNode::updateGeometry() QSGGeometry *fill = geometry(); // Check that the vertex type matches the material. - Q_ASSERT(m_material_type != TypeFlat || fill->stride() == sizeof(Vertex)); - Q_ASSERT(m_material_type != TypeVertexGradient || fill->stride() == sizeof(ColorVertex)); + Q_ASSERT(m_material_type != TypeFlat || fill->sizeOfVertex() == sizeof(Vertex)); + Q_ASSERT(m_material_type != TypeVertexGradient || fill->sizeOfVertex() == sizeof(ColorVertex)); QSGGeometry *borderGeometry = 0; if (m_border) { borderGeometry = border()->geometry(); - Q_ASSERT(borderGeometry->stride() == sizeof(Vertex)); + Q_ASSERT(borderGeometry->sizeOfVertex() == sizeof(Vertex)); } int fillVertexCount = 0; diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp b/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp index ff4913a7b5..ec69a64c58 100644 --- a/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp +++ b/src/declarative/scenegraph/qsgdistancefieldglyphcache.cpp @@ -44,14 +44,15 @@ #include <qmath.h> #include <private/qsgpathsimplifier_p.h> #include <private/qdeclarativeglobal_p.h> -#include <qglshaderprogram.h> -#include <private/qglengineshadersource_p.h> +#include <qopenglshaderprogram.h> +#include <QtGui/private/qopenglengineshadersource_p.h> #include <private/qsgcontext_p.h> #include <private/qrawfont_p.h> -#include <qglfunctions.h> +#include <qopenglfunctions.h> #include <qglyphrun.h> #include <qrawfont.h> #include <qdir.h> +#include <QtGui/qguiapplication.h> QT_BEGIN_NAMESPACE @@ -797,7 +798,7 @@ static bool fontHasNarrowOutlines(const QRawFont &f) return minHThick == 1 || minVThick == 1; } -QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager(const QGLContext *c) +QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager(QOpenGLContext *c) : ctx(c) , m_threshold_func(defaultThresholdFunc) , m_antialiasingSpread_func(defaultAntialiasingSpreadFunc) @@ -827,23 +828,23 @@ QSGDistanceFieldGlyphCacheManager::QSGDistanceFieldGlyphCacheManager(const QGLCo m_textureCoordinateArray[6] = 0.0f; m_textureCoordinateArray[7] = 1.0f; - m_blitProgram = new QGLShaderProgram; + m_blitProgram = new QOpenGLShaderProgram; { QString source; - source.append(QLatin1String(qglslMainWithTexCoordsVertexShader)); - source.append(QLatin1String(qglslUntransformedPositionVertexShader)); + source.append(QLatin1String(qopenglslMainWithTexCoordsVertexShader)); + source.append(QLatin1String(qopenglslUntransformedPositionVertexShader)); - QGLShader *vertexShader = new QGLShader(QGLShader::Vertex, m_blitProgram); + QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_blitProgram); vertexShader->compileSourceCode(source); m_blitProgram->addShader(vertexShader); } { QString source; - source.append(QLatin1String(qglslMainFragmentShader)); - source.append(QLatin1String(qglslImageSrcFragmentShader)); + source.append(QLatin1String(qopenglslMainFragmentShader)); + source.append(QLatin1String(qopenglslImageSrcFragmentShader)); - QGLShader *fragmentShader = new QGLShader(QGLShader::Fragment, m_blitProgram); + QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_blitProgram); fragmentShader->compileSourceCode(source); m_blitProgram->addShader(fragmentShader); @@ -876,7 +877,7 @@ int QSGDistanceFieldGlyphCacheManager::maxTextureSize() const } -QHash<QString, QGLContextGroupResource<QSGDistanceFieldGlyphCache::DistanceFieldTextureData> > QSGDistanceFieldGlyphCache::m_textures_data; +QHash<QString, QOpenGLMultiGroupSharedResource> QSGDistanceFieldGlyphCache::m_textures_data; QSGDistanceFieldGlyphCache::DistanceFieldTextureData *QSGDistanceFieldGlyphCache::textureData() { @@ -885,10 +886,10 @@ QSGDistanceFieldGlyphCache::DistanceFieldTextureData *QSGDistanceFieldGlyphCache .arg(m_font.styleName()) .arg(m_font.weight()) .arg(m_font.style()); - return m_textures_data[key].value(ctx); + return m_textures_data[key].value<QSGDistanceFieldGlyphCache::DistanceFieldTextureData>(QOpenGLContext::currentContext()); } -QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QGLContext *c, const QRawFont &font) +QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font) : m_manager(man) , ctx(c) { @@ -1045,7 +1046,7 @@ void QSGDistanceFieldGlyphCache::derefGlyphs(int count, const glyph_t *glyphs) void QSGDistanceFieldGlyphCache::createTexture(int width, int height) { - if (ctx->d_ptr->workaround_brokenFBOReadBack && m_textureData->image.isNull()) + if (ctx->d_func()->workaround_brokenFBOReadBack && m_textureData->image.isNull()) m_textureData->image = QImage(width, height, QImage::Format_Indexed8); while (glGetError() != GL_NO_ERROR) { } @@ -1083,7 +1084,7 @@ void QSGDistanceFieldGlyphCache::resizeTexture(int width, int height) if (!oldTexture) return; - if (ctx->d_ptr->workaround_brokenFBOReadBack) { + if (ctx->d_func()->workaround_brokenFBOReadBack) { m_textureData->image = m_textureData->image.copy(0, 0, width, height); QImage copy = m_textureData->image.copy(0, 0, oldWidth, oldHeight); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, oldWidth, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, copy.constBits()); @@ -1093,7 +1094,7 @@ void QSGDistanceFieldGlyphCache::resizeTexture(int width, int height) if (!m_textureData->fbo) ctx->functions()->glGenFramebuffers(1, &m_textureData->fbo); - ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_textureData->fbo); + ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_textureData->fbo); GLuint tmp_texture; glGenTextures(1, &tmp_texture); @@ -1105,7 +1106,7 @@ void QSGDistanceFieldGlyphCache::resizeTexture(int width, int height) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); - ctx->functions()->glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + ctx->functions()->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_texture, 0); ctx->functions()->glActiveTexture(GL_TEXTURE0); @@ -1145,12 +1146,12 @@ void QSGDistanceFieldGlyphCache::resizeTexture(int width, int height) glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight); - ctx->functions()->glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_RENDERBUFFER_EXT, 0); + ctx->functions()->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, 0); glDeleteTextures(1, &tmp_texture); glDeleteTextures(1, &oldTexture); - ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, 0); // restore render states if (stencilTestEnabled) @@ -1177,7 +1178,7 @@ void QSGDistanceFieldGlyphCache::updateCache() glBindTexture(GL_TEXTURE_2D, m_textureData->texture); // ### Remove before final release - static bool cacheDistanceFields = QApplication::arguments().contains("--cache-distance-fields"); + static bool cacheDistanceFields = QGuiApplication::arguments().contains(QLatin1String("--cache-distance-fields")); // #define QSGDISTANCEFIELDS_TIME_CREATION #ifdef QSGDISTANCEFIELDS_TIME_CREATION @@ -1214,7 +1215,7 @@ void QSGDistanceFieldGlyphCache::updateCache() QImage glyph = renderDistanceFieldGlyph(glyphIndex); - if (ctx->d_ptr->workaround_brokenFBOReadBack) { + if (ctx->d_func()->workaround_brokenFBOReadBack) { uchar *inBits = glyph.scanLine(0); uchar *outBits = m_textureData->image.scanLine(int(c.y)) + int(c.x); for (int y = 0; y < glyph.height(); ++y) { @@ -1245,7 +1246,7 @@ void QSGDistanceFieldGlyphCache::updateCache() bool QSGDistanceFieldGlyphCache::useWorkaroundBrokenFBOReadback() const { - return ctx->d_ptr->workaround_brokenFBOReadBack; + return ctx->d_func()->workaround_brokenFBOReadBack; } int QSGDistanceFieldGlyphCache::glyphCount() const diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h b/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h index c4dd97bab5..aea7c5952f 100644 --- a/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h +++ b/src/declarative/scenegraph/qsgdistancefieldglyphcache_p.h @@ -42,9 +42,10 @@ #ifndef DISTANCEFIELDGLYPHCACHE_H #define DISTANCEFIELDGLYPHCACHE_H -#include <qgl.h> +#include <qopengl.h> #include <qrawfont.h> -#include <private/qgl_p.h> +#include <private/qopenglcontext_p.h> +#include <QtGui/qopenglfunctions.h> #include <private/qfont_p.h> #include <private/qfontengine_p.h> #include <QtGui/private/qdatabuffer_p.h> @@ -55,13 +56,13 @@ QT_BEGIN_NAMESPACE typedef float (*ThresholdFunc)(float glyphScale); typedef float (*AntialiasingSpreadFunc)(float glyphScale); -class QGLShaderProgram; +class QOpenGLShaderProgram; class QSGDistanceFieldGlyphCache; class Q_DECLARATIVE_EXPORT QSGDistanceFieldGlyphCacheManager { public: - QSGDistanceFieldGlyphCacheManager(const QGLContext *c); + QSGDistanceFieldGlyphCacheManager(QOpenGLContext *c); ~QSGDistanceFieldGlyphCacheManager(); QSGDistanceFieldGlyphCache *cache(const QRawFont &font); @@ -75,7 +76,7 @@ public: AntialiasingSpreadFunc antialiasingSpreadFunc() const { return m_antialiasingSpread_func; } void setAntialiasingSpreadFunc(AntialiasingSpreadFunc func) { m_antialiasingSpread_func = func; } - QGLShaderProgram *blitProgram() { return m_blitProgram; } + QOpenGLShaderProgram *blitProgram() { return m_blitProgram; } const GLfloat *blitVertexArray() const { return &m_vertexCoordinateArray[0]; } const GLfloat *blitTextureArray() const { return &m_textureCoordinateArray[0]; } @@ -84,7 +85,7 @@ public: private: QHash<QFontEngine *, QSGDistanceFieldGlyphCache *> m_caches; - const QGLContext *ctx; + QOpenGLContext *ctx; QSGGlyphNode::AntialiasingMode m_defaultAntialiasingMode; ThresholdFunc m_threshold_func; @@ -92,7 +93,7 @@ private: mutable int m_maxTextureSize; - QGLShaderProgram *m_blitProgram; + QOpenGLShaderProgram *m_blitProgram; GLfloat m_vertexCoordinateArray[8]; GLfloat m_textureCoordinateArray[8]; }; @@ -145,20 +146,22 @@ public: bool useWorkaroundBrokenFBOReadback() const; private: - QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, const QGLContext *c, const QRawFont &font); + QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCacheManager *man, QOpenGLContext *c, const QRawFont &font); void createTexture(int width, int height); void resizeTexture(int width, int height); QSGDistanceFieldGlyphCacheManager *m_manager; + QOpenGLContext *ctx; + QRawFont m_font; QRawFont m_referenceFont; int m_glyphCount; QHash<glyph_t, Metrics> m_metrics; - struct DistanceFieldTextureData { + struct DistanceFieldTextureData : public QOpenGLSharedResource { GLuint texture; GLuint fbo; QSize size; @@ -171,20 +174,33 @@ private: QImage image; bool doubleGlyphResolution; - DistanceFieldTextureData(const QGLContext *) - : texture(0) + DistanceFieldTextureData(QOpenGLContext *ctx) + : QOpenGLSharedResource(ctx->shareGroup()) + , texture(0) , fbo(0) , pendingGlyphs(64) , currX(0) , currY(0) , doubleGlyphResolution(false) - { } + {} + + void invalidateResource() + { + texture = 0; + fbo = 0; + size = QSize(); + } + + void freeResource(QOpenGLContext *ctx) + { + glDeleteTextures(1, &texture); + ctx->functions()->glDeleteFramebuffers(1, &fbo); + } }; + DistanceFieldTextureData *textureData(); DistanceFieldTextureData *m_textureData; - static QHash<QString, QGLContextGroupResource<DistanceFieldTextureData> > m_textures_data; - - const QGLContext *ctx; + static QHash<QString, QOpenGLMultiGroupSharedResource> m_textures_data; friend class QSGDistanceFieldGlyphCacheManager; }; diff --git a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp index c81113f4dc..72c53a2ce7 100644 --- a/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp +++ b/src/declarative/scenegraph/qsgdistancefieldglyphnode_p.cpp @@ -42,7 +42,7 @@ #include "qsgdistancefieldglyphnode_p_p.h" #include "qsgdistancefieldglyphcache_p.h" #include <private/qsgtexture_p.h> -#include <QtOpenGL/qglfunctions.h> +#include <QtGui/qopenglfunctions.h> #include <qmath.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/scenegraph/qsgpathsimplifier.cpp b/src/declarative/scenegraph/qsgpathsimplifier.cpp index 5fac564e21..9e851bf434 100644 --- a/src/declarative/scenegraph/qsgpathsimplifier.cpp +++ b/src/declarative/scenegraph/qsgpathsimplifier.cpp @@ -48,7 +48,7 @@ #include <math.h> -#include <private/qgl_p.h> +#include <private/qopengl_p.h> #include <private/qrbtree_p.h> QT_BEGIN_NAMESPACE diff --git a/src/declarative/scenegraph/scenegraph.pri b/src/declarative/scenegraph/scenegraph.pri index aa9d2bc6b2..d29a3bc561 100644 --- a/src/declarative/scenegraph/scenegraph.pri +++ b/src/declarative/scenegraph/scenegraph.pri @@ -1,9 +1,6 @@ INCLUDEPATH += $$PWD/coreapi $$PWD/convenience $$PWD/3d !contains(QT_CONFIG, egl):DEFINES += QT_NO_EGL -QT += opengl - - # Core API HEADERS += \ $$PWD/coreapi/qsgdefaultrenderer_p.h \ @@ -11,7 +8,9 @@ HEADERS += \ $$PWD/coreapi/qsgmaterial.h \ $$PWD/coreapi/qsgnode.h \ $$PWD/coreapi/qsgnodeupdater_p.h \ - $$PWD/coreapi/qsgrenderer_p.h + $$PWD/coreapi/qsgrenderer_p.h \ + $$PWD/coreapi/qsggeometry_p.h + SOURCES += \ $$PWD/coreapi/qsgdefaultrenderer.cpp \ $$PWD/coreapi/qsggeometry.cpp \ @@ -31,7 +30,7 @@ HEADERS += \ $$PWD/util/qsgsimpletexturenode.h \ $$PWD/util/qsgtexturematerial.h \ $$PWD/util/qsgtexturematerial_p.h \ - $$PWD/util/qsgvertexcolormaterial_p.h \ + $$PWD/util/qsgvertexcolormaterial.h \ $$PWD/util/qsgtexture.h \ $$PWD/util/qsgtexture_p.h \ $$PWD/util/qsgtextureprovider_p.h \ diff --git a/src/declarative/scenegraph/util/qsgflatcolormaterial.cpp b/src/declarative/scenegraph/util/qsgflatcolormaterial.cpp index d954f196ab..affdcadd3b 100644 --- a/src/declarative/scenegraph/util/qsgflatcolormaterial.cpp +++ b/src/declarative/scenegraph/util/qsgflatcolormaterial.cpp @@ -41,7 +41,7 @@ #include "qsgflatcolormaterial.h" -#include <qglshaderprogram.h> +#include <qopenglshaderprogram.h> QT_BEGIN_NAMESPACE @@ -189,4 +189,12 @@ QSGMaterialShader *QSGFlatColorMaterial::createShader() const return new FlatColorMaterialShader; } + +int QSGFlatColorMaterial::compare(const QSGMaterial *other) const +{ + const QSGFlatColorMaterial *flat = static_cast<const QSGFlatColorMaterial *>(other); + return m_color.rgba() - flat->color().rgba(); + +} + QT_END_NAMESPACE diff --git a/src/declarative/scenegraph/util/qsgflatcolormaterial.h b/src/declarative/scenegraph/util/qsgflatcolormaterial.h index ffff7941a3..f6345b6483 100644 --- a/src/declarative/scenegraph/util/qsgflatcolormaterial.h +++ b/src/declarative/scenegraph/util/qsgflatcolormaterial.h @@ -43,6 +43,7 @@ #define FLATCOLORMATERIAL_H #include <qsgmaterial.h> +#include <qcolor.h> QT_BEGIN_HEADER @@ -60,6 +61,8 @@ public: void setColor(const QColor &color); const QColor &color() const { return m_color; } + int compare(const QSGMaterial *other) const; + private: QColor m_color; }; diff --git a/src/declarative/scenegraph/util/qsgpainternode.cpp b/src/declarative/scenegraph/util/qsgpainternode.cpp index ab96591b76..5d548792c6 100644 --- a/src/declarative/scenegraph/util/qsgpainternode.cpp +++ b/src/declarative/scenegraph/util/qsgpainternode.cpp @@ -43,9 +43,12 @@ #include "qsgpainteditem.h" #include <private/qsgcontext_p.h> -#include <qglframebufferobject.h> -#include <qglfunctions.h> +#include <private/qopenglextensions_p.h> +#include <qopenglframebufferobject.h> +#include <qopenglfunctions.h> +#include <qopenglpaintdevice.h> #include <qmath.h> +#include <qpainter.h> QT_BEGIN_NAMESPACE @@ -90,7 +93,7 @@ void QSGPainterTexture::bind() #endif if (m_has_mipmaps && !m_mipmaps_generated) { - const QGLContext *ctx = QGLContext::currentContext(); + QOpenGLContext *ctx = QOpenGLContext::currentContext(); ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D); m_mipmaps_generated = true; } @@ -110,6 +113,7 @@ QSGPainterNode::QSGPainterNode(QSGPaintedItem *item) , m_multisampledFbo(0) , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) , m_texture(0) + , m_gl_device(0) , m_size(1, 1) , m_dirtyContents(false) , m_opaquePainting(false) @@ -134,6 +138,7 @@ QSGPainterNode::~QSGPainterNode() delete m_texture; delete m_fbo; delete m_multisampledFbo; + delete m_gl_device; } void QSGPainterNode::paint() @@ -143,10 +148,19 @@ void QSGPainterNode::paint() QPainter painter; if (m_actualRenderTarget == QSGPaintedItem::Image) painter.begin(&m_image); - else if (m_multisampledFbo) - painter.begin(m_multisampledFbo); - else - painter.begin(m_fbo); + else { + if (!m_gl_device) { + m_gl_device = new QOpenGLPaintDevice(m_fboSize); + m_gl_device->setPaintFlipped(true); + } + + if (m_multisampledFbo) + m_multisampledFbo->bind(); + else + m_fbo->bind(); + + painter.begin(m_gl_device); + } if (m_smoothPainting) { painter.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing @@ -174,9 +188,14 @@ void QSGPainterNode::paint() m_texture->setImage(m_image); m_texture->setDirtyRect(dirtyRect); } else if (m_multisampledFbo) { - QGLFramebufferObject::blitFramebuffer(m_fbo, dirtyRect, m_multisampledFbo, dirtyRect); + QOpenGLFramebufferObject::blitFramebuffer(m_fbo, dirtyRect, m_multisampledFbo, dirtyRect); } + if (m_multisampledFbo) + m_multisampledFbo->release(); + else if (m_fbo) + m_fbo->release(); + m_dirtyRect = QRect(); } @@ -214,7 +233,7 @@ void QSGPainterNode::updateGeometry() if (m_actualRenderTarget == QSGPaintedItem::Image) source = QRectF(0, 0, 1, 1); else - source = QRectF(0, 1, qreal(m_size.width()) / m_fboSize.width(), qreal(-m_size.height()) / m_fboSize.height()); + source = QRectF(0, 0, qreal(m_size.width()) / m_fboSize.width(), qreal(m_size.height()) / m_fboSize.height()); QSGGeometry::updateTexturedRectGeometry(&m_geometry, QRectF(0, 0, m_size.width(), m_size.height()), source); @@ -249,8 +268,8 @@ void QSGPainterNode::updateRenderTarget() } if (m_actualRenderTarget == QSGPaintedItem::FramebufferObject) { - const QGLContext *ctx = QGLContext::currentContext(); - if (m_fbo && !m_dirtyGeometry && (!ctx->format().sampleBuffers() || !m_multisamplingSupported)) + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + if (m_fbo && !m_dirtyGeometry && (!ctx->format().samples() || !m_multisamplingSupported)) return; if (m_fboSize.isEmpty()) @@ -260,22 +279,22 @@ void QSGPainterNode::updateRenderTarget() delete m_multisampledFbo; m_fbo = m_multisampledFbo = 0; - if (m_smoothPainting && ctx->format().sampleBuffers() && m_multisamplingSupported) { + if (m_smoothPainting && ctx->format().samples() && m_multisamplingSupported) { { - QGLFramebufferObjectFormat format; - format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); - format.setSamples(ctx->format().samples()); - m_multisampledFbo = new QGLFramebufferObject(m_fboSize, format); + QOpenGLFramebufferObjectFormat format; + format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + format.setSamples(8); + m_multisampledFbo = new QOpenGLFramebufferObject(m_fboSize, format); } { - QGLFramebufferObjectFormat format; - format.setAttachment(QGLFramebufferObject::NoAttachment); - m_fbo = new QGLFramebufferObject(m_fboSize, format); + QOpenGLFramebufferObjectFormat format; + format.setAttachment(QOpenGLFramebufferObject::NoAttachment); + m_fbo = new QOpenGLFramebufferObject(m_fboSize, format); } } else { - QGLFramebufferObjectFormat format; - format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); - m_fbo = new QGLFramebufferObject(m_fboSize, format); + QOpenGLFramebufferObjectFormat format; + format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + m_fbo = new QOpenGLFramebufferObject(m_fboSize, format); } } else { if (!m_image.isNull() && !m_dirtyGeometry) diff --git a/src/declarative/scenegraph/util/qsgpainternode_p.h b/src/declarative/scenegraph/util/qsgpainternode_p.h index 5b0e9cef2c..435e86e0d2 100644 --- a/src/declarative/scenegraph/util/qsgpainternode_p.h +++ b/src/declarative/scenegraph/util/qsgpainternode_p.h @@ -47,13 +47,16 @@ #include "qsgtexture_p.h" #include "qsgpainteditem.h" +#include <QtGui/qcolor.h> + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class QGLFramebufferObject; +class QOpenGLFramebufferObject; +class QOpenGLPaintDevice; class Q_DECLARATIVE_EXPORT QSGPainterTexture : public QSGPlainTexture { @@ -115,14 +118,15 @@ private: QSGPaintedItem *m_item; - QGLFramebufferObject *m_fbo; - QGLFramebufferObject *m_multisampledFbo; + QOpenGLFramebufferObject *m_fbo; + QOpenGLFramebufferObject *m_multisampledFbo; QImage m_image; QSGOpaqueTextureMaterial m_material; QSGTextureMaterial m_materialO; QSGGeometry m_geometry; QSGPainterTexture *m_texture; + QOpenGLPaintDevice *m_gl_device; QSize m_size; QSize m_fboSize; diff --git a/src/declarative/scenegraph/util/qsgtexture.cpp b/src/declarative/scenegraph/util/qsgtexture.cpp index 536ac8d7fe..bec325f3bb 100644 --- a/src/declarative/scenegraph/util/qsgtexture.cpp +++ b/src/declarative/scenegraph/util/qsgtexture.cpp @@ -42,9 +42,15 @@ #define GL_GLEXT_PROTOTYPES #include <private/qsgtexture_p.h> -#include <qglfunctions.h> +#include <qopenglfunctions.h> #include <private/qsgcontext_p.h> #include <qthread.h> +#include <private/qdeclarativedebugtrace_p.h> + +#if !defined(QT_NO_DEBUG) && (defined(Q_OS_LINUX) || defined(Q_OS_MAC)) +#include <execinfo.h> +#include <QHash> +#endif QT_BEGIN_NAMESPACE @@ -65,36 +71,108 @@ QSGTexturePrivate::QSGTexturePrivate() } #ifndef QT_NO_DEBUG -static int qt_texture_count = 0; -static void qt_print_texture_count() +static int qt_debug_texture_count = 0; + +#if defined(Q_OS_LINUX) || defined (Q_OS_MAC) +DEFINE_BOOL_CONFIG_OPTION(qmlDebugLeakBacktrace, QML_DEBUG_LEAK_BACKTRACE) + +#define BACKTRACE_SIZE 20 +class SGTextureTraceItem { - qDebug("Number of leaked textures: %i", qt_texture_count); - qt_texture_count = -1; -} +public: + void *backTrace[BACKTRACE_SIZE]; + size_t backTraceSize; +}; + +static QHash<QSGTexture*, SGTextureTraceItem*> qt_debug_allocated_textures; #endif +inline static void qt_debug_print_texture_count() +{ + qDebug("Number of leaked textures: %i", qt_debug_texture_count); + qt_debug_texture_count = -1; +#if defined(Q_OS_LINUX) || defined (Q_OS_MAC) + if (qmlDebugLeakBacktrace()) { + while (!qt_debug_allocated_textures.isEmpty()) { + QHash<QSGTexture*, SGTextureTraceItem*>::Iterator it = qt_debug_allocated_textures.begin(); + QSGTexture* texture = it.key(); + SGTextureTraceItem* item = it.value(); -QSGTexture::QSGTexture() - : QObject(*(new QSGTexturePrivate)) + qt_debug_allocated_textures.erase(it); + + qDebug() << "------"; + qDebug() << "Leaked" << texture << "backtrace:"; + + char** symbols = backtrace_symbols(item->backTrace, item->backTraceSize); + + if (symbols) { + for (int i=0; i<(int) item->backTraceSize; i++) + qDebug("Backtrace <%02d>: %s", i, symbols[i]); + free(symbols); + } + + qDebug() << "------"; + + delete item; + } + } +#endif +} + +inline static void qt_debug_add_texture(QSGTexture* texture) { -#ifndef QT_NO_DEBUG - ++qt_texture_count; +#if defined(Q_OS_LINUX) || defined (Q_OS_MAC) + if (qmlDebugLeakBacktrace()) { + SGTextureTraceItem* item = new SGTextureTraceItem; + item->backTraceSize = backtrace(item->backTrace, BACKTRACE_SIZE); + qt_debug_allocated_textures.insert(texture, item); + } +#endif // Q_OS_LINUX + + ++qt_debug_texture_count; + static bool atexit_registered = false; if (!atexit_registered) { - atexit(qt_print_texture_count); + atexit(qt_debug_print_texture_count); atexit_registered = true; } +} + +static void qt_debug_remove_texture(QSGTexture* texture) +{ +#if defined(Q_OS_LINUX) || defined (Q_OS_MAC) + if (qmlDebugLeakBacktrace()) { + SGTextureTraceItem* item = qt_debug_allocated_textures.value(texture, 0); + if (item) { + qt_debug_allocated_textures.remove(texture); + delete item; + } + } +#endif + + --qt_debug_texture_count; + + if (qt_debug_texture_count < 0) + qDebug("Material destroyed after qt_debug_print_texture_count() was called."); +} + +#endif // QT_NO_DEBUG + + +QSGTexture::QSGTexture() + : QObject(*(new QSGTexturePrivate)) +{ +#ifndef QT_NO_DEBUG + qt_debug_add_texture(this); #endif } QSGTexture::~QSGTexture() { #ifndef QT_NO_DEBUG - --qt_texture_count; - if (qt_texture_count < 0) - qDebug("Material destroyed after qt_print_texture_count() was called."); + qt_debug_remove_texture(this); #endif } @@ -260,7 +338,7 @@ void QSGTexture::updateBindOptions(bool force) if (force || d->wrapChanged) { #if !defined(QT_NO_DEBUG) && defined(QT_OPENGL_ES_2) if (d->horizontalWrap == Repeat || d->verticalWrap == Repeat) { - bool npotSupported = QGLContext::currentContext()->functions()->hasOpenGLFeature(QGLFunctions::NPOTTextures); + bool npotSupported = QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures); QSize size = textureSize(); bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height()); if (!npotSupported && isNpot) @@ -341,7 +419,7 @@ void QSGPlainTexture::bind() if (!m_dirty_texture) { glBindTexture(GL_TEXTURE_2D, m_texture_id); if (m_has_mipmaps && !m_mipmaps_generated) { - const QGLContext *ctx = QGLContext::currentContext(); + QOpenGLContext *ctx = QOpenGLContext::currentContext(); ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D); m_mipmaps_generated = true; } @@ -377,7 +455,7 @@ void QSGPlainTexture::bind() #endif if (m_has_mipmaps) { - const QGLContext *ctx = QGLContext::currentContext(); + QOpenGLContext *ctx = QOpenGLContext::currentContext(); ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D); m_mipmaps_generated = true; } diff --git a/src/declarative/scenegraph/util/qsgtexture_p.h b/src/declarative/scenegraph/util/qsgtexture_p.h index 971e5e686c..22812f8640 100644 --- a/src/declarative/scenegraph/util/qsgtexture_p.h +++ b/src/declarative/scenegraph/util/qsgtexture_p.h @@ -44,7 +44,7 @@ #include <private/qobject_p.h> -#include <QtOpenGL/qgl.h> +#include <QtGui/qopengl.h> #include "qsgtexture.h" #include <private/qsgcontext_p.h> diff --git a/src/declarative/scenegraph/util/qsgtexturematerial.cpp b/src/declarative/scenegraph/util/qsgtexturematerial.cpp index 7a7050e073..43bfbcad57 100644 --- a/src/declarative/scenegraph/util/qsgtexturematerial.cpp +++ b/src/declarative/scenegraph/util/qsgtexturematerial.cpp @@ -41,8 +41,8 @@ #include "qsgtexturematerial_p.h" -#include <QtOpenGL/qglshaderprogram.h> -#include <QtOpenGL/qglfunctions.h> +#include <QtGui/qopenglshaderprogram.h> +#include <QtGui/qopenglfunctions.h> QT_BEGIN_NAMESPACE @@ -103,7 +103,7 @@ void QSGOpaqueTextureMaterialShader::updateState(const RenderState &state, QSGMa t->setFiltering(tx->filtering()); #ifdef QT_OPENGL_ES_2 - bool npotSupported = state.context()->functions()->hasOpenGLFeature(QGLFunctions::NPOTTextures); + bool npotSupported = QOpenGLFunctions(const_cast<QOpenGLContext *>(state.context())).hasOpenGLFeature(QOpenGLFunctions::NPOTTextures); QSize size = t->textureSize(); bool isNpot = !isPowerOfTwo(size.width()) || !isPowerOfTwo(size.height()); if (!npotSupported && isNpot) { diff --git a/src/declarative/scenegraph/util/qsgtextureprovider.cpp b/src/declarative/scenegraph/util/qsgtextureprovider.cpp index abaf96ed5a..49d157d480 100644 --- a/src/declarative/scenegraph/util/qsgtextureprovider.cpp +++ b/src/declarative/scenegraph/util/qsgtextureprovider.cpp @@ -41,6 +41,9 @@ #include "qsgtextureprovider_p.h" +#include <qsgimage_p.h> +#include <qsgshadereffectsource_p.h> + #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif @@ -50,16 +53,10 @@ QT_BEGIN_NAMESPACE /*! \class QSGTextureProvider \brief The QSGTextureProvider class encapsulates texture based entities in QML. - */ - -/*! - Convenience function for casting a QObject to a QSGTextureProvider + The QSGTextureProvider lives primarily in the scene graph rendering thread. */ -QSGTextureProvider *QSGTextureProvider::from(QObject *object) -{ - return object ? static_cast<QSGTextureProvider *>(object->qt_metacast("QSGTextureProvider")) : 0; -} + QT_END_NAMESPACE diff --git a/src/declarative/scenegraph/util/qsgtextureprovider_p.h b/src/declarative/scenegraph/util/qsgtextureprovider_p.h index 756f1c613a..ebb6ca8507 100644 --- a/src/declarative/scenegraph/util/qsgtextureprovider_p.h +++ b/src/declarative/scenegraph/util/qsgtextureprovider_p.h @@ -42,8 +42,6 @@ #ifndef QSGTEXTUREPROVIDER_H #define QSGTEXTUREPROVIDER_H -#include <qgl.h> - #include "qsgtexture.h" #include "qobject.h" @@ -53,15 +51,15 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class QSGTextureProvider +class Q_DECLARATIVE_EXPORT QSGTextureProvider : public QObject { + Q_OBJECT public: virtual QSGTexture *texture() const = 0; - virtual const char *textureChangedSignal() const { return 0; } - static QSGTextureProvider *from(QObject *object); +Q_SIGNALS: + void textureChanged(); }; -Q_DECLARE_INTERFACE(QSGTextureProvider, "QSGTextureProvider") QT_END_NAMESPACE diff --git a/src/declarative/scenegraph/util/qsgvertexcolormaterial.cpp b/src/declarative/scenegraph/util/qsgvertexcolormaterial.cpp index 910d7a53f8..637d549279 100644 --- a/src/declarative/scenegraph/util/qsgvertexcolormaterial.cpp +++ b/src/declarative/scenegraph/util/qsgvertexcolormaterial.cpp @@ -39,9 +39,9 @@ ** ****************************************************************************/ -#include "qsgvertexcolormaterial_p.h" +#include "qsgvertexcolormaterial.h" -#include <qglshaderprogram.h> +#include <qopenglshaderprogram.h> QT_BEGIN_NAMESPACE @@ -134,20 +134,20 @@ QSGVertexColorMaterial::QSGVertexColorMaterial() } - /*! - Sets if the renderer should treat colors as opaque. + int QSGVertexColorMaterial::compare() const + + As the vertex color material has all its state in the vertex attributes, + all materials will be equal. - Setting this flag can in some cases improve performance. + \internal */ -void QSGVertexColorMaterial::setColorsAreOpaque(bool opaqueHint) +int QSGVertexColorMaterial::compare(const QSGMaterial *other) const { - setFlag(Blending, !opaqueHint); + return 0; } - - /*! \internal */ diff --git a/src/declarative/scenegraph/util/qsgvertexcolormaterial_p.h b/src/declarative/scenegraph/util/qsgvertexcolormaterial.h index 8392ef2155..c244f63834 100644 --- a/src/declarative/scenegraph/util/qsgvertexcolormaterial_p.h +++ b/src/declarative/scenegraph/util/qsgvertexcolormaterial.h @@ -50,12 +50,12 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class QSGVertexColorMaterial : public QSGMaterial +class Q_DECLARATIVE_EXPORT QSGVertexColorMaterial : public QSGMaterial { public: QSGVertexColorMaterial(); - void setColorsAreOpaque(bool opaqueHint); + int compare(const QSGMaterial *other) const; protected: virtual QSGMaterialType *type() const; |