diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index a99ccd8e7..d77849753 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -449,9 +449,11 @@ cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-egl-private.h
endif
if SUPPORT_SDL
+cogl_experimental_h += $(srcdir)/cogl-sdl.h
cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-sdl-private.h \
- $(srcdir)/winsys/cogl-winsys-sdl.c
+ $(srcdir)/winsys/cogl-winsys-sdl.c \
+ $(srcdir)/cogl-sdl.c
endif
EXTRA_DIST += stb_image.c
diff --git a/cogl/cogl-renderer-private.h b/cogl/cogl-renderer-private.h
index 11dc0bb07..0d119cb81 100644
--- a/cogl/cogl-renderer-private.h
+++ b/cogl/cogl-renderer-private.h
@@ -62,6 +62,12 @@ struct _CoglRenderer
struct wl_compositor *foreign_wayland_compositor;
struct wl_shell *foreign_wayland_shell;
#endif
+
+#ifdef COGL_HAS_SDL_SUPPORT
+ gboolean sdl_event_type_set;
+ guint8 sdl_event_type;
+#endif
+
/* List of callback functions that will be given every native event */
GSList *event_filters;
void *winsys;
diff --git a/cogl/cogl-sdl.c b/cogl/cogl-sdl.c
new file mode 100644
index 000000000..97795932c
--- /dev/null
+++ b/cogl/cogl-sdl.c
@@ -0,0 +1,85 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2012 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
+ * .
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl-sdl.h"
+#include "cogl-context-private.h"
+#include "cogl-renderer-private.h"
+
+void
+cogl_sdl_renderer_set_event_type (CoglRenderer *renderer, guint8 type)
+{
+ renderer->sdl_event_type_set = TRUE;
+ renderer->sdl_event_type = type;
+}
+
+guint8
+cogl_sdl_renderer_get_event_type (CoglRenderer *renderer)
+{
+ _COGL_RETURN_VAL_IF_FAIL (renderer->sdl_event_type_set, SDL_USEREVENT);
+
+ return renderer->sdl_event_type;
+}
+
+CoglContext *
+cogl_sdl_context_new (guint8 type, GError **error)
+{
+ CoglRenderer *renderer = cogl_renderer_new ();
+ CoglDisplay *display;
+
+ cogl_renderer_set_winsys_id (renderer, COGL_WINSYS_ID_SDL);
+
+ cogl_sdl_renderer_set_event_type (renderer, type);
+
+ if (!cogl_renderer_connect (renderer, error))
+ return NULL;
+
+ display = cogl_display_new (renderer, NULL);
+ if (!cogl_display_setup (display, error))
+ return NULL;
+
+ return cogl_context_new (display, error);
+}
+
+void
+cogl_sdl_handle_event (CoglContext *context, SDL_Event *event)
+{
+ const CoglWinsysVtable *winsys;
+
+ _COGL_RETURN_IF_FAIL (cogl_is_context (context));
+
+ winsys = _cogl_context_get_winsys (context);
+
+ if (winsys->poll_dispatch)
+ winsys->poll_dispatch (context, NULL, 0);
+}
+
+void
+cogl_sdl_idle (CoglContext *context)
+{
+ /* NOP since Cogl doesn't currently need to do anything when idle */
+}
diff --git a/cogl/cogl-sdl.h b/cogl/cogl-sdl.h
new file mode 100644
index 000000000..6f33be6f7
--- /dev/null
+++ b/cogl/cogl-sdl.h
@@ -0,0 +1,198 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2012 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 .
+ *
+ *
+ */
+
+#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only can be included directly."
+#endif
+
+#ifndef __COGL_SDL_H__
+#define __COGL_SDL_H__
+
+#include
+#include
+
+G_BEGIN_DECLS
+
+/**
+ * SECTION:cogl-sdl
+ * @short_description: Integration api for the Simple DirectMedia
+ * Layer library.
+ *
+ * Cogl is a portable graphics api that can either be used standalone
+ * or alternatively integrated with certain existing frameworks. This
+ * api enables Cogl to be used in conjunction with the Simple
+ * DirectMedia Layer library.
+ *
+ * Using this API a typical SDL application would look something like
+ * this:
+ * |[
+ * MyAppData data;
+ * GError *error = NULL;
+ *
+ * data.ctx = cogl_sdl_context_new (NULL, SDL_USEREVENT, &error);
+ * if (!data.ctx)
+ * {
+ * fprintf (stderr, "Failed to create context: %s\n",
+ * error->message);
+ * return 1;
+ * }
+ *
+ * my_application_setup (&data);
+ *
+ * data.redraw_queued = TRUE;
+ * while (!data.quit)
+ * {
+ * while (!data.quit)
+ * {
+ * if (!SDL_PollEvent (&event))
+ * {
+ * if (data.redraw_queued)
+ * break;
+ *
+ * cogl_sdl_idle (ctx);
+ * if (!SDL_WaitEvent (&event))
+ * {
+ * fprintf (stderr, "Error waiting for SDL events");
+ * return 1;
+ * }
+ * }
+ *
+ * handle_event (&data, &event);
+ * cogl_sdl_handle_event (ctx, &event);
+ * }
+ *
+ * data.redraw_queued = redraw (&data);
+ * }
+ * ]|
+ */
+
+/**
+ * cogl_sdl_context_new:
+ * @type: An SDL user event type between %SDL_USEREVENT and
+ * %SDL_NUMEVENTS - %1
+ * @error: A GError return location.
+ *
+ * This is a convenience function for creating a new #CoglContext for
+ * use with SDL and specifying what SDL user event type Cogl can use
+ * as a way to interrupt SDL_WaitEvent().
+ *
+ * This function is equivalent to the following code:
+ * |[
+ * CoglRenderer *renderer = cogl_renderer_new ();
+ * CoglDisplay *display;
+ *
+ * cogl_renderer_set_winsys_id (renderer, COGL_WINSYS_ID_SDL);
+ *
+ * cogl_sdl_renderer_set_event_type (renderer, type);
+ *
+ * if (!cogl_renderer_connect (renderer, error))
+ * return NULL;
+ *
+ * display = cogl_display_new (renderer, NULL);
+ * if (!cogl_display_setup (display, error))
+ * return NULL;
+ *
+ * return cogl_context_new (display, error);
+ * ]|
+ *
+ * SDL applications are required to either use this API or
+ * to manually create a #CoglRenderer and call
+ * cogl_sdl_renderer_set_event_type().
+ *
+ * Since: 2.0
+ * Stability: unstable
+ */
+CoglContext *
+cogl_sdl_context_new (guint8 type, GError **error);
+
+/**
+ * cogl_sdl_renderer_set_event_type:
+ * @renderer: A #CoglRenderer
+ * @type: An SDL user event type between %SDL_USEREVENT and
+ * %SDL_NUMEVENTS - %1
+ *
+ * Tells Cogl what SDL user event type it can use as a way to
+ * interrupt SDL_WaitEvent() to ensure that cogl_sdl_handle_event()
+ * will be called in a finite amount of time.
+ *
+ * This should only be called on an un-connected
+ * @renderer.
+ *
+ * For convenience most simple applications can use
+ * cogl_sdl_context_new() if they don't want to manually create
+ * #CoglRenderer and #CoglDisplay objects during
+ * initialization.
+ *
+ * Since: 2.0
+ * Stability: unstable
+ */
+void
+cogl_sdl_renderer_set_event_type (CoglRenderer *renderer, guint8 type);
+
+/**
+ * cogl_sdl_renderer_get_event_type:
+ * @renderer: A #CoglRenderer
+ *
+ * Queries what SDL user event type Cogl is using as a way to
+ * interrupt SDL_WaitEvent(). This is set either using
+ * cogl_sdl_context_new or by using
+ * cogl_sdl_renderer_set_event_type().
+ *
+ * Since: 2.0
+ * Stability: unstable
+ */
+guint8
+cogl_sdl_renderer_get_event_type (CoglRenderer *renderer);
+
+/**
+ * cogl_sdl_handle_event:
+ * @context: A #CoglContext
+ * @event: An SDL event
+ *
+ * Passes control to Cogl so that it may dispatch any internal event
+ * callbacks in response to the given SDL @event. This function must
+ * be called for every SDL event.
+ *
+ * Since: 2.0
+ * Stability: unstable
+ */
+void
+cogl_sdl_handle_event (CoglContext *context, SDL_Event *event);
+
+/**
+ * cogl_sdl_idle:
+ * @context: A #CoglContext
+ *
+ * Notifies Cogl that the application is idle and about to call
+ * SDL_WaitEvent(). Cogl may use this to run low priority book keeping
+ * tasks.
+ *
+ * Since: 2.0
+ * Stability: unstable
+ */
+void
+cogl_sdl_idle (CoglContext *context);
+
+G_END_DECLS
+
+#endif /* __COGL_SDL_H__ */
diff --git a/cogl/cogl.h b/cogl/cogl.h
index 3f1eb5303..0e3c7b6fb 100644
--- a/cogl/cogl.h
+++ b/cogl/cogl.h
@@ -117,6 +117,9 @@
* code has been migrated down into Cogl! */
#include
#endif
+#ifdef COGL_HAS_SDL_SUPPORT
+#include
+#endif
/*
* 2.0 only api...
diff --git a/cogl/winsys/cogl-winsys-sdl.c b/cogl/winsys/cogl-winsys-sdl.c
index deda04520..04fa636a4 100644
--- a/cogl/winsys/cogl-winsys-sdl.c
+++ b/cogl/winsys/cogl-winsys-sdl.c
@@ -159,6 +159,12 @@ error:
static gboolean
_cogl_winsys_context_init (CoglContext *context, GError **error)
{
+ CoglRenderer *renderer = context->display->renderer;
+
+ if (G_UNLIKELY (renderer->sdl_event_type_set == FALSE))
+ g_error ("cogl_sdl_renderer_set_event_type() or cogl_sdl_context_new() "
+ "must be called during initialization");
+
return _cogl_context_update_features (context, error);
}
diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-docs.xml.in b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-docs.xml.in
index 92a47b61f..6c9b91ce6 100644
--- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-docs.xml.in
+++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-docs.xml.in
@@ -18,6 +18,7 @@
2009
2010
2011
+ 2012
Intel Corporation
@@ -130,6 +131,7 @@
Binding and Integrating
+
diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
index a3852bc52..ade861d62 100644
--- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
+++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
@@ -777,3 +777,13 @@ CoglColorMask
GType Integration API
cogl_gtype_matrix_get_type
+
+
+SDL
+SDL Integration
+cogl_sdl_context_new
+cogl_sdl_renderer_set_event_type
+cogl_sdl_renderer_get_event_type
+cogl_sdl_handle_event
+cogl_sdl_idle
+
diff --git a/examples/cogl-sdl-hello.c b/examples/cogl-sdl-hello.c
index 8643c38f6..65e4fee7e 100644
--- a/examples/cogl-sdl-hello.c
+++ b/examples/cogl-sdl-hello.c
@@ -13,9 +13,10 @@ typedef struct Data
float center_x, center_y;
CoglFramebuffer *fb;
gboolean quit;
+ gboolean redraw_queued;
} Data;
-static void
+static gboolean
redraw (Data *data)
{
CoglFramebuffer *fb = data->fb;
@@ -29,6 +30,8 @@ redraw (Data *data)
cogl_framebuffer_pop_matrix (fb);
cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
+
+ return FALSE;
}
static void
@@ -37,7 +40,7 @@ handle_event (Data *data, SDL_Event *event)
switch (event->type)
{
case SDL_VIDEOEXPOSE:
- redraw (data);
+ data->redraw_queued = TRUE;
break;
case SDL_MOUSEMOTION:
@@ -50,7 +53,7 @@ handle_event (Data *data, SDL_Event *event)
data->center_x = event->motion.x * 2.0f / width - 1.0f;
data->center_y = event->motion.y * 2.0f / height - 1.0f;
- redraw (data);
+ data->redraw_queued = TRUE;
}
break;
@@ -60,61 +63,9 @@ handle_event (Data *data, SDL_Event *event)
}
}
-static Uint32
-timer_handler (Uint32 interval, void *user_data)
-{
- static const SDL_UserEvent dummy_event =
- {
- SDL_USEREVENT
- };
-
- /* Post an event to wake up from SDL_WaitEvent */
- SDL_PushEvent ((SDL_Event *) &dummy_event);
-
- return 0;
-}
-
-static gboolean
-wait_event_with_timeout (Data *data, SDL_Event *event, gint64 timeout)
-{
- if (timeout == -1)
- {
- if (SDL_WaitEvent (event))
- return TRUE;
- else
- {
- data->quit = TRUE;
- return FALSE;
- }
- }
- else if (timeout == 0)
- return SDL_PollEvent (event);
- else
- {
- gboolean ret;
- /* Add a timer so that we can wake up the event loop */
- SDL_TimerID timer_id =
- SDL_AddTimer (timeout / 1000, timer_handler, data);
-
- if (SDL_WaitEvent (event))
- ret = TRUE;
- else
- {
- data->quit = TRUE;
- ret = FALSE;
- }
-
- SDL_RemoveTimer (timer_id);
-
- return ret;
- }
-}
-
int
main (int argc, char **argv)
{
- CoglRenderer *renderer;
- CoglDisplay *display;
CoglContext *ctx;
CoglOnscreen *onscreen;
GError *error = NULL;
@@ -126,19 +77,13 @@ main (int argc, char **argv)
Data data;
SDL_Event event;
- /* Force the SDL winsys */
- renderer = cogl_renderer_new ();
- cogl_renderer_set_winsys_id (renderer, COGL_WINSYS_ID_SDL);
- display = cogl_display_new (renderer, NULL);
- ctx = cogl_context_new (display, &error);
+ ctx = cogl_sdl_context_new (SDL_USEREVENT, &error);
if (!ctx)
{
fprintf (stderr, "Failed to create context: %s\n", error->message);
return 1;
}
- SDL_InitSubSystem (SDL_INIT_TIMER);
-
onscreen = cogl_onscreen_new (ctx, 800, 600);
data.fb = COGL_FRAMEBUFFER (onscreen);
@@ -151,31 +96,33 @@ main (int argc, char **argv)
data.triangle = cogl_primitive_new_p2c4 (ctx, COGL_VERTICES_MODE_TRIANGLES,
3, triangle_vertices);
data.pipeline = cogl_pipeline_new (ctx);
+
+ data.redraw_queued = TRUE;
while (!data.quit)
{
- CoglPollFD *poll_fds;
- int n_poll_fds;
- gint64 timeout;
+ while (!data.quit)
+ {
+ if (!SDL_PollEvent (&event))
+ {
+ if (data.redraw_queued)
+ break;
- cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout);
+ cogl_sdl_idle (ctx);
+ if (!SDL_WaitEvent (&event))
+ {
+ fprintf (stderr, "Error waiting for SDL events");
+ return 1;
+ }
+ }
- /* It's difficult to wait for file descriptors using the SDL
- event mechanism, but it the SDL winsys is documented that it
- will never require this so we can assert that there are no
- fds */
- g_assert (n_poll_fds == 0);
-
- if (wait_event_with_timeout (&data, &event, timeout))
- do
handle_event (&data, &event);
- while (SDL_PollEvent (&event));
+ cogl_sdl_handle_event (ctx, &event);
+ }
- cogl_poll_dispatch (ctx, poll_fds, n_poll_fds);
+ data.redraw_queued = redraw (&data);
}
cogl_object_unref (ctx);
- cogl_object_unref (display);
- cogl_object_unref (renderer);
return 0;
}