summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
authorSean Harmer <[email protected]>2012-09-22 16:34:21 +0100
committerThe Qt Project <[email protected]>2013-02-26 16:27:30 +0100
commit10aa64d74c0208ed9f42e88e6deb3000e9cad6df (patch)
tree4fb87da458d75f728c862fd3c34c483438249a14 /src/gui/kernel
parent4b1332783e16423b3b2c54125b130247ee6bc5b2 (diff)
OpenGL: Add a set of version and context specific OpenGL classes
This commit adds part of the output of utils/glgen and some simple modifications to QOpenGLContext to allow easy access to classes containing functions specific to a given OpenGL context and version. This allows compile-time detection of mis-use of OpenGL features. For example, trying to use glBegin(GL_TRIANGLES) with an OpenGL 3.2 Core Profile context will be detected by the compiler rather than at runtime. These capabilities make it much easier to add functionality to Qt and applications that relies upon core features of OpenGL from specific versions e.g. geometry shaders. Change-Id: Ieb584a489792595f831bc77dee84935c03bb5a64 Reviewed-by: Samuel Rødal <[email protected]>
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/qopenglcontext.cpp275
-rw-r--r--src/gui/kernel/qopenglcontext.h63
-rw-r--r--src/gui/kernel/qopenglcontext_p.h3
3 files changed, 341 insertions, 0 deletions
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 645c13a2ea8..483baf0f099 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -54,11 +54,163 @@
#include <QtGui/QScreen>
#include <private/qopenglextensions_p.h>
+#include <private/qopenglversionfunctionsfactory_p.h>
#include <QDebug>
QT_BEGIN_NAMESPACE
+class QOpenGLVersionProfilePrivate
+{
+public:
+ QOpenGLVersionProfilePrivate()
+ : majorVersion(0),
+ minorVersion(0),
+ profile(QSurfaceFormat::NoProfile)
+ {}
+
+ int majorVersion;
+ int minorVersion;
+ QSurfaceFormat::OpenGLContextProfile profile;
+};
+
+
+/*!
+ \class QOpenGLVersionProfile
+ \inmodule QtGui
+ \since 5.1
+ \brief The QOpenGLVersionProfile class represents the version and if applicable
+ the profile of an OpenGL context.
+
+ An object of this class can be passed to QOpenGLContext::versionFunctions() to
+ request a functions object for a specific version and profile of OpenGL.
+
+ It also contains some helper functions to check if a version supports profiles
+ or is a legacy version.
+*/
+
+/*!
+ Creates a default invalid QOpenGLVersionProfile object.
+*/
+QOpenGLVersionProfile::QOpenGLVersionProfile()
+ : d(new QOpenGLVersionProfilePrivate)
+{
+}
+
+/*!
+ Creates a QOpenGLVersionProfile object initialised with the version and profile
+ from \a format.
+*/
+QOpenGLVersionProfile::QOpenGLVersionProfile(const QSurfaceFormat &format)
+ : d(new QOpenGLVersionProfilePrivate)
+{
+ d->majorVersion = format.majorVersion();
+ d->minorVersion = format.minorVersion();
+ d->profile = format.profile();
+}
+
+/*!
+ Constructs a copy of \a other.
+*/
+QOpenGLVersionProfile::QOpenGLVersionProfile(const QOpenGLVersionProfile &other)
+ : d(new QOpenGLVersionProfilePrivate)
+{
+ *d = *(other.d);
+}
+
+/*!
+ Destroys the QOpenGLVersionProfile object.
+*/
+QOpenGLVersionProfile::~QOpenGLVersionProfile()
+{
+ delete d;
+}
+
+/*!
+ Assigns the version and profile of \a rhs to this QOpenGLVersionProfile object.
+*/
+QOpenGLVersionProfile &QOpenGLVersionProfile::operator=(const QOpenGLVersionProfile &rhs)
+{
+ if (this == &rhs)
+ return *this;
+ *d = *(rhs.d);
+ return *this;
+}
+
+/*!
+ Returns a QPair<int,int> where the components represent the major and minor OpenGL
+ version numbers respectively.
+
+ \sa setVersion()
+*/
+QPair<int, int> QOpenGLVersionProfile::version() const
+{
+ return qMakePair( d->majorVersion, d->minorVersion);
+}
+
+/*!
+ Sets the major and minor version numbers to \a majorVersion and \a minorVersion respectively.
+
+ \sa version()
+*/
+void QOpenGLVersionProfile::setVersion(int majorVersion, int minorVersion)
+{
+ d->majorVersion = majorVersion;
+ d->minorVersion = minorVersion;
+}
+
+/*!
+ Returns the OpenGL profile. Only make sense if profiles are supported by this version.
+
+ \sa setProfile(), supportsProfiles()
+*/
+QSurfaceFormat::OpenGLContextProfile QOpenGLVersionProfile::profile() const
+{
+ return d->profile;
+}
+
+/*!
+ Sets the profile. Only make sense if profiles are supported by this version.
+
+ \sa profile(), supportsProfiles()
+*/
+void QOpenGLVersionProfile::setProfile(QSurfaceFormat::OpenGLContextProfile profile)
+{
+ d->profile = profile;
+}
+
+/*!
+ Returns true if profiles are supported by the OpenGL version returned by version(). Only
+ OpenGL versions >= 3.2 support profiles.
+
+ \sa profile(), version()
+*/
+bool QOpenGLVersionProfile::hasProfiles() const
+{
+ return ( d->majorVersion > 3
+ || (d->majorVersion == 3 && d->minorVersion > 1));
+}
+
+/*!
+ Returns true is the OpenGL version returned by version() contains deprecated functions
+ and does not support profiles i.e. if the OpenGL version is <= 3.1.
+*/
+bool QOpenGLVersionProfile::isLegacyVersion() const
+{
+ return (d->majorVersion < 3 || (d->majorVersion == 3 && d->minorVersion == 0));
+}
+
+/*!
+ Returns true if the version number is valid. Note that for a default constructed
+ QOpenGLVersionProfile object this function will return false.
+
+ \sa setVersion(), version()
+*/
+bool QOpenGLVersionProfile::isValid() const
+{
+ return d->majorVersion > 0 && d->minorVersion >= 0;
+}
+
class QGuiGLThreadContext
{
public:
@@ -367,6 +519,10 @@ void QOpenGLContext::destroy()
d->platformGLContext = 0;
delete d->functions;
d->functions = 0;
+ qDeleteAll(d->versionFunctions);
+ d->versionFunctions.clear();
+ qDeleteAll(d->versionFunctionsBackend);
+ d->versionFunctionsBackend.clear();
}
/*!
@@ -425,6 +581,97 @@ QOpenGLFunctions *QOpenGLContext::functions() const
}
/*!
+ \fn T *QOpenGLContext::versionFunctions() const
+
+ Returns a pointer to an object that provides access to all functions for
+ the version and profile of this context. Before using any of the functions
+ they must be initialized by calling QAbstractOpenGLFunctions::initializeOpenGLFunctions().
+
+ Usually one would use the template version of this function to automatically
+ have the result cast to the correct type.
+
+ \code
+ QOpenGLFunctions_3_3_Core* funcs = 0;
+ funcs = context->versionFunctions<QOpenGLFunctions_3_3_Core>();
+ if (!funcs) {
+ qWarning() << "Could not obtain required OpenGL context version";
+ exit(1);
+ }
+ funcs->initializeOpenGLFunctions(context);
+ \endcode
+
+ It is possible to request a functions object for a different version and profile
+ than that for which the context was created. To do this either use the template
+ version of this function specifying the desired functions object type as the
+ template parameter or by passing in a QOpenGLVersionProfile object as an argument
+ to the non-template function.
+
+ Note that requests for function objects of other versions or profiles can fail and
+ in doing so will return a null pointer. Situations in which creation of the functions
+ object can fail are if the request cannot be satisfied due to asking for functions
+ that are not in the version or profile of this context. For example:
+
+ \list
+ \li Requesting a 3.3 core profile functions object would succeed.
+ \li Requesting a 3.3 compatibility profile functions object would fail. We would fail
+ to resolve the deprecated functions.
+ \li Requesting a 4.3 core profile functions object would fail. We would fail to resolve
+ the new core functions introduced in versions 4.0-4.3.
+ \li Requesting a 3.1 functions object would succeed. There is nothing in 3.1 that is not
+ also in 3.3 core.
+ \endlist
+
+ Note that if creating a functions object via this method that the QOpenGLContext
+ retains ownership of the object. This is to allow the object to be cached and shared.
+*/
+
+/*!
+ Returns a pointer to an object that provides access to all functions for
+ the version of the current context. Before using any of the functions
+ they must be initialized by calling QAbstractOpenGLFunctions::initializeOpenGLFunctions().
+
+ Usually one would use the template version of this function to automatically
+ have the result cast to the correct type.
+
+ \sa T *QOpenGLContext::versionFunctions()
+*/
+QAbstractOpenGLFunctions *QOpenGLContext::versionFunctions(const QOpenGLVersionProfile &versionProfile) const
+{
+ Q_D(const QOpenGLContext);
+ const QSurfaceFormat f = format();
+
+ // Ensure we have a valid version and profile. Default to context's if none specified
+ QOpenGLVersionProfile vp = versionProfile;
+ if (!vp.isValid())
+ vp = QOpenGLVersionProfile(f);
+
+ // Check that context is compatible with requested version
+ const QPair<int, int> v = qMakePair(f.majorVersion(), f.minorVersion());
+ if (v < vp.version())
+ return 0;
+
+ // If this context only offers core profile functions then we can't create
+ // function objects for legacy or compatibility profile requests
+ if (((vp.hasProfiles() && vp.profile() != QSurfaceFormat::CoreProfile) || vp.isLegacyVersion())
+ && f.profile() == QSurfaceFormat::CoreProfile)
+ return 0;
+
+ // Create object if suitable one not cached
+ QAbstractOpenGLFunctions* funcs = 0;
+ if (!d->versionFunctions.contains(vp)) {
+ funcs = QOpenGLVersionFunctionsFactory::create(vp);
+ if (funcs) {
+ funcs->setOwningContext(this);
+ d->versionFunctions.insert(vp, funcs);
+ }
+ } else {
+ funcs = d->versionFunctions.value(vp);
+ }
+
+ return funcs;
+}
+
+/*!
Returns the set of OpenGL extensions supported by this context.
The context or a sharing context must be current.
@@ -702,6 +949,34 @@ void QOpenGLContext::deleteQGLContext()
}
/*!
+ \internal
+*/
+QOpenGLVersionFunctionsBackend *QOpenGLContext::functionsBackend(const QOpenGLVersionStatus &v) const
+{
+ Q_D(const QOpenGLContext);
+ return d->versionFunctionsBackend.value(v, 0);
+}
+
+/*!
+ \internal
+*/
+void QOpenGLContext::insertFunctionsBackend(const QOpenGLVersionStatus &v,
+ QOpenGLVersionFunctionsBackend *backend)
+{
+ Q_D(QOpenGLContext);
+ d->versionFunctionsBackend.insert(v, backend);
+}
+
+/*!
+ \internal
+*/
+void QOpenGLContext::removeFunctionsBackend(const QOpenGLVersionStatus &v)
+{
+ Q_D(QOpenGLContext);
+ d->versionFunctionsBackend.remove(v);
+}
+
+/*!
\class QOpenGLContextGroup
\since 5.0
\brief The QOpenGLContextGroup class represents a group of contexts sharing
diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h
index e8d04d7446e..52b4a2da287 100644
--- a/src/gui/kernel/qopenglcontext.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -58,6 +58,10 @@
#endif
#include <QtGui/qopengl.h>
+#include <QtGui/qopenglversionfunctions.h>
+
+#include <QtCore/qhash.h>
+#include <QtCore/qpair.h>
QT_BEGIN_NAMESPACE
@@ -69,6 +73,50 @@ class QPlatformOpenGLContext;
class QScreen;
class QSurface;
+class QOpenGLVersionProfilePrivate;
+
+class Q_GUI_EXPORT QOpenGLVersionProfile
+{
+public:
+ QOpenGLVersionProfile();
+ explicit QOpenGLVersionProfile(const QSurfaceFormat &format);
+ QOpenGLVersionProfile(const QOpenGLVersionProfile &other);
+ ~QOpenGLVersionProfile();
+
+ QOpenGLVersionProfile &operator=(const QOpenGLVersionProfile &rhs);
+
+ QPair<int, int> version() const;
+ void setVersion(int majorVersion, int minorVersion);
+
+ QSurfaceFormat::OpenGLContextProfile profile() const;
+ void setProfile(QSurfaceFormat::OpenGLContextProfile profile);
+
+ bool hasProfiles() const;
+ bool isLegacyVersion() const;
+ bool isValid() const;
+
+private:
+ QOpenGLVersionProfilePrivate* d;
+};
+
+inline uint qHash(const QOpenGLVersionProfile &v, uint seed)
+{
+ return qHash(static_cast<int>(v.profile() * 1000)
+ + v.version().first * 100 + v.version().second * 10, seed);
+}
+
+inline bool operator==(const QOpenGLVersionProfile &lhs, const QOpenGLVersionProfile &rhs)
+{
+ if (lhs.profile() != rhs.profile())
+ return false;
+ return lhs.version() == rhs.version();
+}
+
+inline bool operator!=(const QOpenGLVersionProfile &lhs, const QOpenGLVersionProfile &rhs)
+{
+ return !operator==(lhs, rhs);
+}
+
class Q_GUI_EXPORT QOpenGLContextGroup : public QObject
{
Q_OBJECT
@@ -127,6 +175,15 @@ public:
QOpenGLFunctions *functions() const;
+ QAbstractOpenGLFunctions *versionFunctions(const QOpenGLVersionProfile &versionProfile = QOpenGLVersionProfile()) const;
+
+ template<class TYPE>
+ TYPE *versionFunctions() const
+ {
+ QOpenGLVersionProfile v = TYPE::versionProfile();
+ return static_cast<TYPE*>(versionFunctions(v));
+ }
+
QSet<QByteArray> extensions() const;
bool hasExtension(const QByteArray &extension) const;
@@ -147,11 +204,17 @@ private:
friend class QOpenGL2PaintEngineExPrivate;
friend class QSGDistanceFieldGlyphCache;
friend class QWidgetPrivate;
+ friend class QAbstractOpenGLFunctionsPrivate;
void *qGLContextHandle() const;
void setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *));
void deleteQGLContext();
+ QOpenGLVersionFunctionsBackend* functionsBackend(const QOpenGLVersionStatus &v) const;
+ void insertFunctionsBackend(const QOpenGLVersionStatus &v,
+ QOpenGLVersionFunctionsBackend *backend);
+ void removeFunctionsBackend(const QOpenGLVersionStatus &v);
+
void destroy();
};
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index ba5434e8acd..8a36df3e7ca 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -213,6 +213,9 @@ public:
//QWidgetPrivate::deleteTLSysExtra()
}
+ mutable QHash<QOpenGLVersionProfile, QAbstractOpenGLFunctions *> versionFunctions;
+ mutable QHash<QOpenGLVersionStatus, QOpenGLVersionFunctionsBackend *> versionFunctionsBackend;
+
void *qGLContextHandle;
void (*qGLContextDeleteFunction)(void *handle);