Clutter Wiki

Views
From ClutterProject
Jump to: navigation, search

Contents

CoglFramebuffers

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.

Notes/Requirements

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:

  • fbconfigs and framebuffer objects can represent multiple color buffers and glDrawBuffers allows drawing to more than one buffer concurrently.
    • It seems like mesa doesn't really support auxiliary color buffers associated with window system framebuffers, even though it supports rendering to multiple framebuffer_object renderbuffers.
  • NB: All the enums for glDrawBuffer that imply multiple buffers are redundant since glDrawBuffers was added to OpenGL.
  • COGL_PIXEL_FORMATs may be ok for describing color buffers, but how should we describe depth and stencil buffer formats?
  • NB: Accumulation buffers have been deprecated in GL 3.0
  • all auxiliary and ancillary buffers must have the same width and height
  • all auxiliary color buffers must have the same pixel format
  • window system APIs such as GLX or egl associate a config with the context which constrains the configs that may be used to create windows/pixmaps, so how should we handle this?
    • For example In the GLX fbconfig extension a "compatible" term was introduced to identify which fbconfigs may be used with a drawable and bound to a context. The fbconfigs of the context, and drawable need to be compatible which essentially means drawable fbconfigs represent a subset of the context's fbconfig. The spec notes that the restriction may go away in the future.
  • Applications must be able to gracefully handle a failure to allocate a framebuffer.

Current Design

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:

  1. Developers can either handle errors as they go; they can try to configure one property at a time and at any point if the driver can determine at unsupportable configuration, returning a GError, then a fallback options can be handled in an incremental process.
  2. Developers can simply declare all the configuration properties they want, passing NULL to ignore any GErrors, and then only check for the GError when the allocation is done. For an application with only a limited number of fallback options this might be more convenient.

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.

CoglFamebuffer Configuration

  • cogl_framebuffer_set_size (fb, width, height, &error);
    • How will this interact with texture objects attached as auxiliary color buffers?
    • XXX: We don't allow setting the size of a framebuffer since that would require awkward semantics regarding the resizing of attached CoglColorBuffers
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);

CoglFramebuffer Post Allocation

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);

CoglColorBuffer

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.

  • configuration:
    • cb = cogl_color_buffer_new_with_size (128, 128);
    • cogl_color_buffer_set_width (cb, width, &error);
    • cogl_color_buffer_set_height (cb, height, &error);
      • 'NB: color buffers may later change size if they are associated with an onscreen framebuffer and the corresponding window is resized.'
      • XXX: Should this be *_set_size () instead ?
    • cogl_color_buffer_request_red_bits (cb, 5, &error);
    • cogl_color_buffer_request_green_bits (cb, 6, &error);
    • cogl_color_buffer_request_blue_bits (cb, 5, &error);
    • cogl_color_buffer_set_pixel_format (cb, COGL_PIXEL_FORMAT_RGBA8888, &error);
    • format = cogl_color_buffer_get_pixel_format (cb);
    • cogl_color_buffer_request_multisampling (fb, 0);
    • cogl_color_buffer_allocate (fb, &error);
    • cogl_color_buffer_free (fb); - note this is different to cogl_handle_unref (fb)
      • 'XXX: We can only allocate once the buffer is attached to a framebuffer, so cogl_framebuffer_allocate will actually be responsible for allocating all attached CoglColorBuffers.'
    • cb = cogl_color_buffer_new_from_texture_level (texture, 0);
      • NB: we won't currently be able to support attaching such color buffers to onscreen framebuffers due to limitations with GLX/EGL etc
  • post allocation:
    • cogl_color_buffer_can_move_allocation (); - FALSE for color buffers associated with allocated onscreen framebuffers
      • Maybe we can leave this until it's needed, but the point is we need to document that once an CoglOnscreenFramebuffer is allocated then all attached CoglColorBuffers are fixed, and can not be moved to other framebuffers. On the other hand CoglColorBuffers can be freely moved between CoglOffscreenFramebuffers at any point.
    • cogl_color_buffer_get_allocated_role (); - CoglOnscreen allocation may assign color buffers a role (such as COGL_COLOR_BUFFER_ROLE_BACK_RIGHT) all other color buffers will have a role of COGL_COLOR_BUFFER_ROLE_ANY.
Personal tools