summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@digia.com>2014-06-13 16:36:27 +0200
committerLaszlo Agocs <laszlo.agocs@digia.com>2014-08-08 07:29:53 +0200
commitbb760d9514ed617ee8e7344152b3fa697b2c4171 (patch)
treeff80c5cff36421c1c17bdc86f5349da6194aefa2 /src/gui
parent22e439141384f49028770d2410fafb18ef8cad1f (diff)
Add support for glMapBufferRange in the wrappers and resolvers
QOpenGLBuffer::map() and related helpers are becoming useless in OpenGL ES 3.0 and up: instead of the old GL_OES_map_buffer, glMapBufferRange, but not glMapBuffer, is now part of the standard. On desktop GL_ARB_map_buffer_range is present by default in OpenGL 3.0 and newer. [ChangeLog][QtGui] Added QOpenGLBuffer::mapBufferRange(). Task-number: QTBUG-38168 Change-Id: I4e9bbe8ced9ee4d535ac32849a8c08c26d79cb49 Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/opengl/qopenglbuffer.cpp69
-rw-r--r--src/gui/opengl/qopenglbuffer.h14
-rw-r--r--src/gui/opengl/qopenglextensions_p.h16
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp31
4 files changed, 122 insertions, 8 deletions
diff --git a/src/gui/opengl/qopenglbuffer.cpp b/src/gui/opengl/qopenglbuffer.cpp
index a8a2255104..3ae45abb11 100644
--- a/src/gui/opengl/qopenglbuffer.cpp
+++ b/src/gui/opengl/qopenglbuffer.cpp
@@ -128,6 +128,18 @@ QT_BEGIN_NAMESPACE
\value ReadWrite The buffer will be mapped for reading and writing.
*/
+/*!
+ \enum QOpenGLBuffer::RangeAccessFlag
+ This enum defines the access mode bits for QOpenGLBuffer::mapRange().
+
+ \value RangeRead The buffer will be mapped for reading.
+ \value RangeWrite The buffer will be mapped for writing.
+ \value RangeInvalidate Discard the previous contents of the specified range.
+ \value RangeInvalidateBuffer Discard the previous contents of the entire buffer.
+ \value RangeFlushExplicit Indicates that modifications are to be flushed explicitly via \c glFlushMappedBufferRange.
+ \value RangeUnsynchronized Indicates that pending operations should not be synchronized before returning from mapRange().
+*/
+
class QOpenGLBufferPrivate
{
public:
@@ -514,10 +526,14 @@ int QOpenGLBuffer::size() const
It is assumed that create() has been called on this buffer and that
it has been bound to the current context.
- This function is only supported under OpenGL/ES if the
- \c{GL_OES_mapbuffer} extension is present.
+ \note This function is only supported under OpenGL ES 2.0 or
+ earlier if the \c GL_OES_mapbuffer extension is present.
- \sa unmap(), create(), bind()
+ \note On OpenGL ES 3.0 and newer, or, in case if desktop OpenGL,
+ if \c GL_ARB_map_buffer_range is supported, this function uses
+ \c glMapBufferRange instead of \c glMapBuffer.
+
+ \sa unmap(), create(), bind(), mapRange()
*/
void *QOpenGLBuffer::map(QOpenGLBuffer::Access access)
{
@@ -528,7 +544,48 @@ void *QOpenGLBuffer::map(QOpenGLBuffer::Access access)
#endif
if (!d->guard || !d->guard->id())
return 0;
- return d->funcs->glMapBuffer(d->type, access);
+ if (d->funcs->hasOpenGLExtension(QOpenGLExtensions::MapBufferRange)) {
+ QOpenGLBuffer::RangeAccessFlags rangeAccess = 0;
+ switch (access) {
+ case QOpenGLBuffer::ReadOnly:
+ rangeAccess = QOpenGLBuffer::RangeRead;
+ break;
+ case QOpenGLBuffer::WriteOnly:
+ rangeAccess = QOpenGLBuffer::RangeWrite;
+ break;
+ case QOpenGLBuffer::ReadWrite:
+ rangeAccess = QOpenGLBuffer::RangeRead | QOpenGLBuffer::RangeWrite;
+ break;
+ }
+ return d->funcs->glMapBufferRange(d->type, 0, size(), rangeAccess);
+ } else {
+ return d->funcs->glMapBuffer(d->type, access);
+ }
+}
+
+/*!
+ Maps the range specified by \a offset and \a count of the contents
+ of this buffer into the application's memory space and returns a
+ pointer to it. Returns null if memory mapping is not possible.
+ The \a access parameter specifies a combination of access flags.
+
+ It is assumed that create() has been called on this buffer and that
+ it has been bound to the current context.
+
+ \note This function is not available on OpenGL ES 2.0 and earlier.
+
+ \sa unmap(), create(), bind()
+ */
+void *QOpenGLBuffer::mapRange(int offset, int count, QOpenGLBuffer::RangeAccessFlags access)
+{
+ Q_D(QOpenGLBuffer);
+#ifndef QT_NO_DEBUG
+ if (!isCreated())
+ qWarning("QOpenGLBuffer::mapRange(): buffer not created");
+#endif
+ if (!d->guard || !d->guard->id())
+ return 0;
+ return d->funcs->glMapBufferRange(d->type, offset, count, access);
}
/*!
@@ -539,8 +596,8 @@ void *QOpenGLBuffer::map(QOpenGLBuffer::Access access)
It is assumed that this buffer has been bound to the current context,
and that it was previously mapped with map().
- This function is only supported under OpenGL/ES if the
- \c{GL_OES_mapbuffer} extension is present.
+ \note This function is only supported under OpenGL ES 2.0 and
+ earlier if the \c{GL_OES_mapbuffer} extension is present.
\sa map()
*/
diff --git a/src/gui/opengl/qopenglbuffer.h b/src/gui/opengl/qopenglbuffer.h
index ab564e9001..45e872e9a6 100644
--- a/src/gui/opengl/qopenglbuffer.h
+++ b/src/gui/opengl/qopenglbuffer.h
@@ -92,6 +92,17 @@ public:
ReadWrite = 0x88BA // GL_READ_WRITE
};
+ enum RangeAccessFlag
+ {
+ RangeRead = 0x0001, // GL_MAP_READ_BIT
+ RangeWrite = 0x0002, // GL_MAP_WRITE_BIT
+ RangeInvalidate = 0x0004, // GL_MAP_INVALIDATE_RANGE_BIT
+ RangeInvalidateBuffer = 0x0008, // GL_MAP_INVALIDATE_BUFFER_BIT
+ RangeFlushExplicit = 0x0010, // GL_MAP_FLUSH_EXPLICIT_BIT
+ RangeUnsynchronized = 0x0020 // GL_MAP_UNSYNCHRONIZED_BIT
+ };
+ Q_DECLARE_FLAGS(RangeAccessFlags, RangeAccessFlag)
+
QOpenGLBuffer::Type type() const;
QOpenGLBuffer::UsagePattern usagePattern() const;
@@ -118,6 +129,7 @@ public:
inline void allocate(int count) { allocate(0, count); }
void *map(QOpenGLBuffer::Access access);
+ void *mapRange(int offset, int count, QOpenGLBuffer::RangeAccessFlags access);
bool unmap();
private:
@@ -126,6 +138,8 @@ private:
Q_DECLARE_PRIVATE(QOpenGLBuffer)
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLBuffer::RangeAccessFlags)
+
QT_END_NAMESPACE
#endif // QT_NO_OPENGL
diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h
index 065cbb0e57..907e315e41 100644
--- a/src/gui/opengl/qopenglextensions_p.h
+++ b/src/gui/opengl/qopenglextensions_p.h
@@ -99,7 +99,8 @@ public:
Depth24 = 0x00010000,
SRGBFrameBuffer = 0x00020000,
MapBuffer = 0x00040000,
- GeometryShaders = 0x00080000
+ GeometryShaders = 0x00080000,
+ MapBufferRange = 0x00100000
};
Q_DECLARE_FLAGS(OpenGLExtensions, OpenGLExtension)
@@ -107,6 +108,7 @@ public:
bool hasOpenGLExtension(QOpenGLExtensions::OpenGLExtension extension) const;
GLvoid *glMapBuffer(GLenum target, GLenum access);
+ GLvoid *glMapBufferRange(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr length, GLbitfield access);
GLboolean glUnmapBuffer(GLenum target);
void glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
@@ -131,6 +133,8 @@ public:
explicit QOpenGLExtensionsPrivate(QOpenGLContext *ctx);
GLvoid* (QOPENGLF_APIENTRYP MapBuffer)(GLenum target, GLenum access);
+ GLvoid* (QOPENGLF_APIENTRYP MapBufferRange)(GLenum target, qopengl_GLintptr offset,
+ qopengl_GLsizeiptr length, GLbitfield access);
GLboolean (QOPENGLF_APIENTRYP UnmapBuffer)(GLenum target);
void (QOPENGLF_APIENTRYP BlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
@@ -150,6 +154,16 @@ inline GLvoid *QOpenGLExtensions::glMapBuffer(GLenum target, GLenum access)
return result;
}
+inline GLvoid *QOpenGLExtensions::glMapBufferRange(GLenum target, qopengl_GLintptr offset,
+ qopengl_GLsizeiptr length, GLbitfield access)
+{
+ Q_D(QOpenGLExtensions);
+ Q_ASSERT(QOpenGLExtensions::isInitialized(d));
+ GLvoid *result = d->MapBufferRange(target, offset, length, access);
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
inline GLboolean QOpenGLExtensions::glUnmapBuffer(GLenum target)
{
Q_D(QOpenGLExtensions);
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index 877cc6864d..43fff1c65a 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -388,7 +388,8 @@ static int qt_gl_resolve_extensions()
if (format.majorVersion() >= 3)
extensions |= QOpenGLExtensions::PackedDepthStencil
| QOpenGLExtensions::Depth24
- | QOpenGLExtensions::ElementIndexUint;
+ | QOpenGLExtensions::ElementIndexUint
+ | QOpenGLExtensions::MapBufferRange;
if (extensionMatcher.match("GL_OES_mapbuffer"))
extensions |= QOpenGLExtensions::MapBuffer;
@@ -429,6 +430,8 @@ static int qt_gl_resolve_extensions()
if (extensionMatcher.match("GL_EXT_packed_depth_stencil"))
extensions |= QOpenGLExtensions::PackedDepthStencil;
}
+ if (extensionMatcher.match("GL_ARB_map_buffer_range"))
+ extensions |= QOpenGLExtensions::MapBufferRange;
}
if (format.renderableType() == QSurfaceFormat::OpenGL && format.version() >= qMakePair(3, 2))
@@ -3182,11 +3185,36 @@ static void QOPENGLF_APIENTRY qopenglfResolveVertexAttribPointer(GLuint indx, GL
static GLvoid *QOPENGLF_APIENTRY qopenglfResolveMapBuffer(GLenum target, GLenum access)
{
+#ifdef QT_OPENGL_ES_3
+ // It is possible that GL_OES_map_buffer is present, but then having to
+ // differentiate between glUnmapBufferOES and glUnmapBuffer causes extra
+ // headache. QOpenGLBuffer::map() will handle this automatically, while direct
+ // calls are better off with migrating to the standard glMapBufferRange.
+ if (QOpenGLContext::currentContext()->format().majorVersion() >= 3) {
+ qWarning("QOpenGLFunctions: glMapBuffer is not available in OpenGL ES 3.0 and up. Use glMapBufferRange instead.");
+ return 0;
+ } else
+#endif
RESOLVE_FUNC(GLvoid *, ResolveOES, MapBuffer)(target, access);
}
+static GLvoid *QOPENGLF_APIENTRY qopenglfResolveMapBufferRange(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr length, GLbitfield access)
+{
+#ifdef QT_OPENGL_ES_3
+ if (QOpenGLContext::currentContext()->format().majorVersion() >= 3)
+ return ::glMapBufferRange(target, offset, length, access);
+ else
+#endif
+ RESOLVE_FUNC(GLvoid *, 0, MapBufferRange)(target, offset, length, access);
+}
+
static GLboolean QOPENGLF_APIENTRY qopenglfResolveUnmapBuffer(GLenum target)
{
+#ifdef QT_OPENGL_ES_3
+ if (QOpenGLContext::currentContext()->format().majorVersion() >= 3)
+ return ::glUnmapBuffer(target);
+ else
+#endif
RESOLVE_FUNC(GLboolean, ResolveOES, UnmapBuffer)(target);
}
@@ -3455,6 +3483,7 @@ QOpenGLExtensionsPrivate::QOpenGLExtensionsPrivate(QOpenGLContext *ctx)
: QOpenGLFunctionsPrivate(ctx)
{
MapBuffer = qopenglfResolveMapBuffer;
+ MapBufferRange = qopenglfResolveMapBufferRange;
UnmapBuffer = qopenglfResolveUnmapBuffer;
BlitFramebuffer = qopenglfResolveBlitFramebuffer;
RenderbufferStorageMultisample = qopenglfResolveRenderbufferStorageMultisample;