6731569c18
The aim is that it should be a requirement that all Cogl applications hook their mainloops into Cogl so we should lead by examples. Most of the examples now just call cogl_poll_get_info and then g_poll with a zero timeout so that they can continue to constantly redraw. The SDL example is a bit special because SDL makes it very difficult to wait on either a timeout or any file descriptors. The SDL winsys is documented not to require blocking on any file descriptors so we can ignore that. It implements the timeout by adding an SDL timer which pushes an event to the queue to wake up SDL_GetEvent. The Cogland example was already using the glib main loop so that one has been updated to add the CoglGLibSource to it. Reviewed-by: Robert Bragg <robert@linux.intel.com>
192 lines
4.3 KiB
C
192 lines
4.3 KiB
C
#include <cogl/cogl.h>
|
|
#include <glib.h>
|
|
#include <stdio.h>
|
|
#include <SDL.h>
|
|
|
|
/* This short example is just to demonstrate mixing SDL with Cogl as a
|
|
simple way to get portable support for events */
|
|
|
|
typedef struct Data
|
|
{
|
|
CoglColor black;
|
|
CoglPrimitive *triangle;
|
|
float center_x, center_y;
|
|
CoglFramebuffer *fb;
|
|
gboolean quit;
|
|
} Data;
|
|
|
|
static void
|
|
redraw (Data *data)
|
|
{
|
|
cogl_clear (&data->black, COGL_BUFFER_BIT_COLOR);
|
|
|
|
cogl_push_matrix ();
|
|
cogl_translate (data->center_x, -data->center_y, 0.0f);
|
|
|
|
cogl_primitive_draw (data->triangle);
|
|
cogl_pop_matrix ();
|
|
|
|
cogl_framebuffer_swap_buffers (data->fb);
|
|
}
|
|
|
|
static void
|
|
handle_event (Data *data, SDL_Event *event)
|
|
{
|
|
switch (event->type)
|
|
{
|
|
case SDL_VIDEOEXPOSE:
|
|
redraw (data);
|
|
break;
|
|
|
|
case SDL_MOUSEMOTION:
|
|
{
|
|
int width =
|
|
cogl_framebuffer_get_width (COGL_FRAMEBUFFER (data->fb));
|
|
int height =
|
|
cogl_framebuffer_get_height (COGL_FRAMEBUFFER (data->fb));
|
|
|
|
data->center_x = event->motion.x * 2.0f / width - 1.0f;
|
|
data->center_y = event->motion.y * 2.0f / height - 1.0f;
|
|
|
|
redraw (data);
|
|
}
|
|
break;
|
|
|
|
case SDL_QUIT:
|
|
data->quit = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
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;
|
|
CoglVertexP2C4 triangle_vertices[] = {
|
|
{0, 0.7, 0xff, 0x00, 0x00, 0x80},
|
|
{-0.7, -0.7, 0x00, 0xff, 0x00, 0xff},
|
|
{0.7, -0.7, 0x00, 0x00, 0xff, 0xff}
|
|
};
|
|
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);
|
|
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);
|
|
/* Eventually there will be an implicit allocate on first use so this
|
|
* will become optional... */
|
|
data.fb = COGL_FRAMEBUFFER (onscreen);
|
|
if (!cogl_framebuffer_allocate (data.fb, &error))
|
|
{
|
|
fprintf (stderr, "Failed to allocate framebuffer: %s\n",
|
|
error->message);
|
|
return 1;
|
|
}
|
|
|
|
cogl_color_set_from_4ub (&data.black, 0, 0, 0, 255);
|
|
data.center_x = 0.0f;
|
|
data.center_y = 0.0f;
|
|
data.quit = FALSE;
|
|
|
|
cogl_onscreen_show (onscreen);
|
|
|
|
cogl_push_framebuffer (data.fb);
|
|
|
|
data.triangle = cogl_primitive_new_p2c4 (COGL_VERTICES_MODE_TRIANGLES,
|
|
3, triangle_vertices);
|
|
while (!data.quit)
|
|
{
|
|
CoglPollFD *poll_fds;
|
|
int n_poll_fds;
|
|
gint64 timeout;
|
|
|
|
cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout);
|
|
|
|
/* 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_poll_dispatch (ctx, poll_fds, n_poll_fds);
|
|
}
|
|
|
|
cogl_pop_framebuffer ();
|
|
|
|
cogl_object_unref (ctx);
|
|
cogl_object_unref (display);
|
|
cogl_object_unref (renderer);
|
|
|
|
return 0;
|
|
}
|