Compare commits

..

4 Commits

Author SHA1 Message Date
Georges Basile Stavracas Neto
8d891e625b shaped-texture: Update mipmap counters on invalidation
https://gitlab.gnome.org/GNOME/mutter/merge_requests/861
2019-10-17 08:47:04 +02:00
Georges Basile Stavracas Neto
1a4cc1db59 wayland-surface: Invalidate contents of updated texture
WIP

https://gitlab.gnome.org/GNOME/mutter/merge_requests/861
2019-10-17 08:47:01 +02:00
Georges Basile Stavracas Neto
df2adce2f5 window-content: Track subsurfaces invalidations
WIP

https://gitlab.gnome.org/GNOME/mutter/merge_requests/861
2019-10-17 08:46:57 +02:00
Georges Basile Stavracas Neto
86cf89e787 Add MetaWindowContent
MetaWindowContent is a GObject class that implements ClutterContent.
It draws the contents of the window, unshadowed in the case of server
side decorated windows on X11, as a composition of the contents of
the subsurfaces.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/861
2019-10-17 08:46:54 +02:00
170 changed files with 6288 additions and 1407 deletions

View File

@@ -1,4 +1,4 @@
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stages:
- review

View File

@@ -1,28 +1,39 @@
# Rebuild and push with
#
# cd .gitlab-ci/
# docker build --no-cache -t registry.gitlab.gnome.org/gnome/mutter/master:v3 .
# docker push registry.gitlab.gnome.org/gnome/mutter/master:v3
# docker build --no-cache -t registry.gitlab.gnome.org/gnome/mutter/master:v2 .
# docker push registry.gitlab.gnome.org/gnome/mutter/master:v2
#
FROM fedora:31
FROM fedora:30
RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(builddep)' && \
dnf install -y 'dnf-command(copr)' && \
dnf copr enable -y fmuellner/gnome-shell-ci && \
dnf copr enable -y jadahl/mutter-ci && \
dnf copr enable -y hergertme/sysprof-3 && \
dnf -y update && dnf -y upgrade && \
dnf builddep -y mutter && \
# Until Fedora catches up with new build-deps
dnf install -y 'pkgconfig(graphene-gobject-1.0)' 'pkgconfig(sysprof-capture-3)' && \
# Until Fedora catches up with meson build-deps
dnf install -y meson xorg-x11-server-Xorg gnome-settings-daemon-devel egl-wayland-devel xorg-x11-server-Xwayland graphene-devel && \
# Until Fedora catches up with mesa bug fixes
dnf upgrade -y mesa-dri-drivers mesa-libEGL && \
# For running unit tests
dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 '*/xvfb-run' gdm-lib accountsservice-libs && \
dnf install -y sysprof-devel && \
dnf install -y intltool redhat-rpm-config make && \
# GNOME Shell
dnf builddep -y gnome-shell --setopt=install_weak_deps=False && \
# New dep this cycle
dnf install -y 'pkgconfig(gnome-autoar-0)' && \
dnf remove -y gnome-bluetooth-libs-devel dbus-glib-devel upower-devel python3-devel && \
dnf remove -y --noautoremove mutter mutter-devel && \

View File

@@ -40,12 +40,11 @@ function commit_message_subject_is_compliant() {
return 0
}
RET=0
for commit in $commits; do
commit_short=$(echo $commit | cut -c -8)
if ! commit_message_has_url $commit; then
echo "Commit $commit_short needs a merge request or issue URL"
echo "Missing merge request or issue URL on commit $commit_short"
exit 1
fi
@@ -53,8 +52,6 @@ for commit in $commits; do
if [ $? != 0 ]; then
echo "Commit message for $commit_short is not compliant:"
echo "$errors"
RET=1
exit 1
fi
done
exit $RET

View File

