ANNOUNCE: OpenGLRaw 1.0.0.0

As a first step to make the OpenGL package easier to install, more modular and a bit more flexible, a low-level binding for OpenGL has been uploaded to Hackage. From OpenGLRaw's package description: ------------------------------------------------------------ OpenGLRaw is a raw Haskell binding for the OpenGL 3.1 graphics system and lots of OpenGL extensions. It is basically a 1:1 mapping of OpenGL's C API, intended as a basis for a nicer interface. OpenGLRaw offers access to all necessary functions, tokens and types plus a general facility for loading extension entries. The module hierarchy closely mirrors the naming structure of the OpenGL extensions, making it easy to find the right module to import. All API entries are loaded dynamically, so no special C header files are needed for building this package. If an API entry is not found at runtime, a userError is thrown. OpenGL is the industry's most widely used and supported 2D and 3D graphics application programming interface (API), incorporating a broad set of rendering, texture mapping, special effects, and other powerful visualization functions. For more information about OpenGL and its various extensions, please see http://www.opengl.org/ and http://www.opengl.org/registry/. ------------------------------------------------------------ Version 1.0.0.0 covers the OpenGL 3.1 core, all ARB extensions and all EXT extensions. Great care has been taken to introduce as few build dependencies as possible, so neither autoconf is required, nor any OpenGL headers. Future versions of the OpenGL package will basically be a convenience layer above this package, but you can always fall back to the raw binding if required. To get a taste for it, have a look at http://aedion.de/haskell/SmoothRaw.hs, which should look extremely familiar to anyone who has used OpenGL's C API. Any feedback is highly appreciated. Cheers, S.

Sven Panne wrote:
As a first step to make the OpenGL package easier to install, more modular and a bit more flexible, a low-level binding for OpenGL has been uploaded to Hackage.
Reminds me of Mauricio's "bindings" efforts, though with some different design decisions. Considering that OpenGL has many many functions that may not be supported, in no linear pattern (EXT, or just binding to an OpenGL 2.x implementation, etc.), dynamic loading might be a good choice. Is it fast enough? (Any amount of performance penalty is probably too much for OpenGL -- I remember one time I resorted to some C in my OpenGL haskell program because I couldn't figure out how to unbox enough things in my Haskell code or maybe GHC 6.4 just wasn't as good as low-level optimizations/code generation.) -Isaac
From OpenGLRaw's package description:
------------------------------------------------------------ OpenGLRaw is a raw Haskell binding for the OpenGL 3.1 graphics system and lots of OpenGL extensions. It is basically a 1:1 mapping of OpenGL's C API, intended as a basis for a nicer interface. OpenGLRaw offers access to all necessary functions, tokens and types plus a general facility for loading extension entries. The module hierarchy closely mirrors the naming structure of the OpenGL extensions, making it easy to find the right module to import. All API entries are loaded dynamically, so no special C header files are needed for building this package. If an API entry is not found at runtime, a userError is thrown.
OpenGL is the industry's most widely used and supported 2D and 3D graphics application programming interface (API), incorporating a broad set of rendering, texture mapping, special effects, and other powerful visualization functions. For more information about OpenGL and its various extensions, please see http://www.opengl.org/ and http://www.opengl.org/registry/. ------------------------------------------------------------
Version 1.0.0.0 covers the OpenGL 3.1 core, all ARB extensions and all EXT extensions. Great care has been taken to introduce as few build dependencies as possible, so neither autoconf is required, nor any OpenGL headers. Future versions of the OpenGL package will basically be a convenience layer above this package, but you can always fall back to the raw binding if required. To get a taste for it, have a look at http://aedion.de/haskell/SmoothRaw.hs, which should look extremely familiar to anyone who has used OpenGL's C API.
Any feedback is highly appreciated.
Cheers, S.
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell

Am Donnerstag, 11. Juni 2009 20:56:46 schrieb Isaac Dupree:
Reminds me of Mauricio's "bindings" efforts, though with some different design decisions. Considering that OpenGL has many many functions that may not be supported, in no linear pattern (EXT, or just binding to an OpenGL 2.x implementation, etc.), dynamic loading might be a good choice. Is it fast enough?
Of course the API entries are not dynamically looked up every time they are called, this would kill performance, even when they are not called very often. Let's look at e.g. glCreateShader. The entry is defined via a macro: EXTENSION_ENTRY(glCreateShader,GLenum -> IO GLuint) This expands into (slightly reformatted): ------------------------------------------------------------ glCreateShader :: GLenum -> IO GLuint glCreateShader = dyn_glCreateShader ptr_glCreateShader foreign import ccall unsafe "dynamic" dyn_glCreateShader :: Invoker (GLenum -> IO GLuint) ptr_glCreateShader :: FunPtr a ptr_glCreateShader = unsafePerformIO (getExtensionEntry extensionNameString "glCreateShader") {-# NOINLINE ptr_glCreateShader #-} ------------------------------------------------------------ Invoke is just a handy shortcut: type Invoker a = FunPtr a -> a As you can see, ptr_glCreateShader is a CAF and therefore evaluated at most once. After the first call of glCreateShader, further calls basically boil down to an indirect jump, having a very low overhead. The only downside here is that the addresses of the OpenGL API entries *might* depend on the pixel format on Windows, which could lead to problems when using multiple rendering contexts with different pixel formats. But this issue is ignored by e.g. GLee an GLEW, too, at least if they are built in their default way, so this doesn't seem to be a real problem in practice. As usual, Windows is the only platform having chosen the most silly way of doing things, *nices don't have this problem, even in theory (see e.g. then OpenGL Linux ABI). Dynamically loading the whole OpenGL API has a long tradition, it was e.g. done in Quake 2, and what was good enough for John Carmack in 1997 should be good enough for us in 2009. The macro approach has the advantage that you have a single place to control how API entries are retrieved and called. It e.g. shouldn't be too hard to add logging to every call, just by changing the EXTENSION_ENTRY macro, probably using some Template Haskell (or Oleg comes up with some insane use of a type system extension for the same task... ;-).
(Any amount of performance penalty is probably too much for OpenGL -- I remember one time I resorted to some C in my OpenGL haskell program because I couldn't figure out how to unbox enough things in my Haskell code or maybe GHC 6.4 just wasn't as good as low-level optimizations/code generation.)
Nowadays the API call overhead is completely irrelevant for performance. The immediate mode is deprecated and you can (and should!) throw tens of thousands of textured, lit polygons to OpenGL with a handful of API calls. Or as the OpenGL Super Bible puts it: "This is not your father's OpenGL"... ;-) Cheers, S.
participants (2)
-
Isaac Dupree
-
Sven Panne