From b4e9f40394fb2e4d63bccc9f9d932a5da87cc2a2 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Sat, 27 Feb 2010 09:42:42 +0000 Subject: [PATCH 1/2] eglnative: Update implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the EGL native framebuffer backend to be 1.2-ready: » create the EGL context and the surface inside the create_context() implementation so that a context is always available » simplify the StageWindow implementation » clean up old code http://bugzilla.openedhand.com/show_bug.cgi?id=1997 --- clutter/eglnative/clutter-backend-egl.c | 186 +++++++++++++-- clutter/eglnative/clutter-backend-egl.h | 20 +- clutter/eglnative/clutter-event-egl.c | 60 +++-- clutter/eglnative/clutter-stage-egl.c | 305 ++++++------------------ clutter/eglnative/clutter-stage-egl.h | 8 +- 5 files changed, 298 insertions(+), 281 deletions(-) diff --git a/clutter/eglnative/clutter-backend-egl.c b/clutter/eglnative/clutter-backend-egl.c index 1e8b2d2ca..59fee18dc 100644 --- a/clutter/eglnative/clutter-backend-egl.c +++ b/clutter/eglnative/clutter-backend-egl.c @@ -10,7 +10,6 @@ static ClutterBackendEGL *backend_singleton = NULL; - G_DEFINE_TYPE (ClutterBackendEGL, clutter_backend_egl, CLUTTER_TYPE_BACKEND); static void @@ -61,7 +60,148 @@ static void clutter_backend_egl_ensure_context (ClutterBackend *backend, ClutterStage *stage) { - /* not doing anything since we only have one context */ + /* 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, + EGL_STENCIL_SIZE, 2, +#ifdef HAVE_COGL_GLES2 + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#else /* HAVE_COGL_GLES2 */ + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, +#endif /* HAVE_COGL_GLES2 */ + EGL_NONE + }; + + status = eglGetConfigs (backend_egl->edpy, + configs, + 2, + &config_count); + + if (status != EGL_TRUE) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "No EGL configurations found"); + return FALSE; + } + + status = eglChooseConfig (backend_egl->edpy, + cfg_attribs, + configs, + G_N_ELEMENTS (configs), + &config_count); + + if (status != EGL_TRUE) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Unable to select a valid EGL configuration"); + return FALSE; + } + + CLUTTER_NOTE (BACKEND, "Got %i configs", config_count); + + if (G_UNLIKELY (backend_egl->egl_surface != EGL_NO_SURFACE)) + { + eglDestroySurface (backend_egl->edpy, backend_egl->egl_surface); + backend_egl->egl_surface = EGL_NO_SURFACE; + } + + if (G_UNLIKELY (backend_egl->egl_context != NULL)) + { + eglDestroyContext (backend_egl->edpy, backend_egl->egl_context); + backend_egl->egl_context = NULL; + } + + backend_egl->egl_surface = + eglCreateWindowSurface (backend_egl->edpy, + configs[0], + 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; + } + +#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. + */ + 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); + + return TRUE; } static void @@ -73,32 +213,34 @@ clutter_backend_egl_redraw (ClutterBackend *backend, ClutterStageWindow *impl; impl = _clutter_stage_get_window (stage); - if (!impl) + if (impl == NULL) 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)); + clutter_actor_paint (CLUTTER_ACTOR (stage_egl->wrapper)); cogl_flush (); eglWaitGL(); - eglSwapBuffers (backend_egl->edpy, stage_egl->egl_surface); + eglSwapBuffers (backend_egl->edpy, backend_egl->egl_surface); } -static ClutterActor * +static ClutterStageWindow * clutter_backend_egl_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); - ClutterStageEGL *stage_egl; - ClutterActor *stage; + ClutterStageEGL *stage_egl; + ClutterStageWindow *stage; - if (backend_egl->stage) + if (G_UNLIKELY (backend_egl->stage != NULL)) { - g_warning ("The EGL native backend does not support multiple stages"); + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "The EGL native backend does not support multiple stages"); return backend_egl->stage; } @@ -116,7 +258,7 @@ clutter_backend_egl_create_stage (ClutterBackend *backend, static void clutter_backend_egl_init_events (ClutterBackend *backend) { - _clutter_events_init (backend); + _clutter_events_egl_init (CLUTTER_BACKEND_EGL (backend)); } static const GOptionEntry entries[] = @@ -137,10 +279,23 @@ static void clutter_backend_egl_dispose (GObject *gobject) { ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject); + ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (backend_egl->stage); - _clutter_events_uninit (CLUTTER_BACKEND (backend_egl)); + _clutter_events_egl_uninit (backend_egl); - if (backend_egl->egl_context) + if (backend_egl->stage != NULL) + { + clutter_actor_destroy (CLUTTER_ACTOR (stage_egl->wrapper)); + backend_egl->stage = NULL; + } + + 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->egl_context != NULL) { eglDestroyContext (backend_egl->edpy, backend_egl->egl_context); backend_egl->egl_context = NULL; @@ -152,7 +307,7 @@ clutter_backend_egl_dispose (GObject *gobject) backend_egl->edpy = 0; } - if (backend_egl->event_timer) + if (backend_egl->event_timer != NULL) { g_timer_destroy (backend_egl->event_timer); backend_egl->event_timer = NULL; @@ -190,6 +345,8 @@ clutter_backend_egl_get_features (ClutterBackend *backend) { ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); + g_assert (backend_egl->egl_context != NULL); + CLUTTER_NOTE (BACKEND, "Checking features\n" "GL_VENDOR: %s\n" "GL_RENDERER: %s\n" @@ -221,6 +378,7 @@ clutter_backend_egl_class_init (ClutterBackendEGLClass *klass) backend_class->post_parse = clutter_backend_egl_post_parse; backend_class->init_events = clutter_backend_egl_init_events; 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; diff --git a/clutter/eglnative/clutter-backend-egl.h b/clutter/eglnative/clutter-backend-egl.h index b802495a3..9731d7908 100644 --- a/clutter/eglnative/clutter-backend-egl.h +++ b/clutter/eglnative/clutter-backend-egl.h @@ -1,7 +1,10 @@ /* Clutter. * An OpenGL based 'interactive canvas' library. + * * Authored By Matthew Allum - * Copyright (C) 2006-2007 OpenedHand + * + * Copyright (C) 2006, 2007, 2008 OpenedHand + * Copyright (C) 2009, 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 @@ -38,7 +41,6 @@ G_BEGIN_DECLS typedef struct _ClutterBackendEGL ClutterBackendEGL; typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass; - struct _ClutterBackendEGL { ClutterBackend parent_instance; @@ -48,11 +50,15 @@ struct _ClutterBackendEGL EGLSurface egl_surface; EGLContext egl_context; - gint egl_version_major; - gint egl_version_minor; + /* from the backend */ + gint surface_width; + gint surface_height; + + gint egl_version_major; + gint egl_version_minor; /* main stage singleton */ - ClutterActor *stage; + ClutterStageWindow *stage; /* event source */ GSource *event_source; @@ -70,8 +76,8 @@ struct _ClutterBackendEGLClass GType clutter_backend_egl_get_type (void) G_GNUC_CONST; -void _clutter_events_init (ClutterBackend *backend); -void _clutter_events_uninit (ClutterBackend *backend); +void _clutter_events_egl_init (ClutterBackendEGL *backend); +void _clutter_events_egl_uninit (ClutterBackendEGL *backend); G_END_DECLS diff --git a/clutter/eglnative/clutter-event-egl.c b/clutter/eglnative/clutter-event-egl.c index dc9f39014..56732c4d4 100644 --- a/clutter/eglnative/clutter-event-egl.c +++ b/clutter/eglnative/clutter-event-egl.c @@ -47,8 +47,9 @@ struct _ClutterEventSource { GSource source; - ClutterBackend *backend; - GPollFD event_poll_fd; + ClutterBackendEGL *backend; + GPollFD event_poll_fd; + #ifdef HAVE_TSLIB struct tsdev *ts_device; #endif @@ -71,7 +72,7 @@ static GSourceFuncs event_funcs = { }; static GSource * -clutter_event_source_new (ClutterBackend *backend) +clutter_event_source_new (ClutterBackendEGL *backend) { GSource *source = g_source_new (&event_funcs, sizeof (ClutterEventSource)); ClutterEventSource *event_source = (ClutterEventSource *) source; @@ -92,36 +93,45 @@ get_backend_time (void) } void -_clutter_events_init (ClutterBackend *backend) +_clutter_events_egl_init (ClutterBackendEGL *backend_egl) { - ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); - GSource *source; ClutterEventSource *event_source; + const char *device_name; + GSource *source; CLUTTER_NOTE (EVENT, "Starting timer"); g_assert (backend_egl->event_timer != NULL); g_timer_start (backend_egl->event_timer); #ifdef HAVE_TSLIB - /* FIXME LEAK on error paths */ - source = backend_egl->event_source = clutter_event_source_new (backend); + source = backend_egl->event_source = clutter_event_source_new (backend_egl); event_source = (ClutterEventSource *) source; - event_source->ts_device = ts_open (g_getenv ("TSLIB_TSDEVICE"), 0); + device_name = g_getenv ("TSLIB_TSDEVICE"); + if (device_name == NULL || device_name[0] == '\0') + { + g_warning ("No device for TSLib has been defined; please set the " + "TSLIB_TSDEVICE environment variable to define a touch " + "screen device to be used with Clutter."); + g_source_unref (source); + return; + } + event_source->ts_device = ts_open (device_name, 0); if (event_source->ts_device) { - CLUTTER_NOTE (EVENT, "Opened '%s'", g_getenv ("TSLIB_TSDEVICE")); + CLUTTER_NOTE (EVENT, "Opened '%s'", device_name); if (ts_config (event_source->ts_device)) { - g_warning ("ts_config() failed"); + g_warning ("Closing device '%s': ts_config() failed", device_name); ts_close (event_source->ts_device); + g_source_unref (source); return; } g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS); - event_source->event_poll_fd.fd = ts_fd(event_source->ts_device); + event_source->event_poll_fd.fd = ts_fd (event_source->ts_device); event_source->event_poll_fd.events = G_IO_IN; event_sources = g_list_prepend (event_sources, event_source); @@ -131,24 +141,25 @@ _clutter_events_init (ClutterBackend *backend) g_source_attach (source, NULL); } else - g_warning ("ts_open() failed opening %s'", - g_getenv("TSLIB_TSDEVICE") ? - g_getenv("TSLIB_TSDEVICE") : "None, TSLIB_TSDEVICE not set"); -#endif + { + g_warning ("Unable to open '%s'", device_name); + g_source_unref (source); + } +#endif /* HAVE_TSLIB */ } void -_clutter_events_uninit (ClutterBackend *backend) +_clutter_events_egl_uninit (ClutterBackend *backend) { ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); - if (backend_egl->event_timer) + if (backend_egl->event_timer != NULL) { CLUTTER_NOTE (EVENT, "Stopping the timer"); g_timer_stop (backend_egl->event_timer); } - if (backend_egl->event_source) + if (backend_egl->event_source != NULL) { CLUTTER_NOTE (EVENT, "Destroying the event source"); @@ -157,9 +168,9 @@ _clutter_events_uninit (ClutterBackend *backend) #ifdef HAVE_TSLIB ts_close (event_source->ts_device); - event_sources = g_list_remove (event_sources, - backend_egl->event_source); -#endif + event_sources = g_list_remove (event_sources, backend_egl->event_source); +#endif /* HAVE_TSLIB */ + g_source_destroy (backend_egl->event_source); g_source_unref (backend_egl->event_source); backend_egl->event_source = NULL; @@ -225,7 +236,8 @@ clutter_event_dispatch (GSource *source, (ts_read(event_source->ts_device, &tsevent, 1) == 1)) { /* Avoid sending too many events which are just pressure changes. - * We dont current handle pressure in events (FIXME) and thus + * + * FIXME - We don't current handle pressure in events and thus * event_button_generate gets confused generating lots of double * and triple clicks. */ @@ -266,7 +278,7 @@ clutter_event_dispatch (GSource *source, g_queue_push_head (clutter_context->events_queue, event); } -#endif +#endif /* HAVE_TSLIB */ /* Pop an event off the queue if any */ event = clutter_event_get (); diff --git a/clutter/eglnative/clutter-stage-egl.c b/clutter/eglnative/clutter-stage-egl.c index 8d728f238..0a0dec0cd 100644 --- a/clutter/eglnative/clutter-stage-egl.c +++ b/clutter/eglnative/clutter-stage-egl.c @@ -22,241 +22,13 @@ static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL, clutter_stage_egl, - CLUTTER_TYPE_ACTOR, + G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, clutter_stage_window_iface_init)); -static void -clutter_stage_egl_show (ClutterActor *actor) -{ - CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_MAPPED); - CLUTTER_ACTOR_SET_FLAGS (CLUTTER_STAGE_EGL (actor)->wrapper, - CLUTTER_ACTOR_MAPPED); -} - -static void -clutter_stage_egl_hide (ClutterActor *actor) -{ - CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_MAPPED); - CLUTTER_ACTOR_UNSET_FLAGS (CLUTTER_STAGE_EGL (actor)->wrapper, - CLUTTER_ACTOR_MAPPED); -} - -static void -clutter_stage_egl_unrealize (ClutterActor *actor) -{ - ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor); - - CLUTTER_MARK(); - - if (CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize != NULL) - CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor); - - if (stage_egl->egl_surface) - { - eglDestroySurface (clutter_egl_display (), stage_egl->egl_surface); - stage_egl->egl_surface = EGL_NO_SURFACE; - } -} - -static void -clutter_stage_egl_realize (ClutterActor *actor) -{ - ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor); - ClutterBackendEGL *backend_egl; - 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, - EGL_STENCIL_SIZE, 2, -#ifdef HAVE_COGL_GLES2 - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, -#else /* HAVE_COGL_GLES2 */ - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, -#endif /* HAVE_COGL_GLES2 */ - EGL_NONE }; - - CLUTTER_NOTE (BACKEND, "Realizing main stage"); - - backend_egl = CLUTTER_BACKEND_EGL (clutter_get_default_backend ()); - - status = eglGetConfigs (backend_egl->edpy, - configs, - 2, - &config_count); - - if (status != EGL_TRUE) - { - g_critical ("eglGetConfigs failed"); - CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); - return; - } - - status = eglChooseConfig (backend_egl->edpy, - cfg_attribs, - configs, - G_N_ELEMENTS (configs), - &config_count); - - if (status != EGL_TRUE) - { - g_critical ("eglChooseConfig failed"); - CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); - return; - } - - CLUTTER_NOTE (BACKEND, "Got %i configs", config_count); - - if (stage_egl->egl_surface != EGL_NO_SURFACE) - { - eglDestroySurface (backend_egl->edpy, stage_egl->egl_surface); - stage_egl->egl_surface = EGL_NO_SURFACE; - } - - if (backend_egl->egl_context) - { - eglDestroyContext (backend_egl->edpy, backend_egl->egl_context); - backend_egl->egl_context = NULL; - } - - stage_egl->egl_surface = - eglCreateWindowSurface (backend_egl->edpy, - configs[0], - NULL, - NULL); - - 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; - } - - eglQuerySurface (backend_egl->edpy, - stage_egl->egl_surface, - EGL_WIDTH, - &stage_egl->surface_width); - - eglQuerySurface (backend_egl->edpy, - stage_egl->egl_surface, - EGL_HEIGHT, - &stage_egl->surface_height); - - CLUTTER_NOTE (BACKEND, "EGL surface is %ix%i", - stage_egl->surface_width, - stage_egl->surface_height); - - - if (G_UNLIKELY (backend_egl->egl_context == NULL)) - { -#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_critical ("Unable to create a suitable EGL context"); - - CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); - return; - } - - CLUTTER_NOTE (GL, "Created EGL Context"); - } - - CLUTTER_NOTE (BACKEND, "Setting context"); - - /* eglnative can have only one stage */ - status = eglMakeCurrent (backend_egl->edpy, - stage_egl->egl_surface, - stage_egl->egl_surface, - backend_egl->egl_context); - - if (status != EGL_TRUE) - { - g_critical ("eglMakeCurrent failed"); - - CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); - return; - } - - /* since we only have one size and it cannot change, we - * just need to update the GL viewport now that we have - * been realized - */ - CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_ACTOR_SYNC_MATRICES); -} - -static void -clutter_stage_egl_get_preferred_width (ClutterActor *self, - gfloat for_height, - gfloat *min_width_p, - gfloat *natural_width_p) -{ - ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self); - - if (min_width_p) - *min_width_p = CLUTTER_UNITS_FROM_DEVICE (stage_egl->surface_width); - - if (natural_width_p) - *natural_width_p = CLUTTER_UNITS_FROM_DEVICE (stage_egl->surface_width); -} - -static void -clutter_stage_egl_get_preferred_height (ClutterActor *self, - gfloat for_width, - gfloat *min_height_p, - gfloat *natural_height_p) -{ - ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self); - - if (min_height_p) - *min_height_p = CLUTTER_UNITS_FROM_DEVICE (stage_egl->surface_height); - - if (natural_height_p) - *natural_height_p = CLUTTER_UNITS_FROM_DEVICE (stage_egl->surface_height); -} - -static void -clutter_stage_egl_dispose (GObject *gobject) -{ - ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (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); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - gobject_class->dispose = clutter_stage_egl_dispose; - - actor_class->show = clutter_stage_egl_show; - actor_class->hide = clutter_stage_egl_hide; - actor_class->realize = clutter_stage_egl_realize; - actor_class->unrealize = clutter_stage_egl_unrealize; - actor_class->get_preferred_width = clutter_stage_egl_get_preferred_width; - actor_class->get_preferred_height = clutter_stage_egl_get_preferred_height; } static void @@ -267,18 +39,91 @@ clutter_stage_egl_set_fullscreen (ClutterStageWindow *stage_window, 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_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) +{ + 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) +{ +} + static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface) { iface->set_fullscreen = clutter_stage_egl_set_fullscreen; - iface->set_title = NULL; + 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; } static void diff --git a/clutter/eglnative/clutter-stage-egl.h b/clutter/eglnative/clutter-stage-egl.h index 9141d67e0..49a6c798a 100644 --- a/clutter/eglnative/clutter-stage-egl.h +++ b/clutter/eglnative/clutter-stage-egl.h @@ -21,14 +21,10 @@ struct _ClutterStageEGL { ClutterActor parent_instance; - /* from the backend */ - gint surface_width; - gint surface_height; - - EGLSurface egl_surface; - /* the stage wrapper */ ClutterStage *wrapper; + + /* back pointer to the backend */ ClutterBackendEGL *backend; }; From a2573ad2ad39931d2a817d4585d87b70c3f86526 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 1 Mar 2010 11:38:41 +0000 Subject: [PATCH 2/2] eglnative: Add CLUTTER_FB_DEVICE Some EGL drivers for embedded devices require a specific framebuffer device to be opened and passed to eglCreateWindowSurface(). Since it's optional, we can provide an environment variabled called CLUTTER_FB_DEVICE that can be used to specify the path of the device to be opened. http://bugzilla.openedhand.com/show_bug.cgi?id=1997 --- clutter/eglnative/clutter-backend-egl.c | 59 ++++++++++++++++++++++--- clutter/eglnative/clutter-backend-egl.h | 3 ++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/clutter/eglnative/clutter-backend-egl.c b/clutter/eglnative/clutter-backend-egl.c index 59fee18dc..d3c992e03 100644 --- a/clutter/eglnative/clutter-backend-egl.c +++ b/clutter/eglnative/clutter-backend-egl.c @@ -2,14 +2,21 @@ #include "config.h" #endif +#include +#include +#include + #include "clutter-backend-egl.h" #include "clutter-stage-egl.h" + #include "../clutter-private.h" #include "../clutter-main.h" #include "../clutter-debug.h" static ClutterBackendEGL *backend_singleton = NULL; +static const gchar *clutter_fb_device = NULL; + G_DEFINE_TYPE (ClutterBackendEGL, clutter_backend_egl, CLUTTER_TYPE_BACKEND); static void @@ -23,6 +30,12 @@ static gboolean clutter_backend_egl_pre_parse (ClutterBackend *backend, GError **error) { + const gchar *env_string; + + env_string = g_getenv ("CLUTTER_FB_DEVICE"); + if (env_string != NULL && env_string[0] != '\0') + clutter_fb_device = g_strdup (env_string); + return TRUE; } @@ -130,11 +143,39 @@ clutter_backend_egl_create_context (ClutterBackend *backend, backend_egl->egl_context = NULL; } - backend_egl->egl_surface = - eglCreateWindowSurface (backend_egl->edpy, - configs[0], - NULL, - NULL); + 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 (backend_egl->edpy, + configs[0], + (NativeWindowType) backend_egl->fb_device_id, + NULL); + } + else + { + backend_egl->egl_surface = + eglCreateWindowSurface (backend_egl->edpy, + configs[0], + NULL, + NULL); + } if (backend_egl->egl_surface == EGL_NO_SURFACE) { @@ -295,6 +336,12 @@ clutter_backend_egl_dispose (GObject *gobject) backend_egl->egl_surface = EGL_NO_SURFACE; } + 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) { eglDestroyContext (backend_egl->edpy, backend_egl->egl_context); @@ -394,6 +441,8 @@ clutter_backend_egl_init (ClutterBackendEGL *backend_egl) clutter_backend_set_double_click_distance (backend, 5); backend_egl->event_timer = g_timer_new (); + + backend_egl->fb_device_id = -1; } GType diff --git a/clutter/eglnative/clutter-backend-egl.h b/clutter/eglnative/clutter-backend-egl.h index 9731d7908..deb4e8a41 100644 --- a/clutter/eglnative/clutter-backend-egl.h +++ b/clutter/eglnative/clutter-backend-egl.h @@ -66,6 +66,9 @@ struct _ClutterBackendEGL /* event timer */ GTimer *event_timer; + /* FB device */ + gint fb_device_id; + /*< private >*/ };