1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
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:
- The subclass of the ClutterBackend abstract class.
<backend>/clutter-backend-<backend>.h
<backend>/clutter-backend-<backend>.c
- The implementation of the stage window
<backend>/clutter-stage-<backend>.h
<backend>/clutter-stage-<backend>.c
- The implementation of the input device manager
<backend>/clutter-device-manager-<backend>.h
<backend>/clutter-device-manager-<backend>.c
- Event-specific code (optional)
<backend>/clutter-event-<backend>.c
- 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).
<backend>/clutter-<backend>.h
Implementing ClutterBackend
-------------------------------------------------------------------------------
Each backend must implement the
```cpp
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 Clutter's `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` instance.
- `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 class relaying all the drawing operations
to the actual implementation. The underlying 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 event translator
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.
- If the platform is natively supported by Cogl, you should subclass the
`ClutterStageCogl` class, which will provide you wth a ready to use
implementation of the underlying Cogl machinery.
|