9eb9bd703b
This patch provides a code generator that can be executed offline to generate a few classes for enhancing Qt's support for OpenGL. The generated code effectively provides all the benefits of GLEW in its multi-context form but for all platforms and even for ES2. The code generator takes as input the official Khronos gl.spec specification and gl.tm typemap files. These provide all of the information required to create the OpenGL Desktop related classes. The classes for ES2 are hand-crafted as no similar spec files have been published. The generated code supports all OpenGL extensions listed in the Khronos registry for both Desktop OpenGL and ES 2. There is a helper factory class generated which are used by QOpenGLContext::versionFunctions(). This allows code like the following to be written: QOpenGLFunctions_3_3_Core* m_funcs = 0; m_funcs = m_context->versionFunctions<QOpenGLFunctions_3_3_Core>(); if (!m_funcs) { qWarning() << "Could not obtain required OpenGL context version"; exit(1); } if (!m_funcs->initializeOpenGLFunctions()) { qWarning() << "Failed to resolve entry points"; exit(2); } // Get an extension object QOpenGLExtension_ARB_draw_buffers* ext = 0; if (m_context->hasExtension("GL_ARB_draw_buffers")) { ext = new QOpenGLExtension_ARB_draw_buffers(); ext->initializeOpenGLFunctions(m_context); } Such usage will allow much easier and rigorous use of features in modern OpenGL and extensions both in Qt itself and by users of Qt. Follow-up patches will import the generated files and then use these to reinstate OpenGL geometry shaders, add tessellation shaders, and other OpenGL constructs. Change-Id: Id0172e8aa1fd57eb4e6979a96d10fb5a34826426 Reviewed-by: Samuel Rødal <samuel.rodal@digia.com> Reviewed-by: James Turner <james.turner@kdab.com> |
||
---|---|---|
.. | ||
codegenerator.cpp | ||
codegenerator.h | ||
glgen.pro | ||
main.cpp | ||
qopenglextensions.cpp.footer | ||
qopenglextensions.cpp.header | ||
qopenglextensions.h.footer | ||
qopenglextensions.h.header | ||
qopenglversionfunctions__VERSION__.cpp.footer | ||
qopenglversionfunctions__VERSION__.cpp.header | ||
qopenglversionfunctions__VERSION__.h.footer | ||
qopenglversionfunctions__VERSION__.h.header | ||
qopenglversionfunctions.cpp.footer | ||
qopenglversionfunctions.cpp.header | ||
qopenglversionfunctions.h.footer | ||
qopenglversionfunctions.h.header | ||
qopenglversionfunctionsfactory_p.h.header | ||
qopenglversionfunctionsfactory.cpp.footer | ||
qopenglversionfunctionsfactory.cpp.header | ||
README.txt | ||
specparser.cpp | ||
specparser.h |
Overview ======== This is the glgen application used to generate OpenGL related classes from the official Khronos OpenGL specification and typemap files. To run this application download the gl.spec and gl.tm files from: http://www.opengl.org/registry/api/gl.spec http://www.opengl.org/registry/api/gl.tm and place them into the application directory. These files are not stored in the Qt Project's git repo or downloaded automatically to a) avoid copyright issues b) make sure the version of OpenGL used is controlled by a human The glgen application parses these files and generates: 1) A set of public classes, one for each combination of OpenGL version and profile. 2) A set of backend helper classes that contain the actual function pointers 3) A factory class for the classes in 1) 4) A set of classes, one for each OpenGL extension which introduces new entry points We will now describe each of these categories. OpenGL Version and Profile Classes ================================== The base class of this set is QAbstractOpenGLFunctions. From this we inherit one class for each OpenGL version and if supported, profile. The Core profile contains only the non-deprecated functionality. The Compatibility profile also includes all functionality that was removed in OpenGL 3.1. Therefore, for OpenGL 3.2 onwards we have two classes for each version. All of these classes are named with the following convention: QOpenGLFunctions_<MAJOR>_<MINOR>[_PROFILE] For example QOpenGLFunctions_2_1, QOpenGLFunctions_4_3_Core The source and header files for these classes take the form qopenglfunction_<MAJOR>_<MINOR>[_PROFILE].cpp qopenglfunction_<MAJOR>_<MINOR>[_PROFILE].h and should be moved to $QTBASE/src/gui/opengl/ and forms part of the public QtGui library API. Backend Helper Classes ====================== Every OpenGL function is categorised by which version it was introduced with and whether it is part of the Core Profile and is deemed part of the core specification or whther it is only part of the Compatibility profile and has been marked as deprecated. Glgen creates a backend helper class containing function pointers to match each possible case. E.g. QOpenGLFunctions_1_5_CoreBackend contains functions introduced in OpenGL 1.5 which are still core (not deprecated). The public frontend classes described above contain pointers to the set of backend objects necessary to implement the functions for their version and profile. Creating new instances of these backend objects for each public version functions object would be wasteful in terms of memory (repeated function pointers) and CPU time (no need to keep re-solving the same functions). We cannot share the backend objects globally as OpenGL entry point addresses are specific to the OpenGL context. They cannot even be reliably shared between a context group. This is not surprising if you consider the case of contexts in a share group where the contexts have different versions or even profiles. We therefore share the backend instances at the QOpenGLContext level using a simple reference counting scheme. When the frontend version functions objects are intialized they check to see if the associated context already has suitable backend objects available. If so they use them, otherwise they will create backend objects and associate them with the context. The backend classes are in qopenglversionfunctions.h qopenglversionfunctions.cpp and should also be moved to $QTBASE/src/gui/opengl/ OpenGL Version and Profile Factory ================================== Instances of the OpenGL version and profile classes described above can be obtained from QOpenGLContext by means of the versionFunctions() member. The OpenGLContext retains ownership of the QOpenGLFunctions_* object. If a suitable object does not already exist it is created by the factory class generated by glgen. It is possible to request version functions objects for any version/profile combination from a context. However not all requests can be serviced. For example consider the case of an OpenGL 3.3 Core profile context. In this case: * Requesting a 3.3 core profile functions object would succeed. * Requesting a 3.3 compatibility profile functions object would fail. We would fail to resolve the deprecated functions. * 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. * Requesting a 3.1 functions object would succeed. There is nothing in 3.1 that is not also in 3.3 core. If a request is not able to be serviced the factory, and hence QOpenGLContext::versionFunctions() will return a null pointer that can be checked for. The source and header file for this class should be moved to $QTBASE/src/gui/opengl/ and forms part of the QtGui library. If a user instantiates a version functions object directly (i.e. not via QOpenGLContext) then it bypasses the above checks. However, the same checks are applied in the initializeOpenGLFunctions() method and the result can once again be checked. This approach allows maximum flexibility but ensure's safety in that once the user posesses a functions object that has been successfully initialized they can rely upon its member functions being successfully resolved. OpenGL Extension Classes ======================== In addition, glgen also creates one class for each OpenGL extension that introduces new entry points. These classes are named with the convention QOpenGLExtension_<name-of-extension> The usage pattern for OpenGL extensions is to just use a small number of extensions out of the large number of those available. Rather than bloat QtGui with all possible extensions, a new static library will be introduced to hold these classes. That way users will only link in the code for the extensions that they actually use. The source and header file for these classes should be moved to $QTBASE/src/openglextensions/