diff options
author | Julian Thijssen <Nimthora@gmail.com> | 2016-07-27 15:45:31 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2017-01-23 11:34:05 +0000 |
commit | 7dc88b68904c7f1b7e012bd65ccdcbf48cc6e2e0 (patch) | |
tree | 6de47b86b99200b999eddd8de0f07c2e86d8e027 /src/gui/opengl/qopenglpaintengine_p.h | |
parent | da4b6c4774c0adf8dee5ee4a9a8d9d24967ede3c (diff) |
Add support for OpenGL 3.2+ core profile contexts in QPainter
This change allows painting via QPainter onto a QOpenGLWindow, QOpenGLWidget
or QOpenGLFramebufferObject when an core profile context is in use. This is
important on macOS in particular, where compatibility profiles are not
available, and so the only way to use modern OpenGL is via a core profile
context.
Added core profile compatible shaders with moder GLSL keywords.
The paint engine binds a VAO and two VBOs from now on, whenever VAOs are
supported. Note that this changes behavior also for OpenGL 2.x context that
have VAO support via extensions.
The Lancelot test suite gains support for core profile contexts. This can
be triggered via -coreglbuffer in place of -glbuffer when manually inspecting
via 'lance', while tst_lancelot will automatically run core context-based tests
whenever supported.
Task-number: QTBUG-33535
Change-Id: I6323a7ea2aaa9e111651ebbffd3e40259c8e7a9c
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src/gui/opengl/qopenglpaintengine_p.h')
-rw-r--r-- | src/gui/opengl/qopenglpaintengine_p.h | 74 |
1 files changed, 63 insertions, 11 deletions
diff --git a/src/gui/opengl/qopenglpaintengine_p.h b/src/gui/opengl/qopenglpaintengine_p.h index 807efb1ec2..679b3c0557 100644 --- a/src/gui/opengl/qopenglpaintengine_p.h +++ b/src/gui/opengl/qopenglpaintengine_p.h @@ -65,6 +65,9 @@ #include <private/qopenglextensions_p.h> +#include <QOpenGLVertexArrayObject> +#include <QOpenGLBuffer> + enum EngineMode { ImageDrawingMode, TextDrawingMode, @@ -193,7 +196,11 @@ public: snapToPixelGrid(false), nativePaintingActive(false), inverseScale(1), - lastTextureUnitUsed(QT_UNKNOWN_TEXTURE_UNIT) + lastTextureUnitUsed(QT_UNKNOWN_TEXTURE_UNIT), + vertexBuffer(QOpenGLBuffer::VertexBuffer), + texCoordBuffer(QOpenGLBuffer::VertexBuffer), + opacityBuffer(QOpenGLBuffer::VertexBuffer), + indexBuffer(QOpenGLBuffer::IndexBuffer) { } ~QOpenGL2PaintEngineExPrivate(); @@ -222,7 +229,8 @@ public: void drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat, QStaticTextItem *staticTextItem); // Calls glVertexAttributePointer if the pointer has changed - inline void setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer); + inline void uploadData(unsigned int arrayIndex, const GLfloat *data, GLuint count); + inline bool uploadIndexData(const void *data, GLenum indexValueType, GLuint count); // draws whatever is in the vertex array: void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive); @@ -313,6 +321,12 @@ public: GLenum lastTextureUnitUsed; GLuint lastTextureUsed; + QOpenGLVertexArrayObject vao; + QOpenGLBuffer vertexBuffer; + QOpenGLBuffer texCoordBuffer; + QOpenGLBuffer opacityBuffer; + QOpenGLBuffer indexBuffer; + bool needsSync; bool multisamplingAlwaysEnabled; @@ -326,17 +340,55 @@ public: }; -void QOpenGL2PaintEngineExPrivate::setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer) +void QOpenGL2PaintEngineExPrivate::uploadData(unsigned int arrayIndex, const GLfloat *data, GLuint count) { Q_ASSERT(arrayIndex < 3); - if (pointer == vertexAttribPointers[arrayIndex]) - return; - - vertexAttribPointers[arrayIndex] = pointer; - if (arrayIndex == QT_OPACITY_ATTR) - funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, pointer); - else - funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, pointer); + + // If a vertex array object is created we have a profile that supports them + // and we will upload the data via a QOpenGLBuffer. Otherwise we will use + // the legacy way of uploading the data via glVertexAttribPointer. + if (vao.isCreated()) { + if (arrayIndex == QT_VERTEX_COORDS_ATTR) { + vertexBuffer.bind(); + vertexBuffer.allocate(data, count * sizeof(float)); + } + if (arrayIndex == QT_TEXTURE_COORDS_ATTR) { + texCoordBuffer.bind(); + texCoordBuffer.allocate(data, count * sizeof(float)); + } + if (arrayIndex == QT_OPACITY_ATTR) { + opacityBuffer.bind(); + opacityBuffer.allocate(data, count * sizeof(float)); + } + if (arrayIndex == QT_OPACITY_ATTR) + funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, 0); + else + funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, 0); + } else { + // If we already uploaded the data we don't have to do it again + if (data == vertexAttribPointers[arrayIndex]) + return; + + // Store the data in cache and upload it to the graphics card. + vertexAttribPointers[arrayIndex] = data; + if (arrayIndex == QT_OPACITY_ATTR) + funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, data); + else + funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, data); + } +} + +bool QOpenGL2PaintEngineExPrivate::uploadIndexData(const void *data, GLenum indexValueType, GLuint count) +{ + // Follow the uploadData() logic: VBOs are used only when VAO support is available. + // Otherwise the legacy client-side pointer path is used. + if (vao.isCreated()) { + Q_ASSERT(indexValueType == GL_UNSIGNED_SHORT || indexValueType == GL_UNSIGNED_INT); + indexBuffer.bind(); + indexBuffer.allocate(data, count * (indexValueType == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32))); + return true; + } + return false; } QT_END_NAMESPACE |