2006-11-15 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-actor.h: * clutter/clutter-actor.c: Add new API clutter_actor_move_by(), clutter_actor_get_size() * clutter/clutter-alpha.c: * clutter/clutter-alpha.h: Add clutter alpha sine func * clutter/clutter-behaviours.h: * clutter/clutter-behaviours.c: Add a basic scale behaviour (needs work) * examples/behave.c: (main): More playing with new behaviour functionality * clutter/clutter-feature.c: * clutter/clutter-feature.h: * clutter/clutter-main.c: Add new experimental sync to vblank code Set env CLUTTER_VBLANK=none to disable.
This commit is contained in:
parent
3f62c72d07
commit
5ca4d3718d
@ -874,6 +874,36 @@ clutter_actor_set_position (ClutterActor *self,
|
|||||||
clutter_actor_request_coords (self, &box);
|
clutter_actor_request_coords (self, &box);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_actor_move_by
|
||||||
|
* @self: A #ClutterActor
|
||||||
|
* @dx: Distance to move Actor on X axis.
|
||||||
|
* @dy: Distance to move Actor on Y axis.
|
||||||
|
*
|
||||||
|
* Moves an actor by specified distance relative to
|
||||||
|
* current position.
|
||||||
|
*
|
||||||
|
* Since: 0.2
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_actor_move_by (ClutterActor *self,
|
||||||
|
gint dx,
|
||||||
|
gint dy)
|
||||||
|
{
|
||||||
|
ClutterActorBox box;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||||
|
|
||||||
|
clutter_actor_allocate_coords (self, &box);
|
||||||
|
|
||||||
|
box.x2 += dx;
|
||||||
|
box.y2 += dy;
|
||||||
|
box.x1 += dx;
|
||||||
|
box.y1 += dy;
|
||||||
|
|
||||||
|
clutter_actor_request_coords (self, &box);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_actor_set_size
|
* clutter_actor_set_size
|
||||||
* @self: A #ClutterActor
|
* @self: A #ClutterActor
|
||||||
@ -900,6 +930,29 @@ clutter_actor_set_size (ClutterActor *self,
|
|||||||
clutter_actor_request_coords (self, &box);
|
clutter_actor_request_coords (self, &box);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* clutter_actor_get_size
|
||||||
|
* @self: A #ClutterActor
|
||||||
|
* @x: Location to store width if non NULL.
|
||||||
|
* @y: Location to store height if non NULL.
|
||||||
|
*
|
||||||
|
* Gets the size of an actor ignoring any scaling factors
|
||||||
|
*
|
||||||
|
* Since: 0.2
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_actor_get_size (ClutterActor *self,
|
||||||
|
guint *width,
|
||||||
|
guint *height)
|
||||||
|
{
|
||||||
|
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = clutter_actor_get_width(self);
|
||||||
|
if (height)
|
||||||
|
*height = clutter_actor_get_height(self);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_actor_get_abs_position
|
* clutter_actor_get_abs_position
|
||||||
* @self: A #ClutterActor
|
* @self: A #ClutterActor
|
||||||
|
@ -237,6 +237,16 @@ clutter_actor_get_abs_size (ClutterActor *self,
|
|||||||
guint *width,
|
guint *width,
|
||||||
guint *height);
|
guint *height);
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_actor_get_size (ClutterActor *self,
|
||||||
|
guint *width,
|
||||||
|
guint *height);
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_actor_move_by (ClutterActor *self,
|
||||||
|
gint dx,
|
||||||
|
gint dy);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "clutter-alpha.h"
|
#include "clutter-alpha.h"
|
||||||
#include "clutter-main.h"
|
#include "clutter-main.h"
|
||||||
#include "clutter-marshal.h"
|
#include "clutter-marshal.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterAlpha, clutter_alpha, G_TYPE_OBJECT);
|
G_DEFINE_TYPE (ClutterAlpha, clutter_alpha, G_TYPE_OBJECT);
|
||||||
|
|
||||||
@ -105,6 +106,26 @@ clutter_alpha_ramp_func (ClutterAlpha *alpha)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint32
|
||||||
|
clutter_alpha_sine_func (ClutterAlpha *alpha)
|
||||||
|
{
|
||||||
|
int current_frame_num, nframes;
|
||||||
|
double x;
|
||||||
|
|
||||||
|
current_frame_num =
|
||||||
|
clutter_timeline_get_current_frame (alpha->priv->timeline);
|
||||||
|
nframes =
|
||||||
|
clutter_timeline_get_n_frames (alpha->priv->timeline);
|
||||||
|
|
||||||
|
/* FIXME: fixed point, and fixed point sine() */
|
||||||
|
|
||||||
|
x = (double)(current_frame_num * 2.0f * M_PI) / nframes ;
|
||||||
|
|
||||||
|
printf("%2f\n", ((sin(x-(M_PI/2.0f)) + 1.0f ) * 0.5f ));
|
||||||
|
|
||||||
|
return (guint32) (((sin(x-(M_PI/2.0f)) + 1.0f ) * 0.5f ) * (double)CLUTTER_ALPHA_MAX_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
/* Object */
|
/* Object */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -112,9 +112,13 @@ clutter_alpha_ramp_dec_func (ClutterAlpha *alpha);
|
|||||||
guint32
|
guint32
|
||||||
clutter_alpha_ramp_func (ClutterAlpha *alpha);
|
clutter_alpha_ramp_func (ClutterAlpha *alpha);
|
||||||
|
|
||||||
|
guint32
|
||||||
|
clutter_alpha_sine_func (ClutterAlpha *alpha);
|
||||||
|
|
||||||
#define CLUTTER_ALPHA_RAMP_INC clutter_alpha_ramp_inc_func
|
#define CLUTTER_ALPHA_RAMP_INC clutter_alpha_ramp_inc_func
|
||||||
#define CLUTTER_ALPHA_RAMP_DEC clutter_alpha_ramp_dec_func
|
#define CLUTTER_ALPHA_RAMP_DEC clutter_alpha_ramp_dec_func
|
||||||
#define CLUTTER_ALPHA_RAMP clutter_alpha_ramp_func
|
#define CLUTTER_ALPHA_RAMP clutter_alpha_ramp_func
|
||||||
|
#define CLUTTER_ALPHA_SINE clutter_alpha_sine_func
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -25,10 +25,16 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:clutter-behaviour
|
* SECTION:clutter-behaviour
|
||||||
* @short_description: Class for providing behaviours to actors
|
* @short_description: Class for providing common behaviours to actors
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
* o Document
|
||||||
|
* o Add props
|
||||||
|
* o Optimise
|
||||||
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "clutter-actor.h"
|
#include "clutter-actor.h"
|
||||||
@ -341,6 +347,7 @@ clutter_path_behavior_get_knot (ClutterBehaviourPath *behave,
|
|||||||
guint index)
|
guint index)
|
||||||
{
|
{
|
||||||
/* FIXME: implement */
|
/* FIXME: implement */
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -397,7 +404,7 @@ clutter_behaviour_opacity_frame_foreach (ClutterActor *actor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_behaviour_alpha_notify (ClutterBehaviour *behave)
|
clutter_behaviour_opacity_alpha_notify (ClutterBehaviour *behave)
|
||||||
{
|
{
|
||||||
clutter_behaviour_actors_foreach
|
clutter_behaviour_actors_foreach
|
||||||
(behave,
|
(behave,
|
||||||
@ -439,7 +446,7 @@ clutter_behaviour_opacity_class_init (ClutterBehaviourOpacityClass *klass)
|
|||||||
|
|
||||||
behave_class = (ClutterBehaviourClass*) klass;
|
behave_class = (ClutterBehaviourClass*) klass;
|
||||||
|
|
||||||
behave_class->alpha_notify = clutter_behaviour_alpha_notify;
|
behave_class->alpha_notify = clutter_behaviour_opacity_alpha_notify;
|
||||||
|
|
||||||
g_type_class_add_private (object_class, sizeof (ClutterBehaviourOpacityPrivate));
|
g_type_class_add_private (object_class, sizeof (ClutterBehaviourOpacityPrivate));
|
||||||
}
|
}
|
||||||
@ -469,3 +476,156 @@ clutter_behaviour_opacity_new (ClutterAlpha *alpha,
|
|||||||
return CLUTTER_BEHAVIOUR(behave);
|
return CLUTTER_BEHAVIOUR(behave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ====================== Scale ============================
|
||||||
|
*/
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterBehaviourScale, \
|
||||||
|
clutter_behaviour_scale, \
|
||||||
|
CLUTTER_TYPE_BEHAVIOUR);
|
||||||
|
|
||||||
|
struct ClutterBehaviourScalePrivate
|
||||||
|
{
|
||||||
|
ClutterFixed scale_begin;
|
||||||
|
ClutterFixed scale_end;
|
||||||
|
ClutterGravity gravity;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CLUTTER_BEHAVIOUR_SCALE_GET_PRIVATE(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
|
||||||
|
CLUTTER_TYPE_BEHAVIOUR_SCALE, \
|
||||||
|
ClutterBehaviourScalePrivate))
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_behaviour_scale_frame_foreach (ClutterActor *actor,
|
||||||
|
ClutterBehaviourScale *behave)
|
||||||
|
{
|
||||||
|
ClutterFixed scale, factor;
|
||||||
|
guint32 alpha;
|
||||||
|
ClutterBehaviourScalePrivate *priv;
|
||||||
|
ClutterBehaviour *_behave;
|
||||||
|
gint sw, sh, w, h;
|
||||||
|
|
||||||
|
priv = CLUTTER_BEHAVIOUR_SCALE_GET_PRIVATE (behave);
|
||||||
|
_behave = CLUTTER_BEHAVIOUR (behave);
|
||||||
|
|
||||||
|
alpha = clutter_alpha_get_alpha (clutter_behaviour_get_alpha (_behave));
|
||||||
|
|
||||||
|
/* FIXME: use all fixed if possible
|
||||||
|
factor = CLUTTER_FIXED_DIV(CLUTTER_INT_TO_FIXED(alpha/2),
|
||||||
|
CLUTTER_INT_TO_FIXED(CLUTTER_ALPHA_MAX_ALPHA/2));
|
||||||
|
*/
|
||||||
|
|
||||||
|
factor = CLUTTER_FLOAT_TO_FIXED((double) alpha / CLUTTER_ALPHA_MAX_ALPHA);
|
||||||
|
|
||||||
|
scale = CLUTTER_FIXED_MUL(factor, (priv->scale_end - priv->scale_begin));
|
||||||
|
|
||||||
|
scale += priv->scale_begin;
|
||||||
|
|
||||||
|
clutter_actor_set_scalex (actor, scale, scale);
|
||||||
|
|
||||||
|
if (priv->gravity == CLUTTER_GRAVITY_NONE
|
||||||
|
|| priv->gravity == CLUTTER_GRAVITY_NORTH_WEST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clutter_actor_get_abs_size (actor, (guint*)&sw, (guint*)&sh);
|
||||||
|
clutter_actor_get_size (actor, (guint*)&w, (guint*)&h);
|
||||||
|
|
||||||
|
switch (priv->gravity)
|
||||||
|
{
|
||||||
|
case CLUTTER_GRAVITY_NORTH:
|
||||||
|
break;
|
||||||
|
case CLUTTER_GRAVITY_NORTH_EAST:
|
||||||
|
break;
|
||||||
|
case CLUTTER_GRAVITY_EAST:
|
||||||
|
break;
|
||||||
|
case CLUTTER_GRAVITY_SOUTH_EAST:
|
||||||
|
break;
|
||||||
|
case CLUTTER_GRAVITY_SOUTH:
|
||||||
|
break;
|
||||||
|
case CLUTTER_GRAVITY_SOUTH_WEST:
|
||||||
|
break;
|
||||||
|
case CLUTTER_GRAVITY_WEST:
|
||||||
|
break;
|
||||||
|
case CLUTTER_GRAVITY_CENTER:
|
||||||
|
printf("%i vs %i\n", sw, w);
|
||||||
|
clutter_actor_move_by (actor, sw - w, sh - h);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_behaviour_scale_alpha_notify (ClutterBehaviour *behave)
|
||||||
|
{
|
||||||
|
clutter_behaviour_actors_foreach
|
||||||
|
(behave,
|
||||||
|
(GFunc)clutter_behaviour_scale_frame_foreach,
|
||||||
|
CLUTTER_BEHAVIOUR_SCALE(behave));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_behaviour_scale_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (clutter_behaviour_scale_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_behaviour_scale_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
ClutterBehaviourScale *self = CLUTTER_BEHAVIOUR_SCALE(object);
|
||||||
|
|
||||||
|
if (self->priv)
|
||||||
|
{
|
||||||
|
g_free(self->priv);
|
||||||
|
self->priv = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_behaviour_scale_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_behaviour_scale_class_init (ClutterBehaviourScaleClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class;
|
||||||
|
ClutterBehaviourClass *behave_class;
|
||||||
|
|
||||||
|
object_class = (GObjectClass*) klass;
|
||||||
|
|
||||||
|
object_class->finalize = clutter_behaviour_scale_finalize;
|
||||||
|
object_class->dispose = clutter_behaviour_scale_dispose;
|
||||||
|
|
||||||
|
behave_class = (ClutterBehaviourClass*) klass;
|
||||||
|
|
||||||
|
behave_class->alpha_notify = clutter_behaviour_scale_alpha_notify;
|
||||||
|
|
||||||
|
g_type_class_add_private (object_class, sizeof (ClutterBehaviourScalePrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_behaviour_scale_init (ClutterBehaviourScale *self)
|
||||||
|
{
|
||||||
|
ClutterBehaviourScalePrivate *priv;
|
||||||
|
|
||||||
|
self->priv = priv = CLUTTER_BEHAVIOUR_SCALE_GET_PRIVATE (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterBehaviour*
|
||||||
|
clutter_behaviour_scale_new (ClutterAlpha *alpha,
|
||||||
|
double scale_begin,
|
||||||
|
double scale_end,
|
||||||
|
ClutterGravity gravity)
|
||||||
|
{
|
||||||
|
ClutterBehaviourScale *behave;
|
||||||
|
|
||||||
|
behave = g_object_new (CLUTTER_TYPE_BEHAVIOUR_SCALE,
|
||||||
|
"alpha", alpha,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
behave->priv->scale_begin = CLUTTER_FLOAT_TO_FIXED (scale_begin);
|
||||||
|
behave->priv->scale_end = CLUTTER_FLOAT_TO_FIXED (scale_end);
|
||||||
|
behave->priv->gravity = gravity;
|
||||||
|
|
||||||
|
return CLUTTER_BEHAVIOUR(behave);
|
||||||
|
}
|
||||||
|
@ -80,7 +80,7 @@ clutter_path_behavior_append_knots (ClutterBehaviourPath *pathb,
|
|||||||
const ClutterKnot *first_knot,
|
const ClutterKnot *first_knot,
|
||||||
...);
|
...);
|
||||||
|
|
||||||
/* opacity */
|
/* ============================ opacity ======================== */
|
||||||
|
|
||||||
#define CLUTTER_TYPE_BEHAVIOUR_OPACITY clutter_behaviour_opacity_get_type()
|
#define CLUTTER_TYPE_BEHAVIOUR_OPACITY clutter_behaviour_opacity_get_type()
|
||||||
|
|
||||||
@ -126,6 +126,67 @@ clutter_behaviour_opacity_new (ClutterAlpha *alpha,
|
|||||||
guint8 opacity_start,
|
guint8 opacity_start,
|
||||||
guint8 opacity_end);
|
guint8 opacity_end);
|
||||||
|
|
||||||
|
/* ============================ scale ======================== */
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_BEHAVIOUR_SCALE clutter_behaviour_scale_get_type()
|
||||||
|
|
||||||
|
#define CLUTTER_BEHAVIOUR_SCALE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||||
|
CLUTTER_TYPE_BEHAVIOUR_SCALE, ClutterBehaviourScale))
|
||||||
|
|
||||||
|
#define CLUTTER_BEHAVIOUR_SCALE_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||||
|
CLUTTER_TYPE_BEHAVIOUR_SCALE, ClutterBehaviourScaleClass))
|
||||||
|
|
||||||
|
#define CLUTTER_IS_BEHAVIOUR_SCALE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||||
|
CLUTTER_TYPE_BEHAVIOUR_SCALE))
|
||||||
|
|
||||||
|
#define CLUTTER_IS_BEHAVIOUR_SCALE_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||||
|
CLUTTER_TYPE_BEHAVIOUR_SCALE))
|
||||||
|
|
||||||
|
#define CLUTTER_BEHAVIOUR_SCALE_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||||
|
CLUTTER_TYPE_BEHAVIOUR_SCALE, ClutterBehaviourScaleClass))
|
||||||
|
|
||||||
|
typedef struct _ClutterBehaviourScale ClutterBehaviourScale;
|
||||||
|
typedef struct ClutterBehaviourScalePrivate ClutterBehaviourScalePrivate;
|
||||||
|
typedef struct _ClutterBehaviourScaleClass ClutterBehaviourScaleClass;
|
||||||
|
|
||||||
|
struct _ClutterBehaviourScale
|
||||||
|
{
|
||||||
|
ClutterBehaviour parent;
|
||||||
|
ClutterBehaviourScalePrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterBehaviourScaleClass
|
||||||
|
{
|
||||||
|
ClutterBehaviourClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CLUTTER_GRAVITY_NONE = 0,
|
||||||
|
CLUTTER_GRAVITY_NORTH,
|
||||||
|
CLUTTER_GRAVITY_NORTH_EAST,
|
||||||
|
CLUTTER_GRAVITY_EAST,
|
||||||
|
CLUTTER_GRAVITY_SOUTH_EAST,
|
||||||
|
CLUTTER_GRAVITY_SOUTH,
|
||||||
|
CLUTTER_GRAVITY_SOUTH_WEST,
|
||||||
|
CLUTTER_GRAVITY_WEST,
|
||||||
|
CLUTTER_GRAVITY_NORTH_WEST,
|
||||||
|
CLUTTER_GRAVITY_CENTER
|
||||||
|
} ClutterGravity;
|
||||||
|
|
||||||
|
GType clutter_behaviour_scale_get_type (void);
|
||||||
|
|
||||||
|
ClutterBehaviour*
|
||||||
|
clutter_behaviour_scale_new (ClutterAlpha *alpha,
|
||||||
|
double scale_begin,
|
||||||
|
double scale_end,
|
||||||
|
ClutterGravity gravity);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,21 +31,102 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "clutter-main.h"
|
||||||
#include "clutter-feature.h"
|
#include "clutter-feature.h"
|
||||||
#include "string.h"
|
|
||||||
|
|
||||||
static ClutterFeatureFlags __features = -1;
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
typedef void (*FuncPtr) (void);
|
||||||
|
typedef int (*GLXGetVideoSyncProc) (unsigned int *count);
|
||||||
|
typedef int (*GLXWaitVideoSyncProc) (int divisor,
|
||||||
|
int remainder,
|
||||||
|
unsigned int *count);
|
||||||
|
typedef FuncPtr (*GLXGetProcAddressProc) (const guint8 *procName);
|
||||||
|
|
||||||
|
typedef struct ClutterFeatureFuncs
|
||||||
|
{
|
||||||
|
GLXGetVideoSyncProc get_video_sync;
|
||||||
|
GLXWaitVideoSyncProc wait_video_sync;
|
||||||
|
|
||||||
|
} ClutterFeatureFuncs;
|
||||||
|
|
||||||
|
typedef enum ClutterVBlankType
|
||||||
|
{
|
||||||
|
CLUTTER_VBLANK_NONE = 0,
|
||||||
|
CLUTTER_VBLANK_GLX,
|
||||||
|
CLUTTER_VBLANK_DRI
|
||||||
|
|
||||||
|
} ClutterVBlankType;
|
||||||
|
|
||||||
|
typedef struct ClutterFeatures
|
||||||
|
{
|
||||||
|
ClutterFeatureFlags flags;
|
||||||
|
ClutterFeatureFuncs funcs;
|
||||||
|
gint dri_fd;
|
||||||
|
ClutterVBlankType vblank_type;
|
||||||
|
|
||||||
|
} ClutterFeatures;
|
||||||
|
|
||||||
|
static ClutterFeatures* __features = NULL;
|
||||||
|
|
||||||
|
/* #ifdef linux */
|
||||||
|
#define DRM_VBLANK_RELATIVE 0x1;
|
||||||
|
|
||||||
|
struct drm_wait_vblank_request {
|
||||||
|
int type;
|
||||||
|
unsigned int sequence;
|
||||||
|
unsigned long signal;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_wait_vblank_reply {
|
||||||
|
int type;
|
||||||
|
unsigned int sequence;
|
||||||
|
long tval_sec;
|
||||||
|
long tval_usec;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union drm_wait_vblank {
|
||||||
|
struct drm_wait_vblank_request request;
|
||||||
|
struct drm_wait_vblank_reply reply;
|
||||||
|
} drm_wait_vblank_t;
|
||||||
|
|
||||||
|
#define DRM_IOCTL_BASE 'd'
|
||||||
|
#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
|
||||||
|
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
|
||||||
|
|
||||||
|
static int drm_wait_vblank(int fd, drm_wait_vblank_t *vbl)
|
||||||
|
{
|
||||||
|
int ret, rc;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
|
||||||
|
vbl->request.type &= ~DRM_VBLANK_RELATIVE;
|
||||||
|
rc = errno;
|
||||||
|
}
|
||||||
|
while (ret && rc == EINTR);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
|
||||||
/* Note must be called after context created */
|
/* Note must be called after context created */
|
||||||
static gboolean
|
static gboolean
|
||||||
check_gl_extension (const gchar *name)
|
check_gl_extension (const gchar *name, const gchar *ext)
|
||||||
{
|
{
|
||||||
const gchar *ext;
|
|
||||||
gchar *end;
|
gchar *end;
|
||||||
gint name_len, n;
|
gint name_len, n;
|
||||||
|
|
||||||
ext = (const gchar*)glGetString(GL_EXTENSIONS);
|
|
||||||
|
|
||||||
if (name == NULL || ext == NULL)
|
if (name == NULL || ext == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -65,20 +146,117 @@ check_gl_extension (const gchar *name)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FuncPtr
|
||||||
|
get_proc_address (const gchar *name)
|
||||||
|
{
|
||||||
|
static GLXGetProcAddressProc get_proc_func = NULL;
|
||||||
|
static void *dlhand = NULL;
|
||||||
|
|
||||||
|
if (get_proc_func == NULL && dlhand == NULL)
|
||||||
|
{
|
||||||
|
dlhand = dlopen (NULL, RTLD_LAZY);
|
||||||
|
|
||||||
|
if (dlhand)
|
||||||
|
{
|
||||||
|
dlerror ();
|
||||||
|
get_proc_func
|
||||||
|
= (GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
|
||||||
|
if (dlerror () != NULL)
|
||||||
|
get_proc_func
|
||||||
|
= (GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddressARB");
|
||||||
|
if (dlerror () != NULL)
|
||||||
|
{
|
||||||
|
get_proc_func = NULL;
|
||||||
|
g_warning
|
||||||
|
("failed to bind GLXGetProcAddress or GLXGetProcAddressARB");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_proc_func)
|
||||||
|
return get_proc_func ((unsigned char*)name);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
check_vblank_env (const char *name)
|
||||||
|
{
|
||||||
|
const char *val;
|
||||||
|
|
||||||
|
val = getenv("CLUTTER_VBLANK");
|
||||||
|
|
||||||
|
if (val && !strcasecmp(val, name))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
clutter_feature_init (void)
|
clutter_feature_init (void)
|
||||||
{
|
{
|
||||||
if (__features != -1)
|
const gchar *gl_extensions, *glx_extensions;
|
||||||
|
|
||||||
|
if (__features != NULL)
|
||||||
{
|
{
|
||||||
g_warning ("You should never call clutter_feature_init() "
|
g_warning ("You should never call clutter_feature_init() "
|
||||||
"more than once.");
|
"more than once.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
__features = 0;
|
__features = g_new0 (ClutterFeatures, 1);
|
||||||
|
memset(&__features->funcs, 0, sizeof(ClutterFeatureFuncs));
|
||||||
|
|
||||||
if (check_gl_extension ("GL_ARB_texture_rectangle"))
|
gl_extensions = (const gchar*)glGetString(GL_EXTENSIONS);
|
||||||
__features |= CLUTTER_FEATURE_TEXTURE_RECTANGLE;
|
glx_extensions = glXQueryExtensionsString (clutter_xdisplay(),
|
||||||
|
clutter_xscreen());
|
||||||
|
|
||||||
|
if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions))
|
||||||
|
__features->flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE;
|
||||||
|
|
||||||
|
/* vblank */
|
||||||
|
|
||||||
|
__features->vblank_type = CLUTTER_VBLANK_NONE;
|
||||||
|
|
||||||
|
if (getenv("__GL_SYNC_TO_VBLANK") || check_vblank_env("none"))
|
||||||
|
{
|
||||||
|
CLUTTER_DBG("vblank sync: disabled at user request");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!check_vblank_env("dri")
|
||||||
|
&& check_gl_extension ("GLX_SGI_video_sync", glx_extensions))
|
||||||
|
{
|
||||||
|
__features->funcs.get_video_sync =
|
||||||
|
(GLXGetVideoSyncProc) get_proc_address ("glXGetVideoSyncSGI");
|
||||||
|
|
||||||
|
__features->funcs.wait_video_sync =
|
||||||
|
(GLXWaitVideoSyncProc) get_proc_address ("glXWaitVideoSyncSGI");
|
||||||
|
|
||||||
|
if (__features->funcs.get_video_sync != NULL
|
||||||
|
&& __features->funcs.wait_video_sync != NULL)
|
||||||
|
{
|
||||||
|
CLUTTER_DBG("vblank sync: using glx");
|
||||||
|
__features->vblank_type = CLUTTER_VBLANK_GLX;
|
||||||
|
__features->flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(__features->flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
|
||||||
|
{
|
||||||
|
__features->dri_fd = open("/dev/dri/card0", O_RDWR);
|
||||||
|
if (__features->dri_fd >= 0)
|
||||||
|
{
|
||||||
|
CLUTTER_DBG("vblank sync: using dri");
|
||||||
|
__features->vblank_type = CLUTTER_VBLANK_DRI;
|
||||||
|
__features->flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(__features->flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
|
||||||
|
CLUTTER_DBG("vblank sync: no use-able mechanism found");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,7 +273,7 @@ clutter_feature_init (void)
|
|||||||
gboolean
|
gboolean
|
||||||
clutter_feature_available (ClutterFeatureFlags feature)
|
clutter_feature_available (ClutterFeatureFlags feature)
|
||||||
{
|
{
|
||||||
return (__features & feature);
|
return (__features->flags & feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,5 +288,32 @@ clutter_feature_available (ClutterFeatureFlags feature)
|
|||||||
ClutterFeatureFlags
|
ClutterFeatureFlags
|
||||||
clutter_feature_all (void)
|
clutter_feature_all (void)
|
||||||
{
|
{
|
||||||
return __features;
|
return __features->flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_feature_wait_for_vblank (void)
|
||||||
|
{
|
||||||
|
switch (__features->vblank_type)
|
||||||
|
{
|
||||||
|
case CLUTTER_VBLANK_GLX:
|
||||||
|
{
|
||||||
|
unsigned int retraceCount;
|
||||||
|
__features->funcs.get_video_sync(&retraceCount);
|
||||||
|
__features->funcs.wait_video_sync(2,
|
||||||
|
(retraceCount+1)%2, &retraceCount);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CLUTTER_VBLANK_DRI:
|
||||||
|
{
|
||||||
|
drm_wait_vblank_t blank;
|
||||||
|
blank.request.type = DRM_VBLANK_RELATIVE;
|
||||||
|
blank.request.sequence = 1;
|
||||||
|
drm_wait_vblank (__features->dri_fd, &blank);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CLUTTER_VBLANK_NONE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,11 +41,13 @@ G_END_DECLS
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
CLUTTER_FEATURE_TEXTURE_RECTANGLE = (1 << 1)
|
CLUTTER_FEATURE_TEXTURE_RECTANGLE = (1 << 1),
|
||||||
|
CLUTTER_FEATURE_SYNC_TO_VBLANK = (1 << 2)
|
||||||
} ClutterFeatureFlags;
|
} ClutterFeatureFlags;
|
||||||
|
|
||||||
gboolean clutter_feature_available (ClutterFeatureFlags flags);
|
gboolean clutter_feature_available (ClutterFeatureFlags flags);
|
||||||
ClutterFeatureFlags clutter_feature_get_all (void);
|
ClutterFeatureFlags clutter_feature_get_all (void);
|
||||||
|
void clutter_feature_wait_for_vblank ();
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -289,13 +289,7 @@ clutter_redraw (void)
|
|||||||
|
|
||||||
if (clutter_stage_get_xwindow (stage))
|
if (clutter_stage_get_xwindow (stage))
|
||||||
{
|
{
|
||||||
#if 0
|
clutter_feature_wait_for_vblank ();
|
||||||
unsigned int retraceCount;
|
|
||||||
/* Wait for vertical retrace */
|
|
||||||
/* glXGetVideoSyncSGI(&retraceCount); */
|
|
||||||
/* glXWaitVideoSyncSGI(2, (retraceCount+1)%2, &retraceCount); */
|
|
||||||
glXWaitVideoSyncSGI(1, 0, &retraceCount);
|
|
||||||
#endif
|
|
||||||
glXSwapBuffers(ctx->xdpy, clutter_stage_get_xwindow (stage));
|
glXSwapBuffers(ctx->xdpy, clutter_stage_get_xwindow (stage));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -584,6 +578,7 @@ clutter_init (int *argc, char ***argv)
|
|||||||
|
|
||||||
events_init ();
|
events_init ();
|
||||||
|
|
||||||
|
|
||||||
context->is_initialized = TRUE;
|
context->is_initialized = TRUE;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user