@@ -656,6 +656,7 @@
#include "clutter-units.h"
#include "deprecated/clutter-actor.h"
#include "deprecated/clutter-behaviour.h"
#include "deprecated/clutter-container.h"
/* Internal enum used to control mapped state update. This is a hint
@@ -2372,7 +2373,7 @@ clutter_actor_real_pick (ClutterActor *self)
for (iter = self->priv->first_child;
iter != NULL;
iter = iter->priv->next_sibling)
clutter_actor_pick (iter);
clutter_actor_paint (iter);
}
}
@@ -3875,11 +3876,11 @@ clutter_actor_paint_node (ClutterActor *actor,
void
clutter_actor_paint (ClutterActor *self)
{
g_autoptr (ClutterPaintNode) actor_node = NULL;
g_autoptr (ClutterPaintNode) root_node = NULL;
ClutterActorPrivate *priv;
ClutterPickMode pick_mode;
ClutterActorBox clip;
gboolean clip_set = FALSE;
ClutterStage *stage;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
@@ -3887,11 +3888,16 @@ clutter_actor_paint (ClutterActor *self)
return;
priv = self->priv;
priv->propagated_one_redraw = FALSE;
pick_mode = _clutter_context_get_pick_mode ();
if (pick_mode == CLUTTER_PICK_NONE)
priv->propagated_one_redraw = FALSE;
/* It's an important optimization that we consider painting of
* actors with 0 opacity to be a NOP... */
if (/* ignore top-levels, since they might be transparent */
if (pick_mode == CLUTTER_PICK_NONE &&
/* ignore top-levels, since they might be transparent */
!CLUTTER_ACTOR_IS_TOPLEVEL (self) &&
/* Use the override opacity if its been set */
((priv->opacity_override >= 0) ?
@@ -3906,51 +3912,22 @@ clutter_actor_paint (ClutterActor *self)
clutter_actor_ensure_resource_scale (self);
stage = (ClutterStage *) _clutter_actor_get_stage_internal (self);
/* mark that we are in the paint process */
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IN_PAINT);
actor_node = clutter_actor_node_new (self);
root_node = clutter_paint_node_ref (actor_node);
if (priv->has_clip)
{
clip.x1 = priv->clip.origin.x;
clip.y1 = priv->clip.origin.y;
clip.x2 = priv->clip.origin.x + priv->clip.size.width;
clip.y2 = priv->clip.origin.y + priv->clip.size.height;
clip_set = TRUE;
}
else if (priv->clip_to_allocation)
{
clip.x1 = 0.f;
clip.y1 = 0.f;
clip.x2 = priv->allocation.x2 - priv->allocation.x1;
clip.y2 = priv->allocation.y2 - priv->allocation.y1;
clip_set = TRUE;
}
if (clip_set)
{
ClutterPaintNode *clip_node;
clip_node = clutter_clip_node_new ();
clutter_paint_node_add_rectangle (clip_node, &clip);
clutter_paint_node_add_child (clip_node, root_node);
root_node = g_steal_pointer (&clip_node);
}
cogl_push_matrix ();
if (priv->enable_model_view_transform)
{
ClutterPaintNode *transform_node;
CoglMatrix transform;
CoglMatrix matrix;
clutter_actor_get_transform (self, &transform);
transform_node = clutter_transform_node_new (&transform);
clutter_paint_node_add_child (transform_node, root_node);
root_node = g_steal_pointer (&transform_node);
/* XXX: It could be better to cache the modelview with the actor
* instead of progressively building up the transformations on
* the matrix stack every time we paint. */
cogl_get_modelview_matrix (&matrix);
_clutter_actor_apply_modelview_transform (self, &matrix);
#ifdef CLUTTER_ENABLE_DEBUG
/* Catch when out-of-band transforms have been made by actors not as part
@@ -3962,7 +3939,7 @@ clutter_actor_paint (ClutterActor *self)
_clutter_actor_get_relative_transformation_matrix (self, NULL,
&expected_matrix);
if (!cogl_matrix_equal (&transform, &expected_matrix))
if (!cogl_matrix_equal (&matrix, &expected_matrix))
{
GString *buf = g_string_sized_new (1024);
ClutterActor *parent;
@@ -3989,14 +3966,54 @@ clutter_actor_paint (ClutterActor *self)
}
}
#endif /* CLUTTER_ENABLE_DEBUG */
cogl_set_modelview_matrix (&matrix);
}
/* We check whether we need to add the flatten effect before
* each paint so that we can avoid having a mechanism for
* applications to notify when the value of the
* has_overlaps virtual changes.
*/
add_or_remove_flatten_effect (self);
if (priv->has_clip)
{
clip.x1 = priv->clip.origin.x;
clip.y1 = priv->clip.origin.y;
clip.x2 = priv->clip.origin.x + priv->clip.size.width;
clip.y2 = priv->clip.origin.y + priv->clip.size.height;
clip_set = TRUE;
}
else if (priv->clip_to_allocation)
{
clip.x1 = 0.f;
clip.y1 = 0.f;
clip.x2 = priv->allocation.x2 - priv->allocation.x1;
clip.y2 = priv->allocation.y2 - priv->allocation.y1;
clip_set = TRUE;
}
if (clip_set)
{
if (pick_mode == CLUTTER_PICK_NONE)
{
CoglFramebuffer *fb = _clutter_stage_get_active_framebuffer (stage);
cogl_framebuffer_push_rectangle_clip (fb,
clip.x1,
clip.y1,
clip.x2,
clip.y2);
}
else
{
if (!_clutter_actor_push_pick_clip (self, &clip))
clip_set = FALSE;
}
}
if (pick_mode == CLUTTER_PICK_NONE)
{
/* We check whether we need to add the flatten effect before
each paint so that we can avoid having a mechanism for
applications to notify when the value of the
has_overlaps virtual changes. */
add_or_remove_flatten_effect (self);
}
/* We save the current paint volume so that the next time the
* actor queues a redraw we can constrain the redraw to just
@@ -4025,7 +4042,7 @@ clutter_actor_paint (ClutterActor *self)
* paint then the last-paint-volume would likely represent the new
* actor position not the old.
*/
if (!in_clone_paint ())
if (!in_clone_paint () && pick_mode == CLUTTER_PICK_NONE)
{
gboolean success;
/* annoyingly gcc warns if uninitialized even though
@@ -4053,16 +4070,34 @@ clutter_actor_paint (ClutterActor *self)
priv->next_effect_to_paint =
_clutter_meta_group_peek_metas (priv->effects);
clutter_paint_node_paint (root_node);
clutter_actor_continue_paint (self);
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_VOLUMES))
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_VOLUMES &&
pick_mode == CLUTTER_PICK_NONE))
_clutter_actor_draw_paint_volume (self);
/* If we make it here then the actor has run through a complete
paint run including all the effects so it's no longer dirty */
priv->is_dirty = FALSE;
if (pick_mode == CLUTTER_PICK_NONE)
priv->is_dirty = FALSE;
done:
if (clip_set)
{
if (pick_mode == CLUTTER_PICK_NONE)
{
CoglFramebuffer *fb = _clutter_stage_get_active_framebuffer (stage);
cogl_framebuffer_pop_clip (fb);
}
else
{
_clutter_actor_pop_pick_clip (self);
}
}
cogl_pop_matrix ();
/* paint sequence complete */
CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_IN_PAINT);
}
@@ -4100,28 +4135,43 @@ clutter_actor_continue_paint (ClutterActor *self)
actual actor */
if (priv->next_effect_to_paint == NULL)
{
ClutterPaintNode *dummy;
if (_clutter_context_get_pick_mode () == CLUTTER_PICK_NONE)
{
ClutterPaintNode *dummy;
/* XXX - this will go away in 2.0, when we can get rid of this
* stuff and switch to a pure retained render tree of PaintNodes
* for the entire frame, starting from the Stage; the paint()
* virtual function can then be called directly.
*/
dummy = _clutter_dummy_node_new (self);
clutter_paint_node_set_name (dummy, "Root");
/* XXX - this will go away in 2.0, when we can get rid of this
* stuff and switch to a pure retained render tree of PaintNodes
* for the entire frame, starting from the Stage; the paint()
* virtual function can then be called directly.
*/
dummy = _clutter_dummy_node_new (self);
clutter_paint_node_set_name (dummy, "Root");
/* XXX - for 1.12, we use the return value of paint_node() to
* decide whether we should emit the ::paint signal.
*/
clutter_actor_paint_node (self, dummy);
clutter_paint_node_unref (dummy);
/* XXX - for 1.12, we use the return value of paint_node() to
* decide whether we should emit the ::paint signal.
*/
clutter_actor_paint_node (self, dummy);
clutter_paint_node_unref (dummy);
/* XXX:2.0 - Call the paint() virtual directly */
if (g_signal_has_handler_pending (self, actor_signals[PAINT],
0, TRUE))
g_signal_emit (self, actor_signals[PAINT], 0);
/* XXX:2.0 - Call the paint() virtual directly */
if (g_signal_has_handler_pending (self, actor_signals[PAINT],
0, TRUE))
g_signal_emit (self, actor_signals[PAINT], 0);
else
CLUTTER_ACTOR_GET_CLASS (self)->paint (self);
}
else
CLUTTER_ACTOR_GET_CLASS (self)->paint (self);
{
/* The actor will log a silhouette of itself to the stage pick log.
*
* XXX:2.0 - Call the pick() virtual directly
*/
if (g_signal_has_handler_pending (self, actor_signals[PICK],
0, TRUE))
g_signal_emit (self, actor_signals[PICK], 0);
else
CLUTTER_ACTOR_GET_CLASS (self)->pick (self);
}
}
else
{
@@ -4135,157 +4185,31 @@ clutter_actor_continue_paint (ClutterActor *self)
priv->current_effect = priv->next_effect_to_paint->data;
priv->next_effect_to_paint = priv->next_effect_to_paint->next;
if (priv->is_dirty)
if (_clutter_context_get_pick_mode () == CLUTTER_PICK_NONE)
{
/* If there's an effect queued with this redraw then all
* effects up to that one will be considered dirty. It
* is expected the queued effect will paint the cached
* image and not call clutter_actor_continue_paint again
* (although it should work ok if it does)
*/
if (priv->effect_to_redraw == NULL ||
priv->current_effect != priv->effect_to_redraw)
run_flags |= CLUTTER_EFFECT_PAINT_ACTOR_DIRTY;
if (priv->is_dirty)
{
/* If there's an effect queued with this redraw then all
effects up to that one will be considered dirty. It
is expected the queued effect will paint the cached
image and not call clutter_actor_continue_paint again
(although it should work ok if it does) */
if (priv->effect_to_redraw == NULL ||
priv->current_effect != priv->effect_to_redraw)
run_flags |= CLUTTER_EFFECT_PAINT_ACTOR_DIRTY;
}
_clutter_effect_paint (priv->current_effect, run_flags);
}
_clutter_effect_paint (priv->current_effect, run_flags);
priv->current_effect = old_current_effect;
}
}
/**
* clutter_actor_pick:
* @actor: A #ClutterActor
*
* Asks @actor to perform a pick.
*/
void
clutter_actor_pick (ClutterActor *actor)
{
ClutterActorPrivate *priv;
ClutterActorBox clip;
gboolean clip_set = FALSE;
if (CLUTTER_ACTOR_IN_DESTRUCTION (actor))
return;
priv = actor->priv;
/* if we aren't paintable (not in a toplevel with all
* parents paintable) then do nothing.
*/
if (!CLUTTER_ACTOR_IS_MAPPED (actor))
return;
clutter_actor_ensure_resource_scale (actor);
/* mark that we are in the paint process */
CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_IN_PICK);
cogl_push_matrix ();
if (priv->enable_model_view_transform)
{
CoglMatrix matrix;
cogl_get_modelview_matrix (&matrix);
_clutter_actor_apply_modelview_transform (actor, &matrix);
cogl_set_modelview_matrix (&matrix);
}
if (priv->has_clip)
{
clip.x1 = priv->clip.origin.x;
clip.y1 = priv->clip.origin.y;
clip.x2 = priv->clip.origin.x + priv->clip.size.width;
clip.y2 = priv->clip.origin.y + priv->clip.size.height;
clip_set = TRUE;
}
else if (priv->clip_to_allocation)
{
clip.x1 = 0.f;
clip.y1 = 0.f;
clip.x2 = priv->allocation.x2 - priv->allocation.x1;
clip.y2 = priv->allocation.y2 - priv->allocation.y1;
clip_set = TRUE;
}
if (clip_set)
clip_set = _clutter_actor_push_pick_clip (actor, &clip);
priv->next_effect_to_paint = NULL;
if (priv->effects)
{
priv->next_effect_to_paint =
_clutter_meta_group_peek_metas (priv->effects);
}
clutter_actor_continue_pick (actor);
if (clip_set)
_clutter_actor_pop_pick_clip (actor);
cogl_pop_matrix ();
/* paint sequence complete */
CLUTTER_UNSET_PRIVATE_FLAGS (actor, CLUTTER_IN_PICK);
}
/**
* clutter_actor_continue_pick:
* @actor: A #ClutterActor
*
* Run the next stage of the pick sequence. This function should only
* be called within the implementation of the pick virtual of a
* #ClutterEffect. It will cause the run method of the next effect to
* be applied, or it will pick the actual actor if the current effect
* is the last effect in the chain.
*/
void
clutter_actor_continue_pick (ClutterActor *actor)
{
ClutterActorPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_return_if_fail (CLUTTER_ACTOR_IN_PICK (actor));
priv = actor->priv;
/* Skip any effects that are disabled */
while (priv->next_effect_to_paint &&
!clutter_actor_meta_get_enabled (priv->next_effect_to_paint->data))
priv->next_effect_to_paint = priv->next_effect_to_paint->next;
/* If this has come from the last effect then we'll just pick the
* actual actor.
*/
if (priv->next_effect_to_paint == NULL)
{
/* The actor will log a silhouette of itself to the stage pick log.
*
* XXX:2.0 - Call the pick() virtual directly
*/
if (g_signal_has_handler_pending (actor, actor_signals[PICK],
0, TRUE))
g_signal_emit (actor, actor_signals[PICK], 0);
else
CLUTTER_ACTOR_GET_CLASS (actor)->pick (actor);
}
else
{
ClutterEffect *old_current_effect;
{
/* We can't determine when an actor has been modified since
its last pick so lets just assume it has always been
modified */
run_flags |= CLUTTER_EFFECT_PAINT_ACTOR_DIRTY;
/* Cache the current effect so that we can put it back before
* returning.
*/
old_current_effect = priv->current_effect;
priv->current_effect = priv->next_effect_to_paint->data;
priv->next_effect_to_paint = priv->next_effect_to_paint->next;
_clutter_effect_pick (priv->current_effect);
_clutter_effect_pick (priv->current_effect, run_flags);
}
priv->current_effect = old_current_effect;
}
@@ -14715,6 +14639,40 @@ parse_actor_metas (ClutterScript *script,
return g_slist_reverse (retval);
}
static GSList *
parse_behaviours (ClutterScript *script,
ClutterActor *actor,
JsonNode *node)
{
GList *elements, *l;
GSList *retval = NULL;
if (!JSON_NODE_HOLDS_ARRAY (node))
return NULL;
elements = json_array_get_elements (json_node_get_array (node));
for (l = elements; l != NULL; l = l->next)
{
JsonNode *element = l->data;
const gchar *id_ = _clutter_script_get_id_from_node (element);
GObject *behaviour;
if (id_ == NULL || *id_ == '\0')
continue;
behaviour = clutter_script_get_object (script, id_);
if (behaviour == NULL)
continue;
retval = g_slist_prepend (retval, behaviour);
}
g_list_free (elements);
return g_slist_reverse (retval);
}
static ClutterMargin *
parse_margin (ClutterActor *self,
JsonNode *node)
@@ -14830,6 +14788,24 @@ clutter_actor_parse_custom_node (ClutterScriptable *scriptable,
else
g_slice_free (RotationInfo, info);
}
else if (strcmp (name, "behaviours") == 0)
{
GSList *l;
#ifdef CLUTTER_ENABLE_DEBUG
if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
_clutter_diagnostic_message ("The 'behaviours' key is deprecated "
"and it should not be used in newly "
"written ClutterScript definitions.");
#endif
l = parse_behaviours (script, actor, node);
g_value_init (value, G_TYPE_POINTER);
g_value_set_pointer (value, l);
retval = TRUE;
}
else if (strcmp (name, "actions") == 0 ||
strcmp (name, "constraints") == 0 ||
strcmp (name, "effects") == 0)
@@ -14900,6 +14876,26 @@ clutter_actor_set_custom_property (ClutterScriptable *scriptable,
return;
}
if (strcmp (name, "behaviours") == 0)
{
GSList *behaviours, *l;
if (!G_VALUE_HOLDS (value, G_TYPE_POINTER))
return;
behaviours = g_value_get_pointer (value);
for (l = behaviours; l != NULL; l = l->next)
{
ClutterBehaviour *behaviour = l->data;
clutter_behaviour_apply (behaviour, actor);
}
g_slist_free (behaviours);
return;
}
if (strcmp (name, "actions") == 0 ||
strcmp (name, "constraints") == 0 ||
strcmp (name, "effects") == 0)

View File

@@ -353,10 +353,6 @@ void clutter_actor_paint
CLUTTER_EXPORT
void clutter_actor_continue_paint (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_pick (ClutterActor *actor);
CLUTTER_EXPORT
void clutter_actor_continue_pick (ClutterActor *actor);
CLUTTER_EXPORT
void clutter_actor_queue_redraw (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_queue_redraw_with_clip (ClutterActor *self,

View File

@@ -6,6 +6,45 @@
G_BEGIN_DECLS
typedef enum
{
CLUTTER_DEBUG_MISC = 1 << 0,
CLUTTER_DEBUG_ACTOR = 1 << 1,
CLUTTER_DEBUG_TEXTURE = 1 << 2,
CLUTTER_DEBUG_EVENT = 1 << 3,
CLUTTER_DEBUG_PAINT = 1 << 4,
CLUTTER_DEBUG_PANGO = 1 << 5,
CLUTTER_DEBUG_BACKEND = 1 << 6,
CLUTTER_DEBUG_SCHEDULER = 1 << 7,
CLUTTER_DEBUG_SCRIPT = 1 << 8,
CLUTTER_DEBUG_SHADER = 1 << 9,
CLUTTER_DEBUG_MULTISTAGE = 1 << 10,
CLUTTER_DEBUG_ANIMATION = 1 << 11,
CLUTTER_DEBUG_LAYOUT = 1 << 12,
CLUTTER_DEBUG_PICK = 1 << 13,
CLUTTER_DEBUG_EVENTLOOP = 1 << 14,
CLUTTER_DEBUG_CLIPPING = 1 << 15,
CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 16
} ClutterDebugFlag;
typedef enum
{
CLUTTER_DEBUG_NOP_PICKING = 1 << 0,
} ClutterPickDebugFlag;
typedef enum
{
CLUTTER_DEBUG_DISABLE_SWAP_EVENTS = 1 << 0,
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS = 1 << 1,
CLUTTER_DEBUG_REDRAWS = 1 << 2,
CLUTTER_DEBUG_PAINT_VOLUMES = 1 << 3,
CLUTTER_DEBUG_DISABLE_CULLING = 1 << 4,
CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT = 1 << 5,
CLUTTER_DEBUG_CONTINUOUS_REDRAW = 1 << 6,
CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 7,
CLUTTER_DEBUG_PAINT_DAMAGE_REGION = 1 << 8,
} ClutterDrawDebugFlag;
#ifdef CLUTTER_ENABLE_DEBUG
#define CLUTTER_HAS_DEBUG(type) ((clutter_debug_flags & CLUTTER_DEBUG_##type) != FALSE)

View File

@@ -7,6 +7,10 @@
#include "deprecated/clutter-alpha.h"
#include "deprecated/clutter-animatable.h"
#include "deprecated/clutter-animation.h"
#include "deprecated/clutter-behaviour.h"
#include "deprecated/clutter-behaviour-depth.h"
#include "deprecated/clutter-behaviour-opacity.h"
#include "deprecated/clutter-behaviour-scale.h"
#include "deprecated/clutter-bin-layout.h"
#include "deprecated/clutter-box.h"
#include "deprecated/clutter-cairo-texture.h"

View File

@@ -12,7 +12,8 @@ gboolean _clutter_effect_modify_paint_volume (ClutterEffect
gboolean _clutter_effect_has_custom_paint_volume (ClutterEffect *effect);
void _clutter_effect_paint (ClutterEffect *effect,
ClutterEffectPaintFlags flags);
void _clutter_effect_pick (ClutterEffect *effect);
void _clutter_effect_pick (ClutterEffect *effect,
ClutterEffectPaintFlags flags);
G_END_DECLS

View File

@@ -216,13 +216,14 @@ clutter_effect_real_paint (ClutterEffect *effect,
}
static void
clutter_effect_real_pick (ClutterEffect *effect)
clutter_effect_real_pick (ClutterEffect *effect,
ClutterEffectPaintFlags flags)
{
ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect);
ClutterActor *actor;
actor = clutter_actor_meta_get_actor (actor_meta);
clutter_actor_continue_pick (actor);
clutter_actor_continue_paint (actor);
}
static void
@@ -287,11 +288,12 @@ _clutter_effect_paint (ClutterEffect *effect,
}
void
_clutter_effect_pick (ClutterEffect *effect)
_clutter_effect_pick (ClutterEffect *effect,
ClutterEffectPaintFlags flags)
{
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
CLUTTER_EFFECT_GET_CLASS (effect)->pick (effect);
CLUTTER_EFFECT_GET_CLASS (effect)->pick (effect, flags);
}
gboolean

View File

@@ -82,7 +82,8 @@ struct _ClutterEffectClass
void (* paint) (ClutterEffect *effect,
ClutterEffectPaintFlags flags);
void (* pick) (ClutterEffect *effect);
void (* pick) (ClutterEffect *effect,
ClutterEffectPaintFlags flags);
/*< private >*/
void (* _clutter_effect4) (void);

View File

@@ -970,6 +970,8 @@ typedef enum
/**
* ClutterFeatureFlags:
* @CLUTTER_FEATURE_SWAP_THROTTLE: Set if backend throttles buffer swaps.
* @CLUTTER_FEATURE_TEXTURE_YUV: Set if YUV based textures supported.
* @CLUTTER_FEATURE_TEXTURE_READ_PIXELS: Set if texture pixels can be read.
* @CLUTTER_FEATURE_STAGE_STATIC: Set if stage size if fixed (i.e framebuffer)
* @CLUTTER_FEATURE_STAGE_CURSOR: Set if stage has a graphical cursor.
* @CLUTTER_FEATURE_SHADERS_GLSL: Set if the backend supports GLSL shaders.
@@ -985,6 +987,8 @@ typedef enum
typedef enum
{
CLUTTER_FEATURE_SWAP_THROTTLE = (1 << 3),
CLUTTER_FEATURE_TEXTURE_YUV = (1 << 4),
CLUTTER_FEATURE_TEXTURE_READ_PIXELS = (1 << 5),
CLUTTER_FEATURE_STAGE_STATIC = (1 << 6),
CLUTTER_FEATURE_STAGE_CURSOR = (1 << 8),
CLUTTER_FEATURE_SHADERS_GLSL = (1 << 9),
@@ -1213,7 +1217,8 @@ typedef enum
* @CLUTTER_TEXTURE_RGB_FLAG_PREMULT: Unused flag
* @CLUTTER_TEXTURE_YUV_FLAG_YUV2: Unused flag
*
* Flags for clutter_texture_set_from_rgb_data().
* Flags for clutter_texture_set_from_rgb_data() and
* clutter_texture_set_from_yuv_data().
*
* Since: 0.4
*

View File

@@ -33,6 +33,8 @@
*
* It is possible to ask whether Clutter has support for specific features at
* run-time.
*
* See also cogl_get_features() and #CoglFeatureFlags
*/
#include "clutter-build-config.h"
@@ -58,13 +60,20 @@ typedef struct ClutterFeatures
static ClutterFeatures* __features = NULL;
static ClutterFeatureFlags
clutter_features_from_cogl (void)
clutter_features_from_cogl (guint cogl_flags)
{
ClutterFeatureFlags clutter_flags = 0;
if (cogl_flags & COGL_FEATURE_TEXTURE_YUV)
clutter_flags |= CLUTTER_FEATURE_TEXTURE_YUV;
if (cogl_flags & COGL_FEATURE_TEXTURE_READ_PIXELS)
clutter_flags |= CLUTTER_FEATURE_TEXTURE_READ_PIXELS;
clutter_flags |= CLUTTER_FEATURE_SHADERS_GLSL;
clutter_flags |= CLUTTER_FEATURE_OFFSCREEN;
if (cogl_flags & COGL_FEATURE_OFFSCREEN)
clutter_flags |= CLUTTER_FEATURE_OFFSCREEN;
return clutter_flags;
}
@@ -92,7 +101,7 @@ _clutter_feature_init (GError **error)
if (!_clutter_backend_create_context (context->backend, error))
return FALSE;
__features->flags = (clutter_features_from_cogl ()
__features->flags = (clutter_features_from_cogl (cogl_get_features ())
| _clutter_backend_get_features (context->backend));
__features->features_set = TRUE;

View File

@@ -329,6 +329,9 @@ layout_manager_real_begin_animation (ClutterLayoutManager *manager,
/* let the alpha take ownership of the timeline */
g_object_unref (timeline);
g_signal_connect_swapped (timeline, "completed",
G_CALLBACK (clutter_layout_manager_end_animation),
manager);
g_signal_connect_swapped (timeline, "new-frame",
G_CALLBACK (clutter_layout_manager_layout_changed),
manager);
@@ -372,6 +375,9 @@ layout_manager_real_end_animation (ClutterLayoutManager *manager)
if (clutter_timeline_is_playing (timeline))
clutter_timeline_stop (timeline);
g_signal_handlers_disconnect_by_func (timeline,
G_CALLBACK (clutter_layout_manager_end_animation),
manager);
g_signal_handlers_disconnect_by_func (timeline,
G_CALLBACK (clutter_layout_manager_layout_changed),
manager);

View File

@@ -213,6 +213,15 @@ void clutter_layout_manager_child_get_property (ClutterLayoutMa
const gchar *property_name,
GValue *value);
CLUTTER_DEPRECATED
ClutterAlpha * clutter_layout_manager_begin_animation (ClutterLayoutManager *manager,
guint duration,
gulong mode);
CLUTTER_DEPRECATED
void clutter_layout_manager_end_animation (ClutterLayoutManager *manager);
CLUTTER_DEPRECATED
gdouble clutter_layout_manager_get_animation_progress (ClutterLayoutManager *manager);
G_END_DECLS
#endif /* __CLUTTER_LAYOUT_MANAGER_H__ */

View File

@@ -2605,36 +2605,6 @@ clutter_check_windowing_backend (const char *backend_type)
return FALSE;
}
/**
* clutter_add_debug_flags: (skip)
*
* Adds the debug flags passed to the list of debug flags.
*/
void
clutter_add_debug_flags (ClutterDebugFlag debug_flags,
ClutterDrawDebugFlag draw_flags,
ClutterPickDebugFlag pick_flags)
{
clutter_debug_flags |= debug_flags;
clutter_paint_debug_flags |= draw_flags;
clutter_pick_debug_flags |= pick_flags;
}
/**
* clutter_remove_debug_flags: (skip)
*
* Removes the debug flags passed from the list of debug flags.
*/
void
clutter_remove_debug_flags (ClutterDebugFlag debug_flags,
ClutterDrawDebugFlag draw_flags,
ClutterPickDebugFlag pick_flags)
{
clutter_debug_flags &= ~debug_flags;
clutter_paint_debug_flags &= ~draw_flags;
clutter_pick_debug_flags &= ~pick_flags;
}
void
_clutter_set_sync_to_vblank (gboolean sync_to_vblank)
{

View File

@@ -34,45 +34,6 @@
G_BEGIN_DECLS
typedef enum
{
CLUTTER_DEBUG_MISC = 1 << 0,
CLUTTER_DEBUG_ACTOR = 1 << 1,
CLUTTER_DEBUG_TEXTURE = 1 << 2,
CLUTTER_DEBUG_EVENT = 1 << 3,
CLUTTER_DEBUG_PAINT = 1 << 4,
CLUTTER_DEBUG_PANGO = 1 << 5,
CLUTTER_DEBUG_BACKEND = 1 << 6,
CLUTTER_DEBUG_SCHEDULER = 1 << 7,
CLUTTER_DEBUG_SCRIPT = 1 << 8,
CLUTTER_DEBUG_SHADER = 1 << 9,
CLUTTER_DEBUG_MULTISTAGE = 1 << 10,
CLUTTER_DEBUG_ANIMATION = 1 << 11,
CLUTTER_DEBUG_LAYOUT = 1 << 12,
CLUTTER_DEBUG_PICK = 1 << 13,
CLUTTER_DEBUG_EVENTLOOP = 1 << 14,
CLUTTER_DEBUG_CLIPPING = 1 << 15,
CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 16,
} ClutterDebugFlag;
typedef enum
{
CLUTTER_DEBUG_NOP_PICKING = 1 << 0,
} ClutterPickDebugFlag;
typedef enum
{
CLUTTER_DEBUG_DISABLE_SWAP_EVENTS = 1 << 0,
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS = 1 << 1,
CLUTTER_DEBUG_REDRAWS = 1 << 2,
CLUTTER_DEBUG_PAINT_VOLUMES = 1 << 3,
CLUTTER_DEBUG_DISABLE_CULLING = 1 << 4,
CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT = 1 << 5,
CLUTTER_DEBUG_CONTINUOUS_REDRAW = 1 << 6,
CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 7,
CLUTTER_DEBUG_PAINT_DAMAGE_REGION = 1 << 8,
} ClutterDrawDebugFlag;
/**
* CLUTTER_INIT_ERROR:
*
@@ -197,15 +158,6 @@ guint clutter_get_default_frame_rate (void);
CLUTTER_EXPORT
gboolean clutter_check_windowing_backend (const char *backend_type);
CLUTTER_EXPORT
void clutter_add_debug_flags (ClutterDebugFlag debug_flags,
ClutterDrawDebugFlag draw_flags,
ClutterPickDebugFlag pick_flags);
CLUTTER_EXPORT
void clutter_remove_debug_flags (ClutterDebugFlag debug_flags,
ClutterDrawDebugFlag draw_flags,
ClutterPickDebugFlag pick_flags);
G_END_DECLS

View File

@@ -139,6 +139,30 @@ ClutterPaintNode * clutter_paint_node_get_last_child (Clutter
G_GNUC_INTERNAL
ClutterPaintNode * clutter_paint_node_get_parent (ClutterPaintNode *node);
#define CLUTTER_TYPE_LAYER_NODE (_clutter_layer_node_get_type ())
#define CLUTTER_LAYER_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LAYER_NODE, ClutterLayerNode))
#define CLUTTER_IS_LAYER_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LAYER_NODE))
/*
* ClutterLayerNode:
*
* The #ClutterLayerNode structure is an opaque
* type whose members cannot be directly accessed.
*
* Since: 1.10
*/
typedef struct _ClutterLayerNode ClutterLayerNode;
typedef struct _ClutterLayerNodeClass ClutterLayerNodeClass;
GType _clutter_layer_node_get_type (void) G_GNUC_CONST;
ClutterPaintNode * _clutter_layer_node_new (const CoglMatrix *projection,
const cairo_rectangle_t *viewport,
float width,
float height,
guint8 opacity);
G_END_DECLS
#endif /* __CLUTTER_PAINT_NODE_PRIVATE_H__ */

View File

@@ -183,31 +183,35 @@ clutter_root_node_new (CoglFramebuffer *framebuffer,
}
/*
* ClutterTransformNode
* Transform node
*
* A private PaintNode, that changes the modelview of its child
* nodes.
*/
struct _ClutterTransformNode
{
#define clutter_transform_node_get_type _clutter_transform_node_get_type
typedef struct _ClutterTransformNode {
ClutterPaintNode parent_instance;
CoglMatrix transform;
};
CoglMatrix modelview;
} ClutterTransformNode;
struct _ClutterTransformNodeClass
{
ClutterPaintNodeClass parent_class;
};
typedef struct _ClutterPaintNodeClass ClutterTransformNodeClass;
G_DEFINE_TYPE (ClutterTransformNode, clutter_transform_node, CLUTTER_TYPE_PAINT_NODE)
static gboolean
clutter_transform_node_pre_draw (ClutterPaintNode *node)
{
ClutterTransformNode *transform_node = (ClutterTransformNode *) node;
CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
ClutterTransformNode *tnode = (ClutterTransformNode *) node;
CoglMatrix matrix;
cogl_framebuffer_push_matrix (fb);
cogl_framebuffer_transform (fb, &transform_node->transform);
cogl_push_matrix ();
cogl_get_modelview_matrix (&matrix);
cogl_matrix_multiply (&matrix, &matrix, &tnode->modelview);
cogl_set_modelview_matrix (&matrix);
return TRUE;
}
@@ -215,9 +219,7 @@ clutter_transform_node_pre_draw (ClutterPaintNode *node)
static void
clutter_transform_node_post_draw (ClutterPaintNode *node)
{
CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
cogl_framebuffer_pop_matrix (fb);
cogl_pop_matrix ();
}
static void
@@ -233,24 +235,18 @@ clutter_transform_node_class_init (ClutterTransformNodeClass *klass)
static void
clutter_transform_node_init (ClutterTransformNode *self)
{
cogl_matrix_init_identity (&self->transform);
cogl_matrix_init_identity (&self->modelview);
}
/*
* clutter_transform_node_new:
* @transform: (nullable): the transform matrix to apply
*
* Return value: (transfer full): the newly created #ClutterTransformNode.
* Use clutter_paint_node_unref() when done.
*/
ClutterPaintNode *
clutter_transform_node_new (const CoglMatrix *transform)
_clutter_transform_node_new (const CoglMatrix *modelview)
{
ClutterTransformNode *res;
res = _clutter_paint_node_create (CLUTTER_TYPE_TRANSFORM_NODE);
if (transform)
res->transform = *transform;
res = _clutter_paint_node_create (_clutter_transform_node_get_type ());
if (modelview != NULL)
res->modelview = *modelview;
return (ClutterPaintNode *) res;
}
@@ -1082,101 +1078,10 @@ clutter_clip_node_new (void)
}
/*
* ClutterActorNode
* ClutterLayerNode (private)
*/
struct _ClutterActorNode
{
ClutterPaintNode parent_instance;
ClutterActor *actor;
};
struct _ClutterActorNodeClass
{
ClutterPaintNodeClass parent_class;
};
G_DEFINE_TYPE (ClutterActorNode, clutter_actor_node, CLUTTER_TYPE_PAINT_NODE)
static gboolean
clutter_actor_node_pre_draw (ClutterPaintNode *node)
{
return TRUE;
}
static void
clutter_actor_node_draw (ClutterPaintNode *node)
{
ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node);
clutter_actor_continue_paint (actor_node->actor);
}
static JsonNode *
clutter_actor_node_serialize (ClutterPaintNode *node)
{
ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node);
g_autoptr (JsonBuilder) builder = NULL;
const char *debug_name;
debug_name = _clutter_actor_get_debug_name (actor_node->actor);
builder = json_builder_new ();
json_builder_begin_object (builder);
json_builder_set_member_name (builder, "actor");
json_builder_add_string_value (builder, debug_name);
json_builder_end_object (builder);
return json_builder_get_root (builder);
}
static void
clutter_actor_node_class_init (ClutterActorNodeClass *klass)
{
ClutterPaintNodeClass *node_class;
node_class = CLUTTER_PAINT_NODE_CLASS (klass);
node_class->pre_draw = clutter_actor_node_pre_draw;
node_class->draw = clutter_actor_node_draw;
node_class->serialize = clutter_actor_node_serialize;
}
static void
clutter_actor_node_init (ClutterActorNode *self)
{
}
/*
* clutter_actor_node_new:
* @actor: the actor to paint
*
* Creates a new #ClutterActorNode.
*
* The actor is painted together with any effects
* applied to it. Children of this node will draw
* over the actor contents.
*
* Return value: (transfer full): the newly created #ClutterActorNode.
* Use clutter_paint_node_unref() when done.
*/
ClutterPaintNode *
clutter_actor_node_new (ClutterActor *actor)
{
ClutterActorNode *res;
g_assert (actor != NULL);
res = _clutter_paint_node_create (CLUTTER_TYPE_ACTOR_NODE);
res->actor = actor;
return (ClutterPaintNode *) res;
}
/*
* ClutterLayerNode
*/
#define clutter_layer_node_get_type _clutter_layer_node_get_type
struct _ClutterLayerNode
{
@@ -1363,11 +1268,11 @@ clutter_layer_node_init (ClutterLayerNode *self)
* Since: 1.10
*/
ClutterPaintNode *
clutter_layer_node_new (const CoglMatrix *projection,
const cairo_rectangle_t *viewport,
float width,
float height,
guint8 opacity)
_clutter_layer_node_new (const CoglMatrix *projection,
const cairo_rectangle_t *viewport,
float width,
float height,
guint8 opacity)
{
ClutterLayerNode *res;
CoglColor color;

View File

@@ -143,25 +143,6 @@ CLUTTER_EXPORT
ClutterPaintNode * clutter_text_node_new (PangoLayout *layout,
const ClutterColor *color);
#define CLUTTER_TYPE_ACTOR_NODE (clutter_actor_node_get_type ())
#define CLUTTER_ACTOR_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTOR_NODE, ClutterActorNode))
#define CLUTTER_IS_ACTOR_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTOR_NODE))
/**
* ClutterActorNode:
*
* The #ClutterActorNode structure is an opaque
* type whose members cannot be directly accessed.
*/
typedef struct _ClutterActorNode ClutterActorNode;
typedef struct _ClutterActorNode ClutterActorNodeClass;
CLUTTER_EXPORT
GType clutter_actor_node_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterPaintNode * clutter_actor_node_new (ClutterActor *actor);
#define CLUTTER_TYPE_ROOT_NODE (clutter_root_node_get_type ())
#define CLUTTER_ROOT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ROOT_NODE, ClutterRootNode))
#define CLUTTER_IS_ROOT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ROOT_NODE))
@@ -182,54 +163,6 @@ CLUTTER_EXPORT
ClutterPaintNode * clutter_root_node_new (CoglFramebuffer *framebuffer,
const ClutterColor *clear_color,
CoglBufferBit clear_flags);
#define CLUTTER_TYPE_LAYER_NODE (clutter_layer_node_get_type ())
#define CLUTTER_LAYER_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LAYER_NODE, ClutterLayerNode))
#define CLUTTER_IS_LAYER_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LAYER_NODE))
/*
* ClutterLayerNode:
*
* The #ClutterLayerNode structure is an opaque
* type whose members cannot be directly accessed.
*
* Since: 1.10
*/
typedef struct _ClutterLayerNode ClutterLayerNode;
typedef struct _ClutterLayerNodeClass ClutterLayerNodeClass;
CLUTTER_EXPORT
GType clutter_layer_node_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterPaintNode * clutter_layer_node_new (const CoglMatrix *projection,
const cairo_rectangle_t *viewport,
float width,
float height,
guint8 opacity);
#define CLUTTER_TYPE_TRANSFORM_NODE (clutter_transform_node_get_type ())
#define CLUTTER_TRANSFORM_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TRANSFORM_NODE, ClutterTransformNode))
#define CLUTTER_IS_TRANSFORM_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_TRANSFORM_NODE))
/*
* ClutterTransformNode:
*
* The #ClutterLayerNode structure is an opaque
* type whose members cannot be directly accessed.
*
* Since: 1.10
*/
typedef struct _ClutterTransformNode ClutterTransformNode;
typedef struct _ClutterPaintNodeClass ClutterTransformNodeClass;
CLUTTER_EXPORT
GType clutter_transform_node_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterPaintNode * clutter_transform_node_new (const CoglMatrix *projection);
G_END_DECLS
#endif /* __CLUTTER_PAINT_NODES_H__ */

View File

@@ -27,7 +27,8 @@
* and bezier curves.
*
* A #ClutterPath contains a description of a path consisting of
* straight lines and bezier curves.
* straight lines and bezier curves. This can be used in a
* #ClutterBehaviourPath to animate an actor moving along the path.
*
* The path consists of a series of nodes. Each node is one of the
* following four types:
@@ -243,6 +244,9 @@ clutter_path_finalize (GObject *object)
*
* Creates a new #ClutterPath instance with no nodes.
*
* The object has a floating reference so if you add it to a
* #ClutterBehaviourPath then you do not need to unref it.
*
* Return value: the newly created #ClutterPath
*
* Since: 1.0
@@ -263,6 +267,9 @@ clutter_path_new (void)
* @desc. See clutter_path_add_string() for details of the format of
* the string.
*
* The object has a floating reference so if you add it to a
* #ClutterBehaviourPath then you do not need to unref it.
*
* Return value: the newly created #ClutterPath
*
* Since: 1.0

View File

@@ -67,7 +67,6 @@ typedef struct _ClutterVertex4 ClutterVertex4;
#define CLUTTER_ACTOR_IN_DESTRUCTION(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_DESTRUCTION) != FALSE)
#define CLUTTER_ACTOR_IN_REPARENT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_REPARENT) != FALSE)
#define CLUTTER_ACTOR_IN_PAINT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PAINT) != FALSE)
#define CLUTTER_ACTOR_IN_PICK(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PICK) != FALSE)
#define CLUTTER_ACTOR_IN_RELAYOUT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_RELAYOUT) != FALSE)
#define CLUTTER_ACTOR_IN_PREF_WIDTH(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PREF_WIDTH) != FALSE)
#define CLUTTER_ACTOR_IN_PREF_HEIGHT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PREF_HEIGHT) != FALSE)
@@ -105,10 +104,9 @@ typedef enum
/* Used to avoid recursion */
CLUTTER_IN_PAINT = 1 << 5,
CLUTTER_IN_PICK = 1 << 6,
/* Used to avoid recursion */
CLUTTER_IN_RELAYOUT = 1 << 7,
CLUTTER_IN_RELAYOUT = 1 << 6,
} ClutterPrivateFlags;
/*

View File

@@ -75,6 +75,65 @@
* packing rules of Clutter still apply, and an actor cannot be packed
* in multiple containers without unparenting it in between).
*
* Behaviours and timelines can also be defined inside a UI definition
* buffer:
*
* <informalexample><programlisting><![CDATA[
* {
* "id" : "rotate-behaviour",
* "type" : "ClutterBehaviourRotate",
* "angle-start" : 0.0,
* "angle-end" : 360.0,
* "axis" : "z-axis",
* "alpha" : {
* "timeline" : { "duration" : 4000, "loop" : true },
* "mode" : "easeInSine"
* }
* }
* ]]></programlisting></informalexample>
*
* And then to apply a defined behaviour to an actor defined inside the
* definition of an actor, the "behaviour" member can be used:
*
* <informalexample><programlisting><![CDATA[
* {
* "id" : "my-rotating-actor",
* "type" : "ClutterTexture",
* ...
* "behaviours" : [ "rotate-behaviour" ]
* }
* ]]></programlisting></informalexample>
*
* A #ClutterAlpha belonging to a #ClutterBehaviour can only be defined
* implicitly like in the example above, or explicitly by setting the
* "alpha" property to point to a previously defined #ClutterAlpha, e.g.:
*
* <informalexample><programlisting><![CDATA[
* {
* "id" : "rotate-behaviour",
* "type" : "ClutterBehaviourRotate",
* "angle-start" : 0.0,
* "angle-end" : 360.0,
* "axis" : "z-axis",
* "alpha" : {
* "id" : "rotate-alpha",
* "type" : "ClutterAlpha",
* "timeline" : {
* "id" : "rotate-timeline",
* "type : "ClutterTimeline",
* "duration" : 4000,
* "loop" : true
* },
* "function" : "custom_sine_alpha"
* }
* }
* ]]></programlisting></informalexample>
*
* Implicitely defined #ClutterAlpha<!-- -->s and #ClutterTimeline<!-- -->s
* can omit the `id`, as well as the `type` members, but will not be available
* using clutter_script_get_object() (they can, however, be extracted using the
* #ClutterBehaviour and #ClutterAlpha API respectively).
*
* Signal handlers can be defined inside a Clutter UI definition file and
* then autoconnected to their respective signals using the
* clutter_script_connect_signals() function:
@@ -151,6 +210,7 @@
* function
* "type_func" := the GType function name, for non-standard classes
* "children" := an array of names or objects to add as children
* "behaviours" := an array of names or objects to apply to an actor
* "signals" := an array of signal definitions to connect to an object
* "is-default" := a boolean flag used when defining the #ClutterStage;
* if set to "true" the default stage will be used instead
@@ -186,6 +246,7 @@
#include "clutter-debug.h"
#include "deprecated/clutter-alpha.h"
#include "deprecated/clutter-behaviour.h"
#include "deprecated/clutter-container.h"
#include "deprecated/clutter-state.h"
@@ -463,10 +524,11 @@ clutter_script_init (ClutterScript *script)
/**
* clutter_script_new:
*
* Creates a new #ClutterScript instance. #ClutterScript can be used to load
* objects definitions for scenegraph elements, like actors, or behavioural
* elements, like timelines. The definitions must be encoded using the
* JavaScript Object Notation (JSON) language.
* Creates a new #ClutterScript instance. #ClutterScript can be used
* to load objects definitions for scenegraph elements, like actors,
* or behavioural elements, like behaviours and timelines. The
* definitions must be encoded using the JavaScript Object Notation (JSON)
* language.
*
* Return value: the newly created #ClutterScript instance. Use
* g_object_unref() when done.
@@ -801,7 +863,9 @@ construct_each_objects (gpointer key,
if (oinfo->object == NULL)
_clutter_script_construct_object (script, oinfo);
/* this will take care of setting up properties and adding children */
/* this will take care of setting up properties,
* adding children and applying behaviours
*/
_clutter_script_apply_properties (script, oinfo);
}
}

View File

@@ -235,35 +235,19 @@ _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window)
return TRUE;
}
cairo_region_t *
_clutter_stage_window_get_redraw_clip (ClutterStageWindow *window)
gboolean
_clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow *window,
cairo_rectangle_int_t *stage_clip)
{
ClutterStageWindowInterface *iface;
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->get_redraw_clip != NULL)
return iface->get_redraw_clip (window);
if (iface->get_redraw_clip_bounds != NULL)
return iface->get_redraw_clip_bounds (window, stage_clip);
return NULL;
}
gboolean
_clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow *window,
cairo_rectangle_int_t *stage_clip)
{
cairo_region_t *redraw_clip;
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
redraw_clip = _clutter_stage_window_get_redraw_clip (window);
if (!redraw_clip)
return FALSE;
cairo_region_get_extents (redraw_clip, stage_clip);
cairo_region_destroy (redraw_clip);
return TRUE;
return FALSE;
}
void

View File

@@ -55,7 +55,9 @@ struct _ClutterStageWindowInterface
cairo_rectangle_int_t *stage_rectangle);
gboolean (* has_redraw_clips) (ClutterStageWindow *stage_window);
gboolean (* ignoring_redraw_clips) (ClutterStageWindow *stage_window);
cairo_region_t * (* get_redraw_clip) (ClutterStageWindow *stage_window);
gboolean (* get_redraw_clip_bounds) (ClutterStageWindow *stage_window,
cairo_rectangle_int_t *clip);
void (* set_accept_focus) (ClutterStageWindow *stage_window,
gboolean accept_focus);
@@ -100,7 +102,6 @@ gboolean _clutter_stage_window_has_redraw_clips (ClutterStageWin
gboolean _clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window);
gboolean _clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow *window,
cairo_rectangle_int_t *clip);
cairo_region_t * _clutter_stage_window_get_redraw_clip (ClutterStageWindow *window);
void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
gboolean accept_focus);

