Rework sdl integration api
This re-works the SDL integration api to simplify the integration for application developers and also allow Cogl to know when the application is about to go idle waiting for events so it can perform idle book-keeping work. Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
parent
d3215b802d
commit
9a1f1df83f
@ -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
|
||||
|
@ -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;
|
||||
|
85
cogl/cogl-sdl.c
Normal file
85
cogl/cogl-sdl.c
Normal file
@ -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
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#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 */
|
||||
}
|
198
cogl/cogl-sdl.h
Normal file
198
cogl/cogl-sdl.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cogl/cogl.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __COGL_SDL_H__
|
||||
#define __COGL_SDL_H__
|
||||
|
||||
#include <cogl/cogl-context.h>
|
||||
#include <SDL.h>
|
||||
|
||||
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);
|
||||
* ]|
|
||||
*
|
||||
* <note>SDL applications are required to either use this API or
|
||||
* to manually create a #CoglRenderer and call
|
||||
* cogl_sdl_renderer_set_event_type().</note>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* <note>This should only be called on an un-connected
|
||||
* @renderer.</note>
|
||||
*
|
||||
* <note>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.</note>
|
||||
*
|
||||
* 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__ */
|
@ -117,6 +117,9 @@
|
||||
* code has been migrated down into Cogl! */
|
||||
#include <cogl/cogl-clutter.h>
|
||||
#endif
|
||||
#ifdef COGL_HAS_SDL_SUPPORT
|
||||
#include <cogl/cogl-sdl.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 2.0 only api...
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
<year>2009</year>
|
||||
<year>2010</year>
|
||||
<year>2011</year>
|
||||
<year>2012</year>
|
||||
<holder>Intel Corporation</holder>
|
||||
</copyright>
|
||||
|
||||
@ -130,6 +131,7 @@
|
||||
|
||||
<section id="cogl-integration">
|
||||
<title>Binding and Integrating</title>
|
||||
<xi:include href="xml/cogl-sdl.xml"/>
|
||||
<xi:include href="xml/cogl-gtype.xml"/>
|
||||
</section>
|
||||
|
||||
|
@ -777,3 +777,13 @@ CoglColorMask
|
||||
<TITLE>GType Integration API</TITLE>
|
||||
cogl_gtype_matrix_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>SDL</FILE>
|
||||
<TITLE>SDL Integration</TITLE>
|
||||
cogl_sdl_context_new
|
||||
cogl_sdl_renderer_set_event_type
|
||||
cogl_sdl_renderer_get_event_type
|
||||
cogl_sdl_handle_event
|
||||
cogl_sdl_idle
|
||||
</SECTION>
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user