2008-05-14 Matthew Allum <mallum@openedhand.com>

* clutter/clutter-actor.c:
        * clutter/clutter-main.c:
        * clutter/clutter-private.h:
        Rejid Øyvind's previous commit a little moving more into
        clutter-main.c and using ClutterContext.
        Also Refactor clutter_init & clutter_init_with_args to share
        same core init code.
This commit is contained in:
Matthew Allum 2008-05-13 23:02:45 +00:00
parent a1b240d31b
commit 092fdf1d79
4 changed files with 174 additions and 152 deletions

View File

@ -1,3 +1,13 @@
2008-05-14 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-actor.c:
* clutter/clutter-main.c:
* clutter/clutter-private.h:
Rejid Øyvind's previous commit a little moving more into
clutter-main.c and using ClutterContext.
Also Refactor clutter_init & clutter_init_with_args to share
same core init code.
2008-05-13 Øyvind Kolås <pippin@o-hand.com>
Made it possible to do picking when the colors stored in the

View File

@ -1211,91 +1211,6 @@ _clutter_actor_apply_modelview_transform_recursive (ClutterActor *self,
_clutter_actor_apply_modelview_transform (self);
}
static gint r_available, g_available, b_available;
static gint r_used, g_used, b_used;
static inline void init_bits (void)
{
static gboolean done = FALSE;
if (G_LIKELY (done))
return;
done = TRUE;
cogl_get_bitmasks (&r_available, &g_available, &b_available, NULL);
r_used = r_available;
g_used = g_available;
b_used = b_available;
#ifndef HAVE_CLUTTER_FRUITY
/* We always do fuzzy picking for the fruity backend */
if (g_getenv ("CLUTTER_FUZZY_PICK")!=NULL)
#endif
{
r_used--;
g_used--;
b_used--;
}
}
static inline void
_clutter_id_to_col (guint id,
ClutterColor *col)
{
gint red, green, blue;
init_bits ();
/* compute the numbers we'll store in the components */
red = (id >> (g_used+b_used)) & (0xff >> (8-r_used));
green = (id >> b_used) & (0xff >> (8-g_used));
blue = (id) & (0xff >> (8-b_used));
/* shift left bits a bit and add one, this circumvents
* at least some potential rounding errors in GL/GLES
* driver / hw implementation.
*/
if (r_used != r_available)
red = red * 2 + 1;
if (g_used != g_available)
green = green * 2 + 1;
if (b_used != b_available)
blue = blue * 2 + 1;
/* shift up to be full 8bit values */
red = red << (8-r_available);
green = green << (8-g_available);
blue = blue << (8-b_available);
col->red = red;
col->green = green;
col->blue = blue;
col->alpha = 0xff;
}
guint _clutter_pix_to_id (guchar pixel[4])
{
gint red, green, blue;
guint id;
/* reduce the pixel components to the number of bits actually used of the
* 8bits.
*/
red = pixel[0] >> (8 - r_available);
green = pixel[1] >> (8 - g_available);
blue = pixel[2] >> (8 - b_available);
/* divide by two */
red = red >> (r_available-r_used);
green = green >> (g_available-g_used);
blue = blue >> (b_available-b_used);
/* combine the correct per component values into the final id */
id = blue + (green << b_used) + (red << (b_used + g_used));
return id;
}
/**
* clutter_actor_paint:
* @self: A #ClutterActor
@ -1343,7 +1258,7 @@ clutter_actor_paint (ClutterActor *self)
{
ClutterColor col;
_clutter_id_to_col (clutter_actor_get_gid (self), &col);
_clutter_id_to_color (clutter_actor_get_gid (self), &col);
/* Actor will then paint silhouette of itself in supplied
* color. See clutter_stage_get_actor_at_pos() for where

View File

@ -228,6 +228,82 @@ clutter_get_motion_events_enabled (void)
guint _clutter_pix_to_id (guchar pixel[4]);
static inline void init_bits (void)
{
ClutterMainContext *ctx;
static gboolean done = FALSE;
if (G_LIKELY (done))
return;
ctx = clutter_context_get_default ();
done = TRUE;
}
void
_clutter_id_to_color (guint id, ClutterColor *col)
{
ClutterMainContext *ctx;
gint red, green, blue;
ctx = clutter_context_get_default ();
/* compute the numbers we'll store in the components */
red = (id >> (ctx->fb_g_mask_used+ctx->fb_b_mask_used))
& (0xff >> (8-ctx->fb_r_mask_used));
green = (id >> ctx->fb_b_mask_used) & (0xff >> (8-ctx->fb_g_mask_used));
blue = (id) & (0xff >> (8-ctx->fb_b_mask_used));
/* shift left bits a bit and add one, this circumvents
* at least some potential rounding errors in GL/GLES
* driver / hw implementation.
*/
if (ctx->fb_r_mask_used != ctx->fb_r_mask)
red = red * 2 + 1;
if (ctx->fb_g_mask_used != ctx->fb_g_mask)
green = green * 2 + 1;
if (ctx->fb_b_mask_used != ctx->fb_b_mask)
blue = blue * 2 + 1;
/* shift up to be full 8bit values */
red = red << (8 - ctx->fb_r_mask);
green = green << (8 - ctx->fb_g_mask);
blue = blue << (8 - ctx->fb_b_mask);
col->red = red;
col->green = green;
col->blue = blue;
col->alpha = 0xff;
}
guint
_clutter_pixel_to_id (guchar pixel[4])
{
ClutterMainContext *ctx;
gint red, green, blue;
guint id;
ctx = clutter_context_get_default ();
/* reduce the pixel components to the number of bits actually used of the
* 8bits.
*/
red = pixel[0] >> (8 - ctx->fb_r_mask);
green = pixel[1] >> (8 - ctx->fb_g_mask);
blue = pixel[2] >> (8 - ctx->fb_b_mask);
/* divide potentially by two if 'fuzzy' */
red = red >> (ctx->fb_r_mask - ctx->fb_r_mask_used);
green = green >> (ctx->fb_g_mask - ctx->fb_g_mask_used);
blue = blue >> (ctx->fb_b_mask - ctx->fb_b_mask_used);
/* combine the correct per component values into the final id */
id = blue + (green << ctx->fb_b_mask_used)
+ (red << (ctx->fb_b_mask_used + ctx->fb_g_mask_used));
return id;
}
ClutterActor *
_clutter_do_pick (ClutterStage *stage,
gint x,
@ -266,15 +342,17 @@ _clutter_do_pick (ClutterStage *stage,
* could be nicer.
*/
glFinish();
/* glEnable (GL_DITHER); we never enabled this originally, so its
probably not safe to then enable it */
/* Read the color of the screen co-ords pixel */
glReadPixels (x, viewport[3] - y -1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff)
return CLUTTER_ACTOR (stage);
id = _clutter_pix_to_id (pixel);
id = _clutter_pixel_to_id (pixel);
return clutter_get_actor_by_gid (id);
}
@ -1025,6 +1103,76 @@ clutter_init_error_quark (void)
return g_quark_from_static_string ("clutter-init-error-quark");
}
static ClutterInitError
clutter_init_real (GError **error)
{
ClutterMainContext *ctx;
ClutterActor *stage;
/* Note, creates backend if not already existing, though parse args will
* have likely created it
*/
ctx = clutter_context_get_default ();
/* Stage will give us a GL Context etc */
stage = clutter_stage_get_default ();
if (!stage)
{
if (error)
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to create the default stage");
else
g_critical ("Unable to create the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
if (error)
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to realize the default stage");
else
g_critical ("Unable to realize the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
/* Now we can safely assume we have a valid GL context and can
* start issueing cogl commands
*/
/* Figure out framebuffer masks used for pick */
cogl_get_bitmasks (&ctx->fb_r_mask, &ctx->fb_g_mask, &ctx->fb_b_mask, NULL);
ctx->fb_r_mask_used = ctx->fb_r_mask;
ctx->fb_g_mask_used = ctx->fb_g_mask;
ctx->fb_b_mask_used = ctx->fb_b_mask;
#ifndef HAVE_CLUTTER_FRUITY
/* We always do fuzzy picking for the fruity backend */
if (g_getenv ("CLUTTER_FUZZY_PICK") != NULL)
#endif
{
ctx->fb_r_mask_used--;
ctx->fb_g_mask_used--;
ctx->fb_b_mask_used--;
}
/* Initiate event collection */
_clutter_backend_init_events (ctx->backend);
/* finally features - will call to backend and cogl */
_clutter_feature_init ();
clutter_stage_set_title (CLUTTER_STAGE (stage), g_get_prgname ());
return CLUTTER_INIT_SUCCESS;
}
/**
* clutter_init_with_args:
* @argc: a pointer to the number of command line arguments
@ -1061,11 +1209,9 @@ clutter_init_with_args (int *argc,
char *translation_domain,
GError **error)
{
ClutterMainContext *clutter_context;
GOptionContext *context;
GOptionGroup *group;
gboolean res;
ClutterActor *stage;
if (clutter_is_initialized)
return CLUTTER_INIT_SUCCESS;
@ -1092,35 +1238,8 @@ clutter_init_with_args (int *argc,
if (!res)
return CLUTTER_INIT_ERROR_INTERNAL;
clutter_context = clutter_context_get_default ();
stage = clutter_stage_get_default ();
if (!stage)
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to create the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_INTERNAL,
"Unable to realize the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
_clutter_backend_init_events (clutter_context->backend);
_clutter_feature_init ();
clutter_stage_set_title (CLUTTER_STAGE (stage), g_get_prgname ());
return CLUTTER_INIT_SUCCESS;
/* Do the real work.. */
return clutter_init_real (error);
}
static gboolean
@ -1172,9 +1291,6 @@ ClutterInitError
clutter_init (int *argc,
char ***argv)
{
ClutterMainContext *context;
ClutterActor *stage;
if (clutter_is_initialized)
return CLUTTER_INIT_SUCCESS;
@ -1183,7 +1299,6 @@ clutter_init (int *argc,
if (argc && *argc > 0 && *argv)
g_set_prgname ((*argv)[0]);
/* parse_args will trigger backend creation and things like
* DISPLAY connection etc.
*/
@ -1193,36 +1308,7 @@ clutter_init (int *argc,
return CLUTTER_INIT_ERROR_INTERNAL;
}
/* Note, creates backend if not already existing (though parse args will
* have likely created it)
*/
context = clutter_context_get_default ();
/* Stage will give us a GL Context etc */
stage = clutter_stage_get_default ();
if (!stage)
{
g_critical ("Unable to create the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
clutter_actor_realize (stage);
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
{
g_critical ("Unable to realize the default stage");
return CLUTTER_INIT_ERROR_INTERNAL;
}
/* Initiate event collection */
_clutter_backend_init_events (context->backend);
/* finally features - will call to backend and cogl */
_clutter_feature_init ();
clutter_stage_set_title (CLUTTER_STAGE (stage), g_get_prgname ());
return CLUTTER_INIT_SUCCESS;
return clutter_init_real (NULL);
}
gboolean

View File

@ -105,6 +105,11 @@ or enter/leave events */
GSList *shaders; /* stack of overridden shaders */
ClutterActor *motion_last_actor;
/* fb bit masks for col<->id mapping in picking */
gint fb_r_mask, fb_g_mask, fb_b_mask;
gint fb_r_mask_used, fb_g_mask_used, fb_b_mask_used;
};
#define CLUTTER_CONTEXT() (clutter_context_get_default ())
@ -166,11 +171,17 @@ ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend);
void _clutter_feature_init (void);
/* Picking code */
ClutterActor *_clutter_do_pick (ClutterStage *stage,
gint x,
gint y,
ClutterPickMode mode);
guint _clutter_pixel_to_id (guchar pixel[4]);
void _clutter_id_to_color (guint id, ClutterColor *col);
/* use this function as the accumulator if you have a signal with
* a G_TYPE_BOOLEAN return value; this will stop the emission as
* soon as one handler returns TRUE