View File

@@ -86,6 +86,8 @@
* fully opaque actors covering the whole visible area of the stage,
* i.e. when no blending with the stage color happens over the whole
* stage viewport
*
* A series of hints that enable or disable behaviours on the stage
*/
typedef enum /*< prefix=CLUTTER_STAGE >*/
{
@@ -717,6 +719,17 @@ clutter_stage_allocate (ClutterActor *self,
flags | CLUTTER_DELEGATE_LAYOUT);
}
/* XXX: Until Cogl becomes fully responsible for backend windows
* Clutter need to manually keep it informed of the current window
* size. We do this after the allocation above so that the stage
* window has a chance to update the window size based on the
* allocation.
*/
_clutter_stage_window_get_geometry (priv->impl, &window_size);
cogl_onscreen_clutter_backend_set_size (window_size.width,
window_size.height);
/* reset the viewport if the allocation effectively changed */
clutter_actor_get_allocation_box (self, &alloc);
clutter_actor_box_get_size (&alloc, &new_width, &new_height);
@@ -879,9 +892,9 @@ _clutter_stage_update_active_framebuffer (ClutterStage *stage,
* be able to cull them.
*/
static void
setup_view_for_pick_or_paint (ClutterStage *stage,
ClutterStageView *view,
const cairo_rectangle_int_t *clip)
clutter_stage_do_paint_view (ClutterStage *stage,
ClutterStageView *view,
const cairo_rectangle_int_t *clip)
{
ClutterStagePrivate *priv = stage->priv;
CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view);
@@ -936,14 +949,6 @@ setup_view_for_pick_or_paint (ClutterStage *stage,
_clutter_stage_paint_volume_stack_free_all (stage);
_clutter_stage_update_active_framebuffer (stage, framebuffer);
}
static void
clutter_stage_do_paint_view (ClutterStage *stage,
ClutterStageView *view,
const cairo_rectangle_int_t *clip)
{
setup_view_for_pick_or_paint (stage, view, clip);
clutter_actor_paint (CLUTTER_ACTOR (stage));
}
@@ -1006,7 +1011,7 @@ clutter_stage_pick (ClutterActor *self)
*/
clutter_actor_iter_init (&iter, self);
while (clutter_actor_iter_next (&iter, &child))
clutter_actor_pick (child);
clutter_actor_paint (child);
}
static gboolean
@@ -1633,26 +1638,6 @@ _clutter_stage_has_full_redraw_queued (ClutterStage *stage)
return FALSE;
}
cairo_region_t *
clutter_stage_get_redraw_clip (ClutterStage *stage)
{
ClutterStagePrivate *priv;
cairo_rectangle_int_t clip;
cairo_region_t *region;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
priv = stage->priv;
region = _clutter_stage_window_get_redraw_clip (priv->impl);
if (region)
return region;
/* Set clip to the full extents of the stage */
_clutter_stage_window_get_geometry (priv->impl, &clip);
return cairo_region_create_rectangle (&clip);
}
/**
* clutter_stage_get_redraw_clip_bounds:
* @stage: A #ClutterStage
@@ -1709,8 +1694,7 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage,
cogl_push_framebuffer (fb);
context->pick_mode = mode;
setup_view_for_pick_or_paint (stage, view, NULL);
clutter_actor_pick (CLUTTER_ACTOR (stage));
clutter_stage_do_paint_view (stage, view, NULL);
context->pick_mode = CLUTTER_PICK_NONE;
priv->cached_pick_mode = mode;

View File

@@ -214,8 +214,6 @@ CLUTTER_EXPORT
void clutter_stage_get_redraw_clip_bounds (ClutterStage *stage,
cairo_rectangle_int_t *clip);
CLUTTER_EXPORT
cairo_region_t * clutter_stage_get_redraw_clip (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_ensure_viewport (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_ensure_redraw (ClutterStage *stage);

View File

@@ -46,7 +46,8 @@ G_BEGIN_DECLS
* @CLUTTER_TEXTURE_ERROR_NO_YUV: YUV operation attempted but no YUV support
* found
* @CLUTTER_TEXTURE_ERROR_BAD_FORMAT: The requested format for
* clutter_texture_set_from_rgb_data is unsupported.
* clutter_texture_set_from_rgb_data or
* clutter_texture_set_from_yuv_data is unsupported.
*
* Error enumeration for #ClutterTexture
*

View File

@@ -104,6 +104,7 @@ typedef union _ClutterEvent ClutterEvent;
*/
typedef struct _ClutterEventSequence ClutterEventSequence;
typedef struct _ClutterBehaviour ClutterBehaviour; /* deprecated */
typedef struct _ClutterShader ClutterShader; /* deprecated */
/**

View File

@@ -56,7 +56,7 @@ typedef struct _ClutterStageViewCoglPrivate
*/
#define DAMAGE_HISTORY_MAX 16
#define DAMAGE_HISTORY(x) ((x) & (DAMAGE_HISTORY_MAX - 1))
cairo_region_t * damage_history[DAMAGE_HISTORY_MAX];
cairo_rectangle_int_t damage_history[DAMAGE_HISTORY_MAX];
unsigned int damage_index;
} ClutterStageViewCoglPrivate;
@@ -296,10 +296,13 @@ clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *stage_window)
/* NB: at the start of each new frame there is an implied clip that
* clips everything (i.e. nothing would be drawn) so we need to make
* sure we return True in the un-initialized case here.
*
* NB: a clip width of 0 means a full stage redraw has been queued
* so we effectively don't have any redraw clips in that case.
*/
if (!stage_cogl->initialized_redraw_clip ||
(stage_cogl->initialized_redraw_clip &&
stage_cogl->redraw_clip))
stage_cogl->bounding_redraw_clip.width != 0))
return TRUE;
else
return FALSE;
@@ -310,9 +313,9 @@ clutter_stage_cogl_ignoring_redraw_clips (ClutterStageWindow *stage_window)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
/* NB: a NULL clip means a full stage redraw is required */
/* NB: a clip width of 0 means a full stage redraw is required */
if (stage_cogl->initialized_redraw_clip &&
!stage_cogl->redraw_clip)
stage_cogl->bounding_redraw_clip.width == 0)
return TRUE;
else
return FALSE;
@@ -343,11 +346,11 @@ clutter_stage_cogl_add_redraw_clip (ClutterStageWindow *stage_window,
return;
/* A NULL stage clip means a full stage redraw has been queued and
* we keep track of this by setting a NULL redraw_clip.
*/
* we keep track of this by setting a zero width
* stage_cogl->bounding_redraw_clip */
if (stage_clip == NULL)
{
g_clear_pointer (&stage_cogl->redraw_clip, cairo_region_destroy);
stage_cogl->bounding_redraw_clip.width = 0;
stage_cogl->initialized_redraw_clip = TRUE;
return;
}
@@ -356,27 +359,34 @@ clutter_stage_cogl_add_redraw_clip (ClutterStageWindow *stage_window,
if (stage_clip->width == 0 || stage_clip->height == 0)
return;
if (!stage_cogl->redraw_clip)
if (!stage_cogl->initialized_redraw_clip)
{
stage_cogl->redraw_clip = cairo_region_create_rectangle (stage_clip);
stage_cogl->bounding_redraw_clip = *stage_clip;
}
else
else if (stage_cogl->bounding_redraw_clip.width > 0)
{
cairo_region_union_rectangle (stage_cogl->redraw_clip, stage_clip);
_clutter_util_rectangle_union (&stage_cogl->bounding_redraw_clip,
stage_clip,
&stage_cogl->bounding_redraw_clip);
}
stage_cogl->initialized_redraw_clip = TRUE;
}
static cairo_region_t *
clutter_stage_cogl_get_redraw_clip (ClutterStageWindow *stage_window)
static gboolean
clutter_stage_cogl_get_redraw_clip_bounds (ClutterStageWindow *stage_window,
cairo_rectangle_int_t *stage_clip)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
if (stage_cogl->using_clipped_redraw && stage_cogl->redraw_clip)
return cairo_region_copy (stage_cogl->redraw_clip);
if (stage_cogl->using_clipped_redraw)
{
*stage_clip = stage_cogl->bounding_redraw_clip;
return NULL;
return TRUE;
}
return FALSE;
}
static inline gboolean
@@ -393,47 +403,37 @@ valid_buffer_age (ClutterStageViewCogl *view_cogl,
}
static void
paint_damage_region (ClutterStageWindow *stage_window,
ClutterStageView *view,
cairo_region_t *swap_region)
paint_damage_region (ClutterStageWindow *stage_window,
ClutterStageView *view,
cairo_rectangle_int_t *swap_region)
{
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
static CoglPipeline *overlay_blue = NULL;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
ClutterActor *actor = CLUTTER_ACTOR (stage_cogl->wrapper);
CoglMatrix transform;
int n_rects, i;
float x_1 = swap_region->x;
float x_2 = swap_region->x + swap_region->width;
float y_1 = swap_region->y;
float y_2 = swap_region->y + swap_region->height;
CoglMatrix modelview;
cogl_framebuffer_push_matrix (framebuffer);
clutter_actor_get_transform (actor, &transform);
cogl_framebuffer_transform (framebuffer, &transform);
/* Blue for the swap region */
if (G_UNLIKELY (overlay_blue == NULL))
{
overlay_blue = cogl_pipeline_new (ctx);
cogl_pipeline_set_color4ub (overlay_blue, 0x00, 0x00, 0x33, 0x33);
}
n_rects = cairo_region_num_rectangles (swap_region);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
float x_1, x_2, y_1, y_2;
cogl_framebuffer_push_matrix (framebuffer);
cogl_matrix_init_identity (&modelview);
_clutter_actor_apply_modelview_transform (actor, &modelview);
cogl_framebuffer_set_modelview_matrix (framebuffer, &modelview);
cairo_region_get_rectangle (swap_region, i, &rect);
x_1 = rect.x;
x_2 = rect.x + rect.width;
y_1 = rect.y;
y_2 = rect.y + rect.height;
cogl_framebuffer_draw_rectangle (framebuffer, overlay_blue, x_1, y_1, x_2, y_2);
}
/* Blue for the swap region */
cogl_framebuffer_draw_rectangle (framebuffer, overlay_blue, x_1, y_1, x_2, y_2);
/* Red for the clip */
if (stage_cogl->initialized_redraw_clip &&
stage_cogl->redraw_clip)
if (stage_cogl->initialized_redraw_clip)
{
static CoglPipeline *overlay_red = NULL;
@@ -443,63 +443,55 @@ paint_damage_region (ClutterStageWindow *stage_window,
cogl_pipeline_set_color4ub (overlay_red, 0x33, 0x00, 0x00, 0x33);
}
n_rects = cairo_region_num_rectangles (stage_cogl->redraw_clip);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
float x_1, x_2, y_1, y_2;
x_1 = stage_cogl->bounding_redraw_clip.x;
x_2 = stage_cogl->bounding_redraw_clip.x + stage_cogl->bounding_redraw_clip.width;
y_1 = stage_cogl->bounding_redraw_clip.y;
y_2 = stage_cogl->bounding_redraw_clip.y + stage_cogl->bounding_redraw_clip.height;
cairo_region_get_rectangle (stage_cogl->redraw_clip, i, &rect);
x_1 = rect.x;
x_2 = rect.x + rect.width;
y_1 = rect.y;
y_2 = rect.y + rect.height;
cogl_framebuffer_draw_rectangle (framebuffer, overlay_red, x_1, y_1, x_2, y_2);
}
cogl_framebuffer_draw_rectangle (framebuffer, overlay_red, x_1, y_1, x_2, y_2);
}
cogl_framebuffer_pop_matrix (framebuffer);
}
static gboolean
swap_framebuffer (ClutterStageWindow *stage_window,
ClutterStageView *view,
cairo_region_t *swap_region,
gboolean swap_with_damage)
swap_framebuffer (ClutterStageWindow *stage_window,
ClutterStageView *view,
cairo_rectangle_int_t *swap_region,
gboolean swap_with_damage)
{
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
int *damage, n_rects, i;
int damage[4], ndamage;
damage[0] = swap_region->x;
damage[1] = swap_region->y;
damage[2] = swap_region->width;
damage[3] = swap_region->height;
if (swap_region->width != 0)
ndamage = 1;
else
ndamage = 0;
if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)))
paint_damage_region (stage_window, view, swap_region);
n_rects = cairo_region_num_rectangles (swap_region);
damage = g_newa (int, n_rects * 4);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (swap_region, i, &rect);
damage[i * 4] = rect.x;
damage[i * 4 + 1] = rect.y;
damage[i * 4 + 2] = rect.width;
damage[i * 4 + 3] = rect.height;
}
if (cogl_is_onscreen (framebuffer))
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
/* push on the screen */
if (n_rects > 0 && !swap_with_damage)
if (ndamage == 1 && !swap_with_damage)
{
CLUTTER_NOTE (BACKEND,
"cogl_onscreen_swap_region (onscreen: %p)",
onscreen);
"cogl_onscreen_swap_region (onscreen: %p, "
"x: %d, y: %d, "
"width: %d, height: %d)",
onscreen,
damage[0], damage[1], damage[2], damage[3]);
cogl_onscreen_swap_region (onscreen,
damage, n_rects);
damage, ndamage);
return FALSE;
}
@@ -509,7 +501,7 @@ swap_framebuffer (ClutterStageWindow *stage_window,
onscreen);
cogl_onscreen_swap_buffers_with_damage (onscreen,
damage, n_rects);
damage, ndamage);
return TRUE;
}
@@ -524,126 +516,81 @@ swap_framebuffer (ClutterStageWindow *stage_window,
}
}
static void
scale_and_clamp_rect (const graphene_rect_t *rect,
float scale,
cairo_rectangle_int_t *dest)
{
graphene_rect_t tmp = *rect;
graphene_rect_scale (&tmp, scale, scale, &tmp);
_clutter_util_rectangle_int_extents (&tmp, dest);
}
static void
paint_stage (ClutterStageCogl *stage_cogl,
ClutterStageView *view,
cairo_region_t *clip)
const cairo_rectangle_int_t *clip)
{
ClutterStage *stage = stage_cogl->wrapper;
cairo_rectangle_int_t clip_rect;
cairo_rectangle_int_t paint_rect;
cairo_rectangle_int_t view_rect;
graphene_rect_t rect;
float fb_scale;
clutter_stage_view_get_layout (view, &view_rect);
fb_scale = clutter_stage_view_get_scale (view);
cairo_region_get_extents (clip, &clip_rect);
_clutter_util_rect_from_rectangle (&clip_rect, &rect);
scale_and_clamp_rect (&rect, 1.0f / fb_scale, &paint_rect);
_clutter_util_rectangle_offset (&paint_rect,
view_rect.x,
view_rect.y,
&paint_rect);
_clutter_stage_maybe_setup_viewport (stage, view);
_clutter_stage_paint_view (stage, view, &paint_rect);
_clutter_stage_paint_view (stage, view, clip);
if (clutter_stage_view_get_onscreen (view) !=
clutter_stage_view_get_framebuffer (view))
{
clutter_stage_view_blit_offscreen (view, &paint_rect);
clutter_stage_view_blit_offscreen (view, clip);
}
}
static void
fill_current_damage_history (ClutterStageView *view,
cairo_region_t *damage)
fill_current_damage_history_and_step (ClutterStageView *view)
{
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
ClutterStageViewCoglPrivate *view_priv =
clutter_stage_view_cogl_get_instance_private (view_cogl);
cairo_region_t **current_fb_damage;
cairo_rectangle_int_t view_rect;
float fb_scale;
cairo_rectangle_int_t *current_fb_damage;
current_fb_damage =
&view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index)];
clutter_stage_view_get_layout (view, &view_rect);
fb_scale = clutter_stage_view_get_scale (view);
g_clear_pointer (current_fb_damage, cairo_region_destroy);
*current_fb_damage = cairo_region_copy (damage);
*current_fb_damage = (cairo_rectangle_int_t) {
.x = 0,
.y = 0,
.width = ceilf (view_rect.width * fb_scale),
.height = ceilf (view_rect.height * fb_scale)
};
view_priv->damage_index++;
}
static void
fill_current_damage_history_rectangle (ClutterStageView *view,
const cairo_rectangle_int_t *rect)
{
cairo_region_t *damage;
damage = cairo_region_create_rectangle (rect);
fill_current_damage_history (view, damage);
cairo_region_destroy (damage);
}
static cairo_region_t *
transform_swap_region_to_onscreen (ClutterStageView *view,
cairo_region_t *swap_region)
transform_swap_region_to_onscreen (ClutterStageView *view,
cairo_rectangle_int_t *swap_region)
{
CoglFramebuffer *framebuffer;
cairo_rectangle_int_t layout;
gfloat x1, y1, x2, y2;
gint width, height;
int n_rects, i;
cairo_rectangle_int_t *rects;
cairo_region_t *transformed_region;
framebuffer = clutter_stage_view_get_onscreen (view);
clutter_stage_view_get_layout (view, &layout);
x1 = (float) swap_region->x / layout.width;
y1 = (float) swap_region->y / layout.height;
x2 = (float) (swap_region->x + swap_region->width) / layout.width;
y2 = (float) (swap_region->y + swap_region->height) / layout.height;
clutter_stage_view_transform_to_onscreen (view, &x1, &y1);
clutter_stage_view_transform_to_onscreen (view, &x2, &y2);
width = cogl_framebuffer_get_width (framebuffer);
height = cogl_framebuffer_get_height (framebuffer);
n_rects = cairo_region_num_rectangles (swap_region);
rects = g_newa (cairo_rectangle_int_t, n_rects);
for (i = 0; i < n_rects; i++)
{
gfloat x1, y1, x2, y2;
x1 = floor (x1 * width);
y1 = floor (height - (y1 * height));
x2 = ceil (x2 * width);
y2 = ceil (height - (y2 * height));
cairo_region_get_rectangle (swap_region, i, &rects[i]);
x1 = (float) rects[i].x / layout.width;
y1 = (float) rects[i].y / layout.height;
x2 = (float) (rects[i].x + rects[i].width) / layout.width;
y2 = (float) (rects[i].y + rects[i].height) / layout.height;
clutter_stage_view_transform_to_onscreen (view, &x1, &y1);
clutter_stage_view_transform_to_onscreen (view, &x2, &y2);
x1 = floor (x1 * width);
y1 = floor (height - (y1 * height));
x2 = ceil (x2 * width);
y2 = ceil (height - (y2 * height));
rects[i].x = x1;
rects[i].y = y1;
rects[i].width = x2 - x1;
rects[i].height = y2 - y1;
}
transformed_region = cairo_region_create_rectangles (rects, n_rects);
return transformed_region;
*swap_region = (cairo_rectangle_int_t) {
.x = x1,
.y = y1,
.width = x2 - x1,
.height = y2 - y1
};
}
static void
@@ -677,6 +624,18 @@ is_buffer_age_enabled (void)
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
}
static void
scale_and_clamp_rect (const graphene_rect_t *rect,
float scale,
cairo_rectangle_int_t *dest)
{
graphene_rect_t tmp = *rect;
graphene_rect_scale (&tmp, scale, scale, &tmp);
_clutter_util_rectangle_int_extents (&tmp, dest);
}
static gboolean
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
ClutterStageView *view)
@@ -695,10 +654,9 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
gboolean do_swap_buffer;
gboolean swap_with_damage;
ClutterActor *wrapper;
cairo_region_t *redraw_clip;
cairo_region_t *fb_clip_region;
cairo_region_t *swap_region;
cairo_rectangle_int_t redraw_rect;
cairo_rectangle_int_t redraw_clip;
cairo_rectangle_int_t swap_region;
cairo_rectangle_int_t fb_clip_region;
gboolean clip_region_empty;
float fb_scale;
int subpixel_compensation = 0;
@@ -717,19 +675,20 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled ();
/* NB: a NULL redraw clip == full stage redraw */
if (!stage_cogl->redraw_clip)
/* NB: a zero width redraw clip == full stage redraw */
if (stage_cogl->bounding_redraw_clip.width == 0)
have_clip = FALSE;
else
{
cairo_region_t *view_region;
redraw_clip = cairo_region_copy (stage_cogl->redraw_clip);
redraw_clip = stage_cogl->bounding_redraw_clip;
_clutter_util_rectangle_intersection (&redraw_clip,
&view_rect,
&redraw_clip);
view_region = cairo_region_create_rectangle (&view_rect);
cairo_region_intersect (redraw_clip, view_region);
have_clip = !cairo_region_equal (redraw_clip, view_region);
cairo_region_destroy (view_region);
have_clip = !(redraw_clip.x == view_rect.x &&
redraw_clip.y == view_rect.y &&
redraw_clip.width == view_rect.width &&
redraw_clip.height == view_rect.height);
}
may_use_clipped_redraw = FALSE;
@@ -741,52 +700,25 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3)
{
graphene_rect_t rect;
cairo_rectangle_int_t *rects;
int n_rects, i;
may_use_clipped_redraw = TRUE;
fb_clip_region = cairo_region_create ();
n_rects = cairo_region_num_rectangles (redraw_clip);
rects = g_new (cairo_rectangle_int_t, n_rects);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t new_fb_clip_rect;
cairo_region_get_rectangle (redraw_clip, i, &rects[i]);
_clutter_util_rect_from_rectangle (&rects[i], &rect);
graphene_rect_offset (&rect, -view_rect.x, -view_rect.y);
scale_and_clamp_rect (&rect, fb_scale, &new_fb_clip_rect);
cairo_region_union_rectangle (fb_clip_region, &new_fb_clip_rect);
}
g_free (rects);
_clutter_util_rect_from_rectangle (&redraw_clip, &rect);
graphene_rect_offset (&rect, -view_rect.x, -view_rect.y);
scale_and_clamp_rect (&rect, fb_scale, &fb_clip_region);
if (fb_scale != floorf (fb_scale))
{
subpixel_compensation = ceilf (fb_scale);
n_rects = cairo_region_num_rectangles (fb_clip_region);
rects = g_newa (cairo_rectangle_int_t, n_rects);
for (i = 0; i < n_rects; i++)
{
cairo_region_get_rectangle (fb_clip_region, i, &rects[i]);
rects[i].x -= subpixel_compensation;
rects[i].y -= subpixel_compensation;
rects[i].width += 2 * subpixel_compensation;
rects[i].height += 2 * subpixel_compensation;
}
cairo_region_destroy (fb_clip_region);
fb_clip_region = cairo_region_create_rectangles (rects, n_rects);
fb_clip_region.x -= subpixel_compensation;
fb_clip_region.y -= subpixel_compensation;
fb_clip_region.width += 2 * subpixel_compensation;
fb_clip_region.height += 2 * subpixel_compensation;
}
}
else
{
cairo_rectangle_int_t rect = { 0, 0, view_rect.width, view_rect.height };
fb_clip_region = cairo_region_create_rectangle (&rect);
redraw_clip = cairo_region_copy (fb_clip_region);
fb_clip_region = (cairo_rectangle_int_t) { 0 };
}
if (may_use_clipped_redraw &&
@@ -795,14 +727,16 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
else
use_clipped_redraw = FALSE;
clip_region_empty = may_use_clipped_redraw && cairo_region_is_empty (fb_clip_region);
clip_region_empty = may_use_clipped_redraw && fb_clip_region.width == 0;
swap_with_damage = FALSE;
if (has_buffer_age)
{
if (use_clipped_redraw)
if (use_clipped_redraw && !clip_region_empty)
{
int age;
int age, i;
cairo_rectangle_int_t *current_fb_damage =
&view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index++)];
age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (fb));
@@ -810,66 +744,54 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
{
graphene_rect_t rect;
cairo_rectangle_int_t damage_region;
cairo_rectangle_int_t *rects;
int n_rects, i;
fill_current_damage_history (view, fb_clip_region);
*current_fb_damage = fb_clip_region;
for (i = 1; i <= age; i++)
{
cairo_region_t *fb_damage =
view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - i - 1)];
cairo_region_union (fb_clip_region, fb_damage);
cairo_rectangle_int_t *fb_damage =
&view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index - i - 1)];
_clutter_util_rectangle_union (&fb_clip_region,
fb_damage,
&fb_clip_region);
}
/* Update the redraw clip state with the extra damage. */
n_rects = cairo_region_num_rectangles (fb_clip_region);
rects = g_newa (cairo_rectangle_int_t, n_rects);
for (i = 0; i < n_rects; i++)
{
cairo_region_get_rectangle (fb_clip_region, i, &rects[i]);
_clutter_util_rect_from_rectangle (&rects[i], &rect);
scale_and_clamp_rect (&rect, 1.0f / fb_scale, &damage_region);
_clutter_util_rectangle_offset (&damage_region,
view_rect.x,
view_rect.y,
&damage_region);
cairo_region_union_rectangle (stage_cogl->redraw_clip,
&damage_region);
}
/* Update the bounding redraw clip state with the extra damage. */
_clutter_util_rect_from_rectangle (&fb_clip_region, &rect);
scale_and_clamp_rect (&rect, 1.0f / fb_scale, &damage_region);
_clutter_util_rectangle_offset (&damage_region,
view_rect.x,
view_rect.y,
&damage_region);
_clutter_util_rectangle_union (&stage_cogl->bounding_redraw_clip,
&damage_region,
&stage_cogl->bounding_redraw_clip);
CLUTTER_NOTE (CLIPPING, "Reusing back buffer(age=%d) - repairing region: num rects: %d\n",
CLUTTER_NOTE (CLIPPING, "Reusing back buffer(age=%d) - repairing region: x=%d, y=%d, width=%d, height=%d\n",
age,
cairo_region_num_rectangles (fb_clip_region));
fb_clip_region.x,
fb_clip_region.y,
fb_clip_region.width,
fb_clip_region.height);
swap_with_damage = TRUE;
}
else
{
cairo_rectangle_int_t fb_damage;
CLUTTER_NOTE (CLIPPING, "Invalid back buffer(age=%d): forcing full redraw\n", age);
use_clipped_redraw = FALSE;
fb_damage = (cairo_rectangle_int_t) {
*current_fb_damage = (cairo_rectangle_int_t) {
.x = 0,
.y = 0,
.width = ceilf (view_rect.width * fb_scale),
.height = ceilf (view_rect.height * fb_scale)
.width = view_rect.width * fb_scale,
.height = view_rect.height * fb_scale
};
fill_current_damage_history_rectangle (view, &fb_damage);
}
}
else if (!use_clipped_redraw)
{
cairo_rectangle_int_t fb_damage;
fb_damage = (cairo_rectangle_int_t) {
.x = 0,
.y = 0,
.width = ceilf (view_rect.width * fb_scale),
.height = ceilf (view_rect.height * fb_scale)
};
fill_current_damage_history_rectangle (view, &fb_damage);
fill_current_damage_history_and_step (view);
}
}
@@ -880,12 +802,11 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
}
else if (use_clipped_redraw)
{
cairo_rectangle_int_t clip_rect;
graphene_rect_t rect;
cairo_rectangle_int_t scissor_rect;
cairo_rectangle_int_t paint_rect;
cairo_region_get_extents (fb_clip_region, &clip_rect);
calculate_scissor_region (&clip_rect,
calculate_scissor_region (&fb_clip_region,
subpixel_compensation,
fb_width, fb_height,
&scissor_rect);
@@ -905,8 +826,14 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
scissor_rect.width,
scissor_rect.height);
paint_stage (stage_cogl, view, fb_clip_region);
_clutter_util_rect_from_rectangle (&fb_clip_region, &rect);
scale_and_clamp_rect (&rect, 1.0f / fb_scale, &paint_rect);
_clutter_util_rectangle_offset (&paint_rect,
view_rect.x,
view_rect.y,
&paint_rect);
paint_stage (stage_cogl, view, &paint_rect);
cogl_framebuffer_pop_clip (fb);
stage_cogl->using_clipped_redraw = FALSE;
@@ -916,17 +843,16 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n");
/* If we are trying to debug redraw issues then we want to pass
* the redraw_clip so it can be visualized */
* the bounding_redraw_clip so it can be visualized */
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) &&
may_use_clipped_redraw &&
!clip_region_empty)
{
cairo_rectangle_int_t clip_rect;
graphene_rect_t rect;
cairo_rectangle_int_t scissor_rect;
cairo_rectangle_int_t paint_rect;
cairo_region_get_extents (fb_clip_region, &clip_rect);
calculate_scissor_region (&clip_rect,
calculate_scissor_region (&fb_clip_region,
subpixel_compensation,
fb_width, fb_height,
&scissor_rect);
@@ -937,40 +863,31 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
scissor_rect.width,
scissor_rect.height);
paint_stage (stage_cogl, view, fb_clip_region);
_clutter_util_rect_from_rectangle (&fb_clip_region, &rect);
scale_and_clamp_rect (&rect, 1.0f / fb_scale, &paint_rect);
_clutter_util_rectangle_offset (&paint_rect,
view_rect.x,
view_rect.y,
&paint_rect);
paint_stage (stage_cogl, view, &paint_rect);
cogl_framebuffer_pop_clip (fb);
}
else
{
cairo_rectangle_int_t clip;
cairo_region_t *view_region;
clip = (cairo_rectangle_int_t) {
.x = 0,
.y = 0,
.width = ceilf (view_rect.width * fb_scale),
.height = ceilf (view_rect.height * fb_scale)
};
view_region = cairo_region_create_rectangle (&clip);
paint_stage (stage_cogl, view, view_region);
cairo_region_destroy (view_region);
}
paint_stage (stage_cogl, view, &view_rect);
}
cogl_pop_framebuffer ();
cairo_region_get_extents (redraw_clip, &redraw_rect);
if (may_use_clipped_redraw &&
G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
{
CoglContext *ctx = cogl_framebuffer_get_context (fb);
static CoglPipeline *outline = NULL;
ClutterActor *actor = CLUTTER_ACTOR (wrapper);
float x_1 = redraw_rect.x;
float x_2 = redraw_rect.x + redraw_rect.width;
float y_1 = redraw_rect.y;
float y_2 = redraw_rect.y + redraw_rect.height;
float x_1 = redraw_clip.x;
float x_2 = redraw_clip.x + redraw_clip.width;
float y_1 = redraw_clip.y;
float y_2 = redraw_clip.y + redraw_clip.height;
CoglVertexP2 quad[4] = {
{ x_1, y_1 },
{ x_2, y_1 },
@@ -1016,47 +933,32 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
}
else
{
swap_region = cairo_region_copy (fb_clip_region);
swap_region = fb_clip_region;
g_assert (swap_region.width > 0);
do_swap_buffer = TRUE;
}
}
else
{
swap_region = cairo_region_create ();
swap_region = (cairo_rectangle_int_t) { 0 };
do_swap_buffer = TRUE;
}
if (redraw_clip)
cairo_region_destroy (redraw_clip);
if (fb_clip_region)
cairo_region_destroy (fb_clip_region);
if (do_swap_buffer)
{
gboolean res;
COGL_TRACE_BEGIN_SCOPED (ClutterStageCoglRedrawViewSwapFramebuffer,
"Paint (swap framebuffer)");
if (clutter_stage_view_get_onscreen (view) !=
clutter_stage_view_get_framebuffer (view))
{
cairo_region_t *transformed_swap_region;
transformed_swap_region =
transform_swap_region_to_onscreen (view, swap_region);
cairo_region_destroy (swap_region);
swap_region = transformed_swap_region;
transform_swap_region_to_onscreen (view, &swap_region);
}
res = swap_framebuffer (stage_window,
view,
swap_region,
swap_with_damage);
cairo_region_destroy (swap_region);
return res;
return swap_framebuffer (stage_window,
view,
&swap_region,
swap_with_damage);
}
else
{
@@ -1096,7 +998,6 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
/* reset the redraw clipping for the next paint... */
stage_cogl->initialized_redraw_clip = FALSE;
g_clear_pointer (&stage_cogl->redraw_clip, cairo_region_destroy);
stage_cogl->frame_count++;
@@ -1118,7 +1019,7 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
iface->add_redraw_clip = clutter_stage_cogl_add_redraw_clip;
iface->has_redraw_clips = clutter_stage_cogl_has_redraw_clips;
iface->ignoring_redraw_clips = clutter_stage_cogl_ignoring_redraw_clips;
iface->get_redraw_clip = clutter_stage_cogl_get_redraw_clip;
iface->get_redraw_clip_bounds = clutter_stage_cogl_get_redraw_clip_bounds;
iface->redraw = clutter_stage_cogl_redraw;
}

View File

@@ -62,7 +62,7 @@ struct _ClutterStageCogl
gint last_sync_delay;
cairo_region_t *redraw_clip;
cairo_rectangle_int_t bounding_redraw_clip;
guint initialized_redraw_clip : 1;

View File

@@ -39,7 +39,9 @@
* be available any more in the next major version of Clutter.
*
* A #ClutterAlpha binds a #ClutterTimeline to a progress function which
* translates the time T into an adimensional factor alpha.
* translates the time T into an adimensional factor alpha. The factor can
* then be used to drive a #ClutterBehaviour, which will translate the
* alpha value into something meaningful for a #ClutterActor.
*
* You should provide a #ClutterTimeline and bind it to the #ClutterAlpha
* instance using clutter_alpha_set_timeline(). You should also set an
@@ -57,6 +59,9 @@
* pause, stop or resume the #ClutterAlpha from calling the alpha function by
* using the appropriate functions of the #ClutterTimeline object.
*
* #ClutterAlpha is used to "drive" a #ClutterBehaviour instance, and it
* is internally used by the #ClutterAnimation API.
*
* #ClutterAlpha is available since Clutter 0.2.
*
* #ClutterAlpha is deprecated since Clutter 1.12. #ClutterTimeline and
@@ -73,7 +78,9 @@
*
* The following JSON fragment defines a #ClutterAlpha
* using a #ClutterTimeline with id "sine-timeline" and an alpha
* function called `my_sine_alpha`.
* function called `my_sine_alpha`. The defined #ClutterAlpha
* instance can be reused in multiple #ClutterBehaviour
* definitions or for #ClutterAnimation definitions.
*
* |[
* {
@@ -638,6 +645,9 @@ clutter_alpha_get_timeline (ClutterAlpha *alpha)
* bind a #ClutterTimeline object to the #ClutterAlpha instance
* using clutter_alpha_set_timeline().
*
* You should use the newly created #ClutterAlpha instance inside
* a #ClutterBehaviour object.
*
* Return value: the newly created empty #ClutterAlpha instance.
*
* Since: 0.2

View File

@@ -57,6 +57,13 @@
* #ClutterAnimatable interface it is possible for that instance to
* control the way the initial and final states are interpolated.
*
* #ClutterAnimations are distinguished from #ClutterBehaviours
* because the former can only control #GObject properties of a single
* #GObject instance, while the latter can control multiple properties
* using accessor functions inside the #ClutterBehaviour
* `alpha_notify` virtual function, and can control multiple #ClutterActors
* as well.
*
* For convenience, it is possible to use the clutter_actor_animate()
* function call which will take care of setting up and tearing down
* a #ClutterAnimation instance and animate an actor between its current

View File

@@ -0,0 +1,303 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Jorn Baayen <jorn@openedhand.com>
* Emmanuele Bassi <ebassi@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-actor.h"
#include "clutter-alpha.h"
#include "clutter-behaviour.h"
#include "clutter-behaviour-depth.h"
#include "clutter-enum-types.h"
#include "clutter-main.h"
#include "clutter-debug.h"
#include "clutter-private.h"
/**
* SECTION:clutter-behaviour-depth
* @Title: ClutterBehaviourDepth
* @short_description: A behaviour controlling the Z position
* @Deprecated: 1.6: Use clutter_actor_animate() instead
*
* #ClutterBehaviourDepth is a simple #ClutterBehaviour controlling the
* depth of a set of actors between a start and end depth.
*
* #ClutterBehaviourDepth is available since Clutter 0.4.
*
* Deprecated: 1.6: Use the #ClutterActor:depth property and
* clutter_actor_animate(), or #ClutterAnimator, or #ClutterState
* instead.
*/
struct _ClutterBehaviourDepthPrivate
{
gint depth_start;
gint depth_end;
};
enum
{
PROP_0,
PROP_DEPTH_START,
PROP_DEPTH_END
};
G_DEFINE_TYPE_WITH_PRIVATE (ClutterBehaviourDepth,
clutter_behaviour_depth,
CLUTTER_TYPE_BEHAVIOUR)
static void
alpha_notify_foreach (ClutterBehaviour *behaviour,
ClutterActor *actor,
gpointer user_data)
{
clutter_actor_set_depth (actor, GPOINTER_TO_INT (user_data));
}
static void
clutter_behaviour_depth_alpha_notify (ClutterBehaviour *behaviour,
gdouble alpha_value)
{
ClutterBehaviourDepthPrivate *priv;
gint depth;
priv = CLUTTER_BEHAVIOUR_DEPTH (behaviour)->priv;
/* Need to create factor as to avoid borking signedness */
depth = (alpha_value * (priv->depth_end - priv->depth_start))
+ priv->depth_start;
CLUTTER_NOTE (ANIMATION, "alpha: %.4f, depth: %d", alpha_value, depth);
clutter_behaviour_actors_foreach (behaviour,
alpha_notify_foreach,
GINT_TO_POINTER (depth));
}
static void
clutter_behaviour_depth_applied (ClutterBehaviour *behaviour,
ClutterActor *actor)
{
ClutterBehaviourDepth *depth = CLUTTER_BEHAVIOUR_DEPTH (behaviour);
clutter_actor_set_depth (actor, depth->priv->depth_start);
}
static void
clutter_behaviour_depth_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterBehaviourDepth *depth = CLUTTER_BEHAVIOUR_DEPTH (gobject);
switch (prop_id)
{
case PROP_DEPTH_START:
depth->priv->depth_start = g_value_get_int (value);
break;
case PROP_DEPTH_END:
depth->priv->depth_end = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_depth_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterBehaviourDepth *depth = CLUTTER_BEHAVIOUR_DEPTH (gobject);
switch (prop_id)
{
case PROP_DEPTH_START:
g_value_set_int (value, depth->priv->depth_start);
break;
case PROP_DEPTH_END:
g_value_set_int (value, depth->priv->depth_end);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_depth_class_init (ClutterBehaviourDepthClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBehaviourClass *behaviour_class = CLUTTER_BEHAVIOUR_CLASS (klass);
gobject_class->set_property = clutter_behaviour_depth_set_property;
gobject_class->get_property = clutter_behaviour_depth_get_property;
behaviour_class->alpha_notify = clutter_behaviour_depth_alpha_notify;
behaviour_class->applied = clutter_behaviour_depth_applied;
/**
* ClutterBehaviourDepth:depth-start:
*
* Start depth level to apply to the actors.
*
* Since: 0.4
*
* Deprecated: 1.6
*/
g_object_class_install_property (gobject_class,
PROP_DEPTH_START,
g_param_spec_int ("depth-start",
P_("Start Depth"),
P_("Initial depth to apply"),
G_MININT, G_MAXINT, 0,
CLUTTER_PARAM_READWRITE));
/**
* ClutterBehaviourDepth:depth-end:
*
* End depth level to apply to the actors.
*
* Since: 0.4
*
* Deprecated: 1.6
*/
g_object_class_install_property (gobject_class,
PROP_DEPTH_END,
g_param_spec_int ("depth-end",
P_("End Depth"),
P_("Final depth to apply"),
G_MININT, G_MAXINT, 0,
CLUTTER_PARAM_READWRITE));
}
static void
clutter_behaviour_depth_init (ClutterBehaviourDepth *depth)
{
depth->priv = clutter_behaviour_depth_get_instance_private (depth);
}
/**
* clutter_behaviour_depth_new:
* @alpha: (allow-none): a #ClutterAlpha instance, or %NULL
* @depth_start: initial value of the depth
* @depth_end: final value of the depth
*
* Creates a new #ClutterBehaviourDepth which can be used to control
* the ClutterActor:depth property of a set of #ClutterActor<!-- -->s.
*
* If @alpha is not %NULL, the #ClutterBehaviour will take ownership
* of the #ClutterAlpha instance. In the case when @alpha is %NULL,
* it can be set later with clutter_behaviour_set_alpha().
*
* Return value: (transfer full): the newly created behaviour
*
* Since: 0.4
*
* Deprecated: 1.6
*/
ClutterBehaviour *
clutter_behaviour_depth_new (ClutterAlpha *alpha,
gint depth_start,
gint depth_end)
{
g_return_val_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha), NULL);
return g_object_new (CLUTTER_TYPE_BEHAVIOUR_DEPTH,
"alpha", alpha,
"depth-start", depth_start,
"depth-end", depth_end,
NULL);
}
/**
* clutter_behaviour_depth_set_bounds:
* @behaviour: a #ClutterBehaviourDepth
* @depth_start: initial value of the depth
* @depth_end: final value of the depth
*
* Sets the boundaries of the @behaviour.
*
* Since: 0.6
*
* Deprecated: 1.6
*/
void
clutter_behaviour_depth_set_bounds (ClutterBehaviourDepth *behaviour,
gint depth_start,
gint depth_end)
{
ClutterBehaviourDepthPrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_DEPTH (behaviour));
priv = behaviour->priv;
g_object_freeze_notify (G_OBJECT (behaviour));
if (priv->depth_start != depth_start)
{
priv->depth_start = depth_start;
g_object_notify (G_OBJECT (behaviour), "depth-start");
}
if (priv->depth_end != depth_end)
{
priv->depth_end = depth_end;
g_object_notify (G_OBJECT (behaviour), "depth-end");
}
g_object_thaw_notify (G_OBJECT (behaviour));
}
/**
* clutter_behaviour_depth_get_bounds:
* @behaviour: a #ClutterBehaviourDepth
* @depth_start: (out): return location for the initial depth value, or %NULL
* @depth_end: (out): return location for the final depth value, or %NULL
*
* Gets the boundaries of the @behaviour
*
* Since: 0.6
*
* Deprecated: 1.6
*/
void
clutter_behaviour_depth_get_bounds (ClutterBehaviourDepth *behaviour,
gint *depth_start,
gint *depth_end)
{
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_DEPTH (behaviour));
if (depth_start)
*depth_start = behaviour->priv->depth_start;
if (depth_end)
*depth_end = behaviour->priv->depth_end;
}

View File

@@ -0,0 +1,101 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Jorn Baayen <jorn@openedhand.com>
* Emmanuele Bassi <ebassi@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_BEHAVIOUR_DEPTH__
#define __CLUTTER_BEHAVIOUR_DEPTH__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_BEHAVIOUR_DEPTH (clutter_behaviour_depth_get_type ())
#define CLUTTER_BEHAVIOUR_DEPTH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BEHAVIOUR_DEPTH, ClutterBehaviourDepth))
#define CLUTTER_IS_BEHAVIOUR_DEPTH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BEHAVIOUR_DEPTH))
#define CLUTTER_BEHAVIOUR_DEPTH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BEHAVIOUR_DEPTH, ClutterBehaviourDepthClass))
#define CLUTTER_IS_BEHAVIOUR_DEPTH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BEHAVIOUR_DEPTH))
#define CLUTTER_BEHAVIOUR_DEPTH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BEHAVIOUR_DEPTH, ClutterBehaviourDepthClass))
typedef struct _ClutterBehaviourDepth ClutterBehaviourDepth;
typedef struct _ClutterBehaviourDepthPrivate ClutterBehaviourDepthPrivate;
typedef struct _ClutterBehaviourDepthClass ClutterBehaviourDepthClass;
/**
* ClutterBehaviourDepth:
*
* The #ClutterBehaviourDepth structure contains only private data
* and should be accessed using the provided API
*
* Since: 0.2
*
* Deprecated: 1.6: Use clutter_actor_animate() with #ClutterActor:depth
* instead.
*/
struct _ClutterBehaviourDepth
{
/*< private >*/
ClutterBehaviour parent_instance;
ClutterBehaviourDepthPrivate *priv;
};
/**
* ClutterBehaviourDepthClass:
*
* The #ClutterBehaviourDepthClass structure contains only private data
*
* Since: 0.2
*
* Deprecated: 1.6
*/
struct _ClutterBehaviourDepthClass
{
/*< private >*/
ClutterBehaviourClass parent_class;
};
CLUTTER_DEPRECATED
GType clutter_behaviour_depth_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(clutter_actor_animate and ClutterActor:depth)
ClutterBehaviour *clutter_behaviour_depth_new (ClutterAlpha *alpha,
gint depth_start,
gint depth_end);
CLUTTER_DEPRECATED
void clutter_behaviour_depth_set_bounds (ClutterBehaviourDepth *behaviour,
gint depth_start,
gint depth_end);
CLUTTER_DEPRECATED
void clutter_behaviour_depth_get_bounds (ClutterBehaviourDepth *behaviour,
gint *depth_start,
gint *depth_end);
G_END_DECLS
#endif /* __CLUTTER_BEHAVIOUR_DEPTH__ */

View File

@@ -0,0 +1,310 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:clutter-behaviour-opacity
* @Title: ClutterBehaviourOpacity
* @short_description: A behaviour controlling opacity
* @Deprecated: 1.6: Use clutter_actor_animate() instead.
*
* #ClutterBehaviourOpacity controls the opacity of a set of actors.
*
* Since: 0.2
*
* Deprecated: 1.6: Use the #ClutterActor:opacity property and
* clutter_actor_animate(), or #ClutterAnimator, or #ClutterState
* instead.
*/
#include "clutter-build-config.h"
#include <math.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-alpha.h"
#include "clutter-behaviour.h"
#include "clutter-behaviour-opacity.h"
#include "clutter-private.h"
#include "clutter-debug.h"
struct _ClutterBehaviourOpacityPrivate
{
guint8 opacity_start;
guint8 opacity_end;
};
enum
{
PROP_0,
PROP_OPACITY_START,
PROP_OPACITY_END,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE_WITH_PRIVATE (ClutterBehaviourOpacity,
clutter_behaviour_opacity,
CLUTTER_TYPE_BEHAVIOUR)
static void
alpha_notify_foreach (ClutterBehaviour *behaviour,
ClutterActor *actor,
gpointer data)
{
clutter_actor_set_opacity (actor, GPOINTER_TO_UINT(data));
}
static void
clutter_behaviour_alpha_notify (ClutterBehaviour *behave,
gdouble alpha_value)
{
ClutterBehaviourOpacityPrivate *priv;
guint8 opacity;
priv = CLUTTER_BEHAVIOUR_OPACITY (behave)->priv;
opacity = alpha_value
* (priv->opacity_end - priv->opacity_start)
+ priv->opacity_start;
CLUTTER_NOTE (ANIMATION, "alpha: %.4f, opacity: %u",
alpha_value,
opacity);
clutter_behaviour_actors_foreach (behave,
alpha_notify_foreach,
GUINT_TO_POINTER ((guint) opacity));
}
static void
clutter_behaviour_opacity_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterBehaviourOpacity *self = CLUTTER_BEHAVIOUR_OPACITY (gobject);
switch (prop_id)
{
case PROP_OPACITY_START:
clutter_behaviour_opacity_set_bounds (self,
g_value_get_uint (value),
self->priv->opacity_end);
break;
case PROP_OPACITY_END:
clutter_behaviour_opacity_set_bounds (self,
self->priv->opacity_start,
g_value_get_uint (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_opacity_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterBehaviourOpacity *self = CLUTTER_BEHAVIOUR_OPACITY (gobject);
switch (prop_id)
{
case PROP_OPACITY_START:
g_value_set_uint (value, self->priv->opacity_start);
break;
case PROP_OPACITY_END:
g_value_set_uint (value, self->priv->opacity_end);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_opacity_class_init (ClutterBehaviourOpacityClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBehaviourClass *behave_class = CLUTTER_BEHAVIOUR_CLASS (klass);
GParamSpec *pspec;
gobject_class->set_property = clutter_behaviour_opacity_set_property;
gobject_class->get_property = clutter_behaviour_opacity_get_property;
/**
* ClutterBehaviourOpacity:opacity-start:
*
* Initial opacity level of the behaviour.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
pspec = g_param_spec_uint ("opacity-start",
P_("Opacity Start"),
P_("Initial opacity level"),
0, 255,
0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_OPACITY_START] = pspec;
g_object_class_install_property (gobject_class, PROP_OPACITY_START, pspec);
/**
* ClutterBehaviourOpacity:opacity-end:
*
* Final opacity level of the behaviour.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
pspec = g_param_spec_uint ("opacity-end",
P_("Opacity End"),
P_("Final opacity level"),
0, 255,
0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_OPACITY_END] = pspec;
g_object_class_install_property (gobject_class, PROP_OPACITY_END, pspec);
behave_class->alpha_notify = clutter_behaviour_alpha_notify;
}
static void
clutter_behaviour_opacity_init (ClutterBehaviourOpacity *self)
{
self->priv = clutter_behaviour_opacity_get_instance_private (self);
}
/**
* clutter_behaviour_opacity_new:
* @alpha: (allow-none): a #ClutterAlpha instance, or %NULL
* @opacity_start: minimum level of opacity
* @opacity_end: maximum level of opacity
*
* Creates a new #ClutterBehaviourOpacity object, driven by @alpha
* which controls the opacity property of every actor, making it
* change in the interval between @opacity_start and @opacity_end.
*
* If @alpha is not %NULL, the #ClutterBehaviour will take ownership
* of the #ClutterAlpha instance. In the case when @alpha is %NULL,
* it can be set later with clutter_behaviour_set_alpha().
*
* Return value: the newly created #ClutterBehaviourOpacity
*
* Since: 0.2
*
* Deprecated: 1.6
*/
ClutterBehaviour *
clutter_behaviour_opacity_new (ClutterAlpha *alpha,
guint8 opacity_start,
guint8 opacity_end)
{
return g_object_new (CLUTTER_TYPE_BEHAVIOUR_OPACITY,
"alpha", alpha,
"opacity-start", opacity_start,
"opacity-end", opacity_end,
NULL);
}
/**
* clutter_behaviour_opacity_set_bounds:
* @behaviour: a #ClutterBehaviourOpacity
* @opacity_start: minimum level of opacity
* @opacity_end: maximum level of opacity
*
* Sets the initial and final levels of the opacity applied by @behaviour
* on each actor it controls.
*
* Since: 0.6
*
* Deprecated: 1.6
*/
void
clutter_behaviour_opacity_set_bounds (ClutterBehaviourOpacity *behaviour,
guint8 opacity_start,
guint8 opacity_end)
{
ClutterBehaviourOpacityPrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_OPACITY (behaviour));
priv = behaviour->priv;
g_object_freeze_notify (G_OBJECT (behaviour));
if (priv->opacity_start != opacity_start)
{
priv->opacity_start = opacity_start;
g_object_notify_by_pspec (G_OBJECT (behaviour), obj_props[PROP_OPACITY_START]);
}
if (priv->opacity_end != opacity_end)
{
priv->opacity_end = opacity_end;
g_object_notify_by_pspec (G_OBJECT (behaviour), obj_props[PROP_OPACITY_END]);
}
g_object_thaw_notify (G_OBJECT (behaviour));
}
/**
* clutter_behaviour_opacity_get_bounds:
* @behaviour: a #ClutterBehaviourOpacity
* @opacity_start: (out): return location for the minimum level of opacity, or %NULL
* @opacity_end: (out): return location for the maximum level of opacity, or %NULL
*
* Gets the initial and final levels of the opacity applied by @behaviour
* on each actor it controls.
*
* Since: 0.6
*
* Deprecated: 1.6
*/
void
clutter_behaviour_opacity_get_bounds (ClutterBehaviourOpacity *behaviour,
guint8 *opacity_start,
guint8 *opacity_end)
{
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_OPACITY (behaviour));
if (opacity_start)
*opacity_start = behaviour->priv->opacity_start;
if (opacity_end)
*opacity_end = behaviour->priv->opacity_end;
}

View File

@@ -0,0 +1,115 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Jorn Baayen <jorn@openedhand.com>
* Emmanuele Bassi <ebassi@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_BEHAVIOUR_OPACITY_H__
#define __CLUTTER_BEHAVIOUR_OPACITY_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_BEHAVIOUR_OPACITY (clutter_behaviour_opacity_get_type ())
#define CLUTTER_BEHAVIOUR_OPACITY(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
CLUTTER_TYPE_BEHAVIOUR_OPACITY, ClutterBehaviourOpacity))
#define CLUTTER_BEHAVIOUR_OPACITY_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
CLUTTER_TYPE_BEHAVIOUR_OPACITY, ClutterBehaviourOpacityClass))
#define CLUTTER_IS_BEHAVIOUR_OPACITY(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
CLUTTER_TYPE_BEHAVIOUR_OPACITY))
#define CLUTTER_IS_BEHAVIOUR_OPACITY_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
CLUTTER_TYPE_BEHAVIOUR_OPACITY))
#define CLUTTER_BEHAVIOUR_OPACITY_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
CLUTTER_TYPE_BEHAVIOUR_OPACITY, ClutterBehaviourOpacityClass))
typedef struct _ClutterBehaviourOpacity ClutterBehaviourOpacity;
typedef struct _ClutterBehaviourOpacityPrivate ClutterBehaviourOpacityPrivate;
typedef struct _ClutterBehaviourOpacityClass ClutterBehaviourOpacityClass;
/**
* ClutterBehaviourOpacity:
*
* The #ClutterBehaviourOpacity structure contains only private data and
* should be accessed using the provided API
*
* Since: 0.2
*
* Deprecated: 1.6: Use clutter_actor_animate() and #ClutterActor:opacity
* instead.
*/
struct _ClutterBehaviourOpacity
{
/*< private >*/
ClutterBehaviour parent;
ClutterBehaviourOpacityPrivate *priv;
};
/**
* ClutterBehaviourOpacityClass:
*
* The #ClutterBehaviourOpacityClass structure contains only private data
*
* Since: 0.2
*
* Deprecated: 1.6
*/
struct _ClutterBehaviourOpacityClass
{
/*< private >*/
ClutterBehaviourClass parent_class;
};
CLUTTER_DEPRECATED
GType clutter_behaviour_opacity_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(clutter_actor_animate and ClutterActor:opacity)
ClutterBehaviour *clutter_behaviour_opacity_new (ClutterAlpha *alpha,
guint8 opacity_start,
guint8 opacity_end);
CLUTTER_DEPRECATED
void clutter_behaviour_opacity_set_bounds (ClutterBehaviourOpacity *behaviour,
guint8 opacity_start,
guint8 opacity_end);
CLUTTER_DEPRECATED
void clutter_behaviour_opacity_get_bounds (ClutterBehaviourOpacity *behaviour,
guint8 *opacity_start,
guint8 *opacity_end);
G_END_DECLS
#endif /* __CLUTTER_BEHAVIOUR_OPACITY_H__ */

