+2007-05-28 Matthew Allum <mallum@openedhand.com>
+
+ * clutter/clutter-backend.c:
+ * clutter/clutter-backend.h:
+ * clutter/glx/clutter-stage-glx.c:
+ * clutter/glx/clutter-backend-glx.c:
+ Fix up rendering pipeline removing clutter_backend_XXX_stage_paint
+ and adding clutter_backend_XXX_redraw instead. Duplicates less
+ code in backends, avoids clutter_actor_paint() getting called
+ before stage is set up (viewport wise) and unbreaks things like
+ picking.
+
+ * clutter/clutter-actor.c:
+ * clutter/clutter-actor.h:
+ * clutter/clutter-main.c:
+ * clutter/clutter-private.h:
+ * clutter/clutter-stage.c: (clutter_stage_get_actor_at_pos):
+ Redo picking functionality a different way (via color indexing)
+ as to provide more flexibility, possibly speed and more likely
+ work with GL/ES (doesn't currently however - not sure why).
+
+ * clutter/clutter-group.c:
+ Add groups own 'pick' method.
+
+ * clutter/cogl/cogl.h:
+ * clutter/cogl/gl/cogl.c:
+ * clutter/cogl/gles/cogl.c:
+ Move clipping funtionality into cogl.
+
+ * clutter/cogl/gles/cogl-defines.h:
+ Hack around missing BGR format in GL/ES.
+
+ * clutter/egl/clutter-backend-egl.c:
+ * clutter/egl/clutter-backend-egl.h:
+ * clutter/egl/clutter-stage-egl.c:
+ * clutter/sdl/clutter-backend-sdl.c:
+ * clutter/sdl/clutter-backend-sdl.h:
+ * clutter/sdl/clutter-event-sdl.c:
+ * clutter/sdl/clutter-stage-sdl.c:
+ Update backends to newer API.
+ Add basic mouse event translation to SDL.
+
2007-05-25 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-color.c: (clutter_color_parse):
}
/**
+ * clutter_actor_pick:
+ * @self: A #ClutterActor
+ * @color: A #ClutterColor
+ *
+ * Renders a silhouette of the actor in supplied color.
+ *
+ * This function should not never be called directly by applications.
+ **/
+void
+clutter_actor_pick (ClutterActor *self,
+ const ClutterColor *color)
+{
+ ClutterActorClass *klass;
+
+ klass = CLUTTER_ACTOR_GET_CLASS (self);
+
+ if (G_UNLIKELY(klass->pick))
+ {
+ /* Its pretty unlikely anything other than a container actor
+ * would need to supply its own pick method.
+ */
+ (klass->pick) (self, color);
+ }
+ else
+ {
+ cogl_color (color);
+ cogl_rectangle (0,
+ 0,
+ clutter_actor_get_width(self),
+ clutter_actor_get_height(self));
+ }
+}
+
+/**
* clutter_actor_paint:
* @self: A #ClutterActor
*
{
ClutterActorPrivate *priv;
ClutterActorClass *klass;
+ ClutterMainContext *context;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
priv = self->priv;
}
}
- klass = CLUTTER_ACTOR_GET_CLASS (self);
+ context = clutter_context_get_default ();
+ klass = CLUTTER_ACTOR_GET_CLASS (self);
cogl_push_matrix();
-#if HAVE_COGL_GL
- glLoadName (clutter_actor_get_id (self));
-#endif
-
if (clutter_actor_get_parent (self) != NULL)
{
cogl_translate (CLUTTER_UNITS_TO_INT (priv->coords.x1),
cogl_scale (priv->scale_x, priv->scale_y);
}
-#if HAVE_COGL_GL
if (priv->has_clip)
- {
- ClutterGeometry *clip = &(priv->clip);
-
- /* FIXME: ES ... */
- glEnable (GL_STENCIL_TEST);
+ cogl_clip_set (&(priv->clip));
- glClearStencil (0.0f);
- glClear (GL_STENCIL_BUFFER_BIT);
-
- glStencilFunc (GL_NEVER, 0x1, 0x1);
- glStencilOp (GL_INCR, GL_INCR, GL_INCR);
+ if (G_UNLIKELY(context->pick_mode == TRUE))
+ {
+ ClutterColor col;
+ guint32 id;
- glColor3f (1.0f, 1.0f, 1.0f);
+ id = clutter_actor_get_id (self);
- glRecti (clip->x,
- clip->y,
- clip->x + clip->width,
- clip->y + clip->height);
+ /* Encode the actor id into a color */
+ col.red = (id >> 16) & 0xff;
+ col.green = (id >> 8) & 0xff;
+ col.blue = id & 0xff;
+ col.alpha = 0xff;
- glStencilFunc (GL_EQUAL, 0x1, 0x1);
- glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
+ /* Actor will then paint silhouette of itself in supplied color.
+ * See clutter_stage_get_actor_at_pos() for where picking is enabled.
+ */
+ clutter_actor_pick (self, &col);
+ }
+ else
+ {
+ if (G_LIKELY(klass->paint))
+ (klass->paint) (self);
}
-#endif
-
- if (klass->paint)
- (klass->paint) (self);
-#if CLUTTER_COGL_GL
if (priv->has_clip)
- glDisable (GL_STENCIL_TEST);
-#endif
+ cogl_clip_unset();
if (priv->scale_x != CFX_ONE || priv->scale_y != CFX_ONE)
cogl_scale (CFX_ONE, CFX_ONE);
#include <glib-object.h>
#include <clutter/clutter-fixed.h>
#include <clutter/clutter-units.h>
+#include <clutter/clutter-color.h>
G_BEGIN_DECLS
void (* parent_set) (ClutterActor *actor,
ClutterActor *old_parent);
- void (* destroy) (ClutterActor *actor);
-
- /* to go ? */
- void (* queue_redraw) (ClutterActor *actor);
+ void (* destroy) (ClutterActor *actor);
+ void (* pick) (ClutterActor *actor, const ClutterColor *color);
/* padding for future expansion */
void (*_clutter_actor_1) (void);
void clutter_actor_realize (ClutterActor *self);
void clutter_actor_unrealize (ClutterActor *self);
void clutter_actor_paint (ClutterActor *self);
+void clutter_actor_pick (ClutterActor *actor,
+ const ClutterColor *color);
void clutter_actor_queue_redraw (ClutterActor *self);
void clutter_actor_destroy (ClutterActor *self);
void clutter_actor_request_coords (ClutterActor *self,
return TRUE;
}
+void
+_clutter_backend_redraw (ClutterBackend *backend)
+{
+ ClutterBackendClass *klass;
+
+ klass = CLUTTER_BACKEND_GET_CLASS (backend);
+ if (G_LIKELY(klass->redraw))
+ klass->redraw (backend);
+}
+
ClutterFeatureFlags
_clutter_backend_get_features (ClutterBackend *backend)
{
void (* add_options) (ClutterBackend *backend,
GOptionGroup *group);
ClutterFeatureFlags (* get_features) (ClutterBackend *backend);
+ void (* redraw) (ClutterBackend *backend);
};
GType clutter_backend_get_type (void) G_GNUC_CONST;
#include "clutter-marshal.h"
#include "clutter-enum-types.h"
+#include "cogl.h"
+
enum
{
ADD,
GList *children;
};
+
static void
clutter_group_paint (ClutterActor *actor)
{
CLUTTER_NOTE (PAINT, "ClutterGroup paint leave");
}
+static void
+clutter_group_pick (ClutterActor *actor,
+ const ClutterColor *color)
+{
+ /* Just forward to the paint call which in turn will trigger
+ * the child actors also getting 'picked'. To make ourselves
+ * 'sensitive' to clicks we could also paint a bounding rect
+ * but this is not currently done.
+ */
+ clutter_group_paint (actor);
+}
+
+
static void
clutter_group_request_coords (ClutterActor *self,
ClutterActorBox *box)
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
actor_class->paint = clutter_group_paint;
+ actor_class->pick = clutter_group_pick;
actor_class->show_all = clutter_group_real_show_all;
actor_class->hide_all = clutter_group_real_hide_all;
actor_class->request_coords = clutter_group_request_coords;
#include "clutter-debug.h"
#include "clutter-version.h" /* For flavour define */
+#include "cogl.h"
+
static ClutterMainContext *ClutterCntx = NULL;
static gboolean clutter_is_initialized = FALSE;
clutter_redraw (void)
{
ClutterMainContext *ctx;
+ ClutterColor stage_color;
+ ClutterActor *stage;
+ static GTimer *timer = NULL;
+ static guint timer_n_frames = 0;
- ctx = clutter_context_get_default ();
- if (ctx->backend)
- clutter_actor_paint (_clutter_backend_get_stage (ctx->backend));
+ ctx = clutter_context_get_default ();
+
+ stage = _clutter_backend_get_stage (ctx->backend);
+
+ CLUTTER_NOTE (PAINT, " Redraw enter");
+
+ /* Setup FPS count */
+ if (clutter_get_show_fps ())
+ {
+ if (!timer)
+ timer = g_timer_new ();
+ }
+
+ /* The below cant go in stage paint as base actor_paint will get
+ * called before the below (and break picking etc)
+ */
+ if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES)
+ {
+ cogl_setup_viewport (clutter_actor_get_width (stage),
+ clutter_actor_get_height (stage),
+ 171, /* 60 degrees */
+ CFX_ONE,
+ CLUTTER_FLOAT_TO_FIXED (0.1),
+ CLUTTER_FLOAT_TO_FIXED (100.0));
+ }
+
+ /* Setup the initial paint */
+ clutter_stage_get_color (CLUTTER_STAGE(stage), &stage_color);
+ cogl_paint_init (&stage_color);
+
+ /* Call through ti the actual backend to do the painting down from
+ * the stage. It will likely need to swap buffers, vblank sync etc
+ * which will be windowing system dependant.
+ */
+ _clutter_backend_redraw (ctx->backend);
+
+ /* Complete FPS info */
+ 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");
}
/**
ClutterMainContext*
clutter_context_get_default (void)
{
- if (!ClutterCntx)
+ if (G_UNLIKELY(!ClutterCntx))
{
ClutterMainContext *ctx;
guint main_loop_level;
GSList *main_loops;
guint is_initialized : 1;
+ guint pick_mode :1;
};
#define CLUTTER_CONTEXT() (clutter_context_get_default ())
ClutterActor *_clutter_backend_get_stage (ClutterBackend *backend);
+void _clutter_backend_redraw (ClutterBackend *backend);
+
void _clutter_backend_add_options (ClutterBackend *backend,
GOptionGroup *group);
gboolean _clutter_backend_pre_parse (ClutterBackend *backend,
static guint stage_signals[LAST_SIGNAL] = { 0, };
static void
-clutter_stage_paint (ClutterActor *actor)
+clutter_stage_paint (ClutterActor *self)
{
- /* chain up */
- CLUTTER_NOTE (PAINT, "Chaining up to parent class paint");
-
- CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (actor);
+ CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (self);
}
static void
gint x,
gint y)
{
-#if HAVE_COGL_GL
+ ClutterMainContext *context;
+ guchar pixel[3];
+ GLint viewport[4];
+ ClutterColor white = { 0xff, 0xff, 0xff, 0xff };
+ guint32 id;
- /* FIXME: Add a clutter feature flag for this or figure out
- * for gles.
- */
+ context = clutter_context_get_default ();
- ClutterActor *found = NULL;
- GLuint buff[512] = { 0 };
- GLint hits;
- GLint view[4];
-
- g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
-
- glSelectBuffer (512, buff);
- glGetIntegerv (GL_VIEWPORT, view);
- glRenderMode (GL_SELECT);
-
- glInitNames ();
- glPushName (0);
-
- glMatrixMode (GL_PROJECTION);
- glPushMatrix ();
- glLoadIdentity ();
-
- /* This is gluPickMatrix(x, y, 1.0, 1.0, view); */
- glTranslatef ((view[2] - 2 * (x - view[0])),
- (view[3] - 2 * (y - view[1])), 0);
- glScalef (view[2], -view[3], 1.0);
-
- cogl_perspective (171, /* 60 degrees */
- CFX_ONE,
- CLUTTER_FLOAT_TO_FIXED (0.1),
- CLUTTER_FLOAT_TO_FIXED (100.0));
-
- glMatrixMode (GL_MODELVIEW);
+ cogl_paint_init (&white);
+ cogl_enable (0);
+ /* Render the entire scence in pick mode - just single colored silhouette's
+ * are drawn offscreen (as we never swap buffers)
+ */
+ context->pick_mode = TRUE;
clutter_actor_paint (CLUTTER_ACTOR (stage));
+ context->pick_mode = FALSE;
- glMatrixMode (GL_PROJECTION);
- glPopMatrix ();
+ /* Calls should work under both GL and GLES
+ *
+ * FIXME: of course we need to handle the case where the frame buffer isn't
+ * 24bpp, i.e 16bpp which could be the case with GLES.
+ */
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ glReadPixels(x, viewport[3] - y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
- hits = glRenderMode (GL_RENDER);
+ /* printf("x: %i , y: %i %x:%x:%x\n", x, y, pixel[0], pixel[1], pixel[2]); */
- if (hits != 0)
- {
-#if 1
- gint i;
- for (i = 0; i < hits; i++)
- g_print ("Hit at %i\n", buff[(hits-1) * 4 + 3]);
-#endif
-
- found = clutter_group_find_child_by_id (CLUTTER_GROUP (stage),
- buff[(hits-1) * 4 + 3]);
- }
+ if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff)
+ return CLUTTER_ACTOR(stage);
- CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
+ /* Decode color back into an ID */
+ id = pixel[2] | pixel[1] << 8 | pixel[0] << 16;
- return found;
-#else
- /* GL/ES cannot do this yet.. */
- return NULL;
-#endif
+ return clutter_group_find_child_by_id (CLUTTER_GROUP (stage), id);
}
/**
ClutterFixed z_far);
void
-cogl_paint_init (ClutterColor *color);
+cogl_paint_init (const ClutterColor *color);
void
cogl_push_matrix (void);
cogl_rotate (gint angle, gint x, gint y, gint z);
void
-cogl_color (ClutterColor *color);
+cogl_color (const ClutterColor *color);
+
+void
+cogl_clip_set (const ClutterGeometry *clip);
+
+void
+cogl_clip_unset (void);
void
cogl_enable (gulong flags);
}
void
-cogl_paint_init (ClutterColor *color)
+cogl_paint_init (const ClutterColor *color)
{
GE( glClearColor (((float) color->red / 0xff * 1.0),
((float) color->green / 0xff * 1.0),
}
void
-cogl_color (ClutterColor *color)
+cogl_color (const ClutterColor *color)
{
glColor4ub (color->red, color->green, color->blue, color->alpha);
}
+void
+cogl_clip_set (const ClutterGeometry *clip)
+{
+ GE( glEnable (GL_STENCIL_TEST) );
+
+ GE( glClearStencil (0.0f) );
+ GE( glClear (GL_STENCIL_BUFFER_BIT) );
+
+ GE( glStencilFunc (GL_NEVER, 0x1, 0x1) );
+ GE( glStencilOp (GL_INCR, GL_INCR, GL_INCR) );
+
+ GE( glColor3f (1.0f, 1.0f, 1.0f) );
+
+ GE( glRecti (clip->x,
+ clip->y,
+ clip->x + clip->width,
+ clip->y + clip->height) );
+
+ GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) );
+; GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
+}
+
+void
+cogl_clip_unset (void)
+{
+ GE( glDisable (GL_STENCIL_TEST) );
+}
+
gboolean
cogl_texture_can_size (COGLenum pixel_format,
COGLenum pixel_type,
GE( glEnd () );
}
-
void
cogl_alpha_func (COGLenum func,
ClutterFixed ref)
GE( glAlphaFunc (func, CLUTTER_FIXED_TO_FLOAT(ref)) );
}
-#if 0
-/*
- * Original floating point implementaiton of the perspective function,
- * retained for reference purposes
- */
-static inline void
-frustum (GLfloat left,
- GLfloat right,
- GLfloat bottom,
- GLfloat top,
- GLfloat nearval,
- GLfloat farval)
-{
- GLfloat x, y, a, b, c, d;
- GLfloat m[16];
-
- x = (2.0 * nearval) / (right - left);
- y = (2.0 * nearval) / (top - bottom);
- a = (right + left) / (right - left);
- b = (top + bottom) / (top - bottom);
- c = -(farval + nearval) / ( farval - nearval);
- d = -(2.0 * farval * nearval) / (farval - nearval);
-
-#define M(row,col) m[col*4+row]
- M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
- M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
- M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
- M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
-#undef M
-
- GE( glMultMatrixf (m) );
-}
-
-static inline void
-perspective (GLfloat fovy,
- GLfloat aspect,
- GLfloat zNear,
- GLfloat zFar)
-{
- GLfloat xmin, xmax, ymin, ymax;
-
- ymax = zNear * tan (fovy * M_PI / 360.0);
- ymin = -ymax;
- xmin = ymin * aspect;
- xmax = ymax * aspect;
-
- printf ("%f, %f, %f, %f\n", xmin, xmax, ymin, ymax);
-
- frustum (xmin, xmax, ymin, ymax, zNear, zFar);
-}
-#endif
-
-/*
- * Fixed point implementation of the perspective function
- */
void
cogl_perspective (ClutterAngle fovy,
ClutterFixed aspect,
ClutterFixed xmax, ymax;
ClutterFixed x, y, c, d;
-#ifdef HAVE_COGL_GL
GLfloat m[16];
-#else
- GLfixed m[16];
-#endif
memset (&m[0], 0, sizeof (m));
d = CFX_DIV (-(clutter_qmulx (2*zFar, zNear)), (zFar - zNear));
#define M(row,col) m[col*4+row]
-#ifdef HAVE_COGL_GL
M(0,0) = CLUTTER_FIXED_TO_FLOAT (x);
M(1,1) = CLUTTER_FIXED_TO_FLOAT (y);
M(2,2) = CLUTTER_FIXED_TO_FLOAT (c);
M(3,2) = -1.0F;
GE( glMultMatrixf (m) );
-#else
- M(0,0) = x;
- M(1,1) = y;
- M(2,2) = c;
- M(2,3) = d;
- M(3,2) = 1 + ~CFX_ONE;
-
- GE( glMultMatrixx (m) );
-#endif
#undef M
}
GE( glTranslatef (-0.5f, -0.5f, -z_camera) );
GE( glScalef ( 1.0f / width,
- -1.0f / height,
+ -1.0f / height,
1.0f / width) );
GE( glTranslatef (0.0f, -1.0 * height, 0.0f) );
}
#define CGL_TEXTURE_2D GL_TEXTURE_2D
#define CGL_ARGB GL_ARGB
+
+/* FIXME: There is no BGR support in GLES - so with below BGR textures are
+ * borked. Will likely need a feature flag and some coversion..
+ */
+#define CGL_BGR GL_RGB
+#define CGL_BGRA GL_RGBA
+
#define CGL_TEXTURE_RECTANGLE_ARB 0 /* Its unlikely we support this */
G_END_DECLS
}
void
-cogl_paint_init (ClutterColor *color)
+cogl_paint_init (const ClutterColor *color)
{
#if COGL_DEBUG
fprintf(stderr, "\n ============== Paint Start ================ \n");
}
void
-cogl_color (ClutterColor *color)
+cogl_color (const ClutterColor *color)
{
GE( glColor4x ((color->red << 16) / 0xff,
(color->green << 16) / 0xff,
(color->alpha << 16) / 0xff) );
}
+void
+cogl_clip_set (const ClutterGeometry *clip)
+{
+ GE( glEnable (GL_STENCIL_TEST) );
+
+ GE( glClearStencil (0) );
+ GE( glClear (GL_STENCIL_BUFFER_BIT) );
+
+ GE( glStencilFunc (GL_NEVER, 0x1, 0x1) );
+ GE( glStencilOp (GL_INCR, GL_INCR, GL_INCR) );
+
+ GE( glColor4x (CFX_ONE, CFX_ONE, CFX_ONE, CFX_ONE ) );
+
+ cogl_rectangle (clip->x, clip->y, clip->width, clip->height);
+
+ GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) );
+ GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
+}
+
+void
+cogl_clip_unset (void)
+{
+ GE( glDisable (GL_STENCIL_TEST) );
+}
+
+
+
gboolean
cogl_texture_can_size (COGLenum pixel_format,
COGLenum pixel_type,
int width,
int height)
{
- GLint new_width = 0;
-
-
/* FIXME */
return TRUE;
#if 0
+ GLint new_width = 0;
+
GE( glTexImage2D (GL_PROXY_TEXTURE_2D, 0, GL_RGBA,
width, height, 0 /* border */,
pixel_format, pixel_type, NULL) );
GE( glAlphaFunc (func, CLUTTER_FIXED_TO_FLOAT(ref)) );
}
-
-
/*
* Fixed point implementation of the perspective function
*/
/* camera distance from screen, 0.5 * tan (FOV) */
#define DEFAULT_Z_CAMERA 0.866025404f
z_camera = clutter_tani (fovy) << 1;
-
- GE( glTranslatex (-1 << 15, -1 << 15, -z_camera );
+
+ /*
+ printf("%i vs %i\n",
+ CLUTTER_FLOAT_TO_FIXED(DEFAULT_Z_CAMERA),
+ clutter_tani (fovy) << 1);
+ */
+
+ GE( glTranslatex (-1 << 15, -1 << 15, /*-z_camera*/
+ -CLUTTER_FLOAT_TO_FIXED(DEFAULT_Z_CAMERA)));
GE( glScalex ( CFX_ONE / width,
-CFX_ONE / height,
{ NULL }
};
+static void
+clutter_backend_egl_redraw (ClutterBackend *backend)
+{
+ ClutterBackendEgl *backend_egl = CLUTTER_BACKEND_EGL (backend);
+ ClutterStageEgl *stage_egl;
+
+ stage_egl = CLUTTER_STAGE_EGL(backend_egl->stage);
+
+ clutter_actor_paint (CLUTTER_ACTOR(stage_egl));
+
+ /* Why this paint is done in backend as likely GL windowing system
+ * specific calls, like swapping buffers.
+ */
+ if (stage_egl->xwin)
+ {
+ /* clutter_feature_wait_for_vblank (); */
+ eglSwapBuffers ((EGLDisplay)stage_egl->xdpy, stage_egl->egl_surface);
+ }
+ else
+ {
+ eglWaitGL ();
+ CLUTTER_GLERR ();
+ }
+}
static void
clutter_backend_egl_add_options (ClutterBackend *backend,
return g_object_ref (backend_singleton);
}
-
static void
clutter_backend_egl_class_init (ClutterBackendEglClass *klass)
{
gobject_class->dispose = clutter_backend_egl_dispose;
gobject_class->finalize = clutter_backend_egl_finalize;
- backend_class->pre_parse = clutter_backend_egl_pre_parse;
- backend_class->post_parse = clutter_backend_egl_post_parse;
- backend_class->init_stage = clutter_backend_egl_init_stage;
+ backend_class->pre_parse = clutter_backend_egl_pre_parse;
+ backend_class->post_parse = clutter_backend_egl_post_parse;
+ backend_class->init_stage = clutter_backend_egl_init_stage;
backend_class->init_events = clutter_backend_egl_init_events;
- backend_class->get_stage = clutter_backend_egl_get_stage;
+ backend_class->get_stage = clutter_backend_egl_get_stage;
backend_class->add_options = clutter_backend_egl_add_options;
+ backend_class->redraw = clutter_backend_egl_redraw;
}
static void
GType clutter_backend_egl_get_type (void) G_GNUC_CONST;
+void _clutter_events_init (ClutterBackend *backend);
+void _clutter_events_uninit (ClutterBackend *backend);
+
G_END_DECLS
#endif /* __CLUTTER_BACKEND_EGL_H__ */
/* FIXME */
}
- _clutter_stage_sync_viewport (CLUTTER_STAGE (stage_egl));
-}
-
-static void
-clutter_stage_egl_paint (ClutterActor *self)
-{
- ClutterStageEgl *stage_egl = CLUTTER_STAGE_EGL (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_egl_parent_class)->paint (self);
-
- /* Why this paint is done in backend as likely GL windowing system
- * specific calls, like swapping buffers.
- */
- if (stage_egl->xwin)
- {
- /* clutter_feature_wait_for_vblank (); */
- eglSwapBuffers ((EGLDisplay)stage_egl->xdpy, stage_egl->egl_surface);
- }
- else
- {
- eglWaitGL ();
- CLUTTER_GLERR ();
- }
-
- 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");
+ CLUTTER_SET_PRIVATE_FLAGS(actor, CLUTTER_ACTOR_SYNC_MATRICES);
}
static void
stage_egl->xwin_width,
stage_egl->xwin_height);
- _clutter_stage_sync_viewport (CLUTTER_STAGE (stage_egl));
+ CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
}
if (stage_egl->xwin != None) /* Do we want to bother ? */
XDeleteProperty (stage_egl->xdpy, stage_egl->xwin, atom_WM_STATE);
}
- _clutter_stage_sync_viewport (stage);
+ CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
}
static void
XDefineCursor (stage_egl->xdpy, stage_egl->xwin, curs);
#endif /* HAVE_XFIXES */
}
-
- _clutter_stage_sync_viewport (stage);
}
static void
}
static void
-snapshot_pixbuf_free (guchar *pixels,
- gpointer data)
-{
- g_free (pixels);
-}
-
-static void
clutter_stage_egl_draw_to_pixbuf (ClutterStage *stage,
GdkPixbuf *dest,
gint x,
actor_class->hide = clutter_stage_egl_hide;
actor_class->realize = clutter_stage_egl_realize;
actor_class->unrealize = clutter_stage_egl_unrealize;
- actor_class->paint = clutter_stage_egl_paint;
actor_class->request_coords = clutter_stage_egl_request_coords;
actor_class->allocate_coords = clutter_stage_egl_allocate_coords;
}
static void
+clutter_backend_glx_redraw (ClutterBackend *backend)
+{
+ ClutterBackendGlx *backend_glx = CLUTTER_BACKEND_GLX (backend);
+ ClutterStageGlx *stage_glx;
+
+ stage_glx = CLUTTER_STAGE_GLX(backend_glx->stage);
+
+ clutter_actor_paint (CLUTTER_ACTOR(stage_glx));
+
+ /* Why this paint is done in backend as likely GL windowing system
+ * specific calls, like swapping buffers.
+ */
+ if (stage_glx->xwin)
+ {
+ clutter_backend_glx_wait_for_vblank (stage_glx->backend);
+ glXSwapBuffers (stage_glx->xdpy, stage_glx->xwin);
+ }
+ else
+ {
+ /* offscreen */
+ glXWaitGL ();
+ CLUTTER_GLERR ();
+ }
+
+}
+
+static void
clutter_backend_glx_class_init (ClutterBackendGlxClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = clutter_backend_glx_dispose;
gobject_class->finalize = clutter_backend_glx_finalize;
- backend_class->pre_parse = clutter_backend_glx_pre_parse;
- backend_class->post_parse = clutter_backend_glx_post_parse;
- backend_class->init_stage = clutter_backend_glx_init_stage;
- backend_class->init_events = clutter_backend_glx_init_events;
- backend_class->get_stage = clutter_backend_glx_get_stage;
- backend_class->add_options = clutter_backend_glx_add_options;
+ backend_class->pre_parse = clutter_backend_glx_pre_parse;
+ backend_class->post_parse = clutter_backend_glx_post_parse;
+ backend_class->init_stage = clutter_backend_glx_init_stage;
+ backend_class->init_events = clutter_backend_glx_init_events;
+ backend_class->get_stage = clutter_backend_glx_get_stage;
+ backend_class->add_options = clutter_backend_glx_add_options;
backend_class->get_features = clutter_backend_glx_get_features;
+ backend_class->redraw = clutter_backend_glx_redraw;
}
static void
}
static void
-clutter_stage_glx_paint (ClutterActor *self)
-{
- ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (self);
- ClutterStage *stage = CLUTTER_STAGE (self);
- ClutterColor stage_color;
- static GTimer *timer = NULL;
- static guint timer_n_frames = 0;
-
- CLUTTER_NOTE (PAINT, " Redraw enter");
-
- /* Setup FPS count */
- if (clutter_get_show_fps ())
- {
- if (!timer)
- timer = g_timer_new ();
- }
-
- /* Reset view matrices if needed. */
- if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_SYNC_MATRICES)
- {
- cogl_setup_viewport (clutter_actor_get_width (self),
- clutter_actor_get_height (self),
- 171, /* 60 degrees */
- CFX_ONE,
- CLUTTER_FLOAT_TO_FIXED (0.1),
- CLUTTER_FLOAT_TO_FIXED (100.0));
- }
-
- /* Setup the initial paint */
- clutter_stage_get_color (stage, &stage_color);
- cogl_paint_init (&stage_color);
-
- /* chain up to reach ClutterGroup->paint here and actually paint all */
- CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->paint (self);
-
- /* Why this paint is done in backend as likely GL windowing system
- * specific calls, like swapping buffers.
- */
- if (stage_glx->xwin)
- {
- clutter_backend_glx_wait_for_vblank (stage_glx->backend);
- glXSwapBuffers (stage_glx->xdpy, stage_glx->xwin);
- }
- else
- {
- glXWaitGL ();
- CLUTTER_GLERR ();
- }
-
- /* Complete FPS info */
- 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_glx_allocate_coords (ClutterActor *self,
ClutterActorBox *box)
{
actor_class->hide = clutter_stage_glx_hide;
actor_class->realize = clutter_stage_glx_realize;
actor_class->unrealize = clutter_stage_glx_unrealize;
- actor_class->paint = clutter_stage_glx_paint;
actor_class->request_coords = clutter_stage_glx_request_coords;
actor_class->allocate_coords = clutter_stage_glx_allocate_coords;
}
static void
+clutter_backend_sdl_redraw (ClutterBackend *backend)
+{
+ ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend);
+ ClutterStageSDL *stage_sdl;
+
+ stage_sdl = CLUTTER_STAGE_SDL(backend_sdl->stage);
+
+ clutter_actor_paint (CLUTTER_ACTOR(stage_sdl));
+
+ SDL_GL_SwapBuffers();
+}
+
+static void
clutter_backend_sdl_finalize (GObject *gobject)
{
SDL_Quit();
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;
+ backend_class->redraw = clutter_backend_sdl_redraw;
}
static void
GType clutter_backend_sdl_get_type (void) G_GNUC_CONST;
+void _clutter_events_init (ClutterBackend *backend);
+void _clutter_events_uninit (ClutterBackend *backend);
+
G_END_DECLS
#endif /* __CLUTTER_BACKEND_SDL_H__ */
}
static gboolean
+event_translate (ClutterBackend *backend,
+ ClutterEvent *event,
+ SDL_Event *sdl_event)
+{
+ /* FIXME: Complete */
+ gboolean res;
+
+ res = TRUE;
+
+ switch (sdl_event->type)
+ {
+
+ case SDL_MOUSEBUTTONDOWN:
+ switch (sdl_event->button.button)
+ {
+ case 4: /* up */
+ case 5: /* down */
+ case 6: /* left */
+ case 7: /* right */
+ event->scroll.type = event->type = CLUTTER_SCROLL;
+
+ if (sdl_event->button.button == 4)
+ event->scroll.direction = CLUTTER_SCROLL_UP;
+ else if (sdl_event->button.button == 5)
+ event->scroll.direction = CLUTTER_SCROLL_DOWN;
+ else if (sdl_event->button.button == 6)
+ event->scroll.direction = CLUTTER_SCROLL_LEFT;
+ else
+ event->scroll.direction = CLUTTER_SCROLL_RIGHT;
+
+ event->scroll.time = 0;
+ event->scroll.x = sdl_event->button.x;
+ event->scroll.y = sdl_event->button.y;
+ event->scroll.modifier_state = sdl_event->button.state;
+
+ break;
+ default:
+ event->button.type = event->type = CLUTTER_BUTTON_PRESS;
+ event->button.time = 0;
+ event->button.x = sdl_event->button.x;
+ event->button.y = sdl_event->button.y;
+ event->button.modifier_state = sdl_event->button.state;
+ event->button.button = sdl_event->button.button;
+ _clutter_event_button_generate (backend, event);
+ break;
+ }
+ break;
+
+ case SDL_MOUSEBUTTONUP:
+ /* scroll events don't have a corresponding release */
+ if (sdl_event->button.button == 4 ||
+ sdl_event->button.button == 5 ||
+ sdl_event->button.button == 6 ||
+ sdl_event->button.button == 7)
+ {
+ res = FALSE;
+ break;
+ }
+
+ event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
+ event->button.time = 0;
+ event->button.x = sdl_event->button.x;
+ event->button.y = sdl_event->button.y;
+ event->button.modifier_state = sdl_event->button.state;
+ event->button.button = sdl_event->button.button;
+ break;
+
+ case SDL_MOUSEMOTION:
+ event->motion.type = event->type = CLUTTER_MOTION;
+ event->motion.time = 0;
+ event->motion.x = sdl_event->motion.x;
+ event->motion.y = sdl_event->motion.y;
+ event->motion.modifier_state = sdl_event->motion.state;;
+ break;
+
+ default:
+ res = FALSE;
+ break;
+ }
+
+ return res;
+}
+
+
+static gboolean
clutter_event_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
SDL_Event sdl_event;
ClutterEvent *event = NULL;
+ ClutterBackend *backend = ((ClutterEventSource *) source)->backend;
+ ClutterMainContext *clutter_context;
+
+ clutter_context = clutter_context_get_default ();
while (SDL_PollEvent(&sdl_event))
{
SDL_Quit();
exit(0);
}
+ else
+ {
+ event = clutter_event_new (CLUTTER_NOTHING);
+ if (event_translate (backend, event, &sdl_event))
+ {
+ /* push directly here to avoid copy of queue_put */
+ g_queue_push_head (clutter_context->events_queue, event);
+ }
+ else
+ {
+ clutter_event_free (event);
+ }
+ }
}
- return TRUE;
-
event = clutter_event_get ();
if (event)
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");
+ CLUTTER_SET_PRIVATE_FLAGS(actor, CLUTTER_ACTOR_SYNC_MATRICES);
}
static void
stage_sdl->win_width = new_width;
stage_sdl->win_height = new_height;
- _clutter_stage_sync_viewport (CLUTTER_STAGE (stage_sdl));
+ CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
}
}
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;