2007-05-25 Matthew Allum <mallum@openedhand.com>

* Makefile.am:
        Install a default flavour .pc file.

        * clutter/clutter-actor.c:
        Translate units correctly for translate()

        * clutter/clutter-feature.h:
        Add new texture features.

        * clutter/clutter-fixed.h:
        Add clutter angle conversion defines.

        * clutter/clutter-group.c:
        Use cogl not GL. Dont recurse on show all.

        * clutter/clutter-private.h:
        Remove sync_viewport.

        * clutter/clutter-rectangle.c:
        Fix cogl typo.

        * clutter/clutter-stage.c:
        * clutter/clutter-stage.h:
        Add perspective settings. Remove viewport_sync.
        Add audience stubs. Fix up actor_at_pos a little (still broken)

        * clutter/clutter-texture.h:
        * clutter/clutter-texture.c:
        Redo pixel uploading. Add initial (disabled) YUV support.

        * clutter/clutter-timeline.c:
        Fire 'completed' signal when looping.

        * clutter/cogl/gl/cogl.c:
        Move some backend checks here.

        * clutter/glx/clutter-backend-glx.c:
        Actually check target display has GLX ext.

        * clutter/glx/clutter-stage-glx.c:
        Handle offscreen failing more gracefully.

        * examples/Makefile.am:
        Use AM_LDFLAGS.

        * clutter/clutter-main.c:
        * clutter/clutter-feature.c:
        * clutter/clutter-backend.c:
        * clutter/clutter-alpha.c:
        Fix a compile warnings.

        * tests/Makefile.am:
        * tests/test-offscreen.c:
        * tests/test-scale.c:
        More tests.
This commit is contained in:
Matthew Allum 2007-05-25 10:56:09 +00:00
parent 361cc36aaa
commit d2efd34eb5
24 changed files with 739 additions and 204 deletions

View File

@ -1,3 +1,61 @@
2007-05-25 Matthew Allum <mallum@openedhand.com>
* Makefile.am:
Install a default flavour .pc file.
* clutter/clutter-actor.c:
Translate units correctly for translate()
* clutter/clutter-feature.h:
Add new texture features.
* clutter/clutter-fixed.h:
Add clutter angle conversion defines.
* clutter/clutter-group.c:
Use cogl not GL. Dont recurse on show all.
* clutter/clutter-private.h:
Remove sync_viewport.
* clutter/clutter-rectangle.c:
Fix cogl typo.
* clutter/clutter-stage.c:
* clutter/clutter-stage.h:
Add perspective settings. Remove viewport_sync.
Add audience stubs. Fix up actor_at_pos a little (still broken)
* clutter/clutter-texture.h:
* clutter/clutter-texture.c:
Redo pixel uploading. Add initial (disabled) YUV support.
* clutter/clutter-timeline.c:
Fire 'completed' signal when looping.
* clutter/cogl/gl/cogl.c:
Move some backend checks here.
* clutter/glx/clutter-backend-glx.c:
Actually check target display has GLX ext.
* clutter/glx/clutter-stage-glx.c:
Handle offscreen failing more gracefully.
* examples/Makefile.am:
Use AM_LDFLAGS.
* clutter/clutter-main.c:
* clutter/clutter-feature.c:
* clutter/clutter-backend.c:
* clutter/clutter-alpha.c:
Fix a compile warnings.
* tests/Makefile.am:
* tests/test-offscreen.c:
* tests/test-scale.c:
More tests.
2007-05-23 Tomas Frydrych <tf@openedhand.com>
* clutter/clutter-actor.c:

View File

@ -8,6 +8,16 @@ pcfiles = clutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.pc
pkgconfig_DATA = $(pcfiles)
pkgconfigdir = $(libdir)/pkgconfig
DEFAULT_FLAVOUR=@CLUTTER_FLAVOUR@
install-data-hook:
(cd $(DESTDIR)$(pkgconfigdir) && \
test -f clutter-$(DEFAULT_FLAVOUR)-@CLUTTER_MAJORMINOR@.pc && \
rm -f clutter-@CLUTTER_MAJORMINOR@.pc && cp -f clutter-$(DEFAULT_FLAVOUR)-@CLUTTER_MAJORMINOR@.pc clutter-@CLUTTER_MAJORMINOR@.pc)
uninstall-local:
rm -f $(DESTDIR)$(pkgconfigdir)/clutter-@CLUTTER_MAJORMINOR@.pc
EXTRA_DIST = clutter.pc.in
CLEANFILES = $(pcfiles)

View File

@ -42,8 +42,6 @@
#include "clutter-units.h"
#include "cogl.h"
#include <GL/gl.h>
G_DEFINE_ABSTRACT_TYPE (ClutterActor,
clutter_actor,
G_TYPE_INITIALLY_UNOWNED);
@ -301,16 +299,14 @@ clutter_actor_paint (ClutterActor *self)
cogl_push_matrix();
#define NEG(x) (1 + ~(x))
#if CLUTTER_COGL_GL
#if HAVE_COGL_GL
glLoadName (clutter_actor_get_id (self));
#endif
if (clutter_actor_get_parent (self) != NULL)
{
cogl_translate (CLUTTER_FIXED_TO_FLOAT (priv->coords.x1),
CLUTTER_FIXED_TO_FLOAT (priv->coords.y1),
cogl_translate (CLUTTER_UNITS_TO_INT (priv->coords.x1),
CLUTTER_UNITS_TO_INT (priv->coords.y1),
0);
}
@ -344,7 +340,7 @@ clutter_actor_paint (ClutterActor *self)
cogl_scale (priv->scale_x, priv->scale_y);
}
#if CLUTTER_COGL_GL
#if HAVE_COGL_GL
if (priv->has_clip)
{
ClutterGeometry *clip = &(priv->clip);

View File

@ -801,8 +801,8 @@ guint32
clutter_smoothstep_func (ClutterAlpha *alpha,
gpointer *data)
{
ClutterSmoothstep * smoothstep = data;
ClutterTimeline * timeline;
ClutterSmoothstep *smoothstep = (ClutterSmoothstep*)data;
ClutterTimeline *timeline;
gint frame;
gint n_frames;
gint32 r;

View File

@ -148,7 +148,7 @@ _clutter_backend_get_features (ClutterBackend *backend)
{
ClutterBackendClass *klass;
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), 0);
klass = CLUTTER_BACKEND_GET_CLASS (backend);
if (klass->get_features)

View File

@ -50,7 +50,6 @@ typedef struct ClutterFeatures
} ClutterFeatures;
static ClutterFeatures* __features = NULL;
G_LOCK_DEFINE_STATIC (__features);
void
_clutter_feature_init (void)