View File

@@ -0,0 +1,437 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:clutter-behaviour-scale
* @Title: ClutterBehaviourScale
* @short_description: A behaviour controlling scale
* @Deprecated: 1.6: Use clutter_actor_animate() with #ClutterActor:scale-x
* and #ClutterActor:scale-y instead.
*
* A #ClutterBehaviourScale interpolates actors size between two values.
*
* Deprecated: 1.6: Use the #ClutterActor:scale-x and #ClutterActor:scale-y
* properties, and clutter_actor_animate(), or #ClutterAnimator or
* #ClutterState instead.
*/
#include "clutter-build-config.h"
#include <math.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-actor.h"
#include "clutter-alpha.h"
#include "clutter-behaviour.h"
#include "clutter-behaviour-scale.h"
#include "clutter-debug.h"
#include "clutter-main.h"
#include "clutter-private.h"
struct _ClutterBehaviourScalePrivate
{
gdouble x_scale_start;
gdouble y_scale_start;
gdouble x_scale_end;
gdouble y_scale_end;
};
enum
{
PROP_0,
PROP_X_SCALE_START,
PROP_Y_SCALE_START,
PROP_X_SCALE_END,
PROP_Y_SCALE_END,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE_WITH_PRIVATE (ClutterBehaviourScale,
clutter_behaviour_scale,
CLUTTER_TYPE_BEHAVIOUR)
typedef struct {
gdouble scale_x;
gdouble scale_y;
} ScaleFrameClosure;
static void
scale_frame_foreach (ClutterBehaviour *behaviour,
ClutterActor *actor,
gpointer data)
{
ScaleFrameClosure *closure = data;
clutter_actor_set_scale (actor, closure->scale_x, closure->scale_y);
}
static void
clutter_behaviour_scale_alpha_notify (ClutterBehaviour *behave,
gdouble alpha_value)
{
ClutterBehaviourScalePrivate *priv;
ScaleFrameClosure closure = { 0, };
priv = CLUTTER_BEHAVIOUR_SCALE (behave)->priv;
/* Fix the start/end values, avoids potential rounding errors on large
* values.
*/
if (alpha_value == 1.0)
{
closure.scale_x = priv->x_scale_end;
closure.scale_y = priv->y_scale_end;
}
else if (alpha_value == 0)
{
closure.scale_x = priv->x_scale_start;
closure.scale_y = priv->y_scale_start;
}
else
{
closure.scale_x = (priv->x_scale_end - priv->x_scale_start)
* alpha_value
+ priv->x_scale_start;
closure.scale_y = (priv->y_scale_end - priv->y_scale_start)
* alpha_value
+ priv->y_scale_start;
}
clutter_behaviour_actors_foreach (behave,
scale_frame_foreach,
&closure);
}
static void
clutter_behaviour_scale_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterBehaviourScalePrivate *priv;
priv = CLUTTER_BEHAVIOUR_SCALE (gobject)->priv;
switch (prop_id)
{
case PROP_X_SCALE_START:
priv->x_scale_start = g_value_get_double (value);
break;
case PROP_X_SCALE_END:
priv->x_scale_end = g_value_get_double (value);
break;
case PROP_Y_SCALE_START:
priv->y_scale_start = g_value_get_double (value);
break;
case PROP_Y_SCALE_END:
priv->y_scale_end = g_value_get_double (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_scale_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterBehaviourScalePrivate *priv;
priv = CLUTTER_BEHAVIOUR_SCALE (gobject)->priv;
switch (prop_id)
{
case PROP_X_SCALE_START:
g_value_set_double (value, priv->x_scale_start);
break;
case PROP_X_SCALE_END:
g_value_set_double (value, priv->x_scale_end);
break;
case PROP_Y_SCALE_START:
g_value_set_double (value, priv->y_scale_start);
break;
case PROP_Y_SCALE_END:
g_value_set_double (value, priv->y_scale_end);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_scale_class_init (ClutterBehaviourScaleClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBehaviourClass *behave_class = CLUTTER_BEHAVIOUR_CLASS (klass);
GParamSpec *pspec = NULL;
gobject_class->set_property = clutter_behaviour_scale_set_property;
gobject_class->get_property = clutter_behaviour_scale_get_property;
/**
* ClutterBehaviourScale:x-scale-start:
*
* The initial scaling factor on the X axis for the actors.
*
* Since: 0.6
*
* Deprecated: 1.6
*/
pspec = g_param_spec_double ("x-scale-start",
P_("X Start Scale"),
P_("Initial scale on the X axis"),
0.0, G_MAXDOUBLE,
1.0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_X_SCALE_START] = pspec;
g_object_class_install_property (gobject_class,
PROP_X_SCALE_START,
pspec);
/**
* ClutterBehaviourScale:x-scale-end:
*
* The final scaling factor on the X axis for the actors.
*
* Since: 0.6
*
* Deprecated: 1.6
*/
pspec = g_param_spec_double ("x-scale-end",
P_("X End Scale"),
P_("Final scale on the X axis"),
0.0, G_MAXDOUBLE,
1.0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_X_SCALE_END] = pspec;
g_object_class_install_property (gobject_class,
PROP_X_SCALE_END,
pspec);
/**
* ClutterBehaviourScale:y-scale-start:
*
* The initial scaling factor on the Y axis for the actors.
*
* Since: 0.6
*
* Deprecated: 1.6
*/
pspec = g_param_spec_double ("y-scale-start",
P_("Y Start Scale"),
P_("Initial scale on the Y axis"),
0.0, G_MAXDOUBLE,
1.0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_Y_SCALE_START] = pspec;
g_object_class_install_property (gobject_class,
PROP_Y_SCALE_START,
pspec);
/**
* ClutterBehaviourScale:y-scale-end:
*
* The final scaling factor on the Y axis for the actors.
*
* Since: 0.6
*
* Deprecated: 1.6
*/
pspec = g_param_spec_double ("y-scale-end",
P_("Y End Scale"),
P_("Final scale on the Y axis"),
0.0, G_MAXDOUBLE,
1.0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_Y_SCALE_END] = pspec;
g_object_class_install_property (gobject_class,
PROP_Y_SCALE_END,
pspec);
behave_class->alpha_notify = clutter_behaviour_scale_alpha_notify;
}
static void
clutter_behaviour_scale_init (ClutterBehaviourScale *self)
{
ClutterBehaviourScalePrivate *priv;
self->priv = priv = clutter_behaviour_scale_get_instance_private (self);
priv->x_scale_start = priv->x_scale_end = 1.0;
priv->y_scale_start = priv->y_scale_end = 1.0;
}
/**
* clutter_behaviour_scale_new:
* @alpha: (allow-none): a #ClutterAlpha instance, or %NULL
* @x_scale_start: initial scale factor on the X axis
* @y_scale_start: initial scale factor on the Y axis
* @x_scale_end: final scale factor on the X axis
* @y_scale_end: final scale factor on the Y axis
*
* Creates a new #ClutterBehaviourScale instance.
*
* If @alpha is not %NULL, the #ClutterBehaviour will take ownership
* of the #ClutterAlpha instance. In the case when @alpha is %NULL,
* it can be set later with clutter_behaviour_set_alpha().
*
* Return value: (transfer full): the newly created #ClutterBehaviourScale
*
* Since: 0.2
*
* Deprecated: 1.6
*/
ClutterBehaviour *
clutter_behaviour_scale_new (ClutterAlpha *alpha,
gdouble x_scale_start,
gdouble y_scale_start,
gdouble x_scale_end,
gdouble y_scale_end)
{
g_return_val_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha), NULL);
return g_object_new (CLUTTER_TYPE_BEHAVIOUR_SCALE,
"alpha", alpha,
"x-scale-start", x_scale_start,
"y-scale-start", y_scale_start,
"x-scale-end", x_scale_end,
"y-scale-end", y_scale_end,
NULL);
}
/**
* clutter_behaviour_scale_set_bounds:
* @scale: a #ClutterBehaviourScale
* @x_scale_start: initial scale factor on the X axis
* @y_scale_start: initial scale factor on the Y axis
* @x_scale_end: final scale factor on the X axis
* @y_scale_end: final scale factor on the Y axis
*
* Sets the bounds used by scale behaviour.
*
* Since: 0.6
*
* Deprecated: 1.6
*/
void
clutter_behaviour_scale_set_bounds (ClutterBehaviourScale *scale,
gdouble x_scale_start,
gdouble y_scale_start,
gdouble x_scale_end,
gdouble y_scale_end)
{
ClutterBehaviourScalePrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_SCALE (scale));
priv = scale->priv;
g_object_freeze_notify (G_OBJECT (scale));
if (priv->x_scale_start != x_scale_start)
{
priv->x_scale_start = x_scale_start;
g_object_notify_by_pspec (G_OBJECT (scale), obj_props[PROP_X_SCALE_START]);
}
if (priv->y_scale_start != y_scale_start)
{
priv->y_scale_start = y_scale_start;
g_object_notify_by_pspec (G_OBJECT (scale), obj_props[PROP_Y_SCALE_START]);
}
if (priv->x_scale_end != x_scale_end)
{
priv->x_scale_end = x_scale_end;
g_object_notify_by_pspec (G_OBJECT (scale), obj_props[PROP_X_SCALE_END]);
}
if (priv->y_scale_end != y_scale_end)
{
priv->y_scale_end = y_scale_end;
g_object_notify_by_pspec (G_OBJECT (scale), obj_props[PROP_Y_SCALE_END]);
}
g_object_thaw_notify (G_OBJECT (scale));
}
/**
* clutter_behaviour_scale_get_bounds:
* @scale: a #ClutterBehaviourScale
* @x_scale_start: (out): return location for the initial scale factor on the X
* axis, or %NULL
* @y_scale_start: (out): return location for the initial scale factor on the Y
* axis, or %NULL
* @x_scale_end: (out): return location for the final scale factor on the X axis,
* or %NULL
* @y_scale_end: (out): return location for the final scale factor on the Y axis,
* or %NULL
*
* Retrieves the bounds used by scale behaviour.
*
* Since: 0.4
*
* Deprecated: 1.6
*/
void
clutter_behaviour_scale_get_bounds (ClutterBehaviourScale *scale,
gdouble *x_scale_start,
gdouble *y_scale_start,
gdouble *x_scale_end,
gdouble *y_scale_end)
{
ClutterBehaviourScalePrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_SCALE (scale));
priv = scale->priv;
if (x_scale_start)
*x_scale_start = priv->x_scale_start;
if (x_scale_end)
*x_scale_end = priv->x_scale_end;
if (y_scale_start)
*y_scale_start = priv->y_scale_start;
if (y_scale_end)
*y_scale_end = priv->y_scale_end;
}

