mutter/HACKING.backends

161 lines
5.6 KiB
Plaintext
Raw Normal View History

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 actor.
<backend>/clutter-event-<backend>.c
-- The event handling code (optional).
2008-04-24 13:32:32 -04:00
<backend>/clutter-<backend>.h
2008-04-24 13:32:32 -04:00
-- 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.
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.
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::get_display_size
-- Use this function to retrieve the size of the display.
ClutterBackend::create_context
-- This function is used to create the drawing context to be used
by Clutter.
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.
ClutterBackend::redraw
-- This function is used to draw the passed ClutterStage; the backend
must call clutter_actor_paint() on the ClutterStage that has been
passed as a parameter and then perform backend-specific tasks, like
waiting for vertical blanking and swapping the buffers.
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.
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()
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
- if the backend doesn't have a drawing context (either GL or GLES),
create one and pass it to the backend
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.
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.