View File

@ -41,7 +41,8 @@ typedef enum
{
CLUTTER_FEATURE_TEXTURE_RECTANGLE = (1 << 1),
CLUTTER_FEATURE_SYNC_TO_VBLANK = (1 << 2),
CLUTTER_FEATURE_TEXTURE_READ_PIXELS = (1 << 3)
CLUTTER_FEATURE_TEXTURE_YUV = (1 << 3),
CLUTTER_FEATURE_TEXTURE_READ_PIXELS = (1 << 4)
} ClutterFeatureFlags;
gboolean clutter_feature_available (ClutterFeatureFlags feature);

View File

@ -135,6 +135,10 @@ typedef gint32 ClutterAngle; /* angle such that 1024 == 2*PI */
#define CLUTTER_FIXED_MUL(x,y) ((x) >> 8) * ((y) >> 8)
#define CLUTTER_FIXED_DIV(x,y) ((((x) << 8)/(y)) << 8)
#define CLUTTER_DEGF_TO_CLUTTER_ANGLE(x) CLUTTER_FLOAT_TO_INT ((x / 360.0) * 1024)
#define CLUTTER_ANGLE_TO_DEGF(x) (((float)x * 360.0)/ 1024.0)
/* some handy short aliases to avoid exessively long lines */
#define CFX_INT CLUTTER_FIXED_INT

View File

@ -46,8 +46,6 @@
#include "clutter-marshal.h"
#include "clutter-enum-types.h"
#include <GL/gl.h>
enum
{
ADD,
@ -76,7 +74,7 @@ clutter_group_paint (ClutterActor *actor)
CLUTTER_NOTE (PAINT, "ClutterGroup paint enter");
glPushMatrix();
cogl_push_matrix();
for (child_item = self->priv->children;
child_item != NULL;
@ -90,7 +88,7 @@ clutter_group_paint (ClutterActor *actor)
clutter_actor_paint (child);
}
glPopMatrix();
cogl_pop_matrix();
CLUTTER_NOTE (PAINT, "ClutterGroup paint leave");
}
@ -175,7 +173,7 @@ static void
clutter_group_real_show_all (ClutterActor *actor)
{
clutter_group_foreach (CLUTTER_GROUP (actor),
CLUTTER_CALLBACK (clutter_actor_show_all),
CLUTTER_CALLBACK (clutter_actor_show),
NULL);
clutter_actor_show (actor);
}
@ -185,7 +183,7 @@ clutter_group_real_hide_all (ClutterActor *actor)
{
clutter_actor_hide (actor);
clutter_group_foreach (CLUTTER_GROUP (actor),
CLUTTER_CALLBACK (clutter_actor_hide_all),
CLUTTER_CALLBACK (clutter_actor_hide),
NULL);
}

View File

@ -650,10 +650,12 @@ clutter_base_init (void)
if (!initialised)
{
GType foo; /* Quiet gcc */
initialised = TRUE;
/* initialise GLib type system */
g_type_init ();
(void) clutter_actor_get_type ();
foo = clutter_actor_get_type ();
}
}

View File

@ -116,9 +116,6 @@ void _clutter_event_button_generate (ClutterBackend *backend,
void _clutter_feature_init (void);
/* FIXME: move elsewhere via ClutterAudience */
void _clutter_stage_sync_viewport (ClutterStage *stage);
/* Does this need to be private ? */
void clutter_do_event (ClutterEvent *event);

View File

@ -130,7 +130,7 @@ clutter_rectangle_paint (ClutterActor *self)
cogl_rectangle (0, 0, geom.width, geom.height);
}
cogl_push_matrix();
cogl_pop_matrix();
}
static void

View File