View File

@@ -0,0 +1,107 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Jorn Baayen <jorn@openedhand.com>
* Emmanuele Bassi <ebassi@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_BEHAVIOUR_SCALE_H__
#define __CLUTTER_BEHAVIOUR_SCALE_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#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;
/**
* ClutterBehaviourScale:
*
* The #ClutterBehaviourScale struct contains only private data and
* should be accessed using the provided API
*
* Since: 0.2
*
* Deprecated: 1.6: Use clutter_actor_animate() with #ClutterActor:scale-x
* and #ClutterActor:scale-y instead.
*/
struct _ClutterBehaviourScale
{
/*< private >*/
ClutterBehaviour parent_instance;
ClutterBehaviourScalePrivate *priv;
};
/**
* ClutterBehaviourScaleClass:
*
* The #ClutterBehaviourScaleClass struct contains only private data
*
* Since: 0.2
*
* Deprecated: 1.6
*/
struct _ClutterBehaviourScaleClass
{
/*< private >*/
ClutterBehaviourClass parent_class;
};
CLUTTER_DEPRECATED
GType clutter_behaviour_scale_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(clutter_actor_animate with ClutterActor:scale-x and ClutterActor:scale-y)
ClutterBehaviour *clutter_behaviour_scale_new (ClutterAlpha *alpha,
gdouble x_scale_start,
gdouble y_scale_start,
gdouble x_scale_end,
gdouble y_scale_end);
CLUTTER_DEPRECATED
void clutter_behaviour_scale_set_bounds (ClutterBehaviourScale *scale,
gdouble x_scale_start,
gdouble y_scale_start,
gdouble x_scale_end,
gdouble y_scale_end);
CLUTTER_DEPRECATED
void clutter_behaviour_scale_get_bounds (ClutterBehaviourScale *scale,
gdouble *x_scale_start,
gdouble *y_scale_start,
gdouble *x_scale_end,
gdouble *y_scale_end);
G_END_DECLS
#endif /* __CLUTTER_BEHAVIOUR_SCALE_H__ */

View File

@@ -0,0 +1,657 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:clutter-behaviour
* @Title: ClutterBehaviour
* @short_description: Class for providing behaviours to actors
* @Deprecated: 1.6: Use clutter_actor_animate(), #ClutterAnimator or
* #ClutterState instead
*
* #ClutterBehaviour is the base class for implementing behaviours. A
* behaviour is a controller object for #ClutterActor<!-- -->s; you can
* use a behaviour to control one or more properties of an actor (such
* as its opacity, or its position). A #ClutterBehaviour is driven by
* an "alpha function" stored inside a #ClutterAlpha object; an alpha
* function is a function depending solely on time. The alpha function
* computes a value which is then applied to the properties of the
* actors driven by a behaviour.
*
* Clutter provides some pre-defined behaviours, like #ClutterBehaviourPath,
* which controls the position of a set of actors making them "walk" along
* a set of nodes; #ClutterBehaviourOpacity, which controls the opacity
* of a set of actors; #ClutterBehaviourScale, which controls the width
* and height of a set of actors.
*
* To visualize the effects of different alpha functions on a
* #ClutterBehaviour implementation it is possible to take the
* #ClutterBehaviourPath as an example:
*
* ![](path-alpha-func.png)
*
* The actors position between the path's end points directly correlates
* to the #ClutterAlpha's current alpha value driving the behaviour. With
* the #ClutterAlpha's function set to a linear ramp the actor
* will follow the path at a constant velocity, but when changing to
* a sine wave the actor initially accelerates before quickly
* decelerating.
*
* In order to implement a new behaviour you should subclass #ClutterBehaviour
* and override the "alpha_notify" virtual function; inside the overridden
* function you should obtain the alpha value from the #ClutterAlpha
* instance bound to the behaviour and apply it to the desiderd property
* (or properties) of every actor controlled by the behaviour.
*
* #ClutterBehaviour is available since Clutter 0.2.
*
* #ClutterBehaviour and its sub-classes have been discouraged sing Clutter
* 1.0, and formally deprecated since Clutter 1.6. You should use the
* [implicit animation][clutter-actor-animation] support inside #ClutterActor
* if you still have code using #ClutterBehaviour.
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-behaviour.h"
#include "clutter-alpha.h"
#include "clutter-debug.h"
#include "clutter-main.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-scriptable.h"
#include "clutter-script-private.h"
struct _ClutterBehaviourPrivate
{
ClutterAlpha *alpha;
guint notify_id;
GSList *actors;
};
enum
{
PROP_0,
PROP_ALPHA,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
enum
{
APPLIED,
REMOVED,
LAST_SIGNAL
};
static guint behave_signals[LAST_SIGNAL] = { 0 };
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterBehaviour,
clutter_behaviour,
G_TYPE_OBJECT,
G_ADD_PRIVATE (ClutterBehaviour)
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE,
clutter_scriptable_iface_init))
static gboolean
clutter_behaviour_parse_custom_node (ClutterScriptable *scriptable,
ClutterScript *script,
GValue *value,
const gchar *name,
JsonNode *node)
{
if (strncmp (name, "alpha", 5) == 0)
{
GObject *alpha;
alpha = _clutter_script_parse_alpha (script, node);
if (alpha != NULL)
{
g_value_init (value, CLUTTER_TYPE_ALPHA);
g_value_set_object (value, alpha);
return TRUE;
}
}
return FALSE;
}
static void
clutter_scriptable_iface_init (ClutterScriptableIface *iface)
{
iface->parse_custom_node = clutter_behaviour_parse_custom_node;
}
static void
clutter_behaviour_dispose (GObject *gobject)
{
ClutterBehaviour *self = CLUTTER_BEHAVIOUR (gobject);
clutter_behaviour_set_alpha (self, NULL);
clutter_behaviour_remove_all (self);
G_OBJECT_CLASS (clutter_behaviour_parent_class)->dispose (gobject);
}
static void
clutter_behaviour_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterBehaviour *behaviour = CLUTTER_BEHAVIOUR (object);
switch (prop_id)
{
case PROP_ALPHA:
clutter_behaviour_set_alpha (behaviour, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterBehaviour *behaviour = CLUTTER_BEHAVIOUR (object);
ClutterBehaviourPrivate *priv = behaviour->priv;
switch (prop_id)
{
case PROP_ALPHA:
g_value_set_object (value, priv->alpha);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_alpha_notify_unimplemented (ClutterBehaviour *behaviour,
gdouble alpha_value)
{
g_warning ("ClutterBehaviourClass::alpha_notify not implemented for '%s'",
g_type_name (G_TYPE_FROM_INSTANCE (behaviour)));
}
static void
clutter_behaviour_class_init (ClutterBehaviourClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = clutter_behaviour_dispose;
object_class->set_property = clutter_behaviour_set_property;
object_class->get_property = clutter_behaviour_get_property;
/**
* ClutterBehaviour:alpha:
*
* The #ClutterAlpha object used to drive this behaviour. A #ClutterAlpha
* object binds a #ClutterTimeline and a function which computes a value
* (the "alpha") depending on the time. Each time the alpha value changes
* the alpha-notify virtual function is called.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
obj_props[PROP_ALPHA] =
g_param_spec_object ("alpha",
P_("Alpha"),
P_("Alpha Object to drive the behaviour"),
CLUTTER_TYPE_ALPHA,
CLUTTER_PARAM_READWRITE);
g_object_class_install_properties (object_class,
PROP_LAST,
obj_props);
klass->alpha_notify = clutter_behaviour_alpha_notify_unimplemented;
/**
* ClutterBehaviour::applied:
* @behaviour: the #ClutterBehaviour that received the signal
* @actor: the actor the behaviour was applied to.
*
* The ::apply signal is emitted each time the behaviour is applied
* to an actor.
*
* Since: 0.4
*
* Deprecated: 1.6
*/
behave_signals[APPLIED] =
g_signal_new ("applied",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterBehaviourClass, applied),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
/**
* ClutterBehaviour::removed:
* @behaviour: the #ClutterBehaviour that received the signal
* @actor: the removed actor
*
* The ::removed signal is emitted each time a behaviour is not applied
* to an actor anymore.
*
* Since: 0.4
*
* Deprecated: 1.6
*/
behave_signals[REMOVED] =
g_signal_new ("removed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterBehaviourClass, removed),
NULL, NULL, NULL,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
}
static void
clutter_behaviour_init (ClutterBehaviour *self)
{
self->priv = clutter_behaviour_get_instance_private (self);
}
static void
remove_actor_on_destroy (ClutterActor *actor,
ClutterBehaviour *behaviour)
{
clutter_behaviour_remove (behaviour, actor);
}
/**
* clutter_behaviour_apply:
* @behave: a #ClutterBehaviour
* @actor: a #ClutterActor
*
* Applies @behave to @actor. This function adds a reference on
* the actor.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
void
clutter_behaviour_apply (ClutterBehaviour *behave,
ClutterActor *actor)
{
ClutterBehaviourPrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behave));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
priv = behave->priv;
if (g_slist_find (priv->actors, actor))
{
g_warning ("The behaviour of type %s already applies "
"to the actor of type %s",
g_type_name (G_OBJECT_TYPE (behave)),
g_type_name (G_OBJECT_TYPE (actor)));
return;
}
priv->actors = g_slist_append (priv->actors, g_object_ref (actor));
g_signal_connect (actor, "destroy",
G_CALLBACK (remove_actor_on_destroy),
behave);
g_signal_emit (behave, behave_signals[APPLIED], 0, actor);
}
/**
* clutter_behaviour_is_applied:
* @behave: a #ClutterBehaviour
* @actor: a #ClutterActor
*
* Check if @behave applied to @actor.
*
* Return value: TRUE if actor has behaviour. FALSE otherwise.
*
* Since: 0.4
*
* Deprecated: 1.6
*/
gboolean
clutter_behaviour_is_applied (ClutterBehaviour *behave,
ClutterActor *actor)
{
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR (behave), FALSE);
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE);
return (g_slist_find (behave->priv->actors, actor) != NULL);
}
/**
* clutter_behaviour_remove:
* @behave: a #ClutterBehaviour
* @actor: a #ClutterActor
*
* Removes @actor from the list of #ClutterActor<!-- -->s to which
* @behave applies. This function removes a reference on the actor.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
void
clutter_behaviour_remove (ClutterBehaviour *behave,
ClutterActor *actor)
{
ClutterBehaviourPrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behave));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
priv = behave->priv;
if (!g_slist_find (priv->actors, actor))
{
g_warning ("The behaviour of type %s is not applied "
"to the actor of type %s",
g_type_name (G_OBJECT_TYPE (behave)),
g_type_name (G_OBJECT_TYPE (actor)));
return;
}
g_signal_handlers_disconnect_by_func (actor,
G_CALLBACK (remove_actor_on_destroy),
behave);
priv->actors = g_slist_remove (priv->actors, actor);
g_signal_emit (behave, behave_signals[REMOVED], 0, actor);
g_object_unref (actor);
}
/**
* clutter_behaviour_get_n_actors:
* @behave: a #ClutterBehaviour
*
* Gets the number of actors this behaviour is applied too.
*
* Return value: The number of applied actors
*
* Since: 0.2
*
* Deprecated: 1.6
*/
gint
clutter_behaviour_get_n_actors (ClutterBehaviour *behave)
{
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR (behave), 0);
return g_slist_length (behave->priv->actors);
}
/**
* clutter_behaviour_get_nth_actor:
* @behave: a #ClutterBehaviour
* @index_: the index of an actor this behaviour is applied too.
*
* Gets an actor the behaviour was applied to referenced by index num.
*
* Return value: (transfer none): A Clutter actor or NULL if @index_ is invalid.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
ClutterActor *
clutter_behaviour_get_nth_actor (ClutterBehaviour *behave,
gint index_)
{
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR (behave), NULL);
return g_slist_nth_data (behave->priv->actors, index_);
}
/**
* clutter_behaviour_actors_foreach:
* @behave: a #ClutterBehaviour
* @func: (scope call): a function called for each actor
* @data: optional data to be passed to the function, or %NULL
*
* Calls @func for every actor driven by @behave.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
void
clutter_behaviour_actors_foreach (ClutterBehaviour *behave,
ClutterBehaviourForeachFunc func,
gpointer data)
{
GSList *l;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behave));
g_return_if_fail (func != NULL);
for (l = behave->priv->actors; l != NULL; l = l->next)
{
ClutterActor *actor = l->data;
g_assert (CLUTTER_IS_ACTOR (actor));
func (behave, actor, data);
}
}
/**
* clutter_behaviour_get_alpha:
* @behave: a #ClutterBehaviour
*
* Retrieves the #ClutterAlpha object bound to @behave.
*
* Return value: (transfer none): a #ClutterAlpha object, or %NULL if no alpha
* object has been bound to this behaviour.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
ClutterAlpha *
clutter_behaviour_get_alpha (ClutterBehaviour *behave)
{
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR (behave), NULL);
return behave->priv->alpha;
}
static void
notify_cb (GObject *object,
GParamSpec *param_spec,
ClutterBehaviour *behave)
{
ClutterBehaviourClass *klass;
klass = CLUTTER_BEHAVIOUR_GET_CLASS (behave);
CLUTTER_NOTE (ANIMATION, "notify::alpha");
/* no actors, we can stop right here */
if (behave->priv->actors == NULL)
return;
if (klass->alpha_notify != NULL)
{
gdouble alpha_value = clutter_alpha_get_alpha (behave->priv->alpha);
CLUTTER_NOTE (ANIMATION, "calling %s::alpha_notify (%p, %.4f)",
g_type_name (G_TYPE_FROM_CLASS (klass)),
behave, alpha_value);
klass->alpha_notify (behave, alpha_value);
}
}
/**
* clutter_behaviour_set_alpha:
* @behave: a #ClutterBehaviour
* @alpha: a #ClutterAlpha or %NULL to unset a previously set alpha
*
* Binds @alpha to a #ClutterBehaviour. The #ClutterAlpha object
* is what makes a behaviour work: for each tick of the timeline
* used by #ClutterAlpha a new value of the alpha parameter is
* computed by the alpha function; the value should be used by
* the #ClutterBehaviour to update one or more properties of the
* actors to which the behaviour applies.
*
* If @alpha is not %NULL, the #ClutterBehaviour will take ownership
* of the #ClutterAlpha instance.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
void
clutter_behaviour_set_alpha (ClutterBehaviour *behave,
ClutterAlpha *alpha)
{
ClutterBehaviourPrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behave));
g_return_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha));
priv = behave->priv;
if (priv->alpha == alpha)
return;
if (priv->notify_id)
{
CLUTTER_NOTE (ANIMATION, "removing previous notify-id (%d)",
priv->notify_id);
g_signal_handler_disconnect (priv->alpha, priv->notify_id);
priv->notify_id = 0;
}
if (priv->alpha != NULL)
{
CLUTTER_NOTE (ANIMATION, "removing previous alpha object");
g_object_unref (priv->alpha);
priv->alpha = NULL;
}
if (alpha != NULL)
{
priv->alpha = g_object_ref_sink (alpha);
priv->notify_id = g_signal_connect (priv->alpha, "notify::alpha",
G_CALLBACK(notify_cb),
behave);
CLUTTER_NOTE (ANIMATION, "setting new alpha object (%p, notify:%d)",
priv->alpha, priv->notify_id);
}
g_object_notify_by_pspec (G_OBJECT (behave), obj_props[PROP_ALPHA]);
}
/**
* clutter_behaviour_get_actors:
* @behave: a #ClutterBehaviour
*
* Retrieves all the actors to which @behave applies. It is not recommended
* for derived classes to use this in there alpha notify method but use
* #clutter_behaviour_actors_foreach as it avoids alot of needless allocations.
*
* Return value: (transfer container) (element-type Clutter.Actor): a list of
* actors. You should free the returned list with g_slist_free() when
* finished using it.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
GSList *
clutter_behaviour_get_actors (ClutterBehaviour *behave)
{
ClutterBehaviourPrivate *priv;
GSList *retval, *l;
g_return_val_if_fail (CLUTTER_BEHAVIOUR (behave), NULL);
priv = behave->priv;
retval = NULL;
for (l = priv->actors; l != NULL; l = l->next)
retval = g_slist_prepend (retval, l->data);
return g_slist_reverse (retval);
}
/**
* clutter_behaviour_remove_all:
* @behave: a #ClutterBehaviour
*
* Removes every actor from the list that @behave holds.
*
* Since: 0.4
*
* Deprecated: 1.6
*/
void
clutter_behaviour_remove_all (ClutterBehaviour *behave)
{
ClutterBehaviourPrivate *priv;
GSList *l;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behave));
priv = behave->priv;
for (l = priv->actors; l != NULL; l = l->next)
{
ClutterActor *actor = l->data;
g_signal_emit (behave, behave_signals[REMOVED], 0, actor);
g_signal_handlers_disconnect_by_func (actor,
G_CALLBACK (remove_actor_on_destroy),
behave);
g_object_unref (actor);
}
g_slist_free (priv->actors);
priv->actors = NULL;
}

