Contents |
OpenGL is awkward because window system framebuffers are configured differently from application framebuffer objects, in Cogl we want to present a unified framebuffer management API.
For GLX, window system framebuffers are configured using FBConfigs which are made up of various attributes with a well specified sorting order. The idea is that the user may declare their attribute constraints and get back a list of suitable FBConfigs which it may then optionally look at in further detail to pick the most appropriate, or simply pick the first and rely on the sorting to give the best option.
For wgl (win32) PixelFormats serve a similar purpose to fbconfigs.
Application framebuffers on the other hand are created via glGenFramebuffers, and then additional "renderbuffers" are added to that object; where renderbuffers can represent depth, stencil, and color buffers.
Some things to consider in the design of CoglFramebuffers:
A CoglFramebuffer is an abstract base class that represents an optional depth buffer, optional stencil buffer and N CoglColorBuffers. CoglFramebuffers can describe a window system framebuffer including the color buffer that is drawn on screen, or describe application allocated buffers for drawing offscreen. The implementations are CoglOnscreen and CoglOffscreen.
Internally framebuffers start off "un-allocated", and while un-allocated they can be configured by setting constraints on them, such as the minimum number of stencil or depth buffer bits required. In addition to these constraints, CoglColorBuffers may be attached to them and these will describe the number of red, green and blue bits required.
Note that the configuration of CoglFramebuffers may be constrained by the drivers in a number of ways, either due to lacking hardware features or suitable software extensions. For example running under GLX will require that CoglOnscreen framebuffers are compatible with the CoglDisplay; this is because GLX defines a requirement for GLXFBConfig compatability between GLXDrawables and the current context. Conceptually this makes sense to some extent because it wouldn't make much sense to e.g. allocate RGBA8888 windows when you have an RGB565 display as that would imply a format conversion, still other window systems may have more relaxed constraints.
Once all constraints have been set, and at least one CoglColorBuffer added then the framebuffer may be allocated. The allocation process will allocate memory for the depth and stencil buffers and ensure that each of the attached color buffers is also allocated. It is now ready for rendering too.
Because there are lots of constraints imposed by the underlying drivers and hardware regarding the configuration of framebuffers, the CoglFramebuffer configuration APIs rely heavily on GErrors to report un-supported configurations. Each of the functions used to specify a constraint while configuring can return a GError, and the final allocation step can also return a GError, the intention is to support two principle ways of handling errors:
Most CoglFramebuffer properties will effectively have a default value of "any" so the default configuration should always be allocatable without error.
Although only one CoglFramebuffer may be used for rendering at any time, rendering can output to multiple CoglColorBuffers attached to the same CoglFramebuffer may supported with some drivers.
cogl_framebuffer_attach_color_buffer (fb, 0, buf, &error); //NB: We need to attach with a number so we know how to reference it in glsl. cogl_framebuffer_detach_color_buffer (fb, 0, buf, &error); cogl_framebuffer_enable_color_buffer (fb, 0, buf, &error); - all enabled draw buffers may be output to concurrently in fragment shaders cogl_framebuffer_disable_color_buffer (fb, 1, buf, &error); buffers = cogl_framebuffer_get_color_buffers (fb); cogl_framebuffer_request_stencil_bits (fb, 8, &error); - i.e. any fbconfig with >= requested number of bits is ok cogl_framebuffer_set_stencil_bits (fb, 8, &error); - must match fbconfig exactly cogl_framebuffer_request_depth_bits (fb, 16, &error); cogl_framebuffer_set_depth_bits (fb, 16, &error); // Note: unlike OpenGL, depth and stencil buffers aren't represented as separate // buffers; the implication being that the implementation does not have to preserve // the contents of the depth buffers. We can support explicit buffers that imply // depth/stencil preservation later. cogl_framebuffer_allocate (fb, &error);
cogl_framebuffer_get_size (fb, &width, &height); //for convenience it determines the size from the first attached color buffer
// The size of a framebuffer is implied by its attached color buffers
cogl_framebuffer_free (fb); //note this is different to cogl_handle_unref (fb)
cogl_framebuffer_clear (fb,
COGL_FRAMEBUFFER_CLEAR_DEPTH |
COGL_FRAMEBUFFER_CLEAR_STENCIL |
COGL_FRAMEBUFFER_CLEAR_COLOR);
cogl_framebuffer_swap (fb);
cogl_framebuffer_swap_sub_region (fb);
There is a repeated pattern with several objects in Cogl whereby the object is first instantiated in some kind of configuration state before resources are allocated. In the case a CoglColorBuffers they aren't allocated directly - you have to add them to a CoglFramebuffer and they will be allocated as part of cogl_framebuffer_allocate () - but there is still a distinction between the object being in a config state and once its allocated where it's mostly immutable.