IMPLEMENTING BACKENDS
===============================================================================

Clutter supports multiple backends for handling windowing systems and
GL/GLES API on different platforms.

The GL and GLES API are abstracted by the COGL library. The windowing
system is handled by the ClutterBackend implementations inside Clutter
itself.

Clutter, at the moment, supports only in-tree backends.

In order to write a new backend for a specific platform you should
create a new sub-directory under clutter/clutter containing:

  <backend>/clutter-backend-<backend>.h
  <backend>/clutter-backend-<backend>.c

  -- The subclass of the ClutterBackend abstract class.

  <backend>/clutter-stage-<backend>.h
  <backend>/clutter-stage-<backend>.c

  -- The implementation of the stage window

  <backend>/clutter-device-manager-<backend>.h
  <backend>/clutter-device-manager-<backend>.c

  -- The implementation of the input device manager

  <backend>/clutter-event-<backend>.c

  -- Event-specific code (optional)

  <backend>/clutter-<backend>.h

  -- A header for the backend-specific API that should be installed
     by Clutter inside the include directory along with the rest of
     the public API headers (optional).


Implementing ClutterBackend
-------------------------------------------------------------------------------

Each backend must implement the

  GType
  _clutter_backend_impl_get_type (void);

function declared inside clutter/clutter-private.h. The implementation
of the function must return the same GType of the backend implementation,
for instance:

  GType
  _clutter_backend_impl_get_type (void)
  {
    return CLUTTER_TYPE_BACKEND_GLX;
  }

The ClutterBackend implementation is a singleton instance, and the
backend must ensure that every time g_object_new() is called the same
pointer is returned (with its reference count increased). The GObject
API reference describes how to use the ::constructor virtual function
to implement a singleton, so you should refer to that.

The ClutterBackend implementation should hold a single drawing context
for its entire lifetime; stage implementations should be "made current"
when needed.

When implementing the ClutterBackend subclass these virtual functions
can be overridden:

  ClutterBackend::add_options
  -- Use this function to install new, backend-specific GOptionEntry
     definitions to the Clutter GOptionGroup. This function is guaranteed
     to be called just once.

  ClutterBackend::pre_parse
  -- Use this function to check for environment variables or setting
     up default values before the command line arguments are parsed.
     This function is guaranteed to be called just once.

  ClutterBackend::post_parse
  -- Use this function to prepare the backend with the values either
     set inside the ::pre_parse virtual function or by the command
     line options parsing code. This function is guaranteed to be
     called just once.

  ClutterBackend::init_events
  -- Use this function to initialize the event handling. This function
     is guaranteed to be called just once.

  ClutterBackend::get_features
  -- Use this function to retrieve the features detectable at runtime
     from the GL or GLES implementation, plus the eventual backend-specific
     features.

  ClutterBackend::create_context
  -- This function is used to create the drawing context to be used
     by Clutter. Clutter will call this function during the initialization
     phase. A GL (or GLES) context must always be available after the
     initialization, so that Cogl and Clutter can query it for capabilities.
     This function might be called multiple times so if a context was
     successfully created in a previous call, this function should
     short-circuit early and return TRUE

  ClutterBackend::ensure_context
  -- This function is used to ensure that the backend drawing context
     is made current for passed ClutterStage, using the backend-specific
     API. This function is called each time a new stage is going to
     be painted. If the Stage is inside its destruction sequence this
     function should either fall back the drawing context to a default
     drawing surface or should unset the drawing surface from the
     drawing context.

  ClutterBackend::create_stage
  -- This function is used to create the stage implementation. It will
     receive as an argument the ClutterStage instance that is "wrapping"
     the actual implementation being created. The backend must create
     its stage implementation, initialise it and then return it; in case
     of error, the backend must return NULL and set the passed GError.

  ClutterBackend::get_device_manager
  -- This function is used to return the ClutterDeviceManager instance
     that is going to be returned by clutter_device_manager_get_default()
     and that should be used internally by input event translation.

Implementing the stage
-------------------------------------------------------------------------------

ClutterStage acts as a wrapper object relaying all the drawing operations
to the actual implementation. The implementation of the stage can be any
GObject subclass, as long as it implements the ClutterStageWindow interface.

The ClutterStageWindow interface contains a set of virtual functions that
should be overridden by backends that support a windowing system, like
::set_title(), ::set_fullscreen(), ::set_cursor_visible(), etc.

The stage implementation actor must implement:

  • ClutterStageWindow::get_wrapper()
  • ClutterStageWindow::realize() and ::unrealize()
  • ClutterStageWindow::show() and ::hide()
  • ClutterStageWindow::resize()
  • ClutterStageWindow::get_geometry()
  • ClutterStageWindow::redraw()

The ::get_wrapper() implementation should return the pointer to the
ClutterStage actor using the ClutterStageWindow implementation.

In the ::realize virtual function the stage implementation should:

  - create a new native window handle
  - ensure that there is a GL (or GLES) context
  - make sure that the native window handle is compatible with
    the GL (or GLES) context

The return value should be TRUE if the stage implementation was successfully
realized, and FALSE otherwise.

Inside the ::unrealize function the stage implementation should destroy
the native window handle created in ::realize().

The ::resize() virtual function implementation should cause an update
of the COGL viewport.

The ::redraw() virtual function implementation should contain the platform
specific drawing logic, and call _clutter_stage_do_paint() on the ClutterStage
wrapper instance to cause the scene to be painted.

The stage implementation actor can optionally implement:

  • ClutterStageWindow::get_pending_swaps()

The get_pending_swaps() implementation should return the number of swap
buffer requests pending completion. This is only relevent for backends
that also support CLUTTER_FEATURE_SWAP_EVENTS.

If the stage window is supposed to handle events, then it should also implement
the ClutterEventTranslator interface; this interface has a single virtual
function:

  • ClutterEventTranslator::translate_event()

which gets passed a pointer to the native event data structure, and a pointer
to a newly-allocated, empty ClutterEvent. The EventTranslator implementation
should then decide between three options:

  - translate the native event and return CLUTTER_TRANSLATE_QUEUE to
    let Clutter queue it up in the events queue;
  - return CLUTTER_TRANSLATE_CONTINUE to let other event translators handle
    the event;
  - return CLUTTER_TRANSLATE_REMOVE to ignore the event.

Implementing ClutterDeviceManager
-------------------------------------------------------------------------------

Backends with input devices should provide a ClutterDeviceManager
implementation to handle addition, removal and input device event translation
through the ClutterEventTranslator interface.

NOTES
===============================================================================

• If the platform is using X11 you should probably subclass ClutterBackendX11
  and ClutterStageX11, which will provide you with a ready to use code
  implementation for event handling and window management.