View File

@@ -0,0 +1,170 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Jorn Baayen <jorn@openedhand.com>
* Emmanuele Bassi <ebassi@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_BEHAVIOUR_H__
#define __CLUTTER_BEHAVIOUR_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_BEHAVIOUR clutter_behaviour_get_type()
#define CLUTTER_BEHAVIOUR(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviour))
#define CLUTTER_BEHAVIOUR_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviourClass))
#define CLUTTER_IS_BEHAVIOUR(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
CLUTTER_TYPE_BEHAVIOUR))
#define CLUTTER_IS_BEHAVIOUR_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
CLUTTER_TYPE_BEHAVIOUR))
#define CLUTTER_BEHAVIOUR_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviourClass))
typedef struct _ClutterBehaviourPrivate ClutterBehaviourPrivate;
typedef struct _ClutterBehaviourClass ClutterBehaviourClass;
/**
* ClutterBehaviourForeachFunc:
* @behaviour: the #ClutterBehaviour
* @actor: an actor driven by @behaviour
* @data: (closure): optional data passed to the function
*
* This function is passed to clutter_behaviour_actors_foreach() and
* will be called for each actor driven by @behaviour.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
typedef void (*ClutterBehaviourForeachFunc) (ClutterBehaviour *behaviour,
ClutterActor *actor,
gpointer data);
/**
* ClutterBehaviour:
*
* #ClutterBehaviour-struct contains only private data and should
* be accessed with the functions below.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
struct _ClutterBehaviour
{
/*< private >*/
GObject parent;
ClutterBehaviourPrivate *priv;
};
/**
* ClutterBehaviourClass:
* @alpha_notify: virtual function, called each time the #ClutterAlpha
* computes a new alpha value; the actors to which the behaviour applies
* should be changed in this function. Every subclass of #ClutterBehaviour
* must implement this virtual function
* @applied: signal class handler for the ClutterBehaviour::applied signal
* @removed: signal class handler for the ClutterBehaviour::removed signal
*
* Base class for behaviours.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
struct _ClutterBehaviourClass
{
/*< private >*/
GObjectClass parent_class;
/*< public >*/
/* vfunc, not signal */
void (*alpha_notify) (ClutterBehaviour *behave,
gdouble alpha_value);
/* signals */
void (*applied) (ClutterBehaviour *behave,
ClutterActor *actor);
void (*removed) (ClutterBehaviour *behave,
ClutterActor *actor);
/*< private >*/
/* padding, for future expansion */
void (*_clutter_behaviour1) (void);
void (*_clutter_behaviour2) (void);
void (*_clutter_behaviour3) (void);
void (*_clutter_behaviour4) (void);
void (*_clutter_behaviour5) (void);
void (*_clutter_behaviour6) (void);
};
CLUTTER_DEPRECATED
GType clutter_behaviour_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED
void clutter_behaviour_apply (ClutterBehaviour *behave,
ClutterActor *actor);
CLUTTER_DEPRECATED
void clutter_behaviour_remove (ClutterBehaviour *behave,
ClutterActor *actor);
CLUTTER_DEPRECATED
void clutter_behaviour_remove_all (ClutterBehaviour *behave);
CLUTTER_DEPRECATED
void clutter_behaviour_actors_foreach (ClutterBehaviour *behave,
ClutterBehaviourForeachFunc func,
gpointer data);
CLUTTER_DEPRECATED
gint clutter_behaviour_get_n_actors (ClutterBehaviour *behave);
CLUTTER_DEPRECATED
ClutterActor *clutter_behaviour_get_nth_actor (ClutterBehaviour *behave,
gint index_);
CLUTTER_DEPRECATED
GSList * clutter_behaviour_get_actors (ClutterBehaviour *behave);
CLUTTER_DEPRECATED
ClutterAlpha *clutter_behaviour_get_alpha (ClutterBehaviour *behave);
CLUTTER_DEPRECATED
void clutter_behaviour_set_alpha (ClutterBehaviour *behave,
ClutterAlpha *alpha);
CLUTTER_DEPRECATED
gboolean clutter_behaviour_is_applied (ClutterBehaviour *behave,
ClutterActor *actor);
G_END_DECLS
#endif /* __CLUTTER_BEHAVIOUR_H__ */

View File

@@ -298,7 +298,7 @@ clutter_group_real_pick (ClutterActor *actor)
/* Chain up so we get a bounding box pained (if we are reactive) */
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->pick (actor);
g_list_foreach (priv->children, (GFunc) clutter_actor_pick, NULL);
g_list_foreach (priv->children, (GFunc) clutter_actor_paint, NULL);
}
static void

View File

@@ -0,0 +1,87 @@
#include "clutter-build-config.h"
#include "clutter-layout-manager.h"
/**
* clutter_layout_manager_begin_animation:
* @manager: a #ClutterLayoutManager
* @duration: the duration of the animation, in milliseconds
* @mode: the easing mode of the animation
*
* Begins an animation of @duration milliseconds, using the provided
* easing @mode
*
* The easing mode can be specified either as a #ClutterAnimationMode
* or as a logical id returned by clutter_alpha_register_func()
*
* The result of this function depends on the @manager implementation
*
* Return value: (transfer none): The #ClutterAlpha created by the
* layout manager; the returned instance is owned by the layout
* manager and should not be unreferenced
*
* Since: 1.2
*
* Deprecated: 1.12
*/
ClutterAlpha *
clutter_layout_manager_begin_animation (ClutterLayoutManager *manager,
guint duration,
gulong mode)
{
ClutterLayoutManagerClass *klass;
g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), NULL);
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
return klass->begin_animation (manager, duration, mode);
}
/**
* clutter_layout_manager_end_animation:
* @manager: a #ClutterLayoutManager
*
* Ends an animation started by clutter_layout_manager_begin_animation()
*
* The result of this call depends on the @manager implementation
*
* Since: 1.2
*
* Deprecated: 1.12
*/
void
clutter_layout_manager_end_animation (ClutterLayoutManager *manager)
{
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager)->end_animation (manager);
}
/**
* clutter_layout_manager_get_animation_progress:
* @manager: a #ClutterLayoutManager
*
* Retrieves the progress of the animation, if one has been started by
* clutter_layout_manager_begin_animation()
*
* The returned value has the same semantics of the #ClutterAlpha:alpha
* value
*
* Return value: the progress of the animation
*
* Since: 1.2
*
* Deprecated: 1.12
*/
gdouble
clutter_layout_manager_get_animation_progress (ClutterLayoutManager *manager)
{
ClutterLayoutManagerClass *klass;
g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), 1.0);
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
return klass->get_animation_progress (manager);
}

View File

@@ -1595,6 +1595,67 @@ clutter_texture_set_from_rgb_data (ClutterTexture *texture,
error);
}
/**
* clutter_texture_set_from_yuv_data:
* @texture: A #ClutterTexture
* @data: (array): Image data in YUV type colorspace.
* @width: Width in pixels of image data.
* @height: Height in pixels of image data
* @flags: #ClutterTextureFlags
* @error: Return location for a #GError, or %NULL.
*
* Sets a #ClutterTexture from YUV image data. If an error occurred,
* %FALSE is returned and @error is set.
*
* The YUV support depends on the driver; the format supported by the
* few drivers exposing this capability are not really useful.
*
* The proper way to convert image data in any YUV colorspace to any
* RGB colorspace is to use a fragment shader associated with the
* #ClutterTexture material.
*
* Return value: %TRUE if the texture was successfully updated
*
* Since: 0.4
*
* Deprecated: 1.10: Use a custom #ClutterContent implementation and
* set up the Cogl pipeline using a #ClutterPipelineNode with a
* fragment shader instead.
*/
gboolean
clutter_texture_set_from_yuv_data (ClutterTexture *texture,
const guchar *data,
gint width,
gint height,
ClutterTextureFlags flags,
GError **error)
{
g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), FALSE);
if (!clutter_feature_available (CLUTTER_FEATURE_TEXTURE_YUV))
{
g_set_error (error, CLUTTER_TEXTURE_ERROR,
CLUTTER_TEXTURE_ERROR_NO_YUV,
"YUV textures are not supported");
return FALSE;
}
/* Convert the flags to a CoglPixelFormat */
if ((flags & CLUTTER_TEXTURE_YUV_FLAG_YUV2))
{
g_set_error (error, CLUTTER_TEXTURE_ERROR,
CLUTTER_TEXTURE_ERROR_BAD_FORMAT,
"YUV2 textures are not supported");
return FALSE;
}
return clutter_texture_set_from_data (texture, data,
COGL_PIXEL_FORMAT_YUV,
width, height,
width * 3, 3,
error);
}
/*
* clutter_texture_async_load_complete:
* @self: a #ClutterTexture

View File

@@ -123,6 +123,14 @@ gboolean clutter_texture_get_pick_with_alpha (ClutterTexture
CLUTTER_DEPRECATED_FOR(ClutterOffscreenEffect)
ClutterActor * clutter_texture_new_from_actor (ClutterActor *actor);
CLUTTER_DEPRECATED
gboolean clutter_texture_set_from_yuv_data (ClutterTexture *texture,
const guchar *data,
gint width,
gint height,
ClutterTextureFlags flags,
GError **error);
G_END_DECLS
#endif /* __CLUTTER_TEXTURE_DEPRECATED_H__ */

View File

