Figl
****

This manual is for Figl (version 2.0.0, updated 1 February 2013)

Copyright 2013 Andy Wingo and others.

     Figl is free software: you can redistribute and/or modify it and its documentation under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

     Figl is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.

     You should have received a copy of the GNU Lesser General Public License along with this program.  If not, see http://www.gnu.org/licenses/.

Portions of this document were generated from the upstream OpenGL documentation.  The work as a whole is redistributable under the license above.  Sections containing generated documentation are prefixed with a specific copyright header.

Introduction
************

Figl is the Foreign Interface to GL: an OpenGL binding for Guile.

OpenGL is a family of APIs and layers.  The following chapters discuss the parts of OpenGL and how they are bound by Figl.

But before that, some notes on the Figl binding as a whole.

About Figl
==========

Figl is a foreign interface to OpenGL because it uses the dynamic foreign function interface provided by Guile 2.0, providing access to OpenGL without any C code at all.  In fact, much of Figl (and this manual) is automatically generated from upstream API specifications and documentation.

We have tried to do a very complete job at wrapping OpenGL, and additionally have tried to provide a nice Scheme interface as well. Our strategy has been to separate the binding into low-level and high-level pieces.

The low-level bindings correspond exactly with the GL specification, and are well-documented.  However, these interfaces are not so nice to use from Scheme; output arguments have to be allocated by the caller, and there is only the most basic level of type checking, and no sanity checking at all.  For example, you can pass a bytevector of image data to the low-level glTexImage2D procedure, but no check is made that the dimensions you specify actually correspond to the size of the bytevector.  This function could end up reading past the end of the bytevector.  Worse things can happen with procedures that write to arrays, like glGetTexImage.

The high-level bindings are currently a work in progress, and are being manually written.  They intend to be a complete interface to the GL, without the need to use the low-level bindings.  However, the low-level bindings will always be available for you to use if needed, and have the advantage that their behavior is better documented and specified by OpenGL itself.

Low-level bindings are accessed by loading the (figl MODULE low-level), for example via:

     (use-modules (figl gl low-level))

The high-level modules are named like (figl MODULE), for example (figl gl).

GL
**

About OpenGL
============

OpenGL is a standard API for drawing three-dimensional graphics.  From its origin in Silicon Graphics's workstations the early 1990s, today it has become ubiquitous, with implementations on mobile phones, televisions, tablets, desktops, and even web browsers.

OpenGL has been able to achieve such widespread adoption not just because it co-evolved with powerful graphics hardware, but also because it was conceived of as an interface specification and not a piece of source code.  In fact, these days it is a family of APIs, available in several flavors and versions:

OpenGL 1.x
     This series of specifications started with the original releases in 1992, and ended with OpenGL 1.5 in 2003.  This era corresponds to a time when graphics cards were less powerful and more special-purpose, with dedicated hardware to handle such details as fog and lighting. As such the OpenGL 1.x API reflects the capabilities of these special units.

OpenGL 2.x
     By the early 2000s, graphics hardware had become much more general-purpose and needed a more general-purpose API.  The so-called fixed-function rendering pipeline of the earlier years was replaced with a programmable rendering pipeline, in which effects that would have required special hardware were instead performed by custom programs running on the graphics card.  OpenGL added support for allocating buffer objects on the graphics card, and for shader programs, which did the actual rendering. In time, this buffer-focused API came to be the preferred form of talking to the GL.

OpenGL ES
     OpenGL ES was a ``cut-down'' version of OpenGL 2.x, designed to be small enough to appeal to embedded device vendors.  OpenGL ES 1.x removed some of the legacy functionality from OpenGL, while adding interfaces to use fixed-point math, for devices without floating-point units.  OpenGL ES 2.x went farther still, removing the fixed-function pipeline entirely.  OpenGL ES 2.x is common on current smart phone platforms.

OpenGL 3.x and above
     The OpenGL 3.x series followed the lead of OpenGL ES, first deprecating (in 3.0) and then removing (in 3.1) the fixed-function pipeline.  OpenGL 3.0 was released in 2008, but the free Mesa impementation only began supporting it in 2012, so it is currently (1 February 2013) less common.

Figl wraps the OpenGL 2.1 API.  It's a ubiquitous subset of the OpenGL implementations that are actually deployed in the wild; its legacy API looks back to OpenGL 1.x, while the buffer-oriented API is compatible with OpenGL ES.

GL Contexts
===========

All this talk about drawing is very well and good, but how do you actually get a canvas?  Interestingly enough, this is outside the purview of the OpenGL specification.  There are specific ways to get an OpenGL context for each different windowing system that is out there.  OpenGL is all crayons and no paper.

For the X window system, there is a standard API for creating a GL context given a window (or a drawable), GLX.  See GLX, for more information on its binding in Guile.