@ -48,9 +48,6 @@
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
#define FIXED_PERSPECTIVE
#undef USING_GLES
G_DEFINE_ABSTRACT_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP);
#define CLUTTER_STAGE_GET_PRIVATE(obj) \
@ -58,7 +55,9 @@ G_DEFINE_ABSTRACT_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP);
struct _ClutterStagePrivate
{
ClutterColor color;
ClutterColor color;
ClutterPerspective perspective;
ClutterAudience audience;
guint is_fullscreen : 1;
guint is_offscreen : 1;
@ -72,7 +71,9 @@ enum
PROP_COLOR,
PROP_FULLSCREEN,
PROP_OFFSCREEN,
PROP_CURSOR_VISIBLE
PROP_CURSOR_VISIBLE,
PROP_PERSPECTIVE,
PROP_AUDIENCE
};
enum
@ -98,8 +99,7 @@ clutter_stage_paint (ClutterActor *actor)
/* chain up */
CLUTTER_NOTE (PAINT, "Chaining up to parent class paint");
if (CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint)
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (actor);
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (actor);
}
static void
@ -108,9 +108,9 @@ clutter_stage_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
ClutterStage *stage;
ClutterStage *stage;
ClutterStagePrivate *priv;
ClutterActor *actor;
ClutterActor *actor;
stage = CLUTTER_STAGE (object);
actor = CLUTTER_ACTOR (stage);
@ -122,11 +122,17 @@ clutter_stage_set_property (GObject *object,
clutter_stage_set_color (stage, g_value_get_boxed (value));
break;
case PROP_OFFSCREEN:
if (priv->is_offscreen == g_value_get_boolean (value))
return;
if (CLUTTER_ACTOR_IS_REALIZED (actor))
{
clutter_actor_unrealize (actor);
priv->is_offscreen = g_value_get_boolean (value);
clutter_actor_realize (actor);
if (!CLUTTER_ACTOR_IS_REALIZED (actor))
priv->is_offscreen = ~g_value_get_boolean (value);
}
else
priv->is_offscreen = g_value_get_boolean (value);
@ -143,6 +149,12 @@ clutter_stage_set_property (GObject *object,
else
clutter_stage_hide_cursor (stage);
break;
case PROP_PERSPECTIVE:
clutter_stage_set_perspectivex (stage, g_value_get_boxed (value));
break;
case PROP_AUDIENCE:
clutter_stage_set_audience (stage, g_value_get_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -158,6 +170,8 @@ clutter_stage_get_property (GObject *object,
ClutterStage *stage;
ClutterStagePrivate *priv;
ClutterColor color;
ClutterAudience audience;
ClutterPerspective perspective;
stage = CLUTTER_STAGE(object);
priv = stage->priv;
@ -177,6 +191,14 @@ clutter_stage_get_property (GObject *object,
case PROP_CURSOR_VISIBLE:
g_value_set_boolean (value, priv->is_cursor_visible);
break;
case PROP_PERSPECTIVE:
clutter_stage_get_perspectivex (stage, &perspective);
g_value_set_boxed (value, &perspective);
break;
case PROP_AUDIENCE:
clutter_stage_get_audience (stage, &audience);
g_value_set_boxed (value, &audience);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -470,6 +492,119 @@ clutter_stage_get_color (ClutterStage *stage,
color->alpha = priv->color.alpha;
}
/**
* clutter_stage_set_perspectivex
* @stage: A #ClutterStage
* @perspective: A #ClutterPerspective
*
* Set the stage perspective.
**/
void
clutter_stage_set_perspectivex (ClutterStage *stage,
ClutterPerspective *perspective)
{
ClutterStagePrivate *priv;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
priv = stage->priv;
priv->perspective.fovy = perspective->fovy;
priv->perspective.aspect = perspective->aspect;
priv->perspective.z_near = perspective->z_near;
priv->perspective.z_far = perspective->z_far;
CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
}
/**
* clutter_stage_get_perspectivex
* @stage: A #ClutterStage
* @perspective: return location for a #ClutterPerspective
*
* Retrieves the stage perspective.
*/
void
clutter_stage_get_perspectivex (ClutterStage *stage,
ClutterPerspective *perspective)
{
ClutterStagePrivate *priv;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
priv = stage->priv;
perspective->fovy = priv->perspective.fovy;
perspective->aspect = priv->perspective.aspect;
perspective->z_near = priv->perspective.z_near;
perspective->z_far = priv->perspective.z_far;
}
/**
* clutter_stage_set_perspective
* @stage: A #ClutterStage
* FIXME
*
* Set the stage perspective.
**/
void
clutter_stage_set_perspective (ClutterStage *stage,
gfloat fovy,
gfloat aspect,
gfloat z_near,
gfloat z_far)
{
ClutterStagePrivate *priv;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
priv = stage->priv;
priv->perspective.fovy = CLUTTER_DEGF_TO_CLUTTER_ANGLE(fovy);
priv->perspective.aspect = CLUTTER_FLOAT_TO_FIXED(aspect);
priv->perspective.z_near = CLUTTER_FLOAT_TO_FIXED(z_near);
priv->perspective.z_far = CLUTTER_FLOAT_TO_FIXED(z_far);
CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
}
/**
* clutter_stage_get_perspective
* @stage: A #ClutterStage
* @perspective: return location for a #ClutterPerspective
*
* Retrieves the stage perspective.
*/
void
clutter_stage_get_perspective (ClutterStage *stage,
gfloat *fovy,
gfloat *aspect,
gfloat *z_near,
gfloat *z_far)
{
ClutterStagePrivate *priv;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
priv = stage->priv;
*fovy = CLUTTER_ANGLE_TO_DEGF(priv->perspective.fovy);
*aspect = CLUTTER_FIXED_TO_FLOAT(priv->perspective.aspect);
*z_near = CLUTTER_FIXED_TO_FLOAT(priv->perspective.z_near);
*z_far = CLUTTER_FIXED_TO_FLOAT(priv->perspective.z_far);
}
void
clutter_stage_set_audience (ClutterStage *stage,
ClutterAudience *audience)
{
}
void
clutter_stage_get_audience (ClutterStage *stage,
ClutterAudience *audience)
{
}
/**
* clutter_stage_fullscreen:
* @stage: a #ClutterStage
@ -616,31 +751,6 @@ clutter_stage_snapshot (ClutterStage *stage,
return NULL;
}
void
_clutter_stage_sync_viewport (ClutterStage *stage)
{
/* FIXME:
* Something needs to be done with this func, apps may need to
* overide it and its need better integration into the backend.
*/
ClutterActor *actor;
gint width, height;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
actor = CLUTTER_ACTOR (stage);
width = clutter_actor_get_width (actor);
height = clutter_actor_get_height (actor);
cogl_setup_viewport (width,
height,
171, /* 60 degrees */
CFX_ONE,
CLUTTER_FLOAT_TO_FIXED (0.1),
CLUTTER_FLOAT_TO_FIXED (100.0));
}
/**
* clutter_stage_get_actor_at_pos:
* @stage:
@ -666,9 +776,12 @@ clutter_stage_get_actor_at_pos (ClutterStage *stage,
GLuint buff[64] = { 0 };
GLint hits;
GLint view[4];
ClutterMainContext *ctx;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
ctx = clutter_context_get_default ();
glSelectBuffer (sizeof (buff), buff);
glGetIntegerv (GL_VIEWPORT, view);
glRenderMode (GL_SELECT);
@ -702,17 +815,17 @@ clutter_stage_get_actor_at_pos (ClutterStage *stage,
if (hits != 0)
{
#if 0
gint i
#if 1
gint i;
for (i = 0; i < hits; i++)
g_print ("Hit at %i\n", buff[i * 4 + 3]);
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]);
}
_clutter_stage_sync_viewport (stage);
CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
return found;
#else
@ -809,7 +922,7 @@ clutter_stage_event (ClutterStage *stage,
*
* Return value: an allocated copy of @perspective.
*
* Since: 0.2
* Since: 0.4
*/
ClutterPerspective *
clutter_perspective_copy (const ClutterPerspective *perspective)
@ -852,3 +965,58 @@ clutter_perspective_get_type (void)
(GBoxedFreeFunc) clutter_perspective_free);
return our_type;
}
/*** Audience boxed type ******/
/**
* clutter_audience_copy:
* @audience: a #ClutterAudience
*
* Makes a copy of the audience structure. The result must be
* freed using clutter_audience_free().
*
* Return value: an allocated copy of @audience.
*
* Since: 0.4
*/
ClutterAudience *
clutter_audience_copy (const ClutterAudience *audience)
{
ClutterAudience *result;
g_return_val_if_fail (audience != NULL, NULL);
result = g_slice_new (ClutterAudience);
*result = *audience;
return result;
}
/**
* clutter_audience_free:
* @audience: a #ClutterAudience
*
* Frees a audience structure created with clutter_audience_copy().
*
* Since: 0.4
*/
void
clutter_audience_free (ClutterAudience *audience)
{
g_return_if_fail (audience != NULL);
g_slice_free (ClutterAudience, audience);
}
GType
clutter_audience_get_type (void)
{
static GType our_type = 0;
if (!our_type)
our_type = g_boxed_type_register_static
("ClutterAudience",
(GBoxedCopyFunc) clutter_audience_copy,
(GBoxedFreeFunc) clutter_audience_free);
return our_type;
}

View File

@ -128,14 +128,24 @@ struct _ClutterPerspective
{
ClutterFixed fovy;
ClutterFixed aspect;
ClutterFixed zNear;
ClutterFixed zFar;
ClutterFixed z_near;
ClutterFixed z_far;
};
#define CLUTTER_TYPE_AUDIENCE (clutter_audience_get_type ())
typedef struct _ClutterAudience ClutterAudience;
struct _ClutterAudience
{
};
GType clutter_perspective_get_type (void) G_GNUC_CONST;
ClutterPerspective *clutter_perspective_copy (const ClutterPerspective *perspective);
void clutter_perspective_free (ClutterPerspective *perspective);
GType clutter_audience_get_type (void) G_GNUC_CONST;
ClutterAudience *clutter_audience_copy (const ClutterAudience *audience);
void clutter_audience_free (ClutterAudience *audience);
GType clutter_stage_get_type (void) G_GNUC_CONST;
@ -145,6 +155,24 @@ void clutter_stage_set_color (ClutterStage *stage,
const ClutterColor *color);
void clutter_stage_get_color (ClutterStage *stage,
ClutterColor *color);
void clutter_stage_set_perspectivex (ClutterStage *stage,
ClutterPerspective *perspective);
void clutter_stage_get_perspectivex (ClutterStage *stage,
ClutterPerspective *perspective);
void clutter_stage_set_perspective (ClutterStage *stage,
gfloat fovy,
gfloat aspect,
gfloat z_near,
gfloat z_far);
void clutter_stage_get_perspective (ClutterStage *stage,
gfloat *fovy,
gfloat *aspect,
gfloat *z_near,
gfloat *z_far);
void clutter_stage_set_audience (ClutterStage *stage,
ClutterAudience *audience);
void clutter_stage_get_audience (ClutterStage *stage,
ClutterAudience *audience);
void clutter_stage_fullscreen (ClutterStage *stage);
void clutter_stage_unfullscreen (ClutterStage *stage);
void clutter_stage_show_cursor (ClutterStage *stage);

View File

@ -30,10 +30,13 @@
* #ClutterTexture is a base class for displaying and manipulating pixel
* buffer type data.
*
* The #clutter_texture_set_from_data and #clutter_texture_set_pixbuf are
* The #clutter_texture_set_from_rgb_data and #clutter_texture_set_pixbuf are
* used to copy image data into texture memory and subsequently realize the
* the texture. Unrealizing/hiding frees image data from texture memory moving
* to main system memory. Re-realizing then performs the opposite operation.
* the texture.
*
* If texture reads are supported by underlying GL implementaion
* Unrealizing/hiding frees image data from texture memory moving to main
* system memory. Re-realizing then performs the opposite operation.
* This process allows basic management of commonly limited available texture
* memory.
*/
@ -584,7 +587,7 @@ clutter_texture_realize (ClutterActor *actor)
/* Move any local image data we have from unrealization
* back into video memory.
*/
clutter_texture_set_pixbuf (texture, priv->local_pixbuf);
clutter_texture_set_pixbuf (texture, priv->local_pixbuf, NULL);
g_object_unref (priv->local_pixbuf);
priv->local_pixbuf = NULL;
}
@ -725,7 +728,8 @@ clutter_texture_set_property (GObject *object,
{
case PROP_PIXBUF:
clutter_texture_set_pixbuf (texture,
(GdkPixbuf*)g_value_get_pointer(value));
(GdkPixbuf*)g_value_get_pointer(value),
NULL);
break;
case PROP_USE_TILES:
priv->is_tiled = g_value_get_boolean (value);
@ -739,12 +743,6 @@ clutter_texture_set_property (GObject *object,
case PROP_MAX_TILE_WASTE:
priv->max_tile_waste = g_value_get_int (value);
break;
case PROP_PIXEL_TYPE:
priv->pixel_type = g_value_get_int (value);
break;
case PROP_PIXEL_FORMAT:
priv->pixel_format = g_value_get_int (value);
break;
case PROP_SYNC_SIZE:
priv->sync_actor_size = g_value_get_boolean (value);
break;
@ -919,7 +917,7 @@ clutter_texture_class_init (ClutterTextureClass *klass)
0,
G_MAXINT,
PIXEL_TYPE,
G_PARAM_CONSTRUCT_ONLY | CLUTTER_PARAM_READWRITE));
G_PARAM_READABLE));
g_object_class_install_property
(gobject_class, PROP_PIXEL_FORMAT,
@ -929,7 +927,7 @@ clutter_texture_class_init (ClutterTextureClass *klass)
0,
G_MAXINT,
CGL_RGBA,
G_PARAM_CONSTRUCT_ONLY | CLUTTER_PARAM_READWRITE));
G_PARAM_READABLE));
/**
* ClutterTexture::size-change:
@ -1012,7 +1010,7 @@ pixbuf_destroy_notify (guchar *pixels, gpointer data)
GdkPixbuf*
clutter_texture_get_pixbuf (ClutterTexture* texture)
{
#if CLUTTER_COGL_GL
#if HAVE_COGL_GL
ClutterTexturePrivate *priv;
GdkPixbuf *pixbuf = NULL;
guchar *pixels = NULL;
@ -1137,7 +1135,7 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
}
/**
* clutter_texture_set_from_data:
* clutter_texture_set_from_rgb_data:
* @texture: A #ClutterTexture
* @data: Image data in RGB type colorspace.
* @has_alpha: Set to TRUE if image data has a alpha channel.
@ -1145,39 +1143,60 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
* @height: Height in pixels of image data
* @rowstride: Distance in bytes between row starts.
* @bpp: bytes per pixel ( Currently only 4 supported )
* @flags: #ClutterTextureFlags
* @error: FIXME.
*
* Sets #ClutterTexture image data.
*
* Since 0.2. This function is likely to change in future versions.
* Return value: TRUE on success, FALSE on failure.
*
* Since 0.4. This function is likely to change in future versions.
**/
void
clutter_texture_set_from_data (ClutterTexture *texture,
const guchar *data,
gboolean has_alpha,
gint width,
gint height,
gint rowstride,
gint bpp)
gboolean
clutter_texture_set_from_rgb_data (ClutterTexture *texture,
const guchar *data,
gboolean has_alpha,
gint width,
gint height,
gint rowstride,
gint bpp,
ClutterTextureFlags flags,
GError *error)
{
ClutterTexturePrivate *priv;
gboolean texture_dirty = TRUE;
COGLenum prev_format;
priv = texture->priv;
g_return_if_fail (data != NULL);
g_return_if_fail (bpp == 4);
g_return_val_if_fail (data != NULL, FALSE);
/* Needed for GL_RGBA (internal format) and gdk pixbuf usage */
g_return_val_if_fail (bpp == 4, FALSE);
/* FIXME: check other image props */
texture_dirty = (width != priv->width || height != priv->height);
priv->width = width;
priv->height = height;
prev_format = priv->pixel_format;
if (has_alpha)
priv->pixel_format = CGL_RGBA;
else
priv->pixel_format = CGL_RGB;
if (flags & CLUTTER_TEXTURE_RGB_FLAG_BGR)
{
if (has_alpha)
priv->pixel_format = CGL_BGRA;
else
priv->pixel_format = CGL_BGR;
}
if (prev_format != priv->pixel_format || priv->pixel_type != PIXEL_TYPE)
texture_dirty = TRUE;
priv->pixel_type = PIXEL_TYPE;
priv->width = width;
priv->height = height;
if (texture_dirty)
{
texture_free_gl_resources (texture);
@ -1220,8 +1239,14 @@ clutter_texture_set_from_data (ClutterTexture *texture,
priv->width,
priv->height);
texture_upload_data (texture, data, has_alpha,
width, height, rowstride, bpp);
/* Set Error from this */
texture_upload_data (texture,
data,
has_alpha,
width,
height,
rowstride,
bpp);
CLUTTER_ACTOR_SET_FLAGS (CLUTTER_ACTOR (texture), CLUTTER_ACTOR_REALIZED);
@ -1243,6 +1268,110 @@ clutter_texture_set_from_data (ClutterTexture *texture,
if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR(texture)))
clutter_actor_queue_redraw (CLUTTER_ACTOR(texture));
return TRUE;
}
/**
* clutter_texture_set_from_yuv_data:
* @texture: A #ClutterTexture
* @data: Image data in RGB type colorspace.
* @width: Width in pixels of image data.
* @height: Height in pixels of image data
* @flags: #ClutterTextureFlags
* @error: FIXME.
*
* Sets a #ClutterTexture from YUV image data.
*
* Return value: TRUE on success, FALSE on failure.
*
* Since 0.4. This function is likely to change in future versions.
**/
gboolean
clutter_texture_set_from_yuv_data (ClutterTexture *texture,
const guchar *data,
gint width,
gint height,
ClutterTextureFlags flags,
GError *error)
{
#if 0
gboolean texture_dirty = TRUE;
COGLenum prev_format;
if (!clutter_feature_available(CLUTTER_FEATURE_TEXTURE_YUV))
return FALSE;
priv = texture->priv;
/* FIXME: check other image props */
texture_dirty = (width != priv->width || height != priv->height);
priv->width = width;
priv->height = height;
/* #ifdef GL_YCBCR_MESA */
priv->pixel_format = CGL_YCBCR_MESA;
if (!priv->tiles)
{
priv->tiles = g_new (guint, 1);
glGenTextures (1, priv->tiles);
}
cogl_texture_bind (priv->target_type, priv->tiles[0]);
cogl_texture_set_filters (priv->target_type,
priv->filter_quality ? CGL_LINEAR : CGL_NEAREST,
priv->filter_quality ? CGL_LINEAR : CGL_NEAREST);
if (texture_dirty)
{
if (cogl_texture_can_size(priv->pixel_format,
priv->pixel_type,
clutter_util_next_p2(priv->width),
clutter_util_next_p2(priv->height)))
{
glTexImage2D (CGL_TEXTURE_2D,
0,
GL_YCBCR_MESA,
clutter_util_next_p2(priv->width),
clutter_util_next_p2(priv->height),
0,
GL_YCBCR_MESA,
GL_UNSIGNED_SHORT_8_8_REV_MESA,
NULL);
}
else
/* No tiled support for YUV textures as yet */
return FALSE; /* Set Error */
}
if (flags & CLUTTER_TEXTURE_YUV_FLAG_YUV2)
{
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
priv->width,
priv->height
CGL_YCBCR_MESA,
CGL_UNSIGNED_SHORT_8_8_REV_MESA,
data);
}
else
{
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
priv->width,
priv->height
CGL_YCBCR_MESA,
CGL_UNSIGNED_SHORT_8_8_MESA,
data);
}
#endif
return FALSE;
}
/**
@ -1253,23 +1382,26 @@ clutter_texture_set_from_data (ClutterTexture *texture,
* Sets a #ClutterTexture image data from a #GdkPixbuf
*
**/
void
gboolean
clutter_texture_set_pixbuf (ClutterTexture *texture,
GdkPixbuf *pixbuf)
GdkPixbuf *pixbuf,
GError *error)
{
ClutterTexturePrivate *priv;
priv = texture->priv;
g_return_if_fail (pixbuf != NULL);
g_return_val_if_fail (pixbuf != NULL, FALSE);
clutter_texture_set_from_data (texture,
gdk_pixbuf_get_pixels (pixbuf),
gdk_pixbuf_get_has_alpha (pixbuf),
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
gdk_pixbuf_get_rowstride (pixbuf),
4);
return clutter_texture_set_from_rgb_data (texture,
gdk_pixbuf_get_pixels (pixbuf),
gdk_pixbuf_get_has_alpha (pixbuf),
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
gdk_pixbuf_get_rowstride (pixbuf),
4,
0,
error);
}
/**

View File

@ -31,40 +31,6 @@
G_BEGIN_DECLS
#if 0
/* New API Ideas */
#define CLUTTER_TEXTURE_RGB_FLAG_BRGA (1<<1)
#define CLUTTER_TEXTURE_RGB_FLAG_PREMULT (1<<2)
gboolean
clutter_texture_set_from_rgb_data (ClutterTexture *texture,
const guchar *data,
gboolean has_alpha,
gint width,
gint height,
gint rowstride,
gint bpp,
gint flags,
GError *error);
gboolean
clutter_texture_set_from_yuv_data (ClutterTexture *texture,
const guchar *data,
gint width,
gint height,
gint flags,
GError *error);
Notes
=====
- drop format and type props - would be set in GL texture automagically
via about calls.
#endif
#define CLUTTER_TYPE_TEXTURE (clutter_texture_get_type ())
#define CLUTTER_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TEXTURE, ClutterTexture))
#define CLUTTER_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_TEXTURE, ClutterTextureClass))
@ -101,19 +67,36 @@ struct _ClutterTextureClass
void (*_clutter_texture6) (void);
};
typedef enum ClutterTextureFlags
{
CLUTTER_TEXTURE_RGB_FLAG_BGR = (1<<1),
CLUTTER_TEXTURE_RGB_FLAG_PREMULT = (1<<2),
CLUTTER_TEXTURE_YUV_FLAG_YUV2 = (1<<3)
/* FIXME: add compressed types ? */
} ClutterTextureFlags;
GType clutter_texture_get_type (void) G_GNUC_CONST;
ClutterActor *clutter_texture_new (void);
ClutterActor *clutter_texture_new_from_pixbuf (GdkPixbuf *pixbuf);
void clutter_texture_set_from_data (ClutterTexture *texture,
const guchar *data,
gboolean has_alpha,
gint width,
gint height,
gint rowstride,
gint bpp);
void clutter_texture_set_pixbuf (ClutterTexture *texture,
GdkPixbuf *pixbuf);
gboolean clutter_texture_set_from_rgb_data (ClutterTexture *texture,
const guchar *data,
gboolean has_alpha,
gint width,
gint height,
gint rowstride,
gint bpp,
ClutterTextureFlags flags,
GError *error);
gboolean clutter_texture_set_from_yuv_data (ClutterTexture *texture,
const guchar *data,
gint width,
gint height,
ClutterTextureFlags flags,
GError *error);
gboolean clutter_texture_set_pixbuf (ClutterTexture *texture,
GdkPixbuf *pixbuf,
GError *error);
GdkPixbuf * clutter_texture_get_pixbuf (ClutterTexture *texture);
void clutter_texture_get_base_size (ClutterTexture *texture,
gint *width,

View File

@ -329,7 +329,10 @@ timeline_timeout_func (gpointer data)
}
if (priv->loop)
clutter_timeline_rewind (timeline);
{
clutter_timeline_rewind (timeline);
g_signal_emit (timeline, timeline_signals[COMPLETED], 0);
}
else
{
clutter_timeline_stop (timeline);

View File

@ -29,12 +29,6 @@
#include <GL/gl.h>
#include <string.h>
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define PIXEL_TYPE GL_UNSIGNED_BYTE
#else
#define PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
#endif
static gulong __enable_flags = 0;
#if COGL_DEBUG
@ -110,6 +104,7 @@ check_gl_extension (const gchar *name,
return FALSE;
}
#if 0
static gboolean
is_gl_version_at_least_12 (void)
{
@ -117,7 +112,7 @@ is_gl_version_at_least_12 (void)
return
(g_ascii_strtod ((const gchar*) glGetString (GL_VERSION), NULL) >= 1.2);
#if 0
/* At least GL 1.2 is needed for CLAMP_TO_EDGE */
/* FIXME: move to cogl... */
if (!is_gl_version_at_least_12 ())
@ -127,13 +122,14 @@ is_gl_version_at_least_12 (void)
"Clutter needs at least version 1.2 of OpenGL");
return FALSE;
}
#endif
}
#endif
CoglFuncPtr
cogl_get_proc_address (const gchar* name)
{
/* FIXME */
return NULL;
}
gboolean
@ -583,13 +579,35 @@ cogl_get_features ()
gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);
if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions) ||
check_gl_extension ("GL_EXT_texture_rectangle", gl_extensions))
{
flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE;
}
#ifdef GL_YCBCR_MESA
if (check_gl_extension ("GL_MESA_ycbcr_texture", gl_extensions))
{
flags |= CLUTTER_FEATURE_TEXTURE_YUV;
}
#endif
#if 0
CLUTTER_NOTE (GL,
"\n"
"===========================================\n"
"GL_VENDOR: %s\n"
"GL_RENDERER: %s\n"
"GL_VERSION: %s\n"
"GL_EXTENSIONS: %s\n"
"===========================================\n",
glGetString (GL_VENDOR),
glGetString (GL_RENDERER),
glGetString (GL_VERSION),
glGetString (GL_EXTENSIONS),
: "no");
#endif
return flags;
}