@@ -222,6 +222,10 @@ clutter_deprecated_headers = [
'deprecated/clutter-alpha.h',
'deprecated/clutter-animatable.h',
'deprecated/clutter-animation.h',
'deprecated/clutter-behaviour.h',
'deprecated/clutter-behaviour-depth.h',
'deprecated/clutter-behaviour-opacity.h',
'deprecated/clutter-behaviour-scale.h',
'deprecated/clutter-bin-layout.h',
'deprecated/clutter-box.h',
'deprecated/clutter-cairo-texture.h',
@@ -240,9 +244,14 @@ clutter_deprecated_headers = [
clutter_deprecated_sources = [
'deprecated/clutter-alpha.c',
'deprecated/clutter-animation.c',
'deprecated/clutter-behaviour.c',
'deprecated/clutter-behaviour-depth.c',
'deprecated/clutter-behaviour-opacity.c',
'deprecated/clutter-behaviour-scale.c',
'deprecated/clutter-box.c',
'deprecated/clutter-cairo-texture.c',
'deprecated/clutter-group.c',
'deprecated/clutter-layout-manager-deprecated.c',
'deprecated/clutter-rectangle.c',
'deprecated/clutter-state.c',
'deprecated/clutter-table-layout.c',

View File

@@ -276,7 +276,6 @@ emit_vertex_buffer_geometry (CoglFramebuffer *fb,
gboolean allocated = FALSE;
CoglAttribute *attributes[2];
CoglPrimitive *prim;
CoglIndices *indices;
int i;
n_verts = node->d.texture.rectangles->len * 4;
@@ -355,11 +354,22 @@ emit_vertex_buffer_geometry (CoglFramebuffer *fb,
attributes,
2 /* n_attributes */);
indices =
cogl_get_rectangle_indices (ctx, node->d.texture.rectangles->len);
#ifdef CLUTTER_COGL_HAS_GL
if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUADS))
cogl_primitive_set_mode (prim, GL_QUADS);
else
#endif
{
/* GLES doesn't support GL_QUADS so instead we use a VBO
with indexed vertices to generate GL_TRIANGLES from the
quads */
cogl_primitive_set_indices (prim, indices,
node->d.texture.rectangles->len * 6);
CoglIndices *indices =
cogl_get_rectangle_indices (ctx, node->d.texture.rectangles->len);
cogl_primitive_set_indices (prim, indices,
node->d.texture.rectangles->len * 6);
}
node->d.texture.primitive = prim;

View File

@@ -729,6 +729,18 @@ allocate_space (CoglAtlasTexture *atlas_tex,
return FALSE;
}
/* If we can't use FBOs then it will be too slow to migrate textures
and we shouldn't use the atlas */
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
{
g_set_error_literal (error,
COGL_SYSTEM_ERROR,
COGL_SYSTEM_ERROR_UNSUPPORTED,
"Atlasing disabled because migrations "
"would be too slow");
return FALSE;
}
/* Look for an existing atlas that can hold the texture */
for (l = ctx->atlases; l; l = l->next)
{

View File

@@ -42,6 +42,7 @@
#include "cogl-framebuffer-private.h"
#include "cogl-blit.h"
#include "cogl-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include <stdlib.h>

View File

@@ -46,6 +46,10 @@
#include "cogl-indices-private.h"
#include "cogl-private.h"
#include "cogl-gtype-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#ifdef COGL_PIPELINE_PROGEND_GLSL
#include "driver/gl/cogl-pipeline-progend-glsl-private.h"
#endif
#include <string.h>
#include <stdio.h>

View File

@@ -177,6 +177,24 @@ _cogl_bitmap_map (CoglBitmap *bitmap,
void
_cogl_bitmap_unmap (CoglBitmap *bitmap);
/* These two are replacements for map and unmap that should used when
* the pointer is going to be passed to GL for pixel packing or
* unpacking. The address might not be valid for reading if the bitmap
* was created with new_from_buffer but it will however be good to
* pass to glTexImage2D for example. The access should be READ for
* unpacking and WRITE for packing. It can not be both
*
* TODO: split this bind/unbind functions out into a GL specific file
*/
uint8_t *
_cogl_bitmap_gl_bind (CoglBitmap *bitmap,
CoglBufferAccess access,
CoglBufferMapHint hints,
GError **error);
void
_cogl_bitmap_gl_unbind (CoglBitmap *bitmap);
CoglContext *
_cogl_bitmap_get_context (CoglBitmap *bitmap);

View File

@@ -38,6 +38,7 @@
#include "cogl-pixel-buffer.h"
#include "cogl-context-private.h"
#include "cogl-gtype-private.h"
#include "driver/gl/cogl-buffer-gl-private.h"
#include <string.h>
@@ -442,6 +443,86 @@ _cogl_bitmap_unmap (CoglBitmap *bitmap)
cogl_buffer_unmap (bitmap->buffer);
}
uint8_t *
_cogl_bitmap_gl_bind (CoglBitmap *bitmap,
CoglBufferAccess access,
CoglBufferMapHint hints,
GError **error)
{
uint8_t *ptr;
GError *internal_error = NULL;
g_return_val_if_fail (access & (COGL_BUFFER_ACCESS_READ |
COGL_BUFFER_ACCESS_WRITE),
NULL);
/* Divert to another bitmap if this data is shared */
if (bitmap->shared_bmp)
return _cogl_bitmap_gl_bind (bitmap->shared_bmp, access, hints, error);
g_return_val_if_fail (!bitmap->bound, NULL);
/* If the bitmap wasn't created from a buffer then the
implementation of bind is the same as map */
if (bitmap->buffer == NULL)
{
uint8_t *data = _cogl_bitmap_map (bitmap, access, hints, error);
if (data)
bitmap->bound = TRUE;
return data;
}
if (access == COGL_BUFFER_ACCESS_READ)
ptr = _cogl_buffer_gl_bind (bitmap->buffer,
COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK,
&internal_error);
else if (access == COGL_BUFFER_ACCESS_WRITE)
ptr = _cogl_buffer_gl_bind (bitmap->buffer,
COGL_BUFFER_BIND_TARGET_PIXEL_PACK,
&internal_error);
else
{
ptr = NULL;
g_assert_not_reached ();
return NULL;
}
/* NB: _cogl_buffer_gl_bind() may return NULL in non-error
* conditions so we have to explicitly check internal_error to see
* if an exception was thrown */
if (internal_error)
{
g_propagate_error (error, internal_error);
return NULL;
}
bitmap->bound = TRUE;
/* The data pointer actually stores the offset */
return ptr + GPOINTER_TO_INT (bitmap->data);
}
void
_cogl_bitmap_gl_unbind (CoglBitmap *bitmap)
{
/* Divert to another bitmap if this data is shared */
if (bitmap->shared_bmp)
{
_cogl_bitmap_gl_unbind (bitmap->shared_bmp);
return;
}
g_assert (bitmap->bound);
bitmap->bound = FALSE;
/* If the bitmap wasn't created from a pixel array then the
implementation of unbind is the same as unmap */
if (bitmap->buffer)
_cogl_buffer_gl_unbind (bitmap->buffer);
else
_cogl_bitmap_unmap (bitmap);
}
CoglContext *
_cogl_bitmap_get_context (CoglBitmap *bitmap)
{

View File

@@ -245,6 +245,17 @@ validate_blend_statements (CoglBlendStringStatement *statements,
"for arg0 and DST_COLOR for arg1";
goto error;
}
if (!_cogl_has_private_feature (ctx,
COGL_PRIVATE_FEATURE_BLEND_CONSTANT) &&
arg->factor.is_color &&
(arg->factor.source.info->type ==
COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT))
{
error_string = "Driver doesn't support constant blend factors";
detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
goto error;
}
}
return TRUE;

View File

@@ -137,6 +137,12 @@ _cogl_buffer_initialize (CoglBuffer *buffer,
if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_PBOS))
use_malloc = TRUE;
}
else if (default_target == COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER ||
default_target == COGL_BUFFER_BIND_TARGET_INDEX_BUFFER)
{
if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_VBOS))
use_malloc = TRUE;
}
if (use_malloc)
{

View File

@@ -49,6 +49,7 @@
#include "cogl1-context.h"
#include "cogl-offscreen.h"
#include "cogl-matrix-stack.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
static void *
_cogl_clip_stack_push_entry (CoglClipStack *clip_stack,

View File

@@ -97,6 +97,7 @@ struct _CoglContext
/* Features cache */
unsigned long features[COGL_FLAGS_N_LONGS_FOR_SIZE (_COGL_N_FEATURE_IDS)];
CoglFeatureFlags feature_flags; /* legacy/deprecated feature flags */
unsigned long private_features
[COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_N_PRIVATE_FEATURES)];
@@ -292,6 +293,7 @@ struct _CoglContext
* the eglx backend doesn't yet have a corresponding Cogl winsys
* and so we wont have a renderer in that case. */
#ifdef COGL_HAS_XLIB_SUPPORT
int damage_base;
/* List of callback functions that will be given every Xlib event */
GSList *event_filters;
/* Current top of the XError trap state stack. The actual memory for

View File

@@ -51,6 +51,9 @@
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include "driver/gl/cogl-util-gl-private.h"
#include "winsys/cogl-winsys-private.h"
#include "winsys/cogl-winsys-stub-private.h"
#include "deprecated/cogl-framebuffer-deprecated.h"
#include <string.h>
#include <stdlib.h>
@@ -95,6 +98,9 @@ static CoglContext *_cogl_context = NULL;
static void
_cogl_init_feature_overrides (CoglContext *ctx)
{
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_VBOS)))
COGL_FLAGS_SET (ctx->private_features, COGL_PRIVATE_FEATURE_VBOS, FALSE);
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PBOS)))
COGL_FLAGS_SET (ctx->private_features, COGL_PRIVATE_FEATURE_PBOS, FALSE);
}
@@ -160,6 +166,7 @@ cogl_context_new (CoglDisplay *display,
/* Init default values */
memset (context->features, 0, sizeof (context->features));
context->feature_flags = 0;
memset (context->private_features, 0, sizeof (context->private_features));
memset (context->winsys_features, 0, sizeof (context->winsys_features));
@@ -324,6 +331,17 @@ cogl_context_new (CoglDisplay *display,
context->window_buffer = NULL;
context->framebuffer_stack = _cogl_create_framebuffer_stack ();
/* XXX: In this case the Clutter backend is still responsible for
* the OpenGL binding API and for creating onscreen framebuffers and
* so we have to add a dummy framebuffer to represent the backend
* owned window... */
if (_cogl_context_get_winsys (context) == _cogl_winsys_stub_get_vtable ())
{
CoglOnscreen *window = _cogl_onscreen_new ();
cogl_set_framebuffer (COGL_FRAMEBUFFER (window));
cogl_object_unref (COGL_FRAMEBUFFER (window));
}
context->current_path = NULL;
context->stencil_pipeline = cogl_pipeline_new (context);
@@ -393,7 +411,8 @@ cogl_context_new (CoglDisplay *display,
pipeline to track whether any layers have point sprite coords
enabled. We don't need to do this for GL3 or GLES2 because point
sprites are handled using a builtin varying in the shader. */
if (_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_GL_FIXED))
if (_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_GL_FIXED) &&
cogl_has_feature (context, COGL_FEATURE_ID_POINT_SPRITE))
GE (context, glEnable (GL_POINT_SPRITE));
_cogl_list_init (&context->fences);

View File

@@ -177,19 +177,33 @@ cogl_is_context (void *object);
* @COGL_FEATURE_ID_TEXTURE_RG: Support for
* %COGL_TEXTURE_COMPONENTS_RG as the internal components of a
* texture.
* @COGL_FEATURE_ID_OFFSCREEN: Offscreen rendering support
* @COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE: Multisample support for
* offscreen framebuffers
* @COGL_FEATURE_ID_ONSCREEN_MULTIPLE: Multiple onscreen framebuffers
* supported.
* @COGL_FEATURE_ID_UNSIGNED_INT_INDICES: Set if
* %COGL_INDICES_TYPE_UNSIGNED_INT is supported in
* cogl_indices_new().
* @COGL_FEATURE_ID_DEPTH_RANGE: cogl_pipeline_set_depth_range() support
* @COGL_FEATURE_ID_POINT_SPRITE: Whether
* cogl_pipeline_set_layer_point_sprite_coords_enabled() is supported.
* @COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE: Whether cogl_point_size_in
* can be used as an attribute to set a per-vertex point size.
* @COGL_FEATURE_ID_MAP_BUFFER_FOR_READ: Whether cogl_buffer_map() is
* supported with CoglBufferAccess including read support.
* @COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE: Whether cogl_buffer_map() is
* supported with CoglBufferAccess including write support.
* @COGL_FEATURE_ID_MIRRORED_REPEAT: Whether
* %COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT is supported.
* @COGL_FEATURE_ID_SWAP_BUFFERS_EVENT:
* Available if the window system supports reporting an event
* for swap buffer completions.
* @COGL_FEATURE_ID_BUFFER_AGE: Available if the age of #CoglOnscreen back
* buffers are tracked and so cogl_onscreen_get_buffer_age() can be
* expected to return age values other than 0.
* @COGL_FEATURE_ID_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering
* the depth buffer to a texture.
* @COGL_FEATURE_ID_PRESENTATION_TIME: Whether frame presentation
* time stamps will be recorded in #CoglFrameInfo objects.
*
@@ -201,12 +215,20 @@ cogl_is_context (void *object);
*/
typedef enum _CoglFeatureID
{
COGL_FEATURE_ID_OFFSCREEN,
COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE,
COGL_FEATURE_ID_ONSCREEN_MULTIPLE,
COGL_FEATURE_ID_UNSIGNED_INT_INDICES,
COGL_FEATURE_ID_DEPTH_RANGE,
COGL_FEATURE_ID_POINT_SPRITE,
COGL_FEATURE_ID_MAP_BUFFER_FOR_READ,
COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE,
COGL_FEATURE_ID_MIRRORED_REPEAT,
COGL_FEATURE_ID_SWAP_BUFFERS_EVENT,
COGL_FEATURE_ID_DEPTH_TEXTURE,
COGL_FEATURE_ID_PRESENTATION_TIME,
COGL_FEATURE_ID_FENCE,
COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE,
COGL_FEATURE_ID_TEXTURE_RG,
COGL_FEATURE_ID_BUFFER_AGE,
COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL,

View File

@@ -94,6 +94,11 @@ OPT (DISABLE_BATCHING,
"disable-batching",
N_("Disable Journal batching"),
N_("Disable batching of geometry in the Cogl Journal."))
OPT (DISABLE_VBOS,
N_("Root Cause"),
"disable-vbos",
N_("Disable GL Vertex Buffers"),
N_("Disable use of OpenGL vertex buffer objects"))
OPT (DISABLE_PBOS,
N_("Root Cause"),
"disable-pbos",

View File

@@ -70,6 +70,7 @@ static const int n_cogl_log_debug_keys =
static const GDebugKey cogl_behavioural_debug_keys[] = {
{ "rectangles", COGL_DEBUG_RECTANGLES },
{ "disable-batching", COGL_DEBUG_DISABLE_BATCHING },
{ "disable-vbos", COGL_DEBUG_DISABLE_VBOS },
{ "disable-pbos", COGL_DEBUG_DISABLE_PBOS },
{ "disable-software-transform", COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM },
{ "dump-atlas-image", COGL_DEBUG_DUMP_ATLAS_IMAGE },

View File

@@ -49,6 +49,7 @@ typedef enum
COGL_DEBUG_OBJECT,
COGL_DEBUG_BLEND_STRINGS,
COGL_DEBUG_DISABLE_BATCHING,
COGL_DEBUG_DISABLE_VBOS,
COGL_DEBUG_DISABLE_PBOS,
COGL_DEBUG_JOURNAL,
COGL_DEBUG_BATCHING,

View File

@@ -225,6 +225,13 @@ cogl_depth_state_get_test_function (CoglDepthState *state);
* mapped too although the range must still lye within the range [0,
* 1].
*
* If your driver does not support this feature (for example you are
* using GLES 1 drivers) then if you don't use the default range
* values you will get an error reported when calling
* cogl_pipeline_set_depth_state (). You can check ahead of time for
* the %COGL_FEATURE_ID_DEPTH_RANGE feature with
* cogl_has_feature() to know if this function will succeed.
*
* By default normalized device coordinate depth values are mapped to
* the full range of depth buffer values, [0, 1].
*

View File

@@ -79,6 +79,26 @@ G_BEGIN_DECLS
EGLDisplay
cogl_egl_context_get_egl_display (CoglContext *context);
/**
* cogl_egl_context_get_egl_context:
* @context: A #CoglContext pointer
*
* If you have done a runtime check to determine that Cogl is using
* EGL internally then this API can be used to retrieve the EGLContext
* handle that was setup internally. The result is undefined if Cogl
* is not using EGL.
*
* Note: The current window system backend can be checked using
* cogl_renderer_get_winsys_id().
*
* Return value: The internally setup EGLDisplay handle.
* Since: 1.18
* Stability: unstable
*/
EGLContext
cogl_egl_context_get_egl_context (CoglContext *context);
G_END_DECLS
/* The gobject introspection scanner seems to parse public headers in

View File

@@ -196,7 +196,7 @@ error:
gles_availability, \
namespaces, extension_names) \
{ min_gl_major, min_gl_minor, gles_availability, namespaces, \
extension_names, 0, 0, \
extension_names, 0, 0, 0, \
cogl_ext_ ## name ## _funcs },
#undef COGL_EXT_FUNCTION
#define COGL_EXT_FUNCTION(ret, name, args)

View File

@@ -77,6 +77,8 @@ struct _CoglFeatureData
extension is different from the namespace, you can specify it
with a ':' after the namespace */
const char *extension_names;
/* A set of feature flags to enable if the extension is available */
CoglFeatureFlags feature_flags;
/* A set of private feature flags to enable if the extension is
* available */
int feature_flags_private;

View File

@@ -60,6 +60,7 @@ typedef struct
CoglSwapChain *swap_chain;
gboolean need_stencil;
int samples_per_pixel;
gboolean depth_texture_enabled;
gboolean stereo_enabled;
} CoglFramebufferConfig;

View File

@@ -52,6 +52,7 @@
#include "cogl-private.h"
#include "cogl-primitives-private.h"
#include "cogl-gtype-private.h"
#include "driver/gl/cogl-texture-gl-private.h"
#include "winsys/cogl-winsys-private.h"
extern CoglObjectClass _cogl_onscreen_class;
@@ -705,6 +706,15 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
{
if (framebuffer->config.depth_texture_enabled)
{
g_set_error_literal (error, COGL_FRAMEBUFFER_ERROR,
COGL_FRAMEBUFFER_ERROR_ALLOCATE,
"Can't allocate onscreen framebuffer with a "
"texture based depth buffer");
return FALSE;
}
if (!winsys->onscreen_init (onscreen, error))
return FALSE;
@@ -719,6 +729,14 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
{
CoglOffscreen *offscreen = COGL_OFFSCREEN (framebuffer);
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
{
g_set_error_literal (error, COGL_SYSTEM_ERROR,
COGL_SYSTEM_ERROR_UNSUPPORTED,
"Offscreen framebuffers not supported by system");
return FALSE;
}
if (!cogl_texture_allocate (offscreen->texture, error))
return FALSE;
@@ -1040,6 +1058,32 @@ cogl_framebuffer_set_dither_enabled (CoglFramebuffer *framebuffer,
framebuffer->dither_enabled = dither_enabled;
}
void
cogl_framebuffer_set_depth_texture_enabled (CoglFramebuffer *framebuffer,
gboolean enabled)
{
g_return_if_fail (!framebuffer->allocated);
framebuffer->config.depth_texture_enabled = enabled;
}
gboolean
cogl_framebuffer_get_depth_texture_enabled (CoglFramebuffer *framebuffer)
{
return framebuffer->config.depth_texture_enabled;
}
CoglTexture *
cogl_framebuffer_get_depth_texture (CoglFramebuffer *framebuffer)
{
/* lazily allocate the framebuffer... */
if (!cogl_framebuffer_allocate (framebuffer, NULL))
return NULL;
g_return_val_if_fail (cogl_is_offscreen (framebuffer), NULL);
return COGL_OFFSCREEN(framebuffer)->depth_texture;
}
int
cogl_framebuffer_get_samples_per_pixel (CoglFramebuffer *framebuffer)
{

View File

@@ -837,6 +837,65 @@ void
cogl_framebuffer_set_stereo_mode (CoglFramebuffer *framebuffer,
CoglStereoMode stereo_mode);
/**
* cogl_framebuffer_set_depth_texture_enabled:
* @framebuffer: A #CoglFramebuffer
* @enabled: TRUE or FALSE
*
* If @enabled is #TRUE, the depth buffer used when rendering to @framebuffer
* is available as a texture. You can retrieve the texture with
* cogl_framebuffer_get_depth_texture().
*
* <note>It's possible that your GPU does not support depth textures. You
* should check the %COGL_FEATURE_ID_DEPTH_TEXTURE feature before using this
* function.</note>
* <note>It's not valid to call this function after the framebuffer has been
* allocated as the creation of the depth texture is done at allocation time.
* </note>
*
* Since: 1.14
* Stability: unstable
*/
void
cogl_framebuffer_set_depth_texture_enabled (CoglFramebuffer *framebuffer,
gboolean enabled);
/**
* cogl_framebuffer_get_depth_texture_enabled:
* @framebuffer: A #CoglFramebuffer
*
* Queries whether texture based depth buffer has been enabled via
* cogl_framebuffer_set_depth_texture_enabled().
*
* Return value: %TRUE if a depth texture has been enabled, else
* %FALSE.
*
* Since: 1.14
* Stability: unstable
*/
gboolean
cogl_framebuffer_get_depth_texture_enabled (CoglFramebuffer *framebuffer);
/**
* cogl_framebuffer_get_depth_texture:
* @framebuffer: A #CoglFramebuffer
*
* Retrieves the depth buffer of @framebuffer as a #CoglTexture. You need to
* call cogl_framebuffer_get_depth_texture(fb, TRUE); before using this
* function.
*
* <note>Calling this function implicitely allocates the framebuffer.</note>
* <note>The texture returned stays valid as long as the framebuffer stays
* valid.</note>
*
* Returns: (transfer none): the depth texture
*
* Since: 1.14
* Stability: unstable
*/
CoglTexture *
cogl_framebuffer_get_depth_texture (CoglFramebuffer *framebuffer);
/**
* cogl_framebuffer_set_samples_per_pixel:
* @framebuffer: A #CoglFramebuffer framebuffer

View File

@@ -69,6 +69,8 @@ typedef struct _CoglGLXRenderer
unsigned long base_winsys_features
[COGL_FLAGS_N_LONGS_FOR_SIZE (COGL_WINSYS_FEATURE_N_FEATURES)];
CoglFeatureFlags legacy_feature_flags;
/* Function pointers for core GLX functionality. We can't just link
against these directly because we need to conditionally load
libGL when we are using GLX so that it won't conflict with a GLES

View File

@@ -58,6 +58,26 @@
#include <GL/glx.h>
#include <cogl/cogl-types.h>
G_BEGIN_DECLS
/**
* cogl_glx_context_get_glx_context:
* @context: A #CoglContext pointer
*
* If you have done a runtime check to determine that Cogl is using
* GLX internally then this API can be used to retrieve the GLXContext
* handle that was setup internally. The result is undefined if Cogl
* is not using GLX.
*
* Return value: The internally setup GLXContext handle.
* Since: 1.18
* Stability: unstable
*/
GLXContext
cogl_glx_context_get_glx_context (CoglContext *context);
G_END_DECLS
/* The gobject introspection scanner seems to parse public headers in
* isolation which means we need to be extra careful about how we
* define and undefine __COGL_H_INSIDE__ used to detect when internal

View File

@@ -41,6 +41,7 @@
#include "cogl-point-in-poly-private.h"
#include "cogl-private.h"
#include "cogl1-context.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include "deprecated/cogl-vertex-buffer-private.h"
#include <string.h>
@@ -304,30 +305,46 @@ _cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start,
if (!_cogl_pipeline_get_real_blend_enabled (state->pipeline))
draw_flags |= COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE;
if (batch_len > 1)
{
CoglVerticesMode mode = COGL_VERTICES_MODE_TRIANGLES;
int first_vertex = state->current_vertex * 6 / 4;
_cogl_framebuffer_draw_indexed_attributes (framebuffer,
state->pipeline,
mode,
first_vertex,
batch_len * 6,
state->indices,
attributes,
state->attributes->len,
draw_flags);
}
else
#ifdef HAVE_COGL_GL
if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUADS))
{
/* XXX: it's rather evil that we sneak in the GL_QUADS enum here... */
_cogl_framebuffer_draw_attributes (framebuffer,
state->pipeline,
COGL_VERTICES_MODE_TRIANGLE_FAN,
state->current_vertex, 4,
GL_QUADS,
state->current_vertex, batch_len * 4,
attributes,
state->attributes->len,
draw_flags);
}
else
#endif /* HAVE_COGL_GL */
{
if (batch_len > 1)
{
CoglVerticesMode mode = COGL_VERTICES_MODE_TRIANGLES;
int first_vertex = state->current_vertex * 6 / 4;
_cogl_framebuffer_draw_indexed_attributes (framebuffer,
state->pipeline,
mode,
first_vertex,
batch_len * 6,
state->indices,
attributes,
state->attributes->len,
draw_flags);
}
else
{
_cogl_framebuffer_draw_attributes (framebuffer,
state->pipeline,
COGL_VERTICES_MODE_TRIANGLE_FAN,
state->current_vertex, 4,
attributes,
state->attributes->len,
draw_flags);
}
}
/* DEBUGGING CODE XXX: This path will cause all rectangles to be
* drawn with a coloured outline. Each batch will be rendered with
@@ -620,7 +637,8 @@ _cogl_journal_flush_vbo_offsets_and_entries (CoglJournalEntry *batch_start,
4,
COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
state->indices = cogl_get_rectangle_indices (ctx, batch_len);
if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUADS))
state->indices = cogl_get_rectangle_indices (ctx, batch_len);
/* We only create new Attributes when the stride within the
* AttributeBuffer changes. (due to a change in the number of pipeline
@@ -1127,6 +1145,12 @@ create_attribute_buffer (CoglJournal *journal,
CoglAttributeBuffer *vbo;
CoglContext *ctx = journal->framebuffer->context;
/* If CoglBuffers are being emulated with malloc then there's not
really any point in using the pool so we'll just allocate the
buffer directly */
if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_VBOS))
return cogl_attribute_buffer_new_with_size (ctx, n_bytes);
vbo = journal->vbo_pool[journal->next_vbo_in_pool];
if (vbo == NULL)

View File

@@ -161,6 +161,13 @@ typedef enum
COGL_MATRIX_TEXTURE
} CoglMatrixMode;
void
_cogl_matrix_entry_flush_to_gl_builtins (CoglContext *ctx,
CoglMatrixEntry *entry,
CoglMatrixMode mode,
CoglFramebuffer *framebuffer,
gboolean disable_flip);
void
_cogl_matrix_entry_cache_init (CoglMatrixEntryCache *cache);

View File

@@ -781,6 +781,127 @@ cogl_matrix_entry_is_identity (CoglMatrixEntry *entry)
return entry ? entry->op == COGL_MATRIX_OP_LOAD_IDENTITY : FALSE;
}
static void
_cogl_matrix_flush_to_gl_builtin (CoglContext *ctx,
gboolean is_identity,
CoglMatrix *matrix,
CoglMatrixMode mode)
{
g_assert (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED));
#ifdef HAVE_COGL_GL
if (ctx->flushed_matrix_mode != mode)
{
GLenum gl_mode = 0;
switch (mode)
{
case COGL_MATRIX_MODELVIEW:
gl_mode = GL_MODELVIEW;
break;
case COGL_MATRIX_PROJECTION:
gl_mode = GL_PROJECTION;
break;
case COGL_MATRIX_TEXTURE:
gl_mode = GL_TEXTURE;
break;
}
GE (ctx, glMatrixMode (gl_mode));
ctx->flushed_matrix_mode = mode;
}
if (is_identity)
GE (ctx, glLoadIdentity ());
else
GE (ctx, glLoadMatrixf (cogl_matrix_get_array (matrix)));
#endif
}
void
_cogl_matrix_entry_flush_to_gl_builtins (CoglContext *ctx,
CoglMatrixEntry *entry,
CoglMatrixMode mode,
CoglFramebuffer *framebuffer,
gboolean disable_flip)
{
g_assert (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_GL_FIXED));
#ifdef HAVE_COGL_GL
{
gboolean needs_flip;
CoglMatrixEntryCache *cache;
if (mode == COGL_MATRIX_PROJECTION)
{
/* Because Cogl defines texture coordinates to have a top left
* origin and because offscreen framebuffers may be used for
* rendering to textures we always render upside down to
* offscreen buffers. Also for some backends we need to render
* onscreen buffers upside-down too.
*/
if (disable_flip)
needs_flip = FALSE;
else
needs_flip = cogl_is_offscreen (framebuffer);
cache = &ctx->builtin_flushed_projection;
}
else
{
needs_flip = FALSE;
if (mode == COGL_MATRIX_MODELVIEW)
cache = &ctx->builtin_flushed_modelview;
else
cache = NULL;
}
/* We don't need to do anything if the state is the same */
if (!cache ||
_cogl_matrix_entry_cache_maybe_update (cache, entry, needs_flip))
{
gboolean is_identity;
CoglMatrix matrix;
if (entry->op == COGL_MATRIX_OP_LOAD_IDENTITY)
is_identity = TRUE;
else
{
is_identity = FALSE;
cogl_matrix_entry_get (entry, &matrix);
}
if (needs_flip)
{
CoglMatrix flipped_matrix;
cogl_matrix_multiply (&flipped_matrix,
&ctx->y_flip_matrix,
is_identity ?
&ctx->identity_matrix :
&matrix);
_cogl_matrix_flush_to_gl_builtin (ctx,
/* not identity */
FALSE,
&flipped_matrix,
mode);
}
else
{
_cogl_matrix_flush_to_gl_builtin (ctx,
is_identity,
&matrix,
mode);
}
}
}
#endif
}
gboolean
cogl_matrix_entry_equal (CoglMatrixEntry *entry0,
CoglMatrixEntry *entry1)

View File

@@ -59,6 +59,12 @@ struct _CoglOnscreen
{
CoglFramebuffer _parent;
#ifdef COGL_HAS_X11_SUPPORT
uint32_t foreign_xid;
CoglOnscreenX11MaskCallback foreign_update_mask_callback;
void *foreign_update_mask_data;
#endif
CoglList frame_closures;
gboolean resizable;

View File

@@ -411,16 +411,54 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen)
}
#ifdef COGL_HAS_X11_SUPPORT
void
cogl_x11_onscreen_set_foreign_window_xid (CoglOnscreen *onscreen,
uint32_t xid,
CoglOnscreenX11MaskCallback update,
void *user_data)
{
/* We don't wan't applications to get away with being lazy here and not
* passing an update callback... */
g_return_if_fail (update);
onscreen->foreign_xid = xid;
onscreen->foreign_update_mask_callback = update;
onscreen->foreign_update_mask_data = user_data;
}
uint32_t
cogl_x11_onscreen_get_window_xid (CoglOnscreen *onscreen)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
/* This should only be called for x11 onscreens */
g_return_val_if_fail (winsys->onscreen_x11_get_window_xid != NULL, 0);
if (onscreen->foreign_xid)
return onscreen->foreign_xid;
else
{
const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
return winsys->onscreen_x11_get_window_xid (onscreen);
/* This should only be called for x11 onscreens */
g_return_val_if_fail (winsys->onscreen_x11_get_window_xid != NULL, 0);
return winsys->onscreen_x11_get_window_xid (onscreen);
}
}
uint32_t
cogl_x11_onscreen_get_visual_xid (CoglOnscreen *onscreen)
{
CoglContext *ctx = COGL_FRAMEBUFFER (onscreen)->context;
XVisualInfo *visinfo;
uint32_t id;
/* This should only be called for xlib based onscreens */
visinfo = cogl_xlib_renderer_get_visual_info (ctx->display->renderer);
if (visinfo == NULL)
return 0;
id = (uint32_t)visinfo->visualid;
return id;
}
#endif /* COGL_HAS_X11_SUPPORT */

View File

