mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
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.
This commit is contained in:
parent
c76e576141
commit
101a3cac4e
90
ChangeLog
90
ChangeLog
@ -1,3 +1,93 @@
|
||||
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 Robert Bragg <bob@openedhand.com>
|
||||
|
||||
* clutter/clutter-timeline.c:
|
||||
|
@ -58,6 +58,10 @@ 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:
|
||||
|
||||
@ -106,10 +110,8 @@ can be overridden:
|
||||
|
||||
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (impl));
|
||||
|
||||
The backend must also call clutter_actor_realize() on the stage
|
||||
implementation, and then check if the stage has been realized, using
|
||||
the CLUTTER_ACTOR_IS_REALIZED() macro; if the stage was not
|
||||
realized, it must return NULL and set the passed GError.
|
||||
in case of error, the backend must return NULL and set the passed
|
||||
GError.
|
||||
|
||||
Implementing the stage
|
||||
----------------------
|
||||
@ -130,9 +132,7 @@ 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 assing it to the backend
|
||||
- set the CLUTTER_ACTOR_REALIZED flag on *both* the wrapper and the
|
||||
stage implementation (this is very important)
|
||||
- call clutter_stage_ensure_current() with the wrapper instance
|
||||
- set the CLUTTER_ACTOR_REALIZED flag on itself
|
||||
|
||||
In case of failure, the CLUTTER_ACTOR_REALIZED flag should be unset on
|
||||
the stage implementation.
|
||||
@ -141,7 +141,6 @@ Inside the ::unrealize function the stage implementation should:
|
||||
|
||||
- unset the CLUTTER_ACTOR_REALIZED flag on itself
|
||||
- destroy the native window handle
|
||||
- call clutter_stage_ensure_current() with the wrapper instance
|
||||
|
||||
NOTES
|
||||
=====
|
||||
@ -152,9 +151,6 @@ implementation for event handling and window management.
|
||||
|
||||
Usual points of failure for backends are:
|
||||
|
||||
- not setting the CLUTTER_ACTOR_REALIZED flag on the stage implementation
|
||||
and the stage wrapper inside the ::realized virtual function before
|
||||
calling clutter_stage_ensure_current();
|
||||
- calling public API, like clutter_actor_paint(), or checking properties
|
||||
on the stage implementation instead of the ClutterStage wrapper.
|
||||
|
||||
|
@ -1103,6 +1103,16 @@ clutter_init_with_args (int *argc,
|
||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
clutter_actor_realize (stage);
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_INTERNAL,
|
||||
"Unable to realize the default stage");
|
||||
|
||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
_clutter_backend_init_events (clutter_context->backend);
|
||||
|
||||
_clutter_feature_init ();
|
||||
@ -1195,6 +1205,14 @@ clutter_init (int *argc,
|
||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
clutter_actor_realize (stage);
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
g_critical ("Unable to realize the default stage");
|
||||
|
||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
/* Initiate event collection */
|
||||
_clutter_backend_init_events (context->backend);
|
||||
|
||||
|
@ -187,13 +187,16 @@ clutter_stage_realize (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
/* then realize the implementation */
|
||||
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
CLUTTER_ACTOR_GET_CLASS (priv->impl)->realize (priv->impl);
|
||||
|
||||
/* set the flag on the wrapper if the implementation was successful */
|
||||
/* ensure that the stage is using the context if the
|
||||
* realization sequence was successful
|
||||
*/
|
||||
if (CLUTTER_ACTOR_IS_REALIZED (priv->impl))
|
||||
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE (self));
|
||||
else
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
@ -209,6 +212,8 @@ clutter_stage_unrealize (ClutterActor *self)
|
||||
/* and then unrealize the implementation */
|
||||
g_assert (priv->impl != NULL);
|
||||
CLUTTER_ACTOR_GET_CLASS (priv->impl)->unrealize (priv->impl);
|
||||
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE (self));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -217,6 +222,10 @@ clutter_stage_show (ClutterActor *self)
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (priv->impl))
|
||||
clutter_actor_realize (priv->impl);
|
||||
|
||||
clutter_actor_show (priv->impl);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->show (self);
|
||||
|
@ -100,19 +100,6 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
|
||||
|
||||
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage));
|
||||
|
||||
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||
|
||||
clutter_actor_realize (stage);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_INTERNAL,
|
||||
"Unable to realize the main stage");
|
||||
g_object_unref (stage);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
backend_egl->stage = CLUTTER_ACTOR (stage_egl);
|
||||
|
||||
return stage;
|
||||
|
@ -62,8 +62,6 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
eglDestroySurface (clutter_egl_display (), stage_egl->egl_surface);
|
||||
stage_egl->egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
clutter_stage_ensure_current (stage_egl->wrapper);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -179,7 +177,6 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Marking stage as realized and setting context");
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_egl->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_egl, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
/* eglnative can have only one stage */
|
||||
@ -202,8 +199,6 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage_egl->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -81,6 +81,8 @@ clutter_backend_egl_ensure_context (ClutterBackend *backend,
|
||||
if (!backend_egl->egl_context)
|
||||
return;
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
/* we might get here inside the final dispose cycle, so we
|
||||
* need to handle this gracefully
|
||||
*/
|
||||
@ -100,6 +102,11 @@ clutter_backend_egl_ensure_context (ClutterBackend *backend,
|
||||
stage_egl->egl_surface,
|
||||
stage_egl->egl_surface,
|
||||
backend_egl->egl_context);
|
||||
|
||||
if (clutter_x11_untrap_x_errors ())
|
||||
g_critical ("Unable to make the stage window 0x%x the current "
|
||||
"EGLX drawable",
|
||||
(int) stage_x11->xwin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,19 +252,6 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
|
||||
stage_x11->xscreen,
|
||||
(unsigned int) stage_x11->xwin_root);
|
||||
|
||||
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||
|
||||
clutter_actor_realize (stage);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_INTERNAL,
|
||||
"Unable to realize the main stage");
|
||||
g_object_unref (stage);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return stage;
|
||||
}
|
||||
|
||||
|
@ -63,8 +63,6 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
stage_egl->egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
clutter_stage_ensure_current (stage_x11->wrapper);
|
||||
|
||||
XSync (stage_x11->xdpy, False);
|
||||
|
||||
clutter_x11_untrap_x_errors ();
|
||||
@ -91,6 +89,11 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
|
||||
if (G_LIKELY (!is_offscreen))
|
||||
{
|
||||
int c;
|
||||
int num_configs;
|
||||
int max_tex_units;
|
||||
EGLConfig *all_configs;
|
||||
|
||||
EGLint cfg_attribs[] = {
|
||||
EGL_BUFFER_SIZE, EGL_DONT_CARE,
|
||||
EGL_RED_SIZE, 5,
|
||||
@ -104,49 +107,48 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
2,
|
||||
&config_count);
|
||||
|
||||
int c;
|
||||
int num_configs;
|
||||
EGLConfig *all_configs;
|
||||
|
||||
eglGetConfigs (clutter_eglx_display(), NULL, 0, &num_configs);
|
||||
eglGetConfigs (clutter_eglx_display (), NULL, 0, &num_configs);
|
||||
|
||||
all_configs = g_malloc (num_configs * sizeof (EGLConfig));
|
||||
|
||||
eglGetConfigs (clutter_eglx_display(),
|
||||
eglGetConfigs (clutter_eglx_display (),
|
||||
all_configs,
|
||||
num_configs,
|
||||
&num_configs);
|
||||
|
||||
for (c=0; c<num_configs; ++c)
|
||||
for (c = 0; c < num_configs; ++c)
|
||||
{
|
||||
EGLint red=-1, green=-1, blue=-1, alpha=-1, stencil=-1;
|
||||
eglGetConfigAttrib (clutter_eglx_display(),
|
||||
EGLint red = -1, green = -1, blue = -1, alpha = -1, stencil = -1;
|
||||
|
||||
eglGetConfigAttrib (clutter_eglx_display (),
|
||||
all_configs[c],
|
||||
EGL_RED_SIZE, &red);
|
||||
eglGetConfigAttrib (clutter_eglx_display(),
|
||||
eglGetConfigAttrib (clutter_eglx_display (),
|
||||
all_configs[c],
|
||||
EGL_GREEN_SIZE, &green);
|
||||
eglGetConfigAttrib (clutter_eglx_display(),
|
||||
eglGetConfigAttrib (clutter_eglx_display (),
|
||||
all_configs[c],
|
||||
EGL_BLUE_SIZE, &blue);
|
||||
eglGetConfigAttrib (clutter_eglx_display(),
|
||||
eglGetConfigAttrib (clutter_eglx_display (),
|
||||
all_configs[c],
|
||||
EGL_ALPHA_SIZE, &alpha);
|
||||
eglGetConfigAttrib (clutter_eglx_display(),
|
||||
eglGetConfigAttrib (clutter_eglx_display (),
|
||||
all_configs[c],
|
||||
EGL_STENCIL_SIZE, &stencil);
|
||||
printf("EGLConfig === R:%d G:%d B:%d A:%d S:%d \n",
|
||||
CLUTTER_NOTE (BACKEND, "EGLConfig == R:%d G:%d B:%d A:%d S:%d \n",
|
||||
red, green, blue, alpha, stencil);
|
||||
}
|
||||
|
||||
int max_tex_units = 0;
|
||||
max_tex_units = 0;
|
||||
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_tex_units);
|
||||
printf("Texture units: %d\n", max_tex_units);
|
||||
CLUTTER_NOTE (BACKEND, "Texture units: %d\n", max_tex_units);
|
||||
|
||||
g_free (all_configs);
|
||||
|
||||
if (status != EGL_TRUE)
|
||||
g_warning ("eglGetConfigs failed");
|
||||
{
|
||||
g_critical ("eglGetConfigs failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = eglChooseConfig (backend_egl->edpy,
|
||||
cfg_attribs,
|
||||
@ -155,7 +157,10 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
&config_count);
|
||||
|
||||
if (status != EGL_TRUE)
|
||||
g_warning ("eglChooseConfig failed");
|
||||
{
|
||||
g_critical ("eglChooseConfig failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (stage_x11->xwin == None)
|
||||
stage_x11->xwin =
|
||||
@ -198,9 +203,7 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
if (stage_egl->egl_surface == EGL_NO_SURFACE)
|
||||
{
|
||||
g_critical ("Unable to create an EGL surface");
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (backend_egl->egl_context == None))
|
||||
@ -215,26 +218,26 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
if (backend_egl->egl_context == EGL_NO_CONTEXT)
|
||||
{
|
||||
g_critical ("Unable to create a suitable EGL context");
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* this will make sure to set the current context */
|
||||
CLUTTER_NOTE (BACKEND, "Marking stage as realized and setting context");
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11, CLUTTER_ACTOR_REALIZED);
|
||||
clutter_stage_ensure_current (stage_x11->wrapper);
|
||||
CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning("EGLX Backend does not support offscreen rendering");
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
g_critical ("EGLX Backend does not support offscreen rendering");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
/* we need to chain up to the X11 stage implementation in order to
|
||||
* set the window state in case we set it before realizing the stage
|
||||
*/
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->realize (actor);
|
||||
return;
|
||||
|
||||
fail:
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -99,19 +99,6 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
|
||||
|
||||
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage));
|
||||
|
||||
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||
|
||||
clutter_actor_realize (stage);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_INTERNAL,
|
||||
"Unable to realize the main stage");
|
||||
g_object_unref (stage);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
backend_egl->stage = CLUTTER_ACTOR (stage_egl);
|
||||
|
||||
return stage;
|
||||
|
@ -61,8 +61,6 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
eglDestroySurface (clutter_egl_display (), stage_egl->egl_surface);
|
||||
stage_egl->egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
clutter_stage_ensure_current (stage_egl->wrapper);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -108,7 +106,11 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
&config_count);
|
||||
|
||||
if (status != EGL_TRUE)
|
||||
g_warning ("eglChooseConfig failed");
|
||||
{
|
||||
g_critical ("eglChooseConfig failed");
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stage_egl->egl_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
@ -133,7 +135,6 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
if (stage_egl->egl_surface == EGL_NO_SURFACE)
|
||||
{
|
||||
g_critical ("Unable to create an EGL surface");
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
@ -173,29 +174,24 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
|
||||
/* this will make sure to set the current context */
|
||||
CLUTTER_NOTE (BACKEND, "Marking stage as realized and setting context");
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_egl->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_egl, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
|
||||
/* this should be done in ClutterBackend::ensure_context */
|
||||
status = eglMakeCurrent (backend_egl->edpy,
|
||||
stage_egl->egl_surface,
|
||||
stage_egl->egl_surface,
|
||||
backend_egl->egl_context);
|
||||
|
||||
if (status != EGL_TRUE)
|
||||
g_warning ("eglMakeCurrent");
|
||||
|
||||
/*clutter_stage_ensure_current (stage_egl->wrapper);*/
|
||||
{
|
||||
g_critical ("eglMakeCurrent failed");
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning("EGL Backend does not yet support offscreen rendering\n");
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage_egl->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -382,6 +382,8 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
|
||||
if (backend_glx->gl_context == None)
|
||||
return;
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
/* we might get here inside the final dispose cycle, so we
|
||||
* need to handle this gracefully
|
||||
*/
|
||||
@ -408,6 +410,11 @@ clutter_backend_glx_ensure_context (ClutterBackend *backend,
|
||||
stage_x11->xwin,
|
||||
backend_glx->gl_context);
|
||||
}
|
||||
|
||||
if (clutter_x11_untrap_x_errors ())
|
||||
g_critical ("Unable to make the stage window 0x%x the current "
|
||||
"GLX drawable",
|
||||
(int) stage_x11->xwin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -459,7 +466,7 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
|
||||
CLUTTER_NOTE (BACKEND, "Creating stage of type `%s'",
|
||||
g_type_name (CLUTTER_STAGE_TYPE));
|
||||
|
||||
stage = g_object_new (CLUTTER_STAGE_TYPE, NULL);
|
||||
stage = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL);
|
||||
|
||||
/* copy backend data into the stage */
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
@ -477,24 +484,6 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
|
||||
stage_x11->xscreen,
|
||||
(unsigned int) stage_x11->xwin_root);
|
||||
|
||||
/* needed ? */
|
||||
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||
|
||||
/* FIXME - is this needed? we should call realize inside the clutter
|
||||
* init sequence for the default stage, and let the usual realization
|
||||
* sequence be used for any other stage
|
||||
*/
|
||||
clutter_actor_realize (stage);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_INTERNAL,
|
||||
"Unable to realize the main stage");
|
||||
g_object_unref (stage);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return stage;
|
||||
}
|
||||
|
||||
|
@ -102,9 +102,6 @@ clutter_stage_glx_unrealize (ClutterActor *actor)
|
||||
stage_x11->xwin = None;
|
||||
}
|
||||
|
||||
/* As unrealised the context will now get cleared */
|
||||
clutter_stage_ensure_current (stage_x11->wrapper);
|
||||
|
||||
XSync (stage_x11->xdpy, False);
|
||||
|
||||
clutter_x11_untrap_x_errors ();
|
||||
@ -214,11 +211,8 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
}
|
||||
}
|
||||
|
||||
/* this will make sure to set the current context */
|
||||
CLUTTER_NOTE (BACKEND, "Marking stage as realized and setting context");
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_NOTE (BACKEND, "Marking stage as realized");
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11, CLUTTER_ACTOR_REALIZED);
|
||||
clutter_stage_ensure_current (stage_x11->wrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -281,20 +275,14 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
}
|
||||
}
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
/* below will call glxMakeCurrent */
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_NOTE (BACKEND, "Marking stage as realized");
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_x11, CLUTTER_ACTOR_REALIZED);
|
||||
clutter_stage_ensure_current (stage_x11->wrapper);
|
||||
|
||||
if (clutter_x11_untrap_x_errors ())
|
||||
{
|
||||
g_critical ("Unable to set up offscreen context.");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* we need to chain up to the X11 stage implementation in order to
|
||||
* set the window state in case we set it before realizing the stage
|
||||
*/
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->realize (actor);
|
||||
return;
|
||||
|
||||
fail:
|
||||
|
@ -95,19 +95,6 @@ clutter_backend_sdl_create_stage (ClutterBackend *backend,
|
||||
|
||||
_clutter_stage_set_window (wrapper, CLUTTER_STAGE_WINDOW (stage));
|
||||
|
||||
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||
|
||||
clutter_actor_realize (stage);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_INTERNAL,
|
||||
"Unable to realize the main stage");
|
||||
g_object_unref (stage);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
backend_sdl->stage = stage_sdl;
|
||||
|
||||
return stage;
|
||||
|
@ -80,31 +80,21 @@ clutter_stage_sdl_realize (ClutterActor *actor)
|
||||
0, flags) == NULL)
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "SDL appears not to handle this mode - %s",
|
||||
SDL_GetError());
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_sdl, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (stage_sdl->wrapper,
|
||||
CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_sdl, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_ACTOR_SET_FLAGS (stage_sdl->wrapper, CLUTTER_ACTOR_REALIZED);
|
||||
clutter_stage_ensure_current (stage_sdl->wrapper);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME */
|
||||
g_warning("SDL Backend does not yet support offscreen rendering\n");
|
||||
SDL_GetError ());
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
else
|
||||
CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME */
|
||||
g_critical ("SDL Backend does not yet support offscreen rendering");
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "SDL stage realized");
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage_sdl->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -229,6 +229,83 @@ clutter_stage_x11_request_coords (ClutterActor *self,
|
||||
box);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_wm_title (ClutterStageX11 *stage_x11)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = stage_x11->backend;
|
||||
|
||||
if (stage_x11->xwin == None)
|
||||
return;
|
||||
|
||||
if (stage_x11->title == NULL)
|
||||
{
|
||||
XDeleteProperty (stage_x11->xdpy,
|
||||
stage_x11->xwin,
|
||||
backend_x11->atom_NET_WM_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
XChangeProperty (stage_x11->xdpy,
|
||||
stage_x11->xwin,
|
||||
backend_x11->atom_NET_WM_NAME,
|
||||
backend_x11->atom_UTF8_STRING,
|
||||
8,
|
||||
PropModeReplace,
|
||||
(unsigned char *) stage_x11->title,
|
||||
(int) strlen (stage_x11->title));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_cursor_visible (ClutterStageX11 *stage_x11)
|
||||
{
|
||||
if (stage_x11->xwin == None)
|
||||
return;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "setting cursor state ('%s') over stage window (%u)",
|
||||
stage_x11->is_cursor_visible ? "visible" : "invisible",
|
||||
(unsigned int) stage_x11->xwin);
|
||||
|
||||
if (stage_x11->is_cursor_visible)
|
||||
{
|
||||
#if 0 /* HAVE_XFIXES - seems buggy/unreliable */
|
||||
XFixesShowCursor (stage_x11->xdpy, stage_x11->xwin);
|
||||
#else
|
||||
XUndefineCursor (stage_x11->xdpy, stage_x11->xwin);
|
||||
#endif /* HAVE_XFIXES */
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0 /* HAVE_XFIXES - seems buggy/unreliable, check cursor in firefox
|
||||
* loading page after hiding.
|
||||
*/
|
||||
XFixesHideCursor (stage_x11->xdpy, stage_x11->xwin);
|
||||
#else
|
||||
XColor col;
|
||||
Pixmap pix;
|
||||
Cursor curs;
|
||||
|
||||
pix = XCreatePixmap (stage_x11->xdpy, stage_x11->xwin, 1, 1, 1);
|
||||
memset (&col, 0, sizeof (col));
|
||||
curs = XCreatePixmapCursor (stage_x11->xdpy,
|
||||
pix, pix,
|
||||
&col, &col,
|
||||
1, 1);
|
||||
XFreePixmap (stage_x11->xdpy, pix);
|
||||
XDefineCursor (stage_x11->xdpy, stage_x11->xwin, curs);
|
||||
#endif /* HAVE_XFIXES */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_realize (ClutterActor *actor)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||
|
||||
set_wm_title (stage_x11);
|
||||
set_cursor_visible (stage_x11);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
|
||||
gboolean is_fullscreen)
|
||||
@ -325,42 +402,9 @@ clutter_stage_x11_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
|
||||
if (stage_x11->xwin == None)
|
||||
return;
|
||||
stage_x11->is_cursor_visible = (cursor_visible == TRUE);
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "setting cursor state ('%s') over stage window (%u)",
|
||||
cursor_visible ? "visible" : "invisible",
|
||||
(unsigned int) stage_x11->xwin);
|
||||
|
||||
if (cursor_visible)
|
||||
{
|
||||
#if 0 /* HAVE_XFIXES - seems buggy/unreliable */
|
||||
XFixesShowCursor (stage_x11->xdpy, stage_x11->xwin);
|
||||
#else
|
||||
XUndefineCursor (stage_x11->xdpy, stage_x11->xwin);
|
||||
#endif /* HAVE_XFIXES */
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0 /* HAVE_XFIXES - seems buggy/unreliable, check cursor in firefox
|
||||
* loading page after hiding.
|
||||
*/
|
||||
XFixesHideCursor (stage_x11->xdpy, stage_x11->xwin);
|
||||
#else
|
||||
XColor col;
|
||||
Pixmap pix;
|
||||
Cursor curs;
|
||||
|
||||
pix = XCreatePixmap (stage_x11->xdpy, stage_x11->xwin, 1, 1, 1);
|
||||
memset (&col, 0, sizeof (col));
|
||||
curs = XCreatePixmapCursor (stage_x11->xdpy,
|
||||
pix, pix,
|
||||
&col, &col,
|
||||
1, 1);
|
||||
XFreePixmap (stage_x11->xdpy, pix);
|
||||
XDefineCursor (stage_x11->xdpy, stage_x11->xwin, curs);
|
||||
#endif /* HAVE_XFIXES */
|
||||
}
|
||||
set_cursor_visible (stage_x11);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -368,28 +412,11 @@ clutter_stage_x11_set_title (ClutterStageWindow *stage_window,
|
||||
const gchar *title)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
ClutterBackendX11 *backend_x11 = stage_x11->backend;
|
||||
|
||||
if (stage_x11->xwin == None)
|
||||
return;
|
||||
g_free (stage_x11->title);
|
||||
stage_x11->title = g_strdup (title);
|
||||
|
||||
if (title == NULL)
|
||||
{
|
||||
XDeleteProperty (stage_x11->xdpy,
|
||||
stage_x11->xwin,
|
||||
backend_x11->atom_NET_WM_NAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
XChangeProperty (stage_x11->xdpy,
|
||||
stage_x11->xwin,
|
||||
backend_x11->atom_NET_WM_NAME,
|
||||
backend_x11->atom_UTF8_STRING,
|
||||
8,
|
||||
PropModeReplace,
|
||||
(unsigned char*)title,
|
||||
(int)strlen(title));
|
||||
}
|
||||
set_wm_title (stage_x11);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -407,6 +434,16 @@ clutter_stage_x11_get_wrapper (ClutterStageWindow *stage_window)
|
||||
return CLUTTER_ACTOR (CLUTTER_STAGE_X11 (stage_window)->wrapper);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
|
||||
|
||||
g_free (stage_x11->title);
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_x11_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_dispose (GObject *gobject)
|
||||
{
|
||||
@ -424,8 +461,10 @@ clutter_stage_x11_class_init (ClutterStageX11Class *klass)
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = clutter_stage_x11_finalize;
|
||||
gobject_class->dispose = clutter_stage_x11_dispose;
|
||||
|
||||
actor_class->realize = clutter_stage_x11_realize;
|
||||
actor_class->show = clutter_stage_x11_show;
|
||||
actor_class->hide = clutter_stage_x11_hide;
|
||||
actor_class->request_coords = clutter_stage_x11_request_coords;
|
||||
@ -447,13 +486,13 @@ clutter_stage_x11_init (ClutterStageX11 *stage)
|
||||
stage->is_foreign_xwin = FALSE;
|
||||
stage->fullscreen_on_map = FALSE;
|
||||
stage->handling_configure = FALSE;
|
||||
stage->is_cursor_visible = TRUE;
|
||||
|
||||
stage->title = NULL;
|
||||
|
||||
stage->wrapper = NULL;
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_IS_TOPLEVEL);
|
||||
#if 0
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -47,6 +47,8 @@ struct _ClutterStageX11
|
||||
|
||||
guint is_foreign_xwin : 1;
|
||||
guint fullscreen_on_map : 1;
|
||||
guint handling_configure : 1;
|
||||
guint is_cursor_visible : 1;
|
||||
|
||||
Display *xdpy;
|
||||
Window xwin_root;
|
||||
@ -56,7 +58,7 @@ struct _ClutterStageX11
|
||||
gint xwin_width;
|
||||
gint xwin_height; /* FIXME target_width / height */
|
||||
Pixmap xpixmap;
|
||||
gboolean handling_configure;
|
||||
gchar *title;
|
||||
|
||||
ClutterBackendX11 *backend;
|
||||
ClutterStageState state;
|
||||
|
@ -10,7 +10,7 @@ tex_button_cb (ClutterActor *actor,
|
||||
clutter_actor_hide (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
on_button_press (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
@ -26,6 +26,8 @@ on_button_press (ClutterActor *actor,
|
||||
ClutterBehaviour *r_behave;
|
||||
|
||||
new_stage = clutter_stage_new ();
|
||||
if (!new_stage)
|
||||
return FALSE;
|
||||
|
||||
/* FIXME: below should really be automatic */
|
||||
/* clutter_stage_ensure_cogl_context (CLUTTER_STAGE(new_stage)); */
|
||||
@ -36,7 +38,7 @@ on_button_press (ClutterActor *actor,
|
||||
tex = clutter_texture_new_from_file ("redhand.png", NULL);
|
||||
|
||||
if (!tex)
|
||||
g_error("pixbuf load failed");
|
||||
g_error ("pixbuf load failed");
|
||||
|
||||
clutter_actor_set_reactive (tex, TRUE);
|
||||
g_signal_connect (tex, "button-press-event",
|
||||
@ -88,6 +90,8 @@ on_button_press (ClutterActor *actor,
|
||||
clutter_timeline_start (timeline);
|
||||
|
||||
clutter_actor_show_all (new_stage);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user