2008-04-24 13:31:38 -04:00
|
|
|
IMPLEMENTING BACKENDS
|
2011-02-08 13:03:43 -05:00
|
|
|
===============================================================================
|
2008-04-24 13:31:38 -04:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2011-02-08 13:03:43 -05:00
|
|
|
-- 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
|
2008-04-24 13:31:38 -04:00
|
|
|
|
|
|
|
<backend>/clutter-event-<backend>.c
|
|
|
|
|
2011-02-08 13:03:43 -05:00
|
|
|
-- Event-specific code (optional)
|
2008-04-24 13:31:38 -04:00
|
|
|
|
2008-04-24 13:32:32 -04:00
|
|
|
<backend>/clutter-<backend>.h
|
2008-04-24 13:31:38 -04:00
|
|
|
|
2008-04-24 13:32:32 -04:00
|
|
|
-- A header for the backend-specific API that should be installed
|
2008-04-24 13:31:38 -04:00
|
|
|
by Clutter inside the include directory along with the rest of
|
|
|
|
the public API headers (optional).
|
|
|
|
|
|
|
|
|
|
|
|
Implementing ClutterBackend
|
2011-02-08 13:03:43 -05:00
|
|
|
-------------------------------------------------------------------------------
|
2008-04-24 13:31:38 -04:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
2008-05-12 Emmanuele Bassi <ebassi@openedhand.com>
Rework the stage wrapper/implementation relation: remove
duplicated code and all the bookkeeping from the backends into
ClutterStage whenever possible, to reduce the amount of work a
backend must do (and possibly get wrong). Thanks to Tommi
Komulainen.
* clutter/clutter-main.c:
(clutter_init_with_args), (clutter_init): Realize the default
stage after creation. The default stage is special, because we
use it in the initialization sequence. This removes the burden
from the backends and reduces the things a backend can get
wrong.
* clutter/clutter-stage.c:
(clutter_stage_show): Make sure to realize the implementation if
it hasn't been realized yet.
(clutter_stage_realize): Set the REALIZED flag and call
clutter_stage_ensure_current() if the implementation was
successfully realized.
(clutter_stage_unrealized): Call clutter_stage_ensure_current()
on unrealize.
* clutter/glx/clutter-backend-glx.c:
(clutter_backend_glx_create_stage): Do not realize the stage anymore
when creating it, and let the normal realization sequence take
place.
(clutter_backend_glx_ensure_context): Trap for X11 errors.
* clutter/glx/clutter-stage-glx.c:
(clutter_stage_glx_realize): Chain up to the X11 implementation
so that we can set up the window state (title, cursor visibility)
when we actually have a X window. Also, do not call
clutter_stage_ensure_current(), and rely on the wrapper to do
it for us. This means we can drop setting the REALIZED flag on
the wrapper.
(clutter_stage_glx_unrealize): Do not call
clutter_stage_ensure_current() ourselves, and rely on the wrapper
to do it for us.
* clutter/x11/clutter-stage-x11.c:
(set_wm_title), (set_cursor_visible): Move the WM title and
cursor visibility code inside their own functions.
(clutter_stage_x11_realize): Set the window title and whether the
cursor is visible or not after realizing the stage.
(clutter_stage_x11_set_cursor_visible),
(clutter_stage_x11_set_title): Call set_wm_title() and
set_cursor_visible().
(clutter_stage_x11_finalize): Free the title string.
* clutter/x11/clutter-stage-x11.h: Save more of the stage state,
so that we can set it even when the stage hasn't been realized
yet.
* clutter/eglnative/clutter-backend-egl.c:
(clutter_backend_egl_create_stage):
* clutter/eglnative/clutter-stage-egl.c:
(clutter_stage_egl_unrealize),
(clutter_stage_egl_realize): Update the eglnative backend.
* clutter/eglx/clutter-backend-egl.c:
(clutter_backend_egl_ensure_context),
(clutter_backend_egl_create_stage):
* clutter/eglx/clutter-stage-egl.c:
(clutter_stage_egl_unrealize),
(clutter_stage_egl_realize): Update the eglx backend.
* clutter/sdl/clutter-backend-sdl.c:
(clutter_backend_sdl_create_stage):
* clutter/sdl/clutter-stage-sdl.c:
(clutter_stage_sdl_realize): Update the sdl backend.
* clutter/fruity/clutter-backend-fruity.c:
(clutter_backend_fruity_create_stage):
* clutter/sdl/clutter-stage-fruity.c:
(clutter_stage_fruity_realize): Update the fruity backend.
* tests/test-multistage.c (on_button_press): Bail out if
clutter_stage_new() returns NULL.
* HACKING.backends: Update backend writing documentation.
2008-05-12 11:26:37 -04:00
|
|
|
The ClutterBackend implementation should hold a single drawing context
|
|
|
|
for its entire lifetime; stage implementations should be "made current"
|
|
|
|
when needed.
|
|
|
|
|
2008-04-24 13:31:38 -04:00
|
|
|
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.
|
|
|
|
|
2009-11-18 10:06:37 -05:00
|
|
|
ClutterBackend::create_context
|
|
|
|
-- This function is used to create the drawing context to be used
|
2010-02-12 06:38:47 -05:00
|
|
|
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.
|
2010-03-03 13:17:15 -05:00
|
|
|
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
|
2009-11-18 10:06:37 -05:00
|
|
|
|
2008-04-24 13:31:38 -04:00
|
|
|
ClutterBackend::ensure_context
|
|
|
|
-- This function is used to ensure that the backend drawing context
|
|
|
|
is made current for passed ClutterStage, using the backend-specific
|
2010-03-03 13:17:15 -05:00
|
|
|
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.
|
2008-04-24 13:31:38 -04:00
|
|
|
|
|
|
|
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
|
2008-05-13 06:37:17 -04:00
|
|
|
its stage implementation, initialise it and then return it; in case
|
|
|
|
of error, the backend must return NULL and set the passed GError.
|
2008-04-24 13:31:38 -04:00
|
|
|
|
2011-02-08 13:03:43 -05:00
|
|
|
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.
|
|
|
|
|
2008-04-24 13:31:38 -04:00
|
|
|
Implementing the stage
|
2011-02-08 13:03:43 -05:00
|
|
|
-------------------------------------------------------------------------------
|
2008-04-24 13:31:38 -04:00
|
|
|
|
|
|
|
ClutterStage acts as a wrapper object relaying all the drawing operations
|
|
|
|
to the actual implementation. The implementation of the stage can be any
|
2009-11-18 10:06:37 -05:00
|
|
|
GObject subclass, as long as it implements the ClutterStageWindow interface.
|
2008-04-24 13:31:38 -04:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
2009-11-18 10:06:37 -05:00
|
|
|
The stage implementation actor must implement:
|
|
|
|
|
|
|
|
• ClutterStageWindow::get_wrapper()
|
|
|
|
• ClutterStageWindow::realize() and ::unrealize()
|
|
|
|
• ClutterStageWindow::show() and ::hide()
|
|
|
|
• ClutterStageWindow::resize()
|
|
|
|
• ClutterStageWindow::get_geometry()
|
2011-02-08 13:03:43 -05:00
|
|
|
• ClutterStageWindow::redraw()
|
2009-11-18 10:06:37 -05:00
|
|
|
|
|
|
|
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:
|
2008-04-24 13:31:38 -04:00
|
|
|
|
|
|
|
- create a new native window handle
|
2010-02-12 06:38:47 -05:00
|
|
|
- ensure that there is a GL (or GLES) context
|
|
|
|
- make sure that the native window handle is compatible with
|
|
|
|
the GL (or GLES) context
|
2008-04-24 13:31:38 -04:00
|
|
|
|
2009-11-18 10:06:37 -05:00
|
|
|
The return value should be TRUE if the stage implementation was successfully
|
|
|
|
realized, and FALSE otherwise.
|
2008-04-24 13:31:38 -04:00
|
|
|
|
2009-11-18 10:06:37 -05:00
|
|
|
Inside the ::unrealize function the stage implementation should destroy
|
|
|
|
the native window handle created in ::realize().
|
2008-04-24 13:31:38 -04:00
|
|
|
|
2009-11-18 10:06:37 -05:00
|
|
|
The ::resize() virtual function implementation should cause an update
|
|
|
|
of the COGL viewport.
|
2008-04-24 13:31:38 -04:00
|
|
|
|
2011-02-08 13:03:43 -05:00
|
|
|
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.
|
|
|
|
|
2009-11-12 15:37:01 -05:00
|
|
|
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.
|
|
|
|
|
2011-02-08 13:03:43 -05:00
|
|
|
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.
|
|
|
|
|
2008-04-24 13:31:38 -04:00
|
|
|
NOTES
|
2011-02-08 13:03:43 -05:00
|
|
|
===============================================================================
|
2008-04-24 13:31:38 -04:00
|
|
|
|
2011-02-08 13:03:43 -05:00
|
|
|
• 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.
|