Bseides creating contexts from native windows or drawables, each backend also supports functions to make a context current.  The OpenGL API is stateful; you can think of each call as taking an implicit current context parameter, which holds the current state of the GL and is operated on by the function in question. Contexts are thread-specific, and one context should not be active on more than one thread at a time.

All calls to OpenGL functions must be made while a context is active; otherwise the result is undefined.  Hopefully while you are getting used to this rule, your driver is nice enough not to crash on you if you call a function outside a GL context, but it's not even required to do that.  Backend-specific functions may or may not require a context to be current; for example, Windows requires a context to be current, wheras GLX does not.

There have been a few attempts at abstracting away the need for calling API specific to a given windowing system, notably GLUT and EGL.  GLUT is the older of the two, and though it is practically unchanged since the mid-1990s, it is still widely used on desktops. See GLUT, for more on GLUT.

EGL is technically part of OpenGL ES, and was designed with the modern OpenGL API and mobile hardware in mind, though it also works on the desktop.  Figl does not yet have an EGL binding.

Rendering
=========

To draw with OpenGL, you obtain a drawing context (see GL Contexts) and send the GL some geometry.  (You can think of the GL as a layer over your graphics card.)  You can give the GL points, lines, and triangles in three-dimensional space.  You configure your GL to render a certain part of space, and it takes your geometry, rasterizes it, and writes it to the screen (when you tell it to).

That's the basic idea.  You can customize most parts of this rendering pipeline, by specifying attributes of your geometry with the OpenGL API, and by programmatically operating on the geometry and the pixels with programs called shaders.

GL is an immediate-mode graphics API, which is to say that it doesn't keep around a scene graph of objects.  Instead, at every frame you as the OpenGL user have to tell the GL what is in the world, and how to paint it.  It's a fairly low-level interface, but a powerful one. See http://www.opengl.org/wiki/Rendering_Pipeline_Overview, for more details.

In the old days of OpenGL 1.0, it was common to call a function to paint each individual vertex.  You'll still see this style in some old tutorials.  This quickly gets expensive if you have a lot of vertexes, though.  This style, known as Legacy OpenGL, was deprecated and even removed from some versions of OpenGL.  See http://www.opengl.org/wiki/Legacy_OpenGL, for more on the older APIs.

Instead, the newer thing to do is to send the geometry to the GL in a big array buffer, and have the GL draw geometry from the buffer.  The newer functions like glGenBuffers allocate buffers, returning an integer that names a buffer managed by the GL.  You as a user can update the contents of the buffer, but when drawing you reference the buffer by name.  This has the advantage of reducing the chatter and data transfer between you and the GL, though it can be less convenient to use.

So which API should you use?  Use what you feel like using, if you have a choice.  Legacy OpenGL isn't going away any time soon on the desktop.  Sometimes you don't have a choice, though; for example, when targeting a device that only supports OpenGL ES 2.x, legacy OpenGL is unavailable.

But if you want some advice, we suggest that you use the newer APIs. Not only will your code be future-proof and more efficient on the GL level, reducing the number of API calls improves performance, and it can reduce the amount of heap allocation in your program.  All floating-point numbers are currently allocated on the heap in Guile, and doing less floating-point math in tight loops can only be a good thing.

Low-Level GL
============

     [file low-level-gl.texi not included]

GL Enumerations
===============

     [file low-level-gl-enums.texi not included]

GL Extensions
=============

     The future is already here -- it's just not very evenly distributed.

     -- William Gibson

Before interfaces end up in core OpenGL, the are usually present as vendor-specific or candidate extensions.  Indeed, the making of an OpenGL standard these days seems to be a matter of simply collecting a set of mature extensions and making them coherent.

Figl doesn't currently provide specific interfaces for extensions. Perhaps it should, but that's a lot of work that we haven't had time to do.  Contributions are welcome.

In the meantime, if you know enough about GL to know that you need an extension, you can define one yourself -- after all, Figl is all a bunch of Scheme code anyway.

For example, let's say you decide that you need to render to a framebuffer object.  You go to http://www.opengl.org/registry/ and pick out an extension, say http://www.opengl.org/registry/specs/ARB/framebuffer_object.txt.

This extension defines a procedure, GLboolean glIsRenderBuffer(GLuint).  So you define it:

     (use-modules (figl gl runtime) (figl gl types))
     (define-gl-procedure (glIsRenderBuffer (buf GLuint) -> GLboolean)
       "Render buffer predicate.  Other docs here.")

And that's that.  It's a low-level binding, but what did you expect?

Note that you'll still need to check for the availability of this extension at runtime with (glGetString GL_EXTENSIONS).

GLU
***

Low-Level GLU
=============

     [file low-level-glu.texi not included]

GLX
***

Low-Level GLX
=============

     [file low-level-glx.texi not included]

GLX Enumerations
================

     [file low-level-glx-enums.texi not included]

GLUT
****

TODO: Write GLUT documentation.

FAQ
***

TODO: Write about things readers will want to know (instead of commenting them in the source :)