diff --git a/ChangeLog b/ChangeLog index 21e1c2ca7..d443f4681 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2007-05-02 Matthew Allum + + * clutter/Makefile.am: + * clutter/clutter-stage.c: + * clutter/sdl/Makefile.am: + * clutter/sdl/clutter-backend-sdl.c: + * clutter/sdl/clutter-backend-sdl.h: + * clutter/sdl/clutter-event-sdl.c: + * clutter/sdl/clutter-sdl.h: + * clutter/sdl/clutter-stage-sdl.c: + * clutter/sdl/clutter-stage-sdl.h: + * configure.ac: + Add a basic SDL based backend. Lacks real input event handling + (translation) as yet. + Also allows for clutter to be built against dgles. + 2007-05-02 Matthew Allum * clutter/clutter-actor.c: diff --git a/clutter/Makefile.am b/clutter/Makefile.am index ee2ba3679..179792153 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -2,7 +2,7 @@ NULL = SUBDIRS = cogl pango $(clutterbackend) -DIST_SUBDIRS = pango glx egl cogl +DIST_SUBDIRS = pango glx egl cogl sdl target = $(clutterbackend) diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index 8fb166663..453e496ba 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -120,8 +120,8 @@ typedef void (* ClutterEventFunc) (ClutterEvent *event, /* the event dispatcher function */ extern ClutterEventFunc _clutter_event_func; -extern gpointer _clutter_event_data; -extern GDestroyNotify _clutter_event_destroy; +extern gpointer _clutter_event_data; +extern GDestroyNotify _clutter_event_destroy; void _clutter_set_events_handler (ClutterEventFunc func, gpointer data, diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index bf93a3100..868a496b5 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -619,11 +619,13 @@ clutter_stage_snapshot (ClutterStage *stage, void _clutter_stage_sync_viewport (ClutterStage *stage) { + /* FIXME: + * Something needs to be done with this func, apps may need to + * overide it and its need better integration into the backend. + */ ClutterActor *actor; gint width, height; - /* FIXME: SHould be able to completely overide this func.. */ - g_return_if_fail (CLUTTER_IS_STAGE (stage)); actor = CLUTTER_ACTOR (stage); diff --git a/clutter/sdl/Makefile.am b/clutter/sdl/Makefile.am new file mode 100644 index 000000000..9dc13ff8e --- /dev/null +++ b/clutter/sdl/Makefile.am @@ -0,0 +1,23 @@ +libclutterincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/clutter +libclutterinclude_HEADERS = clutter-sdl.h + +INCLUDES = \ + -DG_LOG_DOMAIN=\"ClutterSDL\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/clutter/cogl \ + -I$(top_srcdir)/clutter/cogl/@CLUTTER_COGL@ \ + $(CLUTTER_CFLAGS) \ + $(CLUTTER_DEBUG_CFLAGS) \ + $(GCC_FLAGS) + +LDADD = $(CLUTTER_LIBS) + +noinst_LTLIBRARIES = libclutter-sdl.la + +libclutter_sdl_la_SOURCES = \ + clutter-backend-sdl.h \ + clutter-backend-sdl.c \ + clutter-event-sdl.c \ + clutter-stage-sdl.h \ + clutter-stage-sdl.c \ + clutter-sdl.h diff --git a/clutter/sdl/clutter-backend-sdl.c b/clutter/sdl/clutter-backend-sdl.c new file mode 100644 index 000000000..1cab47652 --- /dev/null +++ b/clutter/sdl/clutter-backend-sdl.c @@ -0,0 +1,215 @@ +#include "config.h" + +#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) +{ + ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend); + 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; + } + + return TRUE; +} + +static gboolean +clutter_backend_sdl_init_stage (ClutterBackend *backend, + GError **error) +{ + ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend); + + if (!backend_sdl->stage) + { + ClutterStageSDL *stage_sdl; + ClutterActor *stage; + + stage = g_object_new (CLUTTER_TYPE_STAGE_SDL, NULL); + + /* copy backend data into the stage */ + stage_sdl = CLUTTER_STAGE_SDL (stage); + + g_object_set_data (G_OBJECT (stage), "clutter-backend", backend); + + backend_sdl->stage = g_object_ref_sink (stage); + } + + clutter_actor_realize (backend_sdl->stage); + + if (!CLUTTER_ACTOR_IS_REALIZED (backend_sdl->stage)) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_INTERNAL, + "Unable to realize the main stage"); + return FALSE; + } + + return TRUE; +} + +static void +clutter_backend_sdl_init_events (ClutterBackend *backend) +{ + _clutter_events_init (backend); + +} + +static const GOptionEntry entries[] = +{ + { NULL } +}; + + +static void +clutter_backend_sdl_add_options (ClutterBackend *backend, + GOptionGroup *group) +{ + g_option_group_add_entries (group, entries); +} + +static ClutterActor * +clutter_backend_sdl_get_stage (ClutterBackend *backend) +{ + ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend); + + return backend_sdl->stage; +} + +static void +clutter_backend_sdl_finalize (GObject *gobject) +{ + ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (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) + { + g_object_unref (backend_sdl->stage); + backend_sdl->stage = 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 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_stage = clutter_backend_sdl_init_stage; + backend_class->init_events = clutter_backend_sdl_init_events; + backend_class->get_stage = clutter_backend_sdl_get_stage; + backend_class->add_options = clutter_backend_sdl_add_options; +} + +static void +clutter_backend_sdl_init (ClutterBackendSDL *backend_sdl) +{ + ClutterBackend *backend = CLUTTER_BACKEND (backend_sdl); + + backend->events_queue = g_queue_new (); + + backend->button_click_time[0] = backend->button_click_time[1] = 0; + backend->button_number[0] = backend->button_number[1] = -1; + backend->button_x[0] = backend->button_x[1] = 0; + backend->button_y[0] = backend->button_y[1] = 0; + + backend->res_width = backend->res_height = -1; + backend->mm_width = backend->mm_height = -1; + backend->screen_num = 0; + backend->n_screens = 0; + + backend->double_click_time = 250; + backend->double_click_distance = 5; +} + +GType +_clutter_backend_impl_get_type (void) +{ + return clutter_backend_sdl_get_type (); +} + diff --git a/clutter/sdl/clutter-backend-sdl.h b/clutter/sdl/clutter-backend-sdl.h new file mode 100644 index 000000000..bc9de1e31 --- /dev/null +++ b/clutter/sdl/clutter-backend-sdl.h @@ -0,0 +1,63 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CLUTTER_BACKEND_SDL_H__ +#define __CLUTTER_BACKEND_SDL_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BACKEND_SDL (clutter_backend_sdl_get_type ()) +#define CLUTTER_BACKEND_SDL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_SDL, ClutterBackendSDL)) +#define CLUTTER_IS_BACKEND_SDL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_SDL)) +#define CLUTTER_BACKEND_SDL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_SDL, ClutterBackendSDLClass)) +#define CLUTTER_IS_BACKEND_SDL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_SDL)) +#define CLUTTER_BACKEND_SDL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_SDL, ClutterBackendSDLClass)) + +typedef struct _ClutterBackendSDL ClutterBackendSDL; +typedef struct _ClutterBackendSDLClass ClutterBackendSDLClass; + +struct _ClutterBackendSDL +{ + ClutterBackend parent_instance; + + /* main stage singleton */ + ClutterActor *stage; + + /* event source */ + GSource *event_source; + + /*< private >*/ +}; + +struct _ClutterBackendSDLClass +{ + ClutterBackendClass parent_class; +}; + +GType clutter_backend_sdl_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __CLUTTER_BACKEND_SDL_H__ */ diff --git a/clutter/sdl/clutter-event-sdl.c b/clutter/sdl/clutter-event-sdl.c new file mode 100644 index 000000000..5d1fb22b0 --- /dev/null +++ b/clutter/sdl/clutter-event-sdl.c @@ -0,0 +1,186 @@ +/* Clutter. + * An OpenGL based 'interactive canvas' library. + * Authored By Matthew Allum + * Copyright (C) 2006-2007 OpenedHand + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "clutter-stage-sdl.h" +#include "clutter-backend-sdl.h" +#include "clutter-sdl.h" + +#include "../clutter-backend.h" +#include "../clutter-event.h" +#include "../clutter-private.h" +#include "../clutter-debug.h" +#include "../clutter-main.h" + +#include +#include + +typedef struct _ClutterEventSource ClutterEventSource; + +struct _ClutterEventSource +{ + GSource source; + + ClutterBackend *backend; +}; + +static gboolean clutter_event_prepare (GSource *source, + gint *timeout); +static gboolean clutter_event_check (GSource *source); +static gboolean clutter_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data); + +static GList *event_sources = NULL; + +static GSourceFuncs event_funcs = { + clutter_event_prepare, + clutter_event_check, + clutter_event_dispatch, + NULL +}; + +static GSource * +clutter_event_source_new (ClutterBackend *backend) +{ + GSource *source = g_source_new (&event_funcs, sizeof (ClutterEventSource)); + ClutterEventSource *event_source = (ClutterEventSource *) source; + + event_source->backend = backend; + + return source; +} + +void +_clutter_events_init (ClutterBackend *backend) +{ + GSource *source; + ClutterEventSource *event_source; + ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend); + + source = backend_sdl->event_source = clutter_event_source_new (backend); + event_source = (ClutterEventSource *) source; + g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS); + + event_sources = g_list_prepend (event_sources, event_source); + + g_source_set_can_recurse (source, TRUE); + g_source_attach (source, NULL); +} + +void +_clutter_events_uninit (ClutterBackend *backend) +{ + ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend); + + if (backend_sdl->event_source) + { + CLUTTER_NOTE (EVENT, "Destroying the event source"); + + event_sources = g_list_remove (event_sources, + backend_sdl->event_source); + + g_source_destroy (backend_sdl->event_source); + g_source_unref (backend_sdl->event_source); + backend_sdl->event_source = NULL; + } +} + +/** + * clutter_events_pending: + * + * FIXME + * + * Return value: FIXME + * + * Since: 0.4 + */ +gboolean +clutter_events_pending (void) +{ + return FALSE; +} + +static gboolean +clutter_event_prepare (GSource *source, + gint *timeout) +{ + return FALSE; +} + +static gboolean +clutter_event_check (GSource *source) +{ + SDL_Event events; + + /* Pump SDL */ + SDL_PumpEvents(); + + return SDL_PeepEvents(&events, 1, SDL_PEEKEVENT, SDL_ALLEVENTS); +} + +void +_clutter_events_queue (ClutterBackend *backend) +{ + /* FIXME: Implement */ +} + + +static gboolean +clutter_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + ClutterBackend *backend = ((ClutterEventSource *) source)->backend; + SDL_Event sdl_event; + ClutterEvent *event = NULL; + + while (SDL_PollEvent(&sdl_event)) + { + /* FIXME: essentially translate events and push them onto the queue + * below will then pop them out via _clutter_events_queue. + */ + if (sdl_event.type == SDL_QUIT) + { + SDL_Quit(); + exit(0); + } + + } + + return TRUE; + + event = _clutter_event_queue_pop (backend); + + if (event) + { + if (_clutter_event_func) + { + CLUTTER_NOTE (EVENT, "Dispatching _clutter_event_func"); + (* _clutter_event_func) (event, _clutter_event_data); + } + + clutter_event_free (event); + } + + return TRUE; +} diff --git a/clutter/sdl/clutter-sdl.h b/clutter/sdl/clutter-sdl.h new file mode 100644 index 000000000..508dbcd1d --- /dev/null +++ b/clutter/sdl/clutter-sdl.h @@ -0,0 +1,39 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2006 OpenedHand + * + * 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CLUTTER_SDL_H__ +#define __CLUTTER_SDL_H__ + +#include +#include + +#include + +G_BEGIN_DECLS + + +G_END_DECLS + +#endif /* __CLUTTER_SDL_H__ */ diff --git a/clutter/sdl/clutter-stage-sdl.c b/clutter/sdl/clutter-stage-sdl.c new file mode 100644 index 000000000..cfa7900fb --- /dev/null +++ b/clutter/sdl/clutter-stage-sdl.c @@ -0,0 +1,249 @@ +#include "config.h" + +#include "clutter-stage-sdl.h" +#include "clutter-sdl.h" + +#include "../clutter-main.h" +#include "../clutter-feature.h" +#include "../clutter-color.h" +#include "../clutter-util.h" +#include "../clutter-event.h" +#include "../clutter-enum-types.h" +#include "../clutter-private.h" +#include "../clutter-debug.h" + +#include "cogl.h" + +G_DEFINE_TYPE (ClutterStageSDL, clutter_stage_sdl, CLUTTER_TYPE_STAGE); + +static void +clutter_stage_sdl_show (ClutterActor *actor) +{ + ; +} + +static void +clutter_stage_sdl_hide (ClutterActor *actor) +{ + /* No way to easily unmap SDL window ? */ + ; +} + +static void +clutter_stage_sdl_unrealize (ClutterActor *actor) +{ + ; +} + +static void +clutter_stage_sdl_realize (ClutterActor *actor) +{ + ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (actor); + + gboolean is_offscreen, is_fullscreen; + + CLUTTER_NOTE (BACKEND, "Realizing main stage"); + + g_object_get (actor, "offscreen", &is_offscreen, NULL); + g_object_get (actor, "fullscreen", &is_fullscreen, NULL); + + if (G_LIKELY (!is_offscreen)) + { + gint flags = SDL_OPENGL; + + if (is_fullscreen) flags |= SDL_FULLSCREEN; + + SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 0); + + if (SDL_SetVideoMode(stage_sdl->win_width, + stage_sdl->win_height, + 0, flags) == NULL) + { + CLUTTER_NOTE (BACKEND, "SDL appears not to handle this mode - %s", + SDL_GetError()); + CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); + return; + } + } + else + { + /* FIXME */ + g_warning("SDL Backend does not yet support offscreen rendering\n"); + CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); + return; + } + + _clutter_stage_sync_viewport (CLUTTER_STAGE (stage_sdl)); +} + +static void +clutter_stage_sdl_paint (ClutterActor *self) +{ + ClutterStage *stage = CLUTTER_STAGE (self); + ClutterColor stage_color; + static GTimer *timer = NULL; + static guint timer_n_frames = 0; + + CLUTTER_NOTE (PAINT, " Redraw enter"); + + if (clutter_get_show_fps ()) + { + if (!timer) + timer = g_timer_new (); + } + + clutter_stage_get_color (stage, &stage_color); + + cogl_paint_init (&stage_color); + + /* Basically call up to ClutterGroup paint here */ + CLUTTER_ACTOR_CLASS (clutter_stage_sdl_parent_class)->paint (self); + + /* Why this paint is done in backend as likely GL windowing system + * specific calls, like swapping buffers. + */ + + SDL_GL_SwapBuffers(); + + if (clutter_get_show_fps ()) + { + timer_n_frames++; + + if (g_timer_elapsed (timer, NULL) >= 1.0) + { + g_print ("*** FPS: %i ***\n", timer_n_frames); + timer_n_frames = 0; + g_timer_start (timer); + } + } + + CLUTTER_NOTE (PAINT, " Redraw leave"); +} + +static void +clutter_stage_sdl_allocate_coords (ClutterActor *self, + ClutterActorBox *box) +{ + ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (self); + + box->x1 = box->y1 = 0; + box->x2 = box->x1 + stage_sdl->win_width; + box->y2 = box->y1 + stage_sdl->win_height; +} + +static void +clutter_stage_sdl_request_coords (ClutterActor *self, + ClutterActorBox *box) +{ + ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (self); + gint new_width, new_height; + + /* FIXME: some how have X configure_notfiys call this ? */ + new_width = ABS (box->x2 - box->x1); + new_height = ABS (box->y2 - box->y1); + + if (new_width != stage_sdl->win_width || + new_height != stage_sdl->win_height) + { + if (SDL_SetVideoMode(new_width, + new_height, + 0, SDL_OPENGL) == NULL) + { + box->x2 = box->x1 + stage_sdl->win_width; + box->y2 = box->y1 + stage_sdl->win_height; + + /* Failed */ + return; + } + + stage_sdl->win_width = new_width; + stage_sdl->win_height = new_height; + + _clutter_stage_sync_viewport (CLUTTER_STAGE (stage_sdl)); + } +} + +static void +clutter_stage_sdl_set_fullscreen (ClutterStage *stage, + gboolean fullscreen) +{ + ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (stage); + int flags = SDL_OPENGL; + + if (fullscreen) flags |= SDL_FULLSCREEN; + + SDL_SetVideoMode(stage_sdl->win_width, + stage_sdl->win_height, + 0, flags); +} + +static void +clutter_stage_sdl_set_cursor_visible (ClutterStage *stage, + gboolean show_cursor) +{ + SDL_ShowCursor(show_cursor); +} + +static void +clutter_stage_sdl_set_offscreen (ClutterStage *stage, + gboolean offscreen) +{ + g_warning ("Stage of type `%s' do not support ClutterStage::set_offscreen", + G_OBJECT_TYPE_NAME (stage)); +} + +static void +clutter_stage_sdl_draw_to_pixbuf (ClutterStage *stage, + GdkPixbuf *dest, + gint x, + gint y, + gint width, + gint height) +{ + g_warning ("Stage of type `%s' do not support ClutterStage::draw_to_pixbuf", + G_OBJECT_TYPE_NAME (stage)); +} + +static void +clutter_stage_sdl_dispose (GObject *gobject) +{ + ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (gobject); + + clutter_actor_unrealize (CLUTTER_ACTOR (stage_sdl)); + + G_OBJECT_CLASS (clutter_stage_sdl_parent_class)->dispose (gobject); +} + +static void +clutter_stage_sdl_class_init (ClutterStageSDLClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); + ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass); + + gobject_class->dispose = clutter_stage_sdl_dispose; + + actor_class->show = clutter_stage_sdl_show; + actor_class->hide = clutter_stage_sdl_hide; + actor_class->realize = clutter_stage_sdl_realize; + actor_class->unrealize = clutter_stage_sdl_unrealize; + actor_class->paint = clutter_stage_sdl_paint; + actor_class->request_coords = clutter_stage_sdl_request_coords; + actor_class->allocate_coords = clutter_stage_sdl_allocate_coords; + + stage_class->set_fullscreen = clutter_stage_sdl_set_fullscreen; + stage_class->set_cursor_visible = clutter_stage_sdl_set_cursor_visible; + stage_class->set_offscreen = clutter_stage_sdl_set_offscreen; + stage_class->draw_to_pixbuf = clutter_stage_sdl_draw_to_pixbuf; +} + +static void +clutter_stage_sdl_init (ClutterStageSDL *stage) +{ + stage->win_width = 640; + stage->win_height = 480; +} + diff --git a/clutter/sdl/clutter-stage-sdl.h b/clutter/sdl/clutter-stage-sdl.h new file mode 100644 index 000000000..94fda29a7 --- /dev/null +++ b/clutter/sdl/clutter-stage-sdl.h @@ -0,0 +1,32 @@ +#ifndef __CLUTTER_STAGE_SDL_H__ +#define __CLUTTER_STAGE_SDL_H__ + +#include +#include + +#define CLUTTER_TYPE_STAGE_SDL (clutter_stage_sdl_get_type ()) +#define CLUTTER_STAGE_SDL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_SDL, ClutterStageSDL)) +#define CLUTTER_IS_STAGE_SDL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_SDL)) +#define CLUTTER_STAGE_SDL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_SDL, ClutterStageSDLClass)) +#define CLUTTER_IS_STAGE_SDL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_SDL)) +#define CLUTTER_STAGE_SDL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_SDL, ClutterStageSDLClass)) + +typedef struct _ClutterStageSDL ClutterStageSDL; +typedef struct _ClutterStageSDLClass ClutterStageSDLClass; + +struct _ClutterStageSDL +{ + ClutterStage parent_instance; + + gint win_width; + gint win_height; +}; + +struct _ClutterStageSDLClass +{ + ClutterStageClass parent_class; +}; + +GType clutter_stage_sdl_get_type (void) G_GNUC_CONST; + +#endif /* __CLUTTER_STAGE_SDL_H__ */ diff --git a/configure.ac b/configure.ac index ca8a79bdd..960ab405f 100644 --- a/configure.ac +++ b/configure.ac @@ -95,14 +95,63 @@ fi clutterbackend=glx AC_ARG_WITH([flavour], - AC_HELP_STRING([--with-flavour=@<:@glx/egl@:>@], + AC_HELP_STRING([--with-flavour=@<:@glx/egl/sdl@:>@], [Select the Clutter backend]), clutterbackend=$with_flavour) -AC_SUBST([clutterbackend]) - case $clutterbackend in + sdl) + CLUTTER_FLAVOUR="sdl" + AC_DEFINE([HAVE_CLUTTER_SDL], 1, [Have the SDL backend]) + + CLUTTER_COGL="gl" + AC_DEFINE([HAVE_COGL_GL], 1, [Have GL for rendering]) + + AC_PATH_PROG(SDL_CONFIG, sdl-config) + if test "x$SDL_CONFIG" = "x"; then + AC_MSG_ERROR([[No sdl-config binary found in path and SDL flavour requested.]]) + else + SDL_CFLAGS=`$SDL_CONFIG --cflags` + SDL_LIBS=`$SDL_CONFIG --libs` + AC_CHECK_HEADERS([GL/gl.h],,[AC_MSG_ERROR([Unable to locate required GL headers])]) + AC_CHECK_LIB(GL, glEnable, HAVE_LIBGL=yes, HAVE_LIBGL=no) + if test "x$HAVE_LIBGL" = "xno"; then + AC_MSG_ERROR([libGL not found]); + fi + SDL_LIBS="$SDL_LIBS -lGL" + fi + ;; + + sdles) +# +# Temp Hack for building with dgles (runs atop SDL) +# + clutterbackend=sdl + CLUTTER_FLAVOUR="sdl" + AC_DEFINE([HAVE_CLUTTER_SDL], 1, [Have the SDL backend]) + + CLUTTER_COGL="gles" + AC_DEFINE([HAVE_COGL_GLES], 1, [Have GL for rendering]) + + AC_PATH_PROG(SDL_CONFIG, sdl-config) + if test "x$SDL_CONFIG" = "x"; then + AC_MSG_ERROR([[No sdl-config binary found in path and SDL flavour requested.]]) + else + SDL_CFLAGS=`$SDL_CONFIG --cflags` + SDL_LIBS=`$SDL_CONFIG --libs` + fi + +# FIXME: Obviously we need some real detection here + SDL_CFLAGS="-I/usr/local/include $SDL_CFLAGS" + SDL_LIBS="-L/usr/local/lib -lGLES_CM $SDL_LIBS" + + AC_MSG_WARN([]) + AC_MSG_WARN([The SDL/Open GL ES Backend is purely for experimental]) + AC_MSG_WARN([and devlopment purposes. Do not use in production code!!]) + AC_MSG_WARN([]) + ;; + glx) CLUTTER_FLAVOUR="glx" @@ -114,9 +163,9 @@ case $clutterbackend in AC_CHECK_HEADERS([GL/gl.h GL/glx.h],, [AC_MSG_ERROR([Unable to locate required GL headers])]) - AC_CHECK_LIB(GL, glXCreateContext, HAVE_LIBGL=yes, HAVE_LIBGL=no) + AC_CHECK_LIB(GL, glXCreateContext, HAVE_LIBGLX=yes, HAVE_LIBGLX=no) - if test "x$HAVE_LIBGL" = "xno"; then + if test "x$HAVE_LIBGLX" = "xno"; then AC_MSG_ERROR([GLX not found and GLX backend requested]); fi @@ -141,9 +190,6 @@ case $clutterbackend in EGL_LIBS="$EGL_LIBS $X11_LIBS" EGL_CFLAGS="$EGL_CFLAGS $X11_CFLAGS" -# Hack for building against dgles -# EGL_CFLAGS="-I/usr/local/include -I/usr/local/include/GLES $X11_CFLAGS" -# EGL_LIBS="-L/usr/local/lib -lGLES_CM -legl -lSDL $X11_LIBS" ;; *) AC_MSG_ERROR([Invalid backend for Clutter: use glx or egl]) @@ -151,6 +197,7 @@ case $clutterbackend in esac +AC_SUBST([clutterbackend]) AC_SUBST(CLUTTER_FLAVOUR) AC_SUBST(CLUTTER_COGL) @@ -210,8 +257,8 @@ dnl ======================================================================== AC_SUBST(GCC_FLAGS) -CLUTTER_CFLAGS="$EGL_CFLAGS $GLX_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_FIXED_CFLAGS" -CLUTTER_LIBS="$EGL_LIBS $GLX_LIBS $CLUTTER_DEPS_LIBS" +CLUTTER_CFLAGS="$SDL_CFLAGS $EGL_CFLAGS $GLX_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_FIXED_CFLAGS" +CLUTTER_LIBS="$SDL_LIBS $EGL_LIBS $GLX_LIBS $CLUTTER_DEPS_LIBS" AC_SUBST(CLUTTER_CFLAGS) AC_SUBST(CLUTTER_LIBS) @@ -223,6 +270,7 @@ AC_CONFIG_FILES([ clutter/clutter-version.h clutter/glx/Makefile clutter/egl/Makefile + clutter/sdl/Makefile clutter/cogl/Makefile clutter/cogl/gl/Makefile clutter/cogl/gles/Makefile