#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "clutter-backend-sdl.h" #include "clutter-stage-sdl.h" #include "../clutter-private.h" #include "../clutter-main.h" #include "../clutter-debug.h" static ClutterBackendSDL *backend_singleton = NULL; G_DEFINE_TYPE (ClutterBackendSDL, clutter_backend_sdl, CLUTTER_TYPE_BACKEND); static gboolean clutter_backend_sdl_pre_parse (ClutterBackend *backend, GError **error) { return TRUE; } static gboolean clutter_backend_sdl_post_parse (ClutterBackend *backend, GError **error) { int err; if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, "Unable to Initialize SDL"); return FALSE; } #if defined(WIN32) err = SDL_GL_LoadLibrary ("opengl32.dll"); #elif defined(__linux__) || defined(__FreeBSD__) err = SDL_GL_LoadLibrary ("libGL.so"); #else #error Your platform is not supported err = 1; #endif if (err != 0) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, SDL_GetError ()); return FALSE; } CLUTTER_NOTE (BACKEND, "SDL successfully initialized"); return TRUE; } static void clutter_backend_sdl_ensure_context (ClutterBackend *backend, ClutterStage *stage) { /* no context to ensure */ } static void clutter_backend_sdl_redraw (ClutterBackend *backend, ClutterStage *stage) { clutter_actor_paint (CLUTTER_ACTOR (stage)); SDL_GL_SwapBuffers(); } static ClutterActor * clutter_backend_sdl_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend); ClutterStageSDL *stage_sdl; ClutterActor *stage; if (backend_sdl->stage) { g_warning ("The SDL backend does not support multiple stages"); return CLUTTER_ACTOR (backend_sdl->stage); } stage = g_object_new (CLUTTER_TYPE_STAGE_SDL, NULL); /* copy backend data into the stage */ stage_sdl = CLUTTER_STAGE_SDL (stage); stage_sdl->wrapper = wrapper; _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; } static void clutter_backend_sdl_init_events (ClutterBackend *backend) { _clutter_events_init (backend); } static void clutter_backend_sdl_finalize (GObject *gobject) { SDL_Quit(); if (backend_singleton) backend_singleton = NULL; G_OBJECT_CLASS (clutter_backend_sdl_parent_class)->finalize (gobject); } static void clutter_backend_sdl_dispose (GObject *gobject) { ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (gobject); _clutter_events_uninit (CLUTTER_BACKEND (backend_sdl)); if (backend_sdl->stage) { clutter_actor_destroy (CLUTTER_ACTOR (backend_sdl->stage)); backend_sdl->stage = NULL; } if (backend_sdl->timer) { g_timer_destroy (backend_sdl->timer); backend_sdl->timer = NULL; } G_OBJECT_CLASS (clutter_backend_sdl_parent_class)->dispose (gobject); } static GObject * clutter_backend_sdl_constructor (GType gtype, guint n_params, GObjectConstructParam *params) { GObjectClass *parent_class; GObject *retval; if (!backend_singleton) { parent_class = G_OBJECT_CLASS (clutter_backend_sdl_parent_class); retval = parent_class->constructor (gtype, n_params, params); backend_singleton = CLUTTER_BACKEND_SDL (retval); return retval; } 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_sdl_get_features (ClutterBackend *backend) { return CLUTTER_FEATURE_STAGE_CURSOR; } static void clutter_backend_sdl_class_init (ClutterBackendSDLClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); gobject_class->constructor = clutter_backend_sdl_constructor; gobject_class->dispose = clutter_backend_sdl_dispose; gobject_class->finalize = clutter_backend_sdl_finalize; backend_class->pre_parse = clutter_backend_sdl_pre_parse; backend_class->post_parse = clutter_backend_sdl_post_parse; backend_class->init_events = clutter_backend_sdl_init_events; backend_class->create_stage = clutter_backend_sdl_create_stage; backend_class->ensure_context = clutter_backend_sdl_ensure_context; backend_class->redraw = clutter_backend_sdl_redraw; backend_class->get_features = clutter_backend_sdl_get_features; } static void clutter_backend_sdl_init (ClutterBackendSDL *backend_sdl) { ClutterBackend *backend = CLUTTER_BACKEND (backend_sdl); clutter_backend_set_resolution (backend, 96.0); clutter_backend_set_double_click_time (backend, 250); clutter_backend_set_double_click_distance (backend, 5); backend_sdl->timer = g_timer_new (); } GType _clutter_backend_impl_get_type (void) { return clutter_backend_sdl_get_type (); }