View File

@ -149,7 +149,7 @@ clutter_backend_glx_post_parse (ClutterBackend *backend,
if (clutter_display_name)
{
CLUTTER_NOTE (MISC, "XOpenDisplay on `%s'", clutter_display_name);
CLUTTER_NOTE (BACKEND, "XOpenDisplay on `%s'", clutter_display_name);
backend_glx->xdpy = XOpenDisplay (clutter_display_name);
}
else
@ -164,7 +164,9 @@ clutter_backend_glx_post_parse (ClutterBackend *backend,
if (backend_glx->xdpy)
{
CLUTTER_NOTE (MISC, "Getting the X screen");
int glx_major, glx_minor;
CLUTTER_NOTE (BACKEND, "Getting the X screen");
if (clutter_screen == 0)
backend_glx->xscreen = DefaultScreenOfDisplay (backend_glx->xdpy);
@ -179,6 +181,28 @@ clutter_backend_glx_post_parse (ClutterBackend *backend,
backend_glx->display_name = g_strdup (clutter_display_name);
CLUTTER_NOTE (BACKEND, "Checking GLX info");
if (!glXQueryVersion (backend_glx->xdpy, &glx_major, &glx_minor)
|| !(glx_major > 1 || glx_minor > 1))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"XServer appears to lack required GLX support");
return 1;
}
#if 0
/* Prefer current GLX specs over current violations */
if (!(glx_major > 1 || glx_minor > 2))
{
const char* exts = glXQueryExtensionsString (display, screen);
if (!exts || !strstr (exts, "GLX_SGIX_fbconfig"))
have_fbconfig = 0;
}
#endif
}
g_free (clutter_display_name);

View File

@ -210,10 +210,13 @@ clutter_stage_glx_realize (ClutterActor *actor)
else
{
int gl_attributes[] = {
GLX_RGBA,
GLX_DEPTH_SIZE, 0,
GLX_ALPHA_SIZE, 0,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_USE_GL,
GLX_RGBA,
0
};
@ -227,10 +230,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
if (!stage_glx->xvisinfo)
{
g_critical ("Unable to find suitable GL visual.");
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
goto fail;
}
if (stage_glx->gl_context)
@ -240,7 +240,8 @@ clutter_stage_glx_realize (ClutterActor *actor)
stage_glx->xwin_root,
stage_glx->xwin_width,
stage_glx->xwin_height,
stage_glx->xvisinfo->depth);
DefaultDepth (stage_glx->xdpy,
stage_glx->xscreen));
stage_glx->glxpixmap = glXCreateGLXPixmap (stage_glx->xdpy,
stage_glx->xvisinfo,
@ -252,10 +253,18 @@ clutter_stage_glx_realize (ClutterActor *actor)
0,
False);
clutter_glx_trap_x_errors ();
glXMakeCurrent (stage_glx->xdpy,
stage_glx->glxpixmap,
stage_glx->gl_context);
if (clutter_glx_untrap_x_errors ())
{
g_critical ("Unable to set up offscreen context.");
goto fail;
}
#if 0
/* Debug code for monitoring a off screen pixmap via window */
{
@ -282,25 +291,18 @@ clutter_stage_glx_realize (ClutterActor *actor)
XMapWindow(clutter_glx_display(), foo_win);
}
#endif
}
CLUTTER_NOTE (GL,
"\n"
"===========================================\n"
"GL_VENDOR: %s\n"
"GL_RENDERER: %s\n"
"GL_VERSION: %s\n"
"GL_EXTENSIONS: %s\n"
"Direct Rendering: %s\n"
"===========================================\n",
glGetString (GL_VENDOR),
glGetString (GL_RENDERER),
glGetString (GL_VERSION),
glGetString (GL_EXTENSIONS),
glXIsDirect (stage_glx->xdpy, stage_glx->gl_context) ? "yes"
: "no");
CLUTTER_SET_PRIVATE_FLAGS(actor, CLUTTER_ACTOR_SYNC_MATRICES);
_clutter_stage_sync_viewport (CLUTTER_STAGE (stage_glx));
return;
fail:
/* For one reason or another we cant realize the stage.. */
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
return;
}
static void
@ -324,12 +326,12 @@ clutter_stage_glx_paint (ClutterActor *self)
/* Reset view matrices if needed. */
if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_SYNC_MATRICES)
{
/*
cogl_set_view_matrix (view_width,
view_height,
perspective)
*/
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 */
@ -409,7 +411,7 @@ clutter_stage_glx_request_coords (ClutterActor *self,
clutter_actor_realize (self);
}
_clutter_stage_sync_viewport (CLUTTER_STAGE (stage_glx));
CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
}
if (stage_glx->xwin != None) /* Do we want to bother ? */
@ -453,7 +455,7 @@ clutter_stage_glx_set_fullscreen (ClutterStage *stage,
XDeleteProperty (stage_glx->xdpy, stage_glx->xwin, atom_WM_STATE);
}
_clutter_stage_sync_viewport (stage);
CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
}
static void
@ -496,8 +498,6 @@ clutter_stage_glx_set_cursor_visible (ClutterStage *stage,
XDefineCursor (stage_glx->xdpy, stage_glx->xwin, curs);
#endif /* HAVE_XFIXES */
}
_clutter_stage_sync_viewport (stage);
}
static void
@ -623,6 +623,8 @@ clutter_stage_glx_init (ClutterStageGlx *stage)
stage->xvisinfo = None;
stage->is_foreign_xwin = FALSE;
CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES);
}
/**

View File

@ -4,7 +4,7 @@ INCLUDES = -I$(top_srcdir)/
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
AM_CFLAGS = $(CLUTTER_CFLAGS)
LDFLAGS = $(CLUTTER_LIBS)
AM_LDFLAGS = $(CLUTTER_LIBS)
slider_SOURCES = slider.c

View File

@ -1,10 +1,11 @@
noinst_PROGRAMS = test-textures test-events
noinst_PROGRAMS = test-textures test-events test-offscreen test-scale
INCLUDES = -I$(top_srcdir)/
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
AM_CFLAGS = $(CLUTTER_CFLAGS)
LDFLAGS = $(CLUTTER_LIBS)
AM_LDFLAGS = $(CLUTTER_LIBS)
test_textures_SOURCES = test-textures.c
test_events_SOURCES = test-events.c
test_textures_SOURCES = test-textures.c
test_events_SOURCES = test-events.c
test_offscreen_SOURCES = test-offscreen.c
test_scale_SOURCES = test-scale.c

31
tests/test-offscreen.c Normal file
View File

@ -0,0 +1,31 @@
#include <clutter/clutter.h>
/* Very simple test just to see what happens setting up offscreen rendering */
int
main (int argc, char *argv[])
{
ClutterActor *stage;
gboolean offscreen;
clutter_init (&argc, &argv);
stage = clutter_stage_get_default ();
/* Attempt to set up rendering offscreen */
g_object_set (stage, "offscreen", TRUE, NULL);
/* See if it worked */
g_object_get (stage, "offscreen", &offscreen, NULL);
if (offscreen == FALSE)
printf ("FAIL: Unable to setup offscreen rendering\n.");
else
printf ("SUCCESS: Able to setup offscreen rendering\n.");
clutter_actor_show_all (CLUTTER_ACTOR (stage));
clutter_main();
return 0;
}

