diff --git a/clutter/eglnative/clutter-backend-egl.c b/clutter/eglnative/clutter-backend-egl.c
index 031f3a308..babb3c61f 100644
--- a/clutter/eglnative/clutter-backend-egl.c
+++ b/clutter/eglnative/clutter-backend-egl.c
@@ -1,3 +1,30 @@
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright (C) 2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see .
+
+ * Authors:
+ * Matthew Allum
+ * Emmanuele Bassi
+ * Robert Bragg
+ * Neil Roberts
+ */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -5,21 +32,28 @@
#include
#include
#include
+#include
#include
#include "clutter-backend-egl.h"
#include "clutter-stage-egl.h"
+#include "clutter-egl.h"
#include "../clutter-private.h"
#include "../clutter-main.h"
#include "../clutter-debug.h"
+#include "../clutter-version.h"
static ClutterBackendEGL *backend_singleton = NULL;
static const gchar *clutter_fb_device = NULL;
+#ifdef COGL_HAS_X11_SUPPORT
+G_DEFINE_TYPE (ClutterBackendEGL, clutter_backend_egl, CLUTTER_TYPE_BACKEND_X11);
+#else
G_DEFINE_TYPE (ClutterBackendEGL, clutter_backend_egl, CLUTTER_TYPE_BACKEND);
+#endif
static void
clutter_backend_at_exit (void)
@@ -33,6 +67,13 @@ clutter_backend_egl_pre_parse (ClutterBackend *backend,
GError **error)
{
const gchar *env_string;
+#ifdef COGL_HAS_X11_SUPPORT
+ ClutterBackendClass *backend_x11_class =
+ CLUTTER_BACKEND_CLASS (clutter_backend_egl_parent_class);
+
+ if (!backend_x11_class->pre_parse (backend, error))
+ return FALSE;
+#endif
env_string = g_getenv ("CLUTTER_FB_DEVICE");
if (env_string != NULL && env_string[0] != '\0')
@@ -45,15 +86,35 @@ static gboolean
clutter_backend_egl_post_parse (ClutterBackend *backend,
GError **error)
{
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL(backend);
+ ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+#ifdef COGL_HAS_X11_SUPPORT
+ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterBackendClass *backend_x11_class =
+ CLUTTER_BACKEND_CLASS (clutter_backend_egl_parent_class);
+#endif
EGLBoolean status;
+#ifdef COGL_HAS_X11_SUPPORT
+ if (!backend_x11_class->post_parse (backend, error))
+ return FALSE;
+
+#ifndef COGL_HAS_XLIB_SUPPORT
+#error "Clutter's EGL on X11 support currently only works with xlib Displays"
+#endif
+ backend_egl->edpy =
+ eglGetDisplay ((NativeDisplayType) backend_x11->xdpy);
+
+ status = eglInitialize (backend_egl->edpy,
+ &backend_egl->egl_version_major,
+ &backend_egl->egl_version_minor);
+#else
backend_egl->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
- status = eglInitialize (backend_egl->edpy,
- &backend_egl->egl_version_major,
+ status = eglInitialize (backend_egl->edpy,
+ &backend_egl->egl_version_major,
&backend_egl->egl_version_minor);
-
+#endif
+
g_atexit (clutter_backend_at_exit);
if (status != EGL_TRUE)
@@ -65,88 +126,168 @@ clutter_backend_egl_post_parse (ClutterBackend *backend,
}
CLUTTER_NOTE (BACKEND, "EGL Reports version %i.%i",
- backend_egl->egl_version_major,
+ backend_egl->egl_version_major,
backend_egl->egl_version_minor);
return TRUE;
}
-static void
-clutter_backend_egl_ensure_context (ClutterBackend *backend,
- ClutterStage *stage)
-{
- /* not doing anything since we only have one context and
- * it is permanently made current
- */
-}
-
static gboolean
clutter_backend_egl_create_context (ClutterBackend *backend,
GError **error)
{
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
- EGLConfig configs[2];
- EGLint config_count;
- EGLBoolean status;
- EGLint cfg_attribs[] = {
- EGL_BUFFER_SIZE, EGL_DONT_CARE,
- EGL_RED_SIZE, 5,
- EGL_GREEN_SIZE, 6,
- EGL_BLUE_SIZE, 5,
- EGL_DEPTH_SIZE, 16,
- EGL_ALPHA_SIZE, EGL_DONT_CARE,
+#ifdef COGL_HAS_X11_SUPPORT
+ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+#endif
+ EGLConfig config;
+ EGLint config_count = 0;
+ EGLBoolean status;
+ EGLint cfg_attribs[] = {
+ /* NB: This must be the first attribute, since we may
+ * try and fallback to no stencil buffer */
EGL_STENCIL_SIZE, 2,
-#ifdef HAVE_COGL_GLES2
+
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_ALPHA_SIZE, EGL_DONT_CARE,
+
+ EGL_DEPTH_SIZE, 1,
+
+ EGL_BUFFER_SIZE, EGL_DONT_CARE,
+
+#if defined (HAVE_COGL_GLES2)
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-#else /* HAVE_COGL_GLES2 */
+#else
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+#endif
+
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-#endif /* HAVE_COGL_GLES2 */
+
EGL_NONE
};
+ EGLDisplay edpy;
+ gint retry_cookie = 0;
+ const char *error_message = NULL;
+#ifdef COGL_HAS_XLIB_SUPPORT
+ XVisualInfo *xvisinfo;
+ XSetWindowAttributes attrs;
+#endif
- if (backend_egl->egl_context)
+ if (backend_egl->egl_context != EGL_NO_CONTEXT)
return TRUE;
- status = eglGetConfigs (backend_egl->edpy,
- configs,
- 2,
- &config_count);
+ edpy = clutter_egl_display ();
- if (status != EGL_TRUE)
+/* XXX: we should get rid of this goto yukkyness, there is a fail:
+ * goto at the end and this retry: goto at the top, but we should just
+ * have a try_create_context() function and call it in a loop that
+ * tries a different fallback each iteration */
+retry:
+ /* Here we can change the attributes depending on the fallback count... */
+
+ /* Some GLES hardware can't support a stencil buffer: */
+ if (retry_cookie == 1)
{
- g_set_error (error, CLUTTER_INIT_ERROR,
- CLUTTER_INIT_ERROR_BACKEND,
- "No EGL configurations found");
- return FALSE;
+ g_warning ("Trying with stencil buffer disabled...");
+ cfg_attribs[1 /* EGL_STENCIL_SIZE */] = 0;
}
- status = eglChooseConfig (backend_egl->edpy,
+ /* XXX: at this point we only have one fallback */
+
+ status = eglChooseConfig (edpy,
cfg_attribs,
- configs,
- G_N_ELEMENTS (configs),
+ &config, 1,
&config_count);
-
- if (status != EGL_TRUE)
+ if (status != EGL_TRUE || config_count == 0)
{
- g_set_error (error, CLUTTER_INIT_ERROR,
- CLUTTER_INIT_ERROR_BACKEND,
- "Unable to select a valid EGL configuration");
+ error_message = "Unable to select a valid EGL configuration";
+ goto fail;
+ }
+
+ if (backend_egl->egl_context == EGL_NO_CONTEXT)
+ {
+#ifdef HAVE_COGL_GLES2
+ static const EGLint attribs[] =
+ { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+
+ backend_egl->egl_context = eglCreateContext (edpy,
+ config,
+ EGL_NO_CONTEXT,
+ attribs);
+
+#else
+ backend_egl->egl_context = eglCreateContext (edpy,
+ config,
+ EGL_NO_CONTEXT,
+ NULL);
+
+#endif
+ if (backend_egl->egl_context == EGL_NO_CONTEXT)
+ {
+ error_message = "Unable to create a suitable EGL context";
+ goto fail;
+ }
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+ backend_egl->egl_config = config;
+#endif
+ CLUTTER_NOTE (GL, "Created EGL Context");
+ }
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+ /* COGL assumes that there is always a GL context selected; in order
+ * to make sure that an EGL context exists and is made current, we use
+ * a dummy, offscreen override-redirect window to which we can always
+ * fall back if no stage is available */
+
+ xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
+ if (xvisinfo == NULL)
+ {
+ g_critical ("Unable to find suitable GL visual.");
return FALSE;
}
- CLUTTER_NOTE (BACKEND, "Got %i configs", config_count);
+ attrs.override_redirect = True;
+ attrs.colormap = XCreateColormap (backend_x11->xdpy,
+ backend_x11->xwin_root,
+ xvisinfo->visual,
+ AllocNone);
+ attrs.border_pixel = 0;
- if (G_UNLIKELY (backend_egl->egl_surface != EGL_NO_SURFACE))
+ backend_egl->dummy_xwin = XCreateWindow (backend_x11->xdpy,
+ backend_x11->xwin_root,
+ -100, -100, 1, 1,
+ 0,
+ xvisinfo->depth,
+ CopyFromParent,
+ xvisinfo->visual,
+ CWOverrideRedirect |
+ CWColormap |
+ CWBorderPixel,
+ &attrs);
+
+ XFree (xvisinfo);
+
+ backend_egl->dummy_surface =
+ eglCreateWindowSurface (edpy,
+ backend_egl->egl_config,
+ (NativeWindowType) backend_egl->dummy_xwin,
+ NULL);
+
+ if (backend_egl->dummy_surface == EGL_NO_SURFACE)
{
- eglDestroySurface (backend_egl->edpy, backend_egl->egl_surface);
- backend_egl->egl_surface = EGL_NO_SURFACE;
+ g_critical ("Unable to create an EGL surface");
+ return FALSE;
}
- if (G_UNLIKELY (backend_egl->egl_context != NULL))
- {
- eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
- backend_egl->egl_context = NULL;
- }
+ eglMakeCurrent (edpy,
+ backend_egl->dummy_surface,
+ backend_egl->dummy_surface,
+ backend_egl->egl_context);
+
+#else /* COGL_HAS_XLIB_SUPPORT */
if (clutter_fb_device != NULL)
{
@@ -168,17 +309,17 @@ clutter_backend_egl_create_context (ClutterBackend *backend,
backend_egl->fb_device_id = fd;
backend_egl->egl_surface =
- eglCreateWindowSurface (backend_egl->edpy,
- configs[0],
+ eglCreateWindowSurface (edpy,
+ config,
(NativeWindowType) backend_egl->fb_device_id,
NULL);
}
else
{
backend_egl->egl_surface =
- eglCreateWindowSurface (backend_egl->edpy,
- configs[0],
- NULL,
+ eglCreateWindowSurface (edpy,
+ config,
+ (NativeWindowType) NULL,
NULL);
}
@@ -191,42 +332,13 @@ clutter_backend_egl_create_context (ClutterBackend *backend,
return FALSE;
}
-#ifdef HAVE_COGL_GLES2
- {
- static const EGLint attribs[3] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
-
- backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
- configs[0],
- EGL_NO_CONTEXT,
- attribs);
- }
-#else
- /* Seems some GLES implementations 1.x do not like attribs... */
- backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
- configs[0],
- EGL_NO_CONTEXT,
- NULL);
-#endif
-
- if (backend_egl->egl_context == EGL_NO_CONTEXT)
- {
- g_set_error (error, CLUTTER_INIT_ERROR,
- CLUTTER_INIT_ERROR_BACKEND,
- "Unable to create a suitable EGL context");
- return FALSE;
- }
-
- CLUTTER_NOTE (GL, "Created EGL Context");
-
CLUTTER_NOTE (BACKEND, "Setting context");
- /* eglnative can have only one stage, so we store the EGL surface
- * in the backend itself, instead of the StageWindow implementation,
- * and we make it current immediately to make sure the Cogl and
- * Clutter can query the EGL context for features.
+ /* Without X we assume we can have only one stage, so we
+ * store the EGL surface in the backend itself, instead
+ * of the StageWindow implementation, and we make it
+ * current immediately to make sure the Cogl and Clutter
+ * can query the EGL context for features.
*/
status = eglMakeCurrent (backend_egl->edpy,
backend_egl->egl_surface,
@@ -247,70 +359,127 @@ clutter_backend_egl_create_context (ClutterBackend *backend,
backend_egl->surface_width,
backend_egl->surface_height);
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
return TRUE;
+
+fail:
+
+ /* NB: We currently only support a single fallback option */
+ if (retry_cookie == 0)
+ {
+ retry_cookie = 1;
+ goto retry;
+ }
+
+ g_set_error (error, CLUTTER_INIT_ERROR,
+ CLUTTER_INIT_ERROR_BACKEND,
+ "%s", error_message);
+
+ return FALSE;
+}
+
+static void
+clutter_backend_egl_ensure_context (ClutterBackend *backend,
+ ClutterStage *stage)
+{
+#ifndef COGL_HAS_XLIB_SUPPORT
+ /* Without X we only have one EGL surface to worry about
+ * so we can assume it is permanently made current and
+ * don't have to do anything here. */
+#else
+ ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+ ClutterStageWindow *impl;
+
+ if (stage == NULL ||
+ (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_IN_DESTRUCTION) ||
+ ((impl = _clutter_stage_get_window (stage)) == NULL))
+ {
+ CLUTTER_NOTE (BACKEND, "Clearing EGL context");
+ eglMakeCurrent (backend_egl->edpy,
+ EGL_NO_SURFACE,
+ EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ }
+ else
+ {
+ ClutterStageEGL *stage_egl;
+ ClutterStageX11 *stage_x11;
+
+ g_assert (impl != NULL);
+
+ CLUTTER_NOTE (MULTISTAGE, "Setting context for stage of type %s [%p]",
+ g_type_name (G_OBJECT_TYPE (impl)),
+ impl);
+
+ stage_egl = CLUTTER_STAGE_EGL (impl);
+ stage_x11 = CLUTTER_STAGE_X11 (impl);
+
+ if (backend_egl->egl_context == EGL_NO_CONTEXT)
+ return;
+
+ clutter_x11_trap_x_errors ();
+
+ /* we might get here inside the final dispose cycle, so we
+ * need to handle this gracefully
+ */
+ if (stage_x11->xwin == None ||
+ stage_egl->egl_surface == EGL_NO_SURFACE)
+ {
+ CLUTTER_NOTE (MULTISTAGE,
+ "Received a stale stage, clearing all context");
+
+ if (backend_egl->dummy_surface == EGL_NO_SURFACE)
+ eglMakeCurrent (backend_egl->edpy,
+ EGL_NO_SURFACE,
+ EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ else
+ eglMakeCurrent (backend_egl->edpy,
+ backend_egl->dummy_surface,
+ backend_egl->dummy_surface,
+ backend_egl->egl_context);
+ }
+ else
+ {
+ CLUTTER_NOTE (MULTISTAGE, "Setting real surface current");
+ eglMakeCurrent (backend_egl->edpy,
+ 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);
+ }
+#endif /* COGL_HAS_XLIB_SUPPORT */
}
static void
clutter_backend_egl_redraw (ClutterBackend *backend,
ClutterStage *stage)
{
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
- ClutterStageEGL *stage_egl;
ClutterStageWindow *impl;
impl = _clutter_stage_get_window (stage);
- if (impl == NULL)
+ if (!impl)
return;
g_assert (CLUTTER_IS_STAGE_EGL (impl));
- stage_egl = CLUTTER_STAGE_EGL (impl);
- eglWaitNative (EGL_CORE_NATIVE_ENGINE);
- clutter_actor_paint (CLUTTER_ACTOR (stage_egl->wrapper));
- cogl_flush ();
-
- eglWaitGL();
- eglSwapBuffers (backend_egl->edpy, backend_egl->egl_surface);
-}
-
-static ClutterStageWindow *
-clutter_backend_egl_create_stage (ClutterBackend *backend,
- ClutterStage *wrapper,
- GError **error)
-{
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
- ClutterStageEGL *stage_egl;
- ClutterStageWindow *stage;
-
- if (G_UNLIKELY (backend_egl->stage != NULL))
- {
- g_set_error (error, CLUTTER_INIT_ERROR,
- CLUTTER_INIT_ERROR_BACKEND,
- "The EGL native backend does not support multiple stages");
- return backend_egl->stage;
- }
-
- stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL);
-
- stage_egl = CLUTTER_STAGE_EGL (stage);
- stage_egl->backend = backend_egl;
- stage_egl->wrapper = wrapper;
-
- backend_egl->stage = stage;
-
- return stage;
+ clutter_stage_egl_redraw (CLUTTER_STAGE_EGL (impl), stage);
}
+#ifdef HAVE_TSLIB
static void
clutter_backend_egl_init_events (ClutterBackend *backend)
{
+ /* XXX: This should be renamed to _clutter_events_tslib_init */
_clutter_events_egl_init (CLUTTER_BACKEND_EGL (backend));
}
-
-static const GOptionEntry entries[] =
-{
- { NULL }
-};
+#endif
static void
clutter_backend_egl_finalize (GObject *gobject)
@@ -325,29 +494,59 @@ static void
clutter_backend_egl_dispose (GObject *gobject)
{
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);
- ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (backend_egl->stage);
+#ifdef COGL_HAS_X11_SUPPORT
+ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
+#else
+ ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (backend_egl->stage);
+#endif
+ /* We chain up before disposing our own resources so that
+ ClutterBackendX11 will destroy all of the stages before we
+ destroy the egl context. Otherwise the actors may try to make GL
+ calls during destruction which causes a crash */
+ G_OBJECT_CLASS (clutter_backend_egl_parent_class)->dispose (gobject);
+
+#ifdef HAVE_TSLIB
+ /* XXX: This should be renamed to _clutter_events_tslib_uninit */
_clutter_events_egl_uninit (backend_egl);
+#endif
- if (backend_egl->stage != NULL)
+#ifdef COGL_HAS_XLIB_SUPPORT
+ if (backend_egl->dummy_surface != EGL_NO_SURFACE)
{
- clutter_actor_destroy (CLUTTER_ACTOR (stage_egl->wrapper));
- backend_egl->stage = NULL;
+ eglDestroySurface (backend_egl->edpy, backend_egl->dummy_surface);
+ backend_egl->dummy_surface = EGL_NO_SURFACE;
}
+ if (backend_egl->dummy_xwin)
+ {
+ XDestroyWindow (backend_x11->xdpy, backend_egl->dummy_xwin);
+ backend_egl->dummy_xwin = None;
+ }
+
+#else /* COGL_HAS_XLIB_SUPPORT */
+
if (backend_egl->egl_surface != EGL_NO_SURFACE)
{
eglDestroySurface (backend_egl->edpy, backend_egl->egl_surface);
backend_egl->egl_surface = EGL_NO_SURFACE;
}
+ if (backend_egl->stage != NULL)
+ {
+ clutter_actor_destroy (CLUTTER_ACTOR (stage_egl->wrapper));
+ backend_egl->stage = NULL;
+ }
+
if (backend_egl->fb_device_id != -1)
{
close (backend_egl->fb_device_id);
backend_egl->fb_device_id = -1;
}
- if (backend_egl->egl_context != NULL)
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
+ if (backend_egl->egl_context)
{
eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
backend_egl->egl_context = NULL;
@@ -359,13 +558,13 @@ clutter_backend_egl_dispose (GObject *gobject)
backend_egl->edpy = 0;
}
+#ifdef HAVE_TSLIB
if (backend_egl->event_timer != NULL)
{
g_timer_destroy (backend_egl->event_timer);
backend_egl->event_timer = NULL;
}
-
- G_OBJECT_CLASS (clutter_backend_egl_parent_class)->dispose (gobject);
+#endif
}
static GObject *
@@ -388,17 +587,25 @@ clutter_backend_egl_constructor (GType gtype,
g_warning ("Attempting to create a new backend object. This should "
"never happen, so we return the singleton instance.");
-
+
return g_object_ref (backend_singleton);
}
static ClutterFeatureFlags
clutter_backend_egl_get_features (ClutterBackend *backend)
{
- ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+ ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+ ClutterFeatureFlags flags;
g_assert (backend_egl->egl_context != NULL);
+#ifdef COGL_HAS_XLIB_SUPPORT
+ flags = clutter_backend_x11_get_features (backend);
+ flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
+#else
+ flags = CLUTTER_FEATURE_STAGE_STATIC;
+#endif
+
CLUTTER_NOTE (BACKEND, "Checking features\n"
"GL_VENDOR: %s\n"
"GL_RENDERER: %s\n"
@@ -413,41 +620,163 @@ clutter_backend_egl_get_features (ClutterBackend *backend)
eglQueryString (backend_egl->edpy, EGL_VERSION),
eglQueryString (backend_egl->edpy, EGL_EXTENSIONS));
- return CLUTTER_FEATURE_STAGE_STATIC;
+ return flags;
}
+static ClutterStageWindow *
+clutter_backend_egl_create_stage (ClutterBackend *backend,
+ ClutterStage *wrapper,
+ GError **error)
+{
+#ifdef COGL_HAS_XLIB_SUPPORT
+ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterStageWindow *stage;
+ ClutterStageX11 *stage_x11;
+
+ CLUTTER_NOTE (BACKEND, "Creating stage of type '%s'",
+ g_type_name (CLUTTER_STAGE_TYPE));
+
+ stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL);
+
+ /* copy backend data into the stage */
+ stage_x11 = CLUTTER_STAGE_X11 (stage);
+ stage_x11->wrapper = wrapper;
+
+ CLUTTER_NOTE (MISC, "EGLX stage created (display:%p, screen:%d, root:%u)",
+ backend_x11->xdpy,
+ backend_x11->xscreen_num,
+ (unsigned int) backend_x11->xwin_root);
+
+#else /* COGL_HAS_XLIB_SUPPORT */
+
+ ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+ ClutterStageWindow *stage;
+ ClutterStageEGL *stage_egl;
+
+ if (G_UNLIKELY (backend_egl->stage != NULL))
+ {
+ g_set_error (error, CLUTTER_INIT_ERROR,
+ CLUTTER_INIT_ERROR_BACKEND,
+ "The EGL native backend does not support multiple stages");
+ return backend_egl->stage;
+ }
+
+ stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL);
+
+ stage_egl = CLUTTER_STAGE_EGL (stage);
+ stage_egl->backend = backend_egl;
+ stage_egl->wrapper = wrapper;
+
+ backend_egl->stage = stage;
+
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
+ return stage;
+}
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+static XVisualInfo *
+clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11)
+{
+ ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend_x11);
+ XVisualInfo visinfo_template;
+ int template_mask = 0;
+ XVisualInfo *visinfo = NULL;
+ int visinfos_count;
+ EGLint visualid, red_size, green_size, blue_size, alpha_size;
+
+ if (!clutter_backend_egl_create_context (CLUTTER_BACKEND (backend_x11), NULL))
+ return NULL;
+
+ visinfo_template.screen = backend_x11->xscreen_num;
+ template_mask |= VisualScreenMask;
+
+ eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
+ EGL_NATIVE_VISUAL_ID, &visualid);
+
+ if (visualid != 0)
+ {
+ visinfo_template.visualid = visualid;
+ template_mask |= VisualIDMask;
+ }
+ else
+ {
+ /* some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID
+ * attribute, so attempt to find the closest match. */
+
+ eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
+ EGL_RED_SIZE, &red_size);
+ eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
+ EGL_GREEN_SIZE, &green_size);
+ eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
+ EGL_BLUE_SIZE, &blue_size);
+ eglGetConfigAttrib (backend_egl->edpy, backend_egl->egl_config,
+ EGL_ALPHA_SIZE, &alpha_size);
+
+ visinfo_template.depth = red_size + green_size + blue_size + alpha_size;
+ template_mask |= VisualDepthMask;
+ }
+
+ visinfo = XGetVisualInfo (backend_x11->xdpy,
+ template_mask,
+ &visinfo_template,
+ &visinfos_count);
+
+ return visinfo;
+}
+#endif
+
static void
clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
+#ifdef COGL_HAS_X11_SUPPORT
+ ClutterBackendX11Class *backendx11_class = CLUTTER_BACKEND_X11_CLASS (klass);
+#endif
gobject_class->constructor = clutter_backend_egl_constructor;
- gobject_class->dispose = clutter_backend_egl_dispose;
- gobject_class->finalize = clutter_backend_egl_finalize;
+ gobject_class->dispose = clutter_backend_egl_dispose;
+ gobject_class->finalize = clutter_backend_egl_finalize;
backend_class->pre_parse = clutter_backend_egl_pre_parse;
backend_class->post_parse = clutter_backend_egl_post_parse;
+ backend_class->get_features = clutter_backend_egl_get_features;
+#ifdef HAVE_TSLIB
backend_class->init_events = clutter_backend_egl_init_events;
+#endif
backend_class->create_stage = clutter_backend_egl_create_stage;
backend_class->create_context = clutter_backend_egl_create_context;
backend_class->ensure_context = clutter_backend_egl_ensure_context;
backend_class->redraw = clutter_backend_egl_redraw;
- backend_class->get_features = clutter_backend_egl_get_features;
+
+#ifdef COGL_HAS_XLIB_SUPPORT
+ backendx11_class->get_visual_info = clutter_backend_egl_get_visual_info;
+#endif
}
static void
clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
{
+#ifndef COGL_HAS_XLIB_SUPPORT
ClutterBackend *backend = CLUTTER_BACKEND (backend_egl);
clutter_backend_set_resolution (backend, 96.0);
clutter_backend_set_double_click_time (backend, 250);
clutter_backend_set_double_click_distance (backend, 5);
+#ifdef HAVE_TSLIB
backend_egl->event_timer = g_timer_new ();
+#endif
backend_egl->fb_device_id = -1;
+
+#else
+
+ backend_egl->egl_context = EGL_NO_CONTEXT;
+ backend_egl->dummy_surface = EGL_NO_SURFACE;
+
+#endif
}
GType
@@ -456,6 +785,23 @@ _clutter_backend_impl_get_type (void)
return clutter_backend_egl_get_type ();
}
+#ifdef COGL_HAS_XLIB_SUPPORT
+/**
+ * clutter_eglx_display:
+ *
+ * Retrieves the EGLDisplay used by Clutter
+ *
+ * Return value: the EGL display
+ *
+ * Since: 0.4
+ */
+EGLDisplay
+clutter_eglx_display (void)
+{
+ return backend_singleton->edpy;
+}
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
/**
* clutter_egl_display:
*
@@ -468,3 +814,4 @@ clutter_egl_display (void)
{
return backend_singleton->edpy;
}
+
diff --git a/clutter/eglnative/clutter-backend-egl.h b/clutter/eglnative/clutter-backend-egl.h
index fe627fb1e..ca83718e8 100644
--- a/clutter/eglnative/clutter-backend-egl.h
+++ b/clutter/eglnative/clutter-backend-egl.h
@@ -1,8 +1,6 @@
/* Clutter.
* An OpenGL based 'interactive canvas' library.
*
- * Authored By Matthew Allum
- *
* Copyright (C) 2006, 2007, 2008 OpenedHand
* Copyright (C) 2009, 2010 Intel Corp
*
@@ -19,16 +17,24 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
- *
+ * Authors:
+ * Matthew Allum
+ * Robert Bragg
*/
#ifndef __CLUTTER_BACKEND_EGL_H__
#define __CLUTTER_BACKEND_EGL_H__
+#include
+#include
+#include
+#ifdef COGL_HAS_XLIB_SUPPORT
+#include
+#include
+#endif
+
#include "clutter-egl-headers.h"
-#include
-#include
G_BEGIN_DECLS
#define CLUTTER_TYPE_BACKEND_EGL (clutter_backend_egl_get_type ())
@@ -43,6 +49,19 @@ typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass;
struct _ClutterBackendEGL
{
+#ifdef COGL_HAS_XLIB_SUPPORT
+ ClutterBackendX11 parent_instance;
+
+ /* EGL Specific */
+ EGLDisplay edpy;
+ EGLContext egl_context;
+ EGLConfig egl_config;
+
+ Window dummy_xwin;
+ EGLSurface dummy_surface;
+
+#else /* COGL_HAS_X11_SUPPORT */
+
ClutterBackend parent_instance;
/* EGL Specific */
@@ -54,9 +73,6 @@ struct _ClutterBackendEGL
gint surface_width;
gint surface_height;
- gint egl_version_major;
- gint egl_version_minor;
-
/* main stage singleton */
ClutterStageWindow *stage;
@@ -69,12 +85,19 @@ struct _ClutterBackendEGL
/* FB device */
gint fb_device_id;
- /*< private >*/
+#endif /* COGL_HAS_X11_SUPPORT */
+
+ gint egl_version_major;
+ gint egl_version_minor;
};
struct _ClutterBackendEGLClass
{
+#ifdef COGL_HAS_XLIB_SUPPORT
+ ClutterBackendX11Class parent_class;
+#else
ClutterBackendClass parent_class;
+#endif
};
GType clutter_backend_egl_get_type (void) G_GNUC_CONST;
diff --git a/clutter/eglnative/clutter-stage-egl.c b/clutter/eglnative/clutter-stage-egl.c
index 047ce93c1..ec3d5adf1 100644
--- a/clutter/eglnative/clutter-stage-egl.c
+++ b/clutter/eglnative/clutter-stage-egl.c
@@ -18,17 +18,189 @@
#include "../clutter-stage.h"
#include "../clutter-stage-window.h"
+#ifdef COGL_HAS_X11_SUPPORT
+static ClutterStageWindowIface *clutter_stage_egl_parent_iface = NULL;
+#endif
+
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL,
clutter_stage_egl,
+#ifdef COGL_HAS_X11_SUPPORT
+ CLUTTER_TYPE_STAGE_X11,
+#else
G_TYPE_OBJECT,
+#endif
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init));
+#ifdef COGL_HAS_XLIB_SUPPORT
+
static void
-clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
+clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
{
+ ClutterBackend *backend = clutter_get_default_backend ();
+ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
+ ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+
+ CLUTTER_NOTE (BACKEND, "Unrealizing stage");
+
+ clutter_x11_trap_x_errors ();
+
+ if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
+ {
+ XDestroyWindow (backend_x11->xdpy, stage_x11->xwin);
+ stage_x11->xwin = None;
+ }
+ else
+ stage_x11->xwin = None;
+
+ if (stage_egl->egl_surface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface (clutter_eglx_display (), stage_egl->egl_surface);
+ stage_egl->egl_surface = EGL_NO_SURFACE;
+ }
+
+ XSync (backend_x11->xdpy, False);
+
+ clutter_x11_untrap_x_errors ();
+}
+
+static gboolean
+clutter_stage_egl_realize (ClutterStageWindow *stage_window)
+{
+ ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
+ ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+ ClutterBackend *backend;
+ ClutterBackendEGL *backend_egl;
+ ClutterBackendX11 *backend_x11;
+ EGLDisplay edpy;
+
+ CLUTTER_NOTE (BACKEND, "Realizing main stage");
+
+ backend = clutter_get_default_backend ();
+ backend_egl = CLUTTER_BACKEND_EGL (backend);
+ backend_x11 = CLUTTER_BACKEND_X11 (backend);
+
+ edpy = clutter_eglx_display ();
+
+ if (stage_x11->xwin == None)
+ {
+ XSetWindowAttributes xattr;
+ unsigned long mask;
+ XVisualInfo *xvisinfo;
+ gfloat width, height;
+
+ CLUTTER_NOTE (MISC, "Creating stage X window");
+
+ xvisinfo = clutter_backend_x11_get_visual_info (backend_x11);
+ if (xvisinfo == NULL)
+ {
+ g_critical ("Unable to find suitable GL visual.");
+ return FALSE;
+ }
+
+ /* window attributes */
+ xattr.background_pixel = WhitePixel (backend_x11->xdpy,
+ backend_x11->xscreen_num);
+ xattr.border_pixel = 0;
+ xattr.colormap = XCreateColormap (backend_x11->xdpy,
+ backend_x11->xwin_root,
+ xvisinfo->visual,
+ AllocNone);
+ mask = CWBorderPixel | CWColormap;
+
+ /* Call get_size - this will either get the geometry size (which
+ * before we create the window is set to 640x480), or if a size
+ * is set, it will get that. This lets you set a size on the
+ * stage before it's realized.
+ */
+ clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper),
+ &width,
+ &height);
+ stage_x11->xwin_width = (gint)width;
+ stage_x11->xwin_height = (gint)height;
+
+ stage_x11->xwin = XCreateWindow (backend_x11->xdpy,
+ backend_x11->xwin_root,
+ 0, 0,
+ stage_x11->xwin_width,
+ stage_x11->xwin_height,
+ 0,
+ xvisinfo->depth,
+ InputOutput,
+ xvisinfo->visual,
+ mask, &xattr);
+
+ CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d",
+ stage_window,
+ (unsigned int) stage_x11->xwin,
+ stage_x11->xwin_width,
+ stage_x11->xwin_height);
+
+ XFree (xvisinfo);
+ }
+
+ if (stage_egl->egl_surface == EGL_NO_SURFACE)
+ {
+ stage_egl->egl_surface =
+ eglCreateWindowSurface (edpy,
+ backend_egl->egl_config,
+ (NativeWindowType) stage_x11->xwin,
+ NULL);
+ }
+
+ if (stage_egl->egl_surface == EGL_NO_SURFACE)
+ g_warning ("Unable to create an EGL surface");
+
+ if (clutter_x11_has_event_retrieval ())
+ {
+ if (clutter_x11_has_xinput ())
+ {
+ XSelectInput (backend_x11->xdpy, stage_x11->xwin,
+ StructureNotifyMask |
+ FocusChangeMask |
+ ExposureMask |
+ EnterWindowMask | LeaveWindowMask |
+ PropertyChangeMask);
+#ifdef USE_XINPUT
+ _clutter_x11_select_events (stage_x11->xwin);
+#endif
+ }
+ else
+ XSelectInput (backend_x11->xdpy, stage_x11->xwin,
+ StructureNotifyMask |
+ FocusChangeMask |
+ ExposureMask |
+ PointerMotionMask |
+ KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask |
+ EnterWindowMask | LeaveWindowMask |
+ PropertyChangeMask);
+ }
+
+ /* no user resize... */
+ clutter_stage_x11_fix_window_size (stage_x11,
+ stage_x11->xwin_width,
+ stage_x11->xwin_height);
+ clutter_stage_x11_set_wm_protocols (stage_x11);
+
+ return clutter_stage_egl_parent_iface->realize (stage_window);
+}
+
+#else /* COGL_HAS_XLIB_SUPPORT */
+
+static void
+clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
+{
+}
+
+static gboolean
+clutter_stage_egl_realize (ClutterStageWindow *stage_window)
+{
+ /* the EGL surface is created by the backend */
+ return TRUE;
}
static void
@@ -78,18 +250,6 @@ clutter_stage_egl_hide (ClutterStageWindow *stage_window)
clutter_actor_unmap (CLUTTER_ACTOR (stage_egl->wrapper));
}
-static void
-clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
-{
-}
-
-static gboolean
-clutter_stage_egl_realize (ClutterStageWindow *stage_window)
-{
- /* the EGL surface is created by the backend */
- return TRUE;
-}
-
static void
clutter_stage_egl_get_geometry (ClutterStageWindow *stage_window,
ClutterGeometry *geometry)
@@ -113,22 +273,94 @@ clutter_stage_egl_resize (ClutterStageWindow *stage_window,
{
}
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
{
+#ifdef COGL_HAS_X11_SUPPORT
+ clutter_stage_egl_parent_iface = g_type_interface_peek_parent (iface);
+
+ iface->realize = clutter_stage_egl_realize;
+ iface->unrealize = clutter_stage_egl_unrealize;
+
+ /* the rest is inherited from ClutterStageX11 */
+
+#else /* COGL_HAS_X11_SUPPORT */
+
+ iface->realize = clutter_stage_egl_realize;
+ iface->unrealize = clutter_stage_egl_unrealize;
iface->set_fullscreen = clutter_stage_egl_set_fullscreen;
iface->set_title = clutter_stage_egl_set_title;
iface->set_cursor_visible = clutter_stage_egl_set_cursor_visible;
iface->get_wrapper = clutter_stage_egl_get_wrapper;
- iface->realize = clutter_stage_egl_realize;
- iface->unrealize = clutter_stage_egl_unrealize;
iface->get_geometry = clutter_stage_egl_get_geometry;
iface->resize = clutter_stage_egl_resize;
iface->show = clutter_stage_egl_show;
iface->hide = clutter_stage_egl_hide;
+
+#endif /* COGL_HAS_X11_SUPPORT */
+}
+
+#ifdef COGL_HAS_X11_SUPPORT
+static void
+clutter_stage_egl_dispose (GObject *gobject)
+{
+ G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
+}
+
+static void
+clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = clutter_stage_egl_dispose;
}
static void
clutter_stage_egl_init (ClutterStageEGL *stage)
{
+ stage->egl_surface = EGL_NO_SURFACE;
+}
+
+#else /* COGL_HAS_X11_SUPPORT */
+
+static void
+clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
+{
+}
+
+static void
+clutter_stage_egl_init (ClutterStageEGL *stage)
+{
+ /* Without X we only support one surface and that is associated
+ * with the backend directly instead of the stage */
+}
+
+#endif /* COGL_HAS_X11_SUPPORT */
+
+void
+clutter_stage_egl_redraw (ClutterStageEGL *stage_egl,
+ ClutterStage *stage)
+{
+ ClutterBackend *backend = clutter_get_default_backend ();
+ ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+ ClutterActor *wrapper;
+ EGLSurface egl_surface;
+#ifdef COGL_HAS_X11_SUPPORT
+ ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_egl);
+
+ wrapper = CLUTTER_ACTOR (stage_x11->wrapper);
+ egl_surface = stage_egl->egl_surface;
+#else
+ wrapper = CLUTTER_ACTOR (stage_egl->wrapper);
+ /* Without X we only support one surface and that is associated
+ * with the backend directly instead of the stage */
+ egl_surface = backend_egl->egl_surface;
+#endif
+
+ clutter_actor_paint (wrapper);
+ cogl_flush ();
+
+ eglSwapBuffers (backend_egl->edpy, egl_surface);
}
diff --git a/clutter/eglnative/clutter-stage-egl.h b/clutter/eglnative/clutter-stage-egl.h
index 49a6c798a..6167197a8 100644
--- a/clutter/eglnative/clutter-stage-egl.h
+++ b/clutter/eglnative/clutter-stage-egl.h
@@ -35,4 +35,7 @@ struct _ClutterStageEGLClass
GType clutter_stage_egl_get_type (void) G_GNUC_CONST;
+void clutter_stage_egl_redraw (ClutterStageEGL *stage_egl,
+ ClutterStage *stage);
+
#endif /* __CLUTTER_STAGE_EGL_H__ */
diff --git a/clutter/eglx/clutter-backend-egl.c b/clutter/eglx/clutter-backend-egl.c
index 216f31298..4c4281865 100644
--- a/clutter/eglx/clutter-backend-egl.c
+++ b/clutter/eglx/clutter-backend-egl.c
@@ -1,9 +1,45 @@
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Copyright (C) 2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see .
+
+ * Authors:
+ * Matthew Allum
+ * Emmanuele Bassi
+ * Robert Bragg
+ * Neil Roberts
+ */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include
+#include
+#include
+#include
+
+#include
+
#include "clutter-backend-egl.h"
#include "clutter-stage-egl.h"
+#include "clutter-eglx.h"
+
#include "../clutter-private.h"
#include "../clutter-main.h"
#include "../clutter-debug.h"
@@ -11,7 +47,13 @@
static ClutterBackendEGL *backend_singleton = NULL;
+static const gchar *clutter_fb_device = NULL;
+
+#ifdef COGL_HAS_X11_SUPPORT
G_DEFINE_TYPE (ClutterBackendEGL, clutter_backend_egl, CLUTTER_TYPE_BACKEND_X11);
+#else
+G_DEFINE_TYPE (ClutterBackendEGL, clutter_backend_egl, CLUTTER_TYPE_BACKEND);
+#endif
static void
clutter_backend_at_exit (void)
@@ -20,34 +62,67 @@ clutter_backend_at_exit (void)
g_object_run_dispose (G_OBJECT (backend_singleton));
}
+static gboolean
+clutter_backend_egl_pre_parse (ClutterBackend *backend,
+ GError **error)
+{
+ const gchar *env_string;
+#ifdef COGL_HAS_X11_SUPPORT
+ ClutterBackendClass *backend_x11_class =
+ CLUTTER_BACKEND_CLASS (clutter_backend_egl_parent_class);
+
+ if (!backend_x11_class->pre_parse (backend, error))
+ return FALSE;
+#endif
+
+ env_string = g_getenv ("CLUTTER_FB_DEVICE");
+ if (env_string != NULL && env_string[0] != '\0')
+ clutter_fb_device = g_strdup (env_string);
+
+ return TRUE;
+}
+
static gboolean
clutter_backend_egl_post_parse (ClutterBackend *backend,
GError **error)
{
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+#ifdef COGL_HAS_X11_SUPPORT
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+ ClutterBackendClass *backend_x11_class =
+ CLUTTER_BACKEND_CLASS (clutter_backend_egl_parent_class);
+#endif
+ EGLBoolean status;
- if (clutter_backend_x11_post_parse (backend, error))
+#ifdef COGL_HAS_X11_SUPPORT
+ if (!backend_x11_class->post_parse (backend, error))
+ return FALSE;
+
+#ifndef COGL_HAS_XLIB_SUPPORT
+#error "Clutter's EGL on X11 support currently only works with xlib Displays"
+#endif
+ backend_egl->edpy =
+ eglGetDisplay ((NativeDisplayType) backend_x11->xdpy);
+
+ status = eglInitialize (backend_egl->edpy,
+ &backend_egl->egl_version_major,
+ &backend_egl->egl_version_minor);
+#else
+ backend_egl->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
+
+ status = eglInitialize (backend_egl->edpy,
+ &backend_egl->egl_version_major,
+ &backend_egl->egl_version_minor);
+#endif
+
+ g_atexit (clutter_backend_at_exit);
+
+ if (status != EGL_TRUE)
{
- EGLBoolean status;
-
- backend_egl->edpy =
- eglGetDisplay ((NativeDisplayType) backend_x11->xdpy);
-
- status = eglInitialize (backend_egl->edpy,
- &backend_egl->egl_version_major,
- &backend_egl->egl_version_minor);
-
- g_atexit (clutter_backend_at_exit);
-
- if (status != EGL_TRUE)
- {
- g_set_error (error, CLUTTER_INIT_ERROR,
- CLUTTER_INIT_ERROR_BACKEND,
- "Unable to Initialize EGL");
- return FALSE;
- }
-
+ g_set_error (error, CLUTTER_INIT_ERROR,
+ CLUTTER_INIT_ERROR_BACKEND,
+ "Unable to Initialize EGL");
+ return FALSE;
}
CLUTTER_NOTE (BACKEND, "EGL Reports version %i.%i",
@@ -61,45 +136,54 @@ static gboolean
clutter_backend_egl_create_context (ClutterBackend *backend,
GError **error)
{
- ClutterBackendEGL *backend_egl;
- ClutterBackendX11 *backend_x11;
+ ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+#ifdef COGL_HAS_X11_SUPPORT
+ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
+#endif
EGLConfig config;
EGLint config_count = 0;
EGLBoolean status;
EGLint cfg_attribs[] = {
/* NB: This must be the first attribute, since we may
* try and fallback to no stencil buffer */
- EGL_STENCIL_SIZE, 8,
+ EGL_STENCIL_SIZE, 2,
- EGL_RED_SIZE, 5,
- EGL_GREEN_SIZE, 6,
- EGL_BLUE_SIZE, 5,
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_ALPHA_SIZE, EGL_DONT_CARE,
- EGL_BUFFER_SIZE, EGL_DONT_CARE,
+ EGL_DEPTH_SIZE, 1,
-#ifdef HAVE_COGL_GLES2
+ EGL_BUFFER_SIZE, EGL_DONT_CARE,
+
+#if defined (HAVE_COGL_GLES2)
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-#else /* HAVE_COGL_GLES2 */
+#else
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+#endif
+
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-#endif /* HAVE_COGL_GLES2 */
EGL_NONE
};
EGLDisplay edpy;
gint retry_cookie = 0;
+ const char *error_message = NULL;
+#ifdef COGL_HAS_XLIB_SUPPORT
XVisualInfo *xvisinfo;
XSetWindowAttributes attrs;
-
- backend = clutter_get_default_backend ();
- backend_egl = CLUTTER_BACKEND_EGL (backend);
+#endif
if (backend_egl->egl_context != EGL_NO_CONTEXT)
return TRUE;
- backend_x11 = CLUTTER_BACKEND_X11 (backend);
-
edpy = clutter_eglx_display ();
+/* XXX: we should get rid of this goto yukkyness, there is a fail:
+ * goto at the end and this retry: goto at the top, but we should just
+ * have a try_create_context() function and call it in a loop that
+ * tries a different fallback each iteration */
retry:
/* Here we can change the attributes depending on the fallback count... */
@@ -118,37 +202,41 @@ retry:
&config_count);
if (status != EGL_TRUE || config_count == 0)
{
- g_warning ("eglChooseConfig failed");
+ error_message = "Unable to select a valid EGL configuration";
goto fail;
}
- if (G_UNLIKELY (backend_egl->egl_context == EGL_NO_CONTEXT))
+ if (backend_egl->egl_context == EGL_NO_CONTEXT)
{
#ifdef HAVE_COGL_GLES2
- static const EGLint attribs[3]
- = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+ static const EGLint attribs[] =
+ { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
backend_egl->egl_context = eglCreateContext (edpy,
config,
EGL_NO_CONTEXT,
attribs);
+
#else
- /* Seems some GLES implementations 1.x do not like attribs... */
backend_egl->egl_context = eglCreateContext (edpy,
config,
EGL_NO_CONTEXT,
NULL);
+
#endif
if (backend_egl->egl_context == EGL_NO_CONTEXT)
{
- g_warning ("Unable to create a suitable EGL context");
+ error_message = "Unable to create a suitable EGL context";
goto fail;
}
+#ifdef COGL_HAS_XLIB_SUPPORT
backend_egl->egl_config = config;
+#endif
CLUTTER_NOTE (GL, "Created EGL Context");
}
+#ifdef COGL_HAS_XLIB_SUPPORT
/* COGL assumes that there is always a GL context selected; in order
* to make sure that an EGL context exists and is made current, we use
* a dummy, offscreen override-redirect window to which we can always
@@ -199,6 +287,80 @@ retry:
backend_egl->dummy_surface,
backend_egl->egl_context);
+#else /* COGL_HAS_XLIB_SUPPORT */
+
+ if (clutter_fb_device != NULL)
+ {
+ int fd = open (clutter_fb_device, O_RDWR);
+
+ if (fd < 0)
+ {
+ int errno_save = errno;
+
+ g_set_error (error, CLUTTER_INIT_ERROR,
+ CLUTTER_INIT_ERROR_BACKEND,
+ "Unable to open the framebuffer device '%s': %s",
+ clutter_fb_device,
+ g_strerror (errno_save));
+
+ return FALSE;
+ }
+ else
+ backend_egl->fb_device_id = fd;
+
+ backend_egl->egl_surface =
+ eglCreateWindowSurface (edpy,
+ config,
+ (NativeWindowType) backend_egl->fb_device_id,
+ NULL);
+ }
+ else
+ {
+ backend_egl->egl_surface =
+ eglCreateWindowSurface (edpy,
+ config,
+ (NativeWindowType) NULL,
+ NULL);
+ }
+
+ if (backend_egl->egl_surface == EGL_NO_SURFACE)
+ {
+ g_set_error (error, CLUTTER_INIT_ERROR,
+ CLUTTER_INIT_ERROR_BACKEND,
+ "Unable to create EGL window surface");
+
+ return FALSE;
+ }
+
+ CLUTTER_NOTE (BACKEND, "Setting context");
+
+ /* Without X we assume we can have only one stage, so we
+ * store the EGL surface in the backend itself, instead
+ * of the StageWindow implementation, and we make it
+ * current immediately to make sure the Cogl and Clutter
+ * can query the EGL context for features.
+ */
+ status = eglMakeCurrent (backend_egl->edpy,
+ backend_egl->egl_surface,
+ backend_egl->egl_surface,
+ backend_egl->egl_context);
+
+ eglQuerySurface (backend_egl->edpy,
+ backend_egl->egl_surface,
+ EGL_WIDTH,
+ &backend_egl->surface_width);
+
+ eglQuerySurface (backend_egl->edpy,
+ backend_egl->egl_surface,
+ EGL_HEIGHT,
+ &backend_egl->surface_height);
+
+ CLUTTER_NOTE (BACKEND, "EGL surface is %ix%i",
+ backend_egl->surface_width,
+ backend_egl->surface_height);
+
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
return TRUE;
fail:
@@ -210,6 +372,10 @@ fail:
goto retry;
}
+ g_set_error (error, CLUTTER_INIT_ERROR,
+ CLUTTER_INIT_ERROR_BACKEND,
+ "%s", error_message);
+
return FALSE;
}
@@ -217,6 +383,11 @@ static void
clutter_backend_egl_ensure_context (ClutterBackend *backend,
ClutterStage *stage)
{
+#ifndef COGL_HAS_XLIB_SUPPORT
+ /* Without X we only have one EGL surface to worry about
+ * so we can assume it is permanently made current and
+ * don't have to do anything here. */
+#else
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
ClutterStageWindow *impl;
@@ -283,6 +454,7 @@ clutter_backend_egl_ensure_context (ClutterBackend *backend,
"EGLX drawable",
(int) stage_x11->xwin);
}
+#endif /* COGL_HAS_XLIB_SUPPORT */
}
static void
@@ -300,6 +472,15 @@ clutter_backend_egl_redraw (ClutterBackend *backend,
clutter_stage_egl_redraw (CLUTTER_STAGE_EGL (impl), stage);
}
+#ifdef HAVE_TSLIB
+static void
+clutter_backend_egl_init_events (ClutterBackend *backend)
+{
+ /* XXX: This should be renamed to _clutter_events_tslib_init */
+ _clutter_events_egl_init (CLUTTER_BACKEND_EGL (backend));
+}
+#endif
+
static void
clutter_backend_egl_finalize (GObject *gobject)
{
@@ -313,7 +494,11 @@ static void
clutter_backend_egl_dispose (GObject *gobject)
{
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);
+#ifdef COGL_HAS_X11_SUPPORT
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
+#else
+ ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (backend_egl->stage);
+#endif
/* We chain up before disposing our own resources so that
ClutterBackendX11 will destroy all of the stages before we
@@ -321,6 +506,12 @@ clutter_backend_egl_dispose (GObject *gobject)
calls during destruction which causes a crash */
G_OBJECT_CLASS (clutter_backend_egl_parent_class)->dispose (gobject);
+#ifdef HAVE_TSLIB
+ /* XXX: This should be renamed to _clutter_events_tslib_uninit */
+ _clutter_events_egl_uninit (backend_egl);
+#endif
+
+#ifdef COGL_HAS_XLIB_SUPPORT
if (backend_egl->dummy_surface != EGL_NO_SURFACE)
{
eglDestroySurface (backend_egl->edpy, backend_egl->dummy_surface);
@@ -333,6 +524,28 @@ clutter_backend_egl_dispose (GObject *gobject)
backend_egl->dummy_xwin = None;
}
+#else /* COGL_HAS_XLIB_SUPPORT */
+
+ if (backend_egl->egl_surface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface (backend_egl->edpy, backend_egl->egl_surface);
+ backend_egl->egl_surface = EGL_NO_SURFACE;
+ }
+
+ if (backend_egl->stage != NULL)
+ {
+ clutter_actor_destroy (CLUTTER_ACTOR (stage_egl->wrapper));
+ backend_egl->stage = NULL;
+ }
+
+ if (backend_egl->fb_device_id != -1)
+ {
+ close (backend_egl->fb_device_id);
+ backend_egl->fb_device_id = -1;
+ }
+
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
if (backend_egl->egl_context)
{
eglDestroyContext (backend_egl->edpy, backend_egl->egl_context);
@@ -344,6 +557,14 @@ clutter_backend_egl_dispose (GObject *gobject)
eglTerminate (backend_egl->edpy);
backend_egl->edpy = 0;
}
+
+#ifdef HAVE_TSLIB
+ if (backend_egl->event_timer != NULL)
+ {
+ g_timer_destroy (backend_egl->event_timer);
+ backend_egl->event_timer = NULL;
+ }
+#endif
}
static GObject *
@@ -376,8 +597,14 @@ clutter_backend_egl_get_features (ClutterBackend *backend)
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
ClutterFeatureFlags flags;
+ g_assert (backend_egl->egl_context != NULL);
+
+#ifdef COGL_HAS_XLIB_SUPPORT
flags = clutter_backend_x11_get_features (backend);
flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
+#else
+ flags = CLUTTER_FEATURE_STAGE_STATIC;
+#endif
CLUTTER_NOTE (BACKEND, "Checking features\n"
"GL_VENDOR: %s\n"
@@ -401,27 +628,53 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
ClutterStage *wrapper,
GError **error)
{
+#ifdef COGL_HAS_XLIB_SUPPORT
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
- ClutterStageX11 *stage_x11;
ClutterStageWindow *stage;
+ ClutterStageX11 *stage_x11;
CLUTTER_NOTE (BACKEND, "Creating stage of type '%s'",
g_type_name (CLUTTER_STAGE_TYPE));
-
+
stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL);
-
+
/* copy backend data into the stage */
stage_x11 = CLUTTER_STAGE_X11 (stage);
stage_x11->wrapper = wrapper;
-
+
CLUTTER_NOTE (MISC, "EGLX stage created (display:%p, screen:%d, root:%u)",
backend_x11->xdpy,
backend_x11->xscreen_num,
(unsigned int) backend_x11->xwin_root);
-
+
+#else /* COGL_HAS_XLIB_SUPPORT */
+
+ ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+ ClutterStageWindow *stage;
+ ClutterStageEGL *stage_egl;
+
+ if (G_UNLIKELY (backend_egl->stage != NULL))
+ {
+ g_set_error (error, CLUTTER_INIT_ERROR,
+ CLUTTER_INIT_ERROR_BACKEND,
+ "The EGL native backend does not support multiple stages");
+ return backend_egl->stage;
+ }
+
+ stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL);
+
+ stage_egl = CLUTTER_STAGE_EGL (stage);
+ stage_egl->backend = backend_egl;
+ stage_egl->wrapper = wrapper;
+
+ backend_egl->stage = stage;
+
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
return stage;
}
+#ifdef COGL_HAS_XLIB_SUPPORT
static XVisualInfo *
clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11)
{
@@ -471,32 +724,59 @@ clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11)
return visinfo;
}
+#endif
static void
clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
+#ifdef COGL_HAS_X11_SUPPORT
ClutterBackendX11Class *backendx11_class = CLUTTER_BACKEND_X11_CLASS (klass);
+#endif
gobject_class->constructor = clutter_backend_egl_constructor;
gobject_class->dispose = clutter_backend_egl_dispose;
gobject_class->finalize = clutter_backend_egl_finalize;
- backend_class->post_parse = clutter_backend_egl_post_parse;
- backend_class->redraw = clutter_backend_egl_redraw;
- backend_class->get_features = clutter_backend_egl_get_features;
- backend_class->create_stage = clutter_backend_egl_create_stage;
- backend_class->ensure_context = clutter_backend_egl_ensure_context;
- backend_class->create_context = clutter_backend_egl_create_context;
+ backend_class->pre_parse = clutter_backend_egl_pre_parse;
+ backend_class->post_parse = clutter_backend_egl_post_parse;
+ backend_class->get_features = clutter_backend_egl_get_features;
+#ifdef HAVE_TSLIB
+ backend_class->init_events = clutter_backend_egl_init_events;
+#endif
+ backend_class->create_stage = clutter_backend_egl_create_stage;
+ backend_class->create_context = clutter_backend_egl_create_context;
+ backend_class->ensure_context = clutter_backend_egl_ensure_context;
+ backend_class->redraw = clutter_backend_egl_redraw;
+
+#ifdef COGL_HAS_XLIB_SUPPORT
backendx11_class->get_visual_info = clutter_backend_egl_get_visual_info;
+#endif
}
static void
clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
{
+#ifndef COGL_HAS_XLIB_SUPPORT
+ ClutterBackend *backend = CLUTTER_BACKEND (backend_egl);
+
+ clutter_backend_set_resolution (backend, 96.0);
+ clutter_backend_set_double_click_time (backend, 250);
+ clutter_backend_set_double_click_distance (backend, 5);
+
+#ifdef HAVE_TSLIB
+ backend_egl->event_timer = g_timer_new ();
+#endif
+
+ backend_egl->fb_device_id = -1;
+
+#else
+
backend_egl->egl_context = EGL_NO_CONTEXT;
backend_egl->dummy_surface = EGL_NO_SURFACE;
+
+#endif
}
GType
@@ -505,12 +785,13 @@ _clutter_backend_impl_get_type (void)
return clutter_backend_egl_get_type ();
}
+#ifdef COGL_HAS_XLIB_SUPPORT
/**
* clutter_eglx_display:
*
- * Gets the current EGLDisplay.
+ * Retrieves the EGLDisplay used by Clutter
*
- * Return value: an EGLDisplay
+ * Return value: the EGL display
*
* Since: 0.4
*/
@@ -519,3 +800,18 @@ clutter_eglx_display (void)
{
return backend_singleton->edpy;
}
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
+/**
+ * clutter_egl_display:
+ *
+ * Retrieves the EGLDisplay used by Clutter
+ *
+ * Return value: the EGL display
+ */
+EGLDisplay
+clutter_egl_display (void)
+{
+ return backend_singleton->edpy;
+}
+
diff --git a/clutter/eglx/clutter-backend-egl.h b/clutter/eglx/clutter-backend-egl.h
index 8ab5ded86..c3893efd9 100644
--- a/clutter/eglx/clutter-backend-egl.h
+++ b/clutter/eglx/clutter-backend-egl.h
@@ -1,7 +1,8 @@
/* Clutter.
* An OpenGL based 'interactive canvas' library.
- * Authored By Matthew Allum
- * Copyright (C) 2006-2007 OpenedHand
+ *
+ * Copyright (C) 2006, 2007 OpenedHand
+ * Copyright (C) 2010 Intel Corp
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,7 +17,9 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
- *
+ * Authors:
+ * Matthew Allum
+ * Robert Bragg
*/
#ifndef __CLUTTER_BACKEND_EGL_H__
@@ -25,12 +28,17 @@
#include
#include
#include
+#ifdef COGL_HAS_XLIB_SUPPORT
#include
#include
+#endif
#include "clutter-egl-headers.h"
+#ifdef COGL_HAS_X11_SUPPORT
#include "../x11/clutter-backend-x11.h"
+#endif
+
#include "clutter-eglx.h"
G_BEGIN_DECLS
@@ -47,27 +55,62 @@ typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass;
struct _ClutterBackendEGL
{
+#ifdef COGL_HAS_XLIB_SUPPORT
ClutterBackendX11 parent_instance;
/* EGL Specific */
EGLDisplay edpy;
EGLContext egl_context;
EGLConfig egl_config;
+
Window dummy_xwin;
EGLSurface dummy_surface;
+#else /* COGL_HAS_X11_SUPPORT */
+
+ ClutterBackend parent_instance;
+
+ /* EGL Specific */
+ EGLDisplay edpy;
+ EGLSurface egl_surface;
+ EGLContext egl_context;
+
+ /* from the backend */
+ gint surface_width;
+ gint surface_height;
+
+ /* main stage singleton */
+ ClutterStageWindow *stage;
+
+ /* event source */
+ GSource *event_source;
+
+ /* event timer */
+ GTimer *event_timer;
+
+ /* FB device */
+ gint fb_device_id;
+
+#endif /* COGL_HAS_X11_SUPPORT */
+
gint egl_version_major;
gint egl_version_minor;
-
};
struct _ClutterBackendEGLClass
{
+#ifdef COGL_HAS_XLIB_SUPPORT
ClutterBackendX11Class parent_class;
+#else
+ ClutterBackendClass parent_class;
+#endif
};
GType clutter_backend_egl_get_type (void) G_GNUC_CONST;
+void _clutter_events_egl_init (ClutterBackendEGL *backend);
+void _clutter_events_egl_uninit (ClutterBackendEGL *backend);
+
G_END_DECLS
#endif /* __CLUTTER_BACKEND_EGL_H__ */
diff --git a/clutter/eglx/clutter-stage-egl.c b/clutter/eglx/clutter-stage-egl.c
index ca20fc3fa..58f8b4b8f 100644
--- a/clutter/eglx/clutter-stage-egl.c
+++ b/clutter/eglx/clutter-stage-egl.c
@@ -2,9 +2,9 @@
#include "config.h"
#endif
-#include "clutter-backend-egl.h"
#include "clutter-stage-egl.h"
#include "clutter-eglx.h"
+#include "clutter-backend-egl.h"
#include "../clutter-main.h"
#include "../clutter-feature.h"
@@ -15,20 +15,27 @@
#include "../clutter-private.h"
#include "../clutter-debug.h"
#include "../clutter-units.h"
-#include "../clutter-container.h"
#include "../clutter-stage.h"
#include "../clutter-stage-window.h"
+#ifdef COGL_HAS_X11_SUPPORT
static ClutterStageWindowIface *clutter_stage_egl_parent_iface = NULL;
+#endif
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL,
clutter_stage_egl,
+#ifdef COGL_HAS_X11_SUPPORT
CLUTTER_TYPE_STAGE_X11,
+#else
+ G_TYPE_OBJECT,
+#endif
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init));
+#ifdef COGL_HAS_XLIB_SUPPORT
+
static void
clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
{
@@ -182,21 +189,124 @@ clutter_stage_egl_realize (ClutterStageWindow *stage_window)
return clutter_stage_egl_parent_iface->realize (stage_window);
}
+#else /* COGL_HAS_XLIB_SUPPORT */
+
static void
-clutter_stage_egl_dispose (GObject *gobject)
+clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
{
- G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
}
+static gboolean
+clutter_stage_egl_realize (ClutterStageWindow *stage_window)
+{
+ /* the EGL surface is created by the backend */
+ return TRUE;
+}
+
+static void
+clutter_stage_egl_set_fullscreen (ClutterStageWindow *stage_window,
+ gboolean fullscreen)
+{
+ g_warning ("Stage of type '%s' do not support ClutterStage::set_fullscreen",
+ G_OBJECT_TYPE_NAME (stage_window));
+}
+
+static void
+clutter_stage_egl_set_title (ClutterStageWindow *stage_window,
+ const gchar *title)
+{
+ g_warning ("Stage of type '%s' do not support ClutterStage::set_title",
+ G_OBJECT_TYPE_NAME (stage_window));
+}
+
+static void
+clutter_stage_egl_set_cursor_visible (ClutterStageWindow *stage_window,
+ gboolean cursor_visible)
+{
+ g_warning ("Stage of type '%s' do not support ClutterStage::set_cursor_visible",
+ G_OBJECT_TYPE_NAME (stage_window));
+}
+
+static ClutterActor *
+clutter_stage_egl_get_wrapper (ClutterStageWindow *stage_window)
+{
+ return CLUTTER_ACTOR (CLUTTER_STAGE_EGL (stage_window)->wrapper);
+}
+
+static void
+clutter_stage_egl_show (ClutterStageWindow *stage_window,
+ gboolean do_raise)
+{
+ ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
+
+ clutter_actor_map (CLUTTER_ACTOR (stage_egl->wrapper));
+}
+
+static void
+clutter_stage_egl_hide (ClutterStageWindow *stage_window)
+{
+ ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
+
+ clutter_actor_unmap (CLUTTER_ACTOR (stage_egl->wrapper));
+}
+
+static void
+clutter_stage_egl_get_geometry (ClutterStageWindow *stage_window,
+ ClutterGeometry *geometry)
+{
+ ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
+ ClutterBackendEGL *backend_egl = stage_egl->backend;
+
+ if (geometry)
+ {
+ geometry->x = geometry->y = 0;
+
+ geometry->width = backend_egl->surface_width;
+ geometry->height = backend_egl->surface_height;
+ }
+}
+
+static void
+clutter_stage_egl_resize (ClutterStageWindow *stage_window,
+ gint width,
+ gint height)
+{
+}
+
+#endif /* COGL_HAS_XLIB_SUPPORT */
+
static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
{
+#ifdef COGL_HAS_X11_SUPPORT
clutter_stage_egl_parent_iface = g_type_interface_peek_parent (iface);
iface->realize = clutter_stage_egl_realize;
iface->unrealize = clutter_stage_egl_unrealize;
/* the rest is inherited from ClutterStageX11 */
+
+#else /* COGL_HAS_X11_SUPPORT */
+
+ iface->realize = clutter_stage_egl_realize;
+ iface->unrealize = clutter_stage_egl_unrealize;
+ iface->set_fullscreen = clutter_stage_egl_set_fullscreen;
+ iface->set_title = clutter_stage_egl_set_title;
+ iface->set_cursor_visible = clutter_stage_egl_set_cursor_visible;
+ iface->get_wrapper = clutter_stage_egl_get_wrapper;
+ iface->get_geometry = clutter_stage_egl_get_geometry;
+ iface->resize = clutter_stage_egl_resize;
+ iface->show = clutter_stage_egl_show;
+ iface->hide = clutter_stage_egl_hide;
+
+#endif /* COGL_HAS_X11_SUPPORT */
+}
+
+#ifdef COGL_HAS_X11_SUPPORT
+static void
+clutter_stage_egl_dispose (GObject *gobject)
+{
+ G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
}
static void
@@ -213,24 +323,44 @@ clutter_stage_egl_init (ClutterStageEGL *stage)
stage->egl_surface = EGL_NO_SURFACE;
}
+#else /* COGL_HAS_X11_SUPPORT */
+
+static void
+clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
+{
+}
+
+static void
+clutter_stage_egl_init (ClutterStageEGL *stage)
+{
+ /* Without X we only support one surface and that is associated
+ * with the backend directly instead of the stage */
+}
+
+#endif /* COGL_HAS_X11_SUPPORT */
+
void
clutter_stage_egl_redraw (ClutterStageEGL *stage_egl,
ClutterStage *stage)
{
ClutterBackend *backend = clutter_get_default_backend ();
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
+ ClutterActor *wrapper;
+ EGLSurface egl_surface;
+#ifdef COGL_HAS_X11_SUPPORT
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_egl);
- ClutterStageWindow *impl;
- impl = _clutter_stage_get_window (stage);
- if (impl == NULL)
- return;
+ wrapper = CLUTTER_ACTOR (stage_x11->wrapper);
+ egl_surface = stage_egl->egl_surface;
+#else
+ wrapper = CLUTTER_ACTOR (stage_egl->wrapper);
+ /* Without X we only support one surface and that is associated
+ * with the backend directly instead of the stage */
+ egl_surface = backend_egl->egl_surface;
+#endif
- g_assert (CLUTTER_IS_STAGE_EGL (impl));
- stage_egl = CLUTTER_STAGE_EGL (impl);
-
- clutter_actor_paint (CLUTTER_ACTOR (stage_x11->wrapper));
+ clutter_actor_paint (wrapper);
cogl_flush ();
- eglSwapBuffers (backend_egl->edpy, stage_egl->egl_surface);
+ eglSwapBuffers (backend_egl->edpy, egl_surface);
}