@@ -75,6 +75,67 @@ CoglOnscreen *
cogl_onscreen_new (CoglContext *context, int width, int height);
#ifdef COGL_HAS_X11
typedef void (*CoglOnscreenX11MaskCallback) (CoglOnscreen *onscreen,
uint32_t event_mask,
void *user_data);
/**
* cogl_x11_onscreen_set_foreign_window_xid:
* @onscreen: The unallocated framebuffer to associated with an X
* window.
* @xid: The XID of an existing X window
* @update: (scope async): A callback that notifies of updates to what Cogl
* requires to be in the core X protocol event mask.
* @user_data: user data passed to @update
*
* Ideally we would recommend that you let Cogl be responsible for
* creating any X window required to back an onscreen framebuffer but
* if you really need to target a window created manually this
* function can be called before @onscreen has been allocated to set a
* foreign XID for your existing X window.
*
* Since Cogl needs, for example, to track changes to the size of an X
* window it requires that certain events be selected for via the core
* X protocol. This requirement may also be changed asynchronously so
* you must pass in an @update callback to inform you of Cogl's
* required event mask.
*
* For example if you are using Xlib you could use this API roughly
* as follows:
* [{
* static void
* my_update_cogl_x11_event_mask (CoglOnscreen *onscreen,
* uint32_t event_mask,
* void *user_data)
* {
* XSetWindowAttributes attrs;
* MyData *data = user_data;
* attrs.event_mask = event_mask | data->my_event_mask;
* XChangeWindowAttributes (data->xdpy,
* data->xwin,
* CWEventMask,
* &attrs);
* }
*
* {
* *snip*
* cogl_x11_onscreen_set_foreign_window_xid (onscreen,
* data->xwin,
* my_update_cogl_x11_event_mask,
* data);
* *snip*
* }
* }]
*
* Since: 2.0
* Stability: Unstable
*/
void
cogl_x11_onscreen_set_foreign_window_xid (CoglOnscreen *onscreen,
uint32_t xid,
CoglOnscreenX11MaskCallback update,
void *user_data);
/**
* cogl_x11_onscreen_get_window_xid:
* @onscreen: A #CoglOnscreen framebuffer
@@ -95,6 +156,10 @@ cogl_onscreen_new (CoglContext *context, int width, int height);
uint32_t
cogl_x11_onscreen_get_window_xid (CoglOnscreen *onscreen);
/* XXX: we should maybe remove this, since nothing currently uses
* it and the current implementation looks dubious. */
uint32_t
cogl_x11_onscreen_get_visual_xid (CoglOnscreen *onscreen);
#endif /* COGL_HAS_X11 */
/**

View File

@@ -613,6 +613,30 @@ cogl_pipeline_set_layer_point_sprite_coords_enabled (CoglPipeline *pipeline,
g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
/* Don't allow point sprite coordinates to be enabled if the driver
doesn't support it */
if (enable && !cogl_has_feature (ctx, COGL_FEATURE_ID_POINT_SPRITE))
{
if (error)
{
g_set_error_literal (error,
COGL_SYSTEM_ERROR,
COGL_SYSTEM_ERROR_UNSUPPORTED,
"Point sprite texture coordinates are enabled for "
"a layer but the GL driver does not support it.");
}
else
{
static gboolean warning_seen = FALSE;
if (!warning_seen)
g_warning ("Point sprite texture coordinates are enabled "
"for a layer but the GL driver does not support it.");
warning_seen = TRUE;
}
return FALSE;
}
/* Note: this will ensure that the layer exists, creating one if it
* doesn't already.
*

View File

@@ -432,6 +432,10 @@ cogl_pipeline_get_layer_mag_filter (CoglPipeline *pipeline,
* have 1.0,1.0. If @enable is %FALSE then the coordinates will be
* fixed for the entire point.
*
* This function will only work if %COGL_FEATURE_ID_POINT_SPRITE is
* available. If the feature is not available then the function will
* return %FALSE and set @error.
*
* Return value: %TRUE if the function succeeds, %FALSE otherwise.
* Since: 2.0
* Stability: unstable

View File

@@ -1014,6 +1014,9 @@ cogl_pipeline_set_blend_constant (CoglPipeline *pipeline,
g_return_if_fail (cogl_is_pipeline (pipeline));
if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLEND_CONSTANT))
return;
#if defined(HAVE_COGL_GLES2) || defined(HAVE_COGL_GL)
{
CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
@@ -1347,6 +1350,16 @@ cogl_pipeline_set_per_vertex_point_size (CoglPipeline *pipeline,
if (authority->big_state->per_vertex_point_size == enable)
return TRUE;
if (enable && !cogl_has_feature (ctx, COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE))
{
g_set_error_literal (error,
COGL_SYSTEM_ERROR,
COGL_SYSTEM_ERROR_UNSUPPORTED,
"Per-vertex point size is not supported");
return FALSE;
}
/* - Flush journal primitives referencing the current state.
* - Make sure the pipeline has no dependants so it may be modified.
* - If the pipeline isn't currently an authority for the state being

View File

@@ -544,6 +544,11 @@ cogl_pipeline_get_point_size (CoglPipeline *pipeline);
* and cogl_point_size_out is not written to then the results are
* undefined.
*
* Note that enabling this will only work if the
* %COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE feature is available. If
* this is not available then the function will return %FALSE and set
* a #GError.
*
* Since: 2.0
* Stability: Unstable
* Return value: %TRUE if the change suceeded or %FALSE otherwise

View File

@@ -49,6 +49,7 @@
#include "cogl-depth-state-private.h"
#include "cogl1-context.h"
#include "cogl-gtype-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include <glib.h>
#include <glib/gprintf.h>

View File

@@ -42,6 +42,7 @@
#include "cogl-framebuffer-private.h"
#include "cogl1-context.h"
#include "cogl-primitives-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include "deprecated/cogl-vertex-buffer-private.h"
#include <string.h>

View File

@@ -43,7 +43,9 @@ typedef enum
COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE,
COGL_PRIVATE_FEATURE_MESA_PACK_INVERT,
COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER,
COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES,
COGL_PRIVATE_FEATURE_PBOS,
COGL_PRIVATE_FEATURE_VBOS,
COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL,
COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL,
COGL_PRIVATE_FEATURE_TEXTURE_FORMAT_BGRA8888,
@@ -52,6 +54,8 @@ typedef enum
COGL_PRIVATE_FEATURE_READ_PIXELS_ANY_FORMAT,
COGL_PRIVATE_FEATURE_ALPHA_TEST,
COGL_PRIVATE_FEATURE_FORMAT_CONVERSION,
COGL_PRIVATE_FEATURE_QUADS,
COGL_PRIVATE_FEATURE_BLEND_CONSTANT,
COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS,
COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM,
COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS,

View File

@@ -46,7 +46,9 @@
#include "cogl-config-private.h"
#include "cogl-gtype-private.h"
#include "driver/gl/cogl-util-gl-private.h"
#include "winsys/cogl-winsys-private.h"
#include "winsys/cogl-winsys-stub-private.h"
#ifdef COGL_HAS_EGL_PLATFORM_XLIB_SUPPORT
#include "winsys/cogl-winsys-egl-x11-private.h"
@@ -141,6 +143,7 @@ static CoglWinsysVtableGetter _cogl_winsys_vtable_getters[] =
#ifdef COGL_HAS_EGL_PLATFORM_XLIB_SUPPORT
_cogl_winsys_egl_xlib_get_vtable,
#endif
_cogl_winsys_stub_get_vtable,
};
static void _cogl_renderer_free (CoglRenderer *renderer);
@@ -228,7 +231,7 @@ cogl_xlib_renderer_set_foreign_display (CoglRenderer *renderer,
/* If the application is using a foreign display then we can assume
it will also do its own event retrieval */
renderer->xlib_enable_event_retrieval = FALSE;
cogl_xlib_renderer_set_event_retrieval_enabled (renderer, FALSE);
}
Display *
@@ -239,6 +242,17 @@ cogl_xlib_renderer_get_foreign_display (CoglRenderer *renderer)
return renderer->foreign_xdpy;
}
void
cogl_xlib_renderer_set_event_retrieval_enabled (CoglRenderer *renderer,
gboolean enable)
{
g_return_if_fail (cogl_is_renderer (renderer));
/* NB: Renderers are considered immutable once connected */
g_return_if_fail (!renderer->connected);
renderer->xlib_enable_event_retrieval = enable;
}
void
cogl_xlib_renderer_request_reset_on_video_memory_purge (CoglRenderer *renderer,
gboolean enable)
@@ -720,6 +734,20 @@ _cogl_renderer_get_proc_address (CoglRenderer *renderer,
return winsys->renderer_get_proc_address (renderer, name, in_core);
}
int
cogl_renderer_get_n_fragment_texture_units (CoglRenderer *renderer)
{
int n = 0;
_COGL_GET_CONTEXT (ctx, 0);
#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES2)
GE (ctx, glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &n));
#endif
return n;
}
void
cogl_renderer_add_constraint (CoglRenderer *renderer,
CoglRendererConstraint constraint)

View File

@@ -202,6 +202,20 @@ cogl_renderer_set_winsys_id (CoglRenderer *renderer,
CoglWinsysID
cogl_renderer_get_winsys_id (CoglRenderer *renderer);
/**
* cogl_renderer_get_n_fragment_texture_units:
* @renderer: A #CoglRenderer
*
* Queries how many texture units can be used from fragment programs
*
* Returns: the number of texture image units.
*
* Since: 1.8
* Stability: Unstable
*/
int
cogl_renderer_get_n_fragment_texture_units (CoglRenderer *renderer);
/**
* cogl_renderer_check_onscreen_template: (skip)
* @renderer: A #CoglRenderer

View File

@@ -294,7 +294,8 @@ G_BEGIN_DECLS
* will be the bottom right. Note that there is currently a bug in
* Cogl where when rendering to an offscreen buffer these
* coordinates will be upside-down. The value is undefined when not
* rendering points.
* rendering points. This builtin can only be used if the
* %COGL_FEATURE_ID_POINT_SPRITE feature is available.
* </para></glossdef>
* </glossentry>
* </glosslist>

View File

@@ -52,6 +52,8 @@
#include "cogl-primitive-texture.h"
#include "cogl-gtype-private.h"
#include "driver/gl/cogl-texture-gl-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include "driver/gl/cogl-texture-gl-private.h"
#include <string.h>
#include <stdlib.h>

View File

@@ -44,6 +44,7 @@
#include "cogl-framebuffer-private.h"
#include "cogl-gtype-private.h"
#include "driver/gl/cogl-texture-2d-gl-private.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#ifdef COGL_HAS_EGL_SUPPORT
#include "winsys/cogl-winsys-egl-private.h"
#endif

View File

@@ -546,6 +546,9 @@ get_texture_bits_via_offscreen (CoglTexture *meta_texture,
GError *ignore_error = NULL;
CoglPixelFormat real_format;
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
return FALSE;
offscreen = _cogl_offscreen_new_with_texture_full
(sub_texture,
COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL,

View File

@@ -110,6 +110,52 @@ typedef struct _CoglTextureVertex CoglTextureVertex;
#define COGL_DEPTH_BIT (1 << 8)
#define COGL_STENCIL_BIT (1 << 9)
/**
* CoglFeatureFlags:
* @COGL_FEATURE_TEXTURE_YUV: ycbcr conversion support
* @COGL_FEATURE_TEXTURE_READ_PIXELS: glReadPixels() support
* @COGL_FEATURE_OFFSCREEN: FBO support
* @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs
* @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available
* @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support
* @COGL_FEATURE_VBOS: VBO support
* @COGL_FEATURE_PBOS: PBO support
* @COGL_FEATURE_UNSIGNED_INT_INDICES: Set if
* %COGL_INDICES_TYPE_UNSIGNED_INT is supported in
* cogl_vertex_buffer_indices_new().
* @COGL_FEATURE_DEPTH_RANGE: cogl_material_set_depth_range() support
* @COGL_FEATURE_POINT_SPRITE: Whether
* cogl_material_set_layer_point_sprite_coords_enabled() is supported.
* @COGL_FEATURE_MAP_BUFFER_FOR_READ: Whether cogl_buffer_map() is
* supported with CoglBufferAccess including read support.
* @COGL_FEATURE_MAP_BUFFER_FOR_WRITE: Whether cogl_buffer_map() is
* supported with CoglBufferAccess including write support.
* @COGL_FEATURE_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering the
* depth buffer to a texture.
*
* Flags for the supported features.
*
* Since: 0.8
*/
typedef enum
{
COGL_FEATURE_TEXTURE_YUV = (1 << 3),
COGL_FEATURE_TEXTURE_READ_PIXELS = (1 << 4),
COGL_FEATURE_OFFSCREEN = (1 << 6),
COGL_FEATURE_OFFSCREEN_MULTISAMPLE = (1 << 7),
COGL_FEATURE_FOUR_CLIP_PLANES = (1 << 9),
COGL_FEATURE_STENCIL_BUFFER = (1 << 10),
COGL_FEATURE_VBOS = (1 << 11),
COGL_FEATURE_PBOS = (1 << 12),
COGL_FEATURE_UNSIGNED_INT_INDICES = (1 << 13),
COGL_FEATURE_DEPTH_RANGE = (1 << 14),
COGL_FEATURE_POINT_SPRITE = (1 << 18),
COGL_FEATURE_MAP_BUFFER_FOR_READ = (1 << 21),
COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22),
COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23),
COGL_FEATURE_DEPTH_TEXTURE = (1 << 24)
} CoglFeatureFlags;
/**
* CoglBufferTarget:
* @COGL_WINDOW_BUFFER: FIXME

View File

@@ -45,4 +45,10 @@ struct _CoglXlibTrapState
CoglXlibTrapState *old_state;
};
void
_cogl_xlib_query_damage_extension (void);
int
_cogl_xlib_get_damage_base (void);
#endif /* __COGL_XLIB_PRIVATE_H */

View File

@@ -92,6 +92,9 @@ _cogl_xlib_renderer_untrap_errors (CoglRenderer *renderer,
CoglXlibRenderer *
_cogl_xlib_renderer_get_data (CoglRenderer *renderer);
int64_t
_cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer);
CoglOutput *
_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer,
int x,

View File

@@ -597,6 +597,22 @@ cogl_xlib_renderer_remove_filter (CoglRenderer *renderer,
(CoglNativeFilterFunc)func, data);
}
int64_t
_cogl_xlib_renderer_get_dispatch_timeout (CoglRenderer *renderer)
{
CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
if (renderer->xlib_enable_event_retrieval)
{
if (XPending (xlib_renderer->xdpy))
return 0;
else
return -1;
}
else
return -1;
}
CoglOutput *
_cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer,
int x,
@@ -632,3 +648,15 @@ _cogl_xlib_renderer_output_for_rectangle (CoglRenderer *renderer,
return max_overlapped;
}
XVisualInfo *
cogl_xlib_renderer_get_visual_info (CoglRenderer *renderer)
{
CoglXlibRenderer *xlib_renderer;
g_return_val_if_fail (cogl_is_renderer (renderer), NULL);
xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
return xlib_renderer->xvisinfo;
}

View File

@@ -136,7 +136,8 @@ cogl_xlib_renderer_get_foreign_display (CoglRenderer *renderer);
* Sets a foreign Xlib display that Cogl will use for and Xlib based winsys
* backend.
*
* Note that calling this function will automatically disable Cogl's
* Note that calling this function will automatically call
* cogl_xlib_renderer_set_event_retrieval_enabled() to disable Cogl's
* event retrieval. Cogl still needs to see all of the X events so the
* application should also use cogl_xlib_renderer_handle_event() if it
* uses this function.
@@ -145,12 +146,39 @@ void
cogl_xlib_renderer_set_foreign_display (CoglRenderer *renderer,
Display *display);
/**
* cogl_xlib_renderer_set_event_retrieval_enabled: (skip)
* @renderer: a #CoglRenderer
* @enable: The new value
*
* Sets whether Cogl should automatically retrieve events from the X
* display. This defaults to %TRUE unless
* cogl_xlib_renderer_set_foreign_display() is called. It can be set
* to %FALSE if the application wants to handle its own event
* retrieval. Note that Cogl still needs to see all of the X events to
* function properly so the application should call
* cogl_xlib_renderer_handle_event() for each event if it disables
* automatic event retrieval.
*
* Since: 1.10
* Stability: unstable
*/
void
cogl_xlib_renderer_set_event_retrieval_enabled (CoglRenderer *renderer,
gboolean enable);
/**
* cogl_xlib_renderer_get_display: (skip)
*/
Display *
cogl_xlib_renderer_get_display (CoglRenderer *renderer);
/**
* cogl_xlib_renderer_get_visual_info: (skip)
*/
XVisualInfo *
cogl_xlib_renderer_get_visual_info (CoglRenderer *renderer);
/**
* cogl_xlib_renderer_request_reset_on_video_memory_purge: (skip)
* @renderer: a #CoglRenderer

110
cogl/cogl/cogl-xlib.c Normal file
View File

@@ -0,0 +1,110 @@
/*
* Cogl
*
* A Low Level GPU Graphics and Utilities API
*
* Copyright (C) 2010,2011 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors:
* Robert Bragg <robert@linux.intel.com>
*
*/
#include "cogl-config.h"
#include <cogl-xlib.h>
#include <cogl-object-private.h>
#include <cogl-context-private.h>
#include <cogl-framebuffer-private.h>
#include <cogl-display-private.h>
#include <cogl-renderer-private.h>
#include <cogl-xlib-renderer-private.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xdamage.h>
#include "cogl-xlib.h"
/* FIXME: when we remove the last X11 based Clutter backend then we
* will get rid of these functions and instead rely on the equivalent
* _cogl_xlib_renderer API
*/
/* This can't be in the Cogl context because it can be set before
context is created */
static Display *_cogl_xlib_display = NULL;
Display *
cogl_xlib_get_display (void)
{
_COGL_GET_CONTEXT (ctx, NULL);
return cogl_xlib_renderer_get_display (ctx->display->renderer);
}
void
cogl_xlib_set_display (Display *display)
{
/* This can only be called once before the Cogl context is created */
g_assert (_cogl_xlib_display == NULL);
_cogl_xlib_display = display;
}
/* These three functions are wrappers around the equivalent renderer
functions. They can be removed once all xlib-based backends in
Clutter know about the renderer */
CoglFilterReturn
cogl_xlib_handle_event (XEvent *xevent)
{
_COGL_GET_CONTEXT (ctx, COGL_FILTER_CONTINUE);
/* Pass the event on to the renderer */
return cogl_xlib_renderer_handle_event (ctx->display->renderer, xevent);
}
void
_cogl_xlib_query_damage_extension (void)
{
int damage_error;
Display *display;
_COGL_GET_CONTEXT (ctxt, NO_RETVAL);
/* Check whether damage events are supported on this display */
display = cogl_xlib_renderer_get_display (ctxt->display->renderer);
if (!XDamageQueryExtension (display, &ctxt->damage_base, &damage_error))
ctxt->damage_base = -1;
}
int
_cogl_xlib_get_damage_base (void)
{
CoglX11Renderer *x11_renderer;
_COGL_GET_CONTEXT (ctxt, -1);
x11_renderer =
(CoglX11Renderer *) _cogl_xlib_renderer_get_data (ctxt->display->renderer);
return x11_renderer->damage_base;
}

View File

@@ -55,9 +55,66 @@
#endif /* COGL_COMPILATION */
#include <cogl/cogl-types.h>
#include <cogl/deprecated/cogl-clutter-xlib.h>
#include <cogl/cogl-xlib-renderer.h>
#include <cogl/cogl-macros.h>
G_BEGIN_DECLS
/*
* cogl_xlib_get_display:
*
* Return value: the Xlib display that will be used by the Xlib winsys
* backend. The display needs to be set with _cogl_xlib_set_display()
* before this function is called.
*
* Stability: Unstable
* Deprecated: 1.16: Use cogl_xlib_renderer_get_display() instead
*/
COGL_DEPRECATED_FOR (cogl_xlib_renderer_get_display)
Display *
cogl_xlib_get_display (void);
/*
* cogl_xlib_set_display:
*
* Sets the Xlib display that Cogl will use for the Xlib winsys
* backend. This function should eventually go away when Cogl gains a
* more complete winsys abstraction.
*
* Stability: Unstable
* Deprecated: 1.16: Use cogl_xlib_renderer_set_foreign_display()
* instead
*/
COGL_DEPRECATED_FOR (cogl_xlib_renderer_set_foreign_display)
void
cogl_xlib_set_display (Display *display);
/*
* cogl_xlib_handle_event:
* @xevent: pointer to XEvent structure
*
* This function processes a single X event; it can be used to hook
* into external X event retrieval (for example that done by Clutter
* or GDK).
*
* Return value: #CoglXlibFilterReturn. %COGL_XLIB_FILTER_REMOVE
* indicates that Cogl has internally handled the event and the
* caller should do no further processing. %COGL_XLIB_FILTER_CONTINUE
* indicates that Cogl is either not interested in the event,
* or has used the event to update internal state without taking
* any exclusive action.
*
* Stability: Unstable
* Deprecated: 1.16: Use cogl_xlib_renderer_handle_event() instead
*/
COGL_DEPRECATED_FOR (cogl_xlib_renderer_handle_event)
CoglFilterReturn
cogl_xlib_handle_event (XEvent *xevent);
G_END_DECLS
/* The gobject introspection scanner seems to parse public headers in
* isolation which means we need to be extra careful about how we
* define and undefine __COGL_H_INSIDE__ used to detect when internal

View File

@@ -52,7 +52,10 @@
#include "cogl-private.h"
#include "cogl1-context.h"
#include "cogl-offscreen.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include "driver/gl/cogl-attribute-gl-private.h"
#include "winsys/cogl-winsys-private.h"
#include "deprecated/cogl-clutter.h"
#include "deprecated/cogl-framebuffer-deprecated.h"
@@ -76,6 +79,13 @@ _cogl_check_extension (const char *name, char * const *ext)
return FALSE;
}
/* XXX: This has been deprecated as public API */
gboolean
cogl_check_extension (const char *name, const char *ext)
{
return cogl_clutter_check_extension (name, ext);
}
/* XXX: it's expected that we'll deprecated this with
* cogl_framebuffer_clear at some point. */
void
@@ -183,6 +193,22 @@ cogl_viewport (unsigned int width,
cogl_set_viewport (0, 0, width, height);
}
CoglFeatureFlags
cogl_get_features (void)
{
_COGL_GET_CONTEXT (ctx, 0);
return ctx->feature_flags;
}
gboolean
cogl_features_available (CoglFeatureFlags features)
{
_COGL_GET_CONTEXT (ctx, 0);
return (ctx->feature_flags & features) == features;
}
gboolean
cogl_has_feature (CoglContext *ctx, CoglFeatureID feature)
{

View File

@@ -230,6 +230,8 @@ cogl_framebuffer_get_blue_bits
cogl_framebuffer_get_color_format
cogl_framebuffer_get_context
cogl_framebuffer_get_depth_bits
cogl_framebuffer_get_depth_texture
cogl_framebuffer_get_depth_texture_enabled
cogl_framebuffer_get_depth_write_enabled
cogl_framebuffer_get_dither_enabled
cogl_framebuffer_get_green_bits
@@ -267,6 +269,7 @@ cogl_framebuffer_rotate_euler
#endif
cogl_framebuffer_scale
cogl_framebuffer_set_depth_texture_enabled
cogl_framebuffer_set_depth_write_enabled
cogl_framebuffer_set_dither_enabled
cogl_framebuffer_set_modelview_matrix
@@ -297,6 +300,7 @@ cogl_get_bitmasks
cogl_get_clock_time
cogl_get_depth_test_enabled
cogl_get_draw_framebuffer
cogl_get_features
cogl_get_graphics_reset_status
cogl_get_modelview_matrix
cogl_get_option_group
@@ -728,6 +732,7 @@ cogl_renderer_get_driver
#ifdef COGL_HAS_GTYPE_SUPPORT
cogl_renderer_get_gtype
#endif
cogl_renderer_get_n_fragment_texture_units
cogl_renderer_error_get_type
cogl_renderer_get_winsys_id
cogl_renderer_new

View File

@@ -61,6 +61,36 @@ GOptionGroup *
cogl_get_option_group (void);
/* Misc */
/**
* cogl_get_features:
*
* Returns all of the features supported by COGL.
*
* Return value: A logical OR of all the supported COGL features.
*
* Since: 0.8
* Deprecated: 1.10: Use cogl_foreach_feature() instead
*/
COGL_DEPRECATED_FOR (cogl_foreach_feature)
CoglFeatureFlags
cogl_get_features (void);
/**
* cogl_features_available:
* @features: A bitmask of features to check for
*
* Checks whether the given COGL features are available. Multiple
* features can be checked for by or-ing them together with the '|'
* operator. %TRUE is only returned if all of the requested features
* are available.
*
* Return value: %TRUE if the features are available, %FALSE otherwise.
* Deprecated: 1.10: Use cogl_has_feature() instead
*/
COGL_DEPRECATED_FOR (cogl_has_feature)
gboolean
cogl_features_available (CoglFeatureFlags features);
/**
* cogl_get_proc_address: (skip)
* @name: the name of the function.
@@ -79,6 +109,27 @@ cogl_get_option_group (void);
GCallback
cogl_get_proc_address (const char *name);
/**
* cogl_check_extension:
* @name: extension to check for
* @ext: list of extensions
*
* Check whether @name occurs in list of extensions in @ext.
*
* Return value: %TRUE if the extension occurs in the list, %FALSE otherwise.
*
* Deprecated: 1.2: OpenGL is an implementation detail for Cogl and so it's
* not appropriate to expose OpenGL extensions through the Cogl API. This
* function can be replaced by the following equivalent code:
* |[
* gboolean retval = (strstr (ext, name) != NULL) ? TRUE : FALSE;
* ]|
*/
COGL_DEPRECATED
gboolean
cogl_check_extension (const char *name,
const char *ext);
/**
* cogl_get_bitmasks:
* @red: (out): Return location for the number of red bits or %NULL

View File

@@ -3,7 +3,7 @@
*
* A Low Level GPU Graphics and Utilities API
*
* Copyright (C) 2007 OpenedHand
* Copyright (C) 2011 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -24,29 +24,27 @@
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*
*/
#ifndef __COGL_BITMAP_GL_PRIVATE_H
#define __COGL_BITMAP_GL_PRIVATE_H
#if !defined(__COGL_XLIB_H_INSIDE__) && !defined(COGL_COMPILATION)
#error "Only <cogl/cogl-xlib.h> can be included directly."
#endif
#include "cogl-bitmap-private.h"
#ifndef __COGL_CLUTTER_XLIB_H__
#define __COGL_CLUTTER_XLIB_H__
/* These two are replacements for map and unmap that should used when
* the pointer is going to be passed to GL for pixel packing or
* unpacking. The address might not be valid for reading if the bitmap
* was created with new_from_buffer but it will however be good to
* pass to glTexImage2D for example. The access should be READ for
* unpacking and WRITE for packing. It can not be both
#include <X11/Xutil.h>
G_BEGIN_DECLS
#define cogl_clutter_winsys_xlib_get_visual_info cogl_clutter_winsys_xlib_get_visual_info_CLUTTER
/**
* cogl_clutter_winsys_xlib_get_visual_info_CLUTTER: (skip)
*/
uint8_t *
_cogl_bitmap_gl_bind (CoglBitmap *bitmap,
CoglBufferAccess access,
CoglBufferMapHint hints,
GError **error);
XVisualInfo *
cogl_clutter_winsys_xlib_get_visual_info (void);
void
_cogl_bitmap_gl_unbind (CoglBitmap *bitmap);
G_END_DECLS
#endif /* __COGL_BITMAP_GL_PRIVATE_H */
#endif /* __COGL_CLUTTER_XLIB_H__ */

View File

@@ -41,13 +41,72 @@
#include "cogl-framebuffer-private.h"
#include "cogl-onscreen-private.h"
#ifdef COGL_HAS_XLIB_SUPPORT
#include "cogl-clutter-xlib.h"
#include "cogl-xlib-renderer.h"
#endif
#include "winsys/cogl-winsys-private.h"
#include "winsys/cogl-winsys-stub-private.h"
#include "deprecated/cogl-clutter.h"
gboolean
cogl_clutter_check_extension (const char *name, const char *ext)
{
char *end;
int name_len, n;
if (name == NULL || ext == NULL)
return FALSE;
end = (char*)(ext + strlen(ext));
name_len = strlen(name);
while (ext < end)
{
n = strcspn(ext, " ");
if ((name_len == n) && (!strncmp(name, ext, n)))
return TRUE;
ext += (n + 1);
}
return FALSE;
}
gboolean
cogl_clutter_winsys_has_feature (CoglWinsysFeature feature)
{
return _cogl_winsys_has_feature (feature);
}
void
cogl_onscreen_clutter_backend_set_size (int width, int height)
{
CoglFramebuffer *framebuffer;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (_cogl_context_get_winsys (ctx) != _cogl_winsys_stub_get_vtable ())
return;
framebuffer = COGL_FRAMEBUFFER (ctx->window_buffer);
_cogl_framebuffer_winsys_update_size (framebuffer, width, height);
}
#ifdef COGL_HAS_XLIB_SUPPORT
XVisualInfo *
cogl_clutter_winsys_xlib_get_visual_info (void)
{
CoglRenderer *renderer;
_COGL_GET_CONTEXT (ctx, NULL);
g_return_val_if_fail (ctx->display != NULL, NULL);
renderer = cogl_display_get_renderer (ctx->display);
g_return_val_if_fail (renderer != NULL, NULL);
return cogl_xlib_renderer_get_visual_info (renderer);
}
#endif

Some files were not shown because too many files have changed in this diff Show More