-
Notifications
You must be signed in to change notification settings - Fork 18
Merging OpenGLRaw and gl
Currently there are 2 similar, but different Haskell packages available for the raw access to OpenGL, OpenGLRaw and gl. While competition is good and healthy, especially in the Open Source world, the situation is a bit confusing for users: Which package should they use? And why should 2 different teams duplicate their effort for something functionally equivalent? To improve the situation, this proposal aims to merge those packages, basically making it possible to deprecate gl
afterwards. The result will be a new version of OpenGLRaw
containing "the best of both worlds", at the cost of not being backwards-compatible with neither OpenGLRaw
nor gl
. This is a price one has to pay to get a clean slate after a long time, and it's a small one considering the fact that previous versions are still available on Hackage.
-
OpenGLRaw
exposes OpenGL tokens as plain old Haskell values, e.g.gl_LINES = 0x0001
whilegl
uses bidirectional pattern synonyms, e.g.pattern GL_LINES = 0x0001
. While it is a tiny bit more convenient to use and visually resembles the original OpenGL C API slightly more, thePatternSynonyms
extension is only available in GHC >= 7.8.1 (released April 2014). Proposal: This is a tough call, it’s basically backwards compatibility vs. ease of use. Perhaps we should use pattern synonyms?
[Edward Kmett: the pattern synonyms were a very deliberate choice on the behalf of gl
, because they can be used naked in pattern position. This can generate both more efficient and more readable code.]
[Sven Panne: Using pattern synonyms and dropping support for GHC < 7.8 is fine with me. For people using an older GHC, Hackage still has the old OpenGLRaw versions and should find a build plan for them, so older stuff continues to work.]
- The types of the OpenGL tokes are slightly different, too:
OpenGLRaw
uses the more exact types from the OpenGL registry, i.e. one ofGLbitfield
,GLenum
,GLubyte
,GLuint
, orGLuint64
, whilegl
always uses(Num a, Eq a) => a
. OpenGL is actually a bit sloppy regarding its types, but the generality provided byNum
doesn't help: A survey of the uses offromIntegral
in theOpenGL
package shows that basically all conversions are either due to the type of the value returned by someglGetFOO
or by an impedance mismatch between OpenGL's types andInt
(forced by some other library). In both cases, the more liberal type of the tokens wouldn't have helped. Resolution: Use the more exact types, any kind of conversions should be explicit. -
OpenGLRaw
has types per OpenGL version (see e.g. Core45),gl
always exposes all of them (see Types).OpenGLRaw
’s approach is following the spec more closely, e.g.GLsizeiptr
is only mentioned in OpenGL >= 1.5. Resolution: UseOpenGLRaw
’s approach. - The
gl
package exposes OpenGL ES APIs, too, but this is wrong for several reasons (Proposal: Do not expose OpenGL ES stuff, this should live in a separate package):- The token values can be API-dependent, and there is actually one example of this:
GL_ACTIVE_PROGRAM_EXT
has the value 0x8259 under OpenGL ES 2, while it has the value 0x8B8D under OpenGL. While this was actually a specification glitch, it is out in the wild now and ignoring it doesn’t it make go away. - OpenGL versions of extensions can be completely unrelated to their OpenGL ES versions, see e.g.
GL_EXT_separate_shader_objects
. - API entry points for OpenGL ES have to be retrieved via EGL, while OpenGL entry points must be retrieved via GLX/WGL/…, i.e. window-system-specific ways. Perhaps in some bright future EGL will be the one and only way (see e.g. the EGL_KHR_create_context) extension, but this is not the case at the moment.
- The token values can be API-dependent, and there is actually one example of this:
[Edward Kmett: I was actually in the process of going further in gl
and starting to roll in WebGL support! So this may be a bit of a sticking point.]
[Sven Panne: Until EGL unifies everything, offering both WebGL an "normal" OpenGL in a single package won't really work. The current EGL won't give you OpenGL-only entry points, and there is no guarantee that GLX/WGL/... will return the right entry points for WebGL. Annoying, but that's how it is today.]
- Extensions in
OpenGLRaw
come in 2 versions when needed (core and compatibility, see e.g. VertexType2101010RevCore and VertexType2101010RevCompatibility), whilegl
ignores that distinction. Resolution: Do it likeOpenGLRaw
, the OpenGL registry clearly makes it explicit that extensions are profile-dependent in general.
-
The module prefix used by
OpenGLRaw
isGraphics.Rendering.OpenGL.Raw
, whilegl
uses the shorterGraphics.GL
.OpenGLRaw
’s prefix is overly long and dates back many years, to a time when there was consensus that this might be a good idea. Nowadaysgl
’s choice looks much saner. Nevertheless, it’s desirable to distinguish the raw binding from any higher-level packages building on it, likeOpenGL
. Resolution: UseGraphics.GL.Raw
as the prefix. -
gl
uses an additionalExt
level belowGraphics.GL
for modules containing extensions, but this is superfluous and only makes things more verbose. The extensions are already grouped by their vendor IDs, which form their own sub-namespaces. Resolution: Simply dropExt
, this even buys us back 3 characters, which we spend onRaw
(see item above). -
OpenGLRaw
uses the module nameVersionXY
for OpenGL versions without profiles, whilegl
usesStandardXY
. Proposal: UseVersionXY
, it’s more consistent with the OpenGL CPP defines. -
Although formally OpenGL 3.2 introduced the notion of profiles, the OpenGL registry already does it for 3.0 and 3.1, too.
OpenGLRaw
follows the registry, whilegl
does not. The differences are small, though, onlyGL_INDEX
,GL_TEXTURE_LUMINANCE_TYPE
, andGL_TEXTURE_INTENSITY_TYPE
. Resolution: Follow the registry.
-
OpenGLRaw
links to all possible man page versions of an API entry, whilegl
only links to the latest one, compare e.g. the documentation forglCreateProgram
in OpenGLRaw and in gl. Note that the latest man page might document stuff which is not supported in previous versions and therefore it can be quite misleading. The documentation for an entity is always the same, regardless of the version. This is caused by the fact that the various modules basically consist of re-exports only, which is necessary to mix versions and extensions. Resolution: UseOpenGLRaw
’s man page links, so the user can choose the right one. -
OpenGLRaw
documents each parameter directly in the signature, whilegl
does it in a more separated way, compare e.g. the documentation forglGetDebugMessageLog
in OpenGLRaw and in gl. The former way avoids the mental matching of parameters and their corresponding documentation and is more direct. Resolution: UseOpenGLRaw
’s way of parameter documentation. -
gl
repeatedly expands enumerant groups in the documentation, whileOpenGLRaw
just mentions the group names, compare e.g. the documentation forglGetTexLevelParameterfv
in gl and in OpenGLRaw. The problem with enumerant groups in the registry is that they are highly incomplete, inconsistent and poorly maintained, but most importantly: They should better depend on the OpenGL version, which they don’t, so mentioning the individual enumerants is wrong and misleading in general (OpenGL versions both remove and add tokens/functions). Nevertheless, people seem to like it. Resolution: Change the group names into links to separately documented enumerant groups, getting rid of the duplication and visual overload. A new version of OpenGL containing that change is already on Hackage, compare e.g. the documentation forglGetTexLevelParameterfv
in gl and in OpenGLRaw (The Hackage docs are broken due to a buggy Haddock version). Note that the alias computation for enumerants still needs some love, but it's basically working, and it's something not ingl
.
The differences are not really relevant for users of the package, they are just here for reference.
-
Both
OpenGLRaw
andgl
generate most of the binding from the XML API description from the OpenGL registry.OpenGLRaw
has the resulting Haskell files checked in, whilegl
dynamically generates them during build time. Having the generated files checked in removes the need to build various XML-related packages, so it’s more convenient and faster for people just wanting to use OpenGL. Furthermore, when the OpenGL registry has changed, one has to look at the generated files anyway: The cabal file needs an update, perhaps needing some kind of version bump. Note thatgl
ships the build artifacts, too, but the library user nevertheless needs several (useless)hxt
-related packages. Resolution: Continue to check in the generated files. -
OpenGLRaw
uses a git submodule for an OpenGL registry mirror to getgl.xml
, whilegl
uses a checked-in version. Resolution: Use a git submodule, it’s a bit more explicit. Perhaps a note in the README about the git magic involved might be nice.
Thanks to Edward Kmett and Gabríel Arthúr Pétursson for their work on gl
, thereby urging me to do things I would have been too lazy to do otherwise... 😉