80
tests/test-scale.c Normal file
View File

@ -0,0 +1,80 @@
#include <clutter/clutter.h>
ClutterGravity gravitys[] = {
CLUTTER_GRAVITY_NORTH_EAST,
CLUTTER_GRAVITY_NORTH,
CLUTTER_GRAVITY_NORTH_WEST,
CLUTTER_GRAVITY_WEST,
CLUTTER_GRAVITY_SOUTH_WEST,
CLUTTER_GRAVITY_SOUTH,
CLUTTER_GRAVITY_SOUTH_EAST,
CLUTTER_GRAVITY_EAST,
CLUTTER_GRAVITY_CENTER,
CLUTTER_GRAVITY_NONE
};
gint gindex = 0;
void
on_timeline_completed (ClutterTimeline *cluttertimeline,
gpointer data)
{
ClutterBehaviourScale *behave = CLUTTER_BEHAVIOUR_SCALE(data);
if (++gindex > G_N_ELEMENTS(gravitys))
gindex = 0;
g_object_set (behave, "scale-gravity", gravitys[gindex], NULL);
}
int
main (int argc, char *argv[])
{
ClutterActor *stage, *rect;
ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
ClutterColor rect_color = { 0xff, 0xff, 0xff, 0x99 };
ClutterTimeline *timeline;
ClutterAlpha *alpha;
ClutterBehaviour *behave;
clutter_init (&argc, &argv);
stage = clutter_stage_get_default ();
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
clutter_actor_set_size (stage, 300, 300);
rect = clutter_rectangle_new_with_color(&rect_color);
clutter_actor_set_size (rect, 100, 100);
clutter_actor_set_position (rect, 100, 100);
clutter_group_add (CLUTTER_GROUP(stage), rect);
rect_color.alpha = 0xff;
rect = clutter_rectangle_new_with_color(&rect_color);
clutter_actor_set_size (rect, 100, 100);
clutter_actor_set_position (rect, 100, 100);
clutter_group_add (CLUTTER_GROUP(stage), rect);
timeline = clutter_timeline_new (20, 30);
alpha = clutter_alpha_new_full (timeline,
CLUTTER_ALPHA_RAMP,
NULL, NULL);
behave = clutter_behaviour_scale_new (alpha,
0.0,
1.0,
gravitys[gindex]);
clutter_behaviour_apply (behave, rect);
clutter_timeline_set_loop (timeline, TRUE);
g_signal_connect (timeline, "completed",
G_CALLBACK(on_timeline_completed), behave);
clutter_timeline_start (timeline);
clutter_actor_show_all (stage);
clutter_main();
}