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:
parent
a1b240d31b
commit
092fdf1d79
4 changed files with 174 additions and 152 deletions
10
ChangeLog
10
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue