diff --git a/clutter/Makefile.am b/clutter/Makefile.am index c514406ff..e658c58f6 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -95,6 +95,7 @@ source_h = \ $(srcdir)/clutter-colorize-effect.h \ $(srcdir)/clutter-constraint.h \ $(srcdir)/clutter-container.h \ + $(srcdir)/clutter-deform-effect.h \ $(srcdir)/clutter-deprecated.h \ $(srcdir)/clutter-desaturate-effect.h \ $(srcdir)/clutter-device-manager.h \ @@ -182,6 +183,7 @@ source_c = \ $(srcdir)/clutter-colorize-effect.c \ $(srcdir)/clutter-constraint.c \ $(srcdir)/clutter-container.c \ + $(srcdir)/clutter-deform-effect.c \ $(srcdir)/clutter-desaturate-effect.c \ $(srcdir)/clutter-device-manager.c \ $(srcdir)/clutter-drag-action.c \ diff --git a/clutter/clutter-deform-effect.c b/clutter/clutter-deform-effect.c new file mode 100644 index 000000000..ff96816f1 --- /dev/null +++ b/clutter/clutter-deform-effect.c @@ -0,0 +1,739 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * 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 . + * + * Author: + * Emmanuele Bassi + * + * Based on the MxDeformTexture class, written by: + * Chris Lord + */ + +/** + * SECTION:clutter-deform-effect + * @Title: ClutterDeformEffect + * @Short_Description: A base class for effects deforming the geometry + * of an actor + * + * #ClutterDeformEffect is an abstract class providing all the plumbing + * for creating effects that result in the deformation of an actor's + * geometry. + * + * #ClutterDeformEffect uses offscreen buffers to render the contents of + * a #ClutterActor and then the Cogl vertex buffers API to submit the + * geomtry to the GPU. + * + * + * Implementing ClutterDeformEffect + * Sub-classes of #ClutterDeformEffect should override the + * deform_vertex() virtual function; this function + * is called on every vertex that needs to be deformed by the effect. + * Each passed vertex is an in-out parameter that initially contains the + * position of the vertex and should be modified according to a specific + * deformation algorithm. + * + * + * #ClutterDeformEffect is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-deform-effect.h" + +#include + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-private.h" + +#define DEFAULT_N_TILES 32 + +struct _ClutterDeformEffectPrivate +{ + CoglHandle back_material; + + gint x_tiles; + gint y_tiles; + + CoglHandle vbo; + + CoglHandle indices; + CoglHandle back_indices; + gint n_indices; + + CoglTextureVertex *vertices; + + gulong allocation_id; + + guint is_dirty : 1; +}; + +enum +{ + PROP_0, + + PROP_X_TILES, + PROP_Y_TILES, + + PROP_BACK_MATERIAL +}; + +G_DEFINE_ABSTRACT_TYPE (ClutterDeformEffect, + clutter_deform_effect, + CLUTTER_TYPE_OFFSCREEN_EFFECT); + +static void +clutter_deform_effect_real_deform_vertex (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex) +{ + g_warning ("%s: Deformation effect of type '%s' does not implement " + "the required ClutterDeformEffect::deform_vertex virtual " + "function.", + G_STRLOC, + G_OBJECT_TYPE_NAME (effect)); +} + +void +_clutter_deform_effect_deform_vertex (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex) +{ + CLUTTER_DEFORM_EFFECT_GET_CLASS (effect)->deform_vertex (effect, + width, height, + vertex); +} + +static void +vbo_invalidate (ClutterActor *actor, + const ClutterActorBox *allocation, + ClutterAllocationFlags flags, + ClutterDeformEffect *effect) +{ + effect->priv->is_dirty = TRUE; +} + +static void +clutter_deform_effect_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterDeformEffectPrivate *priv = CLUTTER_DEFORM_EFFECT (meta)->priv; + + if (priv->allocation_id != 0) + { + ClutterActor *old_actor = clutter_actor_meta_get_actor (meta); + + g_signal_handler_disconnect (old_actor, priv->allocation_id); + priv->allocation_id = 0; + } + + /* we need to invalidate the VBO whenever the allocation of the actor + * changes + */ + if (actor != NULL) + priv->allocation_id = g_signal_connect (actor, "allocation-changed", + G_CALLBACK (vbo_invalidate), + meta); + + priv->is_dirty = TRUE; + + CLUTTER_ACTOR_META_CLASS (clutter_deform_effect_parent_class)->set_actor (meta, actor); +} + +static void +clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect) +{ + ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect); + ClutterDeformEffectPrivate *priv = self->priv; + gboolean is_depth_enabled, is_cull_enabled; + CoglHandle material; + gint n_tiles; + + if (priv->is_dirty) + { + ClutterActor *actor; + gfloat width, height; + guint opacity; + gint i, j; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + opacity = clutter_actor_get_paint_opacity (actor); + clutter_actor_get_size (actor, &width, &height); + + for (i = 0; i < priv->y_tiles + 1; i++) + { + for (j = 0; j < priv->x_tiles + 1; j++) + { + CoglTextureVertex *vertex; + + vertex = &priv->vertices[(i * (priv->x_tiles + 1)) + j]; + + vertex->tx = (float) j / priv->x_tiles; + vertex->ty = (float) i / priv->y_tiles; + + vertex->x = width * vertex->tx; + vertex->y = height * vertex->ty; + vertex->z = 0.0f; + + cogl_color_set_from_4ub (&vertex->color, 255, 255, 255, opacity); + + _clutter_deform_effect_deform_vertex (self, width, height, vertex); + } + } + + /* XXX in theory, the sub-classes should tell us what they changed + * in the texture vertices; we then would be able to avoid resubmitting + * the same data, if it did not change. for the time being, we resubmit + * everything + */ + cogl_vertex_buffer_add (priv->vbo, "gl_Vertex", + 3, + COGL_ATTRIBUTE_TYPE_FLOAT, + FALSE, + sizeof (CoglTextureVertex), + &priv->vertices->x); + cogl_vertex_buffer_add (priv->vbo, "gl_MultiTexCoord0", + 2, + COGL_ATTRIBUTE_TYPE_FLOAT, + FALSE, + sizeof (CoglTextureVertex), + &priv->vertices->tx); + cogl_vertex_buffer_add (priv->vbo, "gl_Color", + 4, + COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE, + FALSE, + sizeof (CoglTextureVertex), + &priv->vertices->color); + + priv->is_dirty = FALSE; + } + + /* enable depth test, if it's not already enabled */ + is_depth_enabled = cogl_get_depth_test_enabled (); + if (!is_depth_enabled) + cogl_set_depth_test_enabled (TRUE); + + /* enable backface culling if it's not already enabled and if + * we have a back material + */ + is_cull_enabled = cogl_get_backface_culling_enabled (); + if (priv->back_material != COGL_INVALID_HANDLE && !is_cull_enabled) + cogl_set_backface_culling_enabled (TRUE); + else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled) + cogl_set_backface_culling_enabled (FALSE); + + n_tiles = (priv->x_tiles + 1) * (priv->y_tiles + 1); + + /* draw the front */ + material = clutter_offscreen_effect_get_target (effect); + if (material != COGL_INVALID_HANDLE) + { + cogl_set_source (material); + cogl_vertex_buffer_draw_elements (priv->vbo, + COGL_VERTICES_MODE_TRIANGLE_STRIP, + priv->indices, + 0, + n_tiles, + 0, + priv->n_indices); + } + + /* draw the back */ + material = priv->back_material; + if (material != COGL_INVALID_HANDLE) + { + cogl_set_source (priv->back_material); + cogl_vertex_buffer_draw_elements (priv->vbo, + COGL_VERTICES_MODE_TRIANGLE_STRIP, + priv->back_indices, + 0, + n_tiles, + 0, + priv->n_indices); + } + + /* restore the previous state */ + if (!is_depth_enabled) + cogl_set_depth_test_enabled (FALSE); + + if (priv->back_material != COGL_INVALID_HANDLE && !is_cull_enabled) + cogl_set_backface_culling_enabled (FALSE); + else if (priv->back_material == COGL_INVALID_HANDLE && is_cull_enabled) + cogl_set_backface_culling_enabled (TRUE); +} + +static inline void +clutter_deform_effect_free_arrays (ClutterDeformEffect *self) +{ + ClutterDeformEffectPrivate *priv = self->priv; + + if (priv->vbo != COGL_INVALID_HANDLE) + { + cogl_handle_unref (priv->vbo); + priv->vbo = COGL_INVALID_HANDLE; + } + + if (priv->indices != COGL_INVALID_HANDLE) + { + cogl_handle_unref (priv->indices); + priv->indices = COGL_INVALID_HANDLE; + } + + g_free (priv->vertices); + priv->vertices = NULL; +} + +static void +clutter_deform_effect_init_arrays (ClutterDeformEffect *self) +{ + ClutterDeformEffectPrivate *priv = self->priv; + GLushort *static_indices, *static_back_indices; + GLushort *idx, *back_idx; + gint x, y, direction; + gint n_tiles; + + clutter_deform_effect_free_arrays (self); + + priv->n_indices = (2 + 2 * priv->x_tiles) + * priv->y_tiles + + (priv->y_tiles - 1); + + static_indices = g_new (GLushort, priv->n_indices); + static_back_indices = g_new (GLushort, priv->n_indices); + +#define MESH_INDEX(x,y) ((y) * (priv->x_tiles + 1) + (x)) + + /* compute all the triangles from the various tiles */ + direction = 1; + + idx = static_indices; + idx[0] = MESH_INDEX (0, 0); + idx[1] = MESH_INDEX (0, 1); + idx += 2; + + back_idx = static_back_indices; + back_idx[0] = MESH_INDEX (priv->x_tiles, 0); + back_idx[1] = MESH_INDEX (priv->x_tiles, 1); + back_idx += 2; + + for (y = 0; y < priv->y_tiles; y++) + { + for (x = 0; x < priv->x_tiles; x++) + { + if (direction) + { + idx[0] = MESH_INDEX (x + 1, y); + idx[1] = MESH_INDEX (x + 1, y + 1); + + back_idx[0] = MESH_INDEX (priv->x_tiles - (x + 1), y); + back_idx[1] = MESH_INDEX (priv->x_tiles - (x + 1), y + 1); + } + else + { + idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y); + idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1); + + back_idx[0] = MESH_INDEX (x + 1, y); + back_idx[1] = MESH_INDEX (x + 1, y + 1); + } + + idx += 2; + back_idx += 2; + } + + if (y == (priv->y_tiles - 1)) + break; + + if (direction) + { + idx[0] = MESH_INDEX (priv->x_tiles, y + 1); + idx[1] = MESH_INDEX (priv->x_tiles, y + 1); + idx[2] = MESH_INDEX (priv->x_tiles, y + 2); + + back_idx[0] = MESH_INDEX (0, y + 1); + back_idx[1] = MESH_INDEX (0, y + 1); + back_idx[2] = MESH_INDEX (0, y + 2); + } + else + { + idx[0] = MESH_INDEX (0, y + 1); + idx[1] = MESH_INDEX (0, y + 1); + idx[2] = MESH_INDEX (0, y + 2); + + back_idx[0] = MESH_INDEX (priv->x_tiles, y + 1); + back_idx[1] = MESH_INDEX (priv->x_tiles, y + 1); + back_idx[2] = MESH_INDEX (priv->x_tiles, y + 2); + } + + idx += 3; + back_idx += 3; + + direction = !direction; + } + +#undef MESH_INDEX + + priv->indices = + cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT, + static_indices, + priv->n_indices); + priv->back_indices = + cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT, + static_back_indices, + priv->n_indices); + + g_free (static_indices); + g_free (static_back_indices); + + n_tiles = (priv->x_tiles + 1) * (priv->y_tiles + 1); + priv->vertices = g_new (CoglTextureVertex, n_tiles); + priv->vbo = cogl_vertex_buffer_new (n_tiles); + + priv->is_dirty = TRUE; +} + +static inline void +clutter_deform_effect_free_back_material (ClutterDeformEffect *self) +{ + ClutterDeformEffectPrivate *priv = self->priv; + + if (priv->back_material != NULL) + { + cogl_handle_unref (priv->back_material); + priv->back_material = COGL_INVALID_HANDLE; + } +} + +static void +clutter_deform_effect_finalize (GObject *gobject) +{ + ClutterDeformEffect *self = CLUTTER_DEFORM_EFFECT (gobject); + + clutter_deform_effect_free_arrays (self); + clutter_deform_effect_free_back_material (self); + + G_OBJECT_CLASS (clutter_deform_effect_parent_class)->finalize (gobject); +} + +static void +clutter_deform_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterDeformEffect *self = CLUTTER_DEFORM_EFFECT (gobject); + + switch (prop_id) + { + case PROP_X_TILES: + clutter_deform_effect_set_n_tiles (self, g_value_get_uint (value), + self->priv->y_tiles); + break; + + case PROP_Y_TILES: + clutter_deform_effect_set_n_tiles (self, self->priv->x_tiles, + g_value_get_uint (value)); + break; + + case PROP_BACK_MATERIAL: + clutter_deform_effect_set_back_material (self, g_value_get_boxed (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_deform_effect_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterDeformEffectPrivate *priv = CLUTTER_DEFORM_EFFECT (gobject)->priv; + + switch (prop_id) + { + case PROP_X_TILES: + g_value_set_uint (value, priv->x_tiles); + break; + + case PROP_Y_TILES: + g_value_set_uint (value, priv->y_tiles); + break; + + case PROP_BACK_MATERIAL: + g_value_set_boxed (value, priv->back_material); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_deform_effect_class_init (ClutterDeformEffectClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + ClutterOffscreenEffectClass *offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); + GParamSpec *pspec; + + g_type_class_add_private (klass, sizeof (ClutterDeformEffectPrivate)); + + klass->deform_vertex = clutter_deform_effect_real_deform_vertex; + + gobject_class->set_property = clutter_deform_effect_set_property; + gobject_class->get_property = clutter_deform_effect_get_property; + gobject_class->finalize = clutter_deform_effect_finalize; + + /** + * ClutterDeformEffect:x-tiles: + * + * The number of horizontal tiles. The bigger the number, the + * smaller the tiles + * + * Since: 1.4 + */ + pspec = g_param_spec_uint ("x-tiles", + "Horiontal Tiles", + "The number of horizontal tiles", + 1, G_MAXUINT, + DEFAULT_N_TILES, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_X_TILES, pspec); + + /** + * ClutterDeformEffect:y-tiles: + * + * The number of vertical tiles. The bigger the number, the + * smaller the tiles + * + * Since: 1.4 + */ + pspec = g_param_spec_uint ("y-tiles", + "Vertical Tiles", + "The number of vertical tiles", + 1, G_MAXUINT, + DEFAULT_N_TILES, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_Y_TILES, pspec); + + /** + * ClutterDeformEffect:back-material: + * + * A material to be used when painting the back of the actor + * to which this effect has been applied + * + * By default, no material will be used + * + * Since: 1.4 + */ + pspec = g_param_spec_boxed ("back-material", + "Back Material", + "The material to be used when painting the " + "back of the actor", + COGL_TYPE_HANDLE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_BACK_MATERIAL, pspec); + + meta_class->set_actor = clutter_deform_effect_set_actor; + + offscreen_class->paint_target = clutter_deform_effect_paint_target; +} + +static void +clutter_deform_effect_init (ClutterDeformEffect *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_DEFORM_EFFECT, + ClutterDeformEffectPrivate); + + self->priv->x_tiles = self->priv->y_tiles = DEFAULT_N_TILES; + self->priv->back_material = COGL_INVALID_HANDLE; + + clutter_deform_effect_init_arrays (self); +} + +/** + * clutter_deform_effect_set_back_material: + * @effect: a #ClutterDeformEffect + * @material: (allow-none): a handle to a Cogl material + * + * Sets the material that should be used when drawing the back face + * of the actor during a deformation + * + * The #ClutterDeformEffect will take a reference on the material's + * handle + * + * Since: 1.4 + */ +void +clutter_deform_effect_set_back_material (ClutterDeformEffect *effect, + CoglHandle material) +{ + ClutterDeformEffectPrivate *priv; + + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + g_return_if_fail (material == COGL_INVALID_HANDLE || cogl_is_material (material)); + + priv = effect->priv; + + clutter_deform_effect_free_back_material (effect); + + priv->back_material = material; + if (priv->back_material != COGL_INVALID_HANDLE) + cogl_handle_ref (priv->back_material); + + clutter_deform_effect_invalidate (effect); +} + +/** + * clutter_deform_effect_get_back_material: + * @effect: a #ClutterDeformEffect + * + * Retrieves the handle to the back face material used by @effect + * + * Return value: (transfer none): a handle for the material, or %NULL. + * The returned material is owned by the #ClutterDeformEffect and it + * should not be freed directly + * + * Since: 1.4 + */ +CoglHandle +clutter_deform_effect_get_back_material (ClutterDeformEffect *effect) +{ + g_return_val_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect), NULL); + + return effect->priv->back_material; +} + +/** + * clutter_deform_effect_set_n_tiles: + * @effect: a #ClutterDeformEffect + * @x_tiles: number of horizontal tiles + * @y_tiles: number of vertical tiles + * + * Sets the number of horizontal and vertical tiles to be used + * when applying the effect + * + * More tiles allow a finer grained deformation at the expenses + * of computation + * + * Since: 1.4 + */ +void +clutter_deform_effect_set_n_tiles (ClutterDeformEffect *effect, + guint x_tiles, + guint y_tiles) +{ + ClutterDeformEffectPrivate *priv; + gboolean tiles_changed = FALSE; + + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + g_return_if_fail (x_tiles > 0 && y_tiles > 0); + + priv = effect->priv; + + g_object_freeze_notify (G_OBJECT (effect)); + + if (priv->x_tiles != x_tiles) + { + priv->x_tiles = x_tiles; + + g_object_notify (G_OBJECT (effect), "x-tiles"); + + tiles_changed = TRUE; + } + + if (priv->y_tiles != y_tiles) + { + priv->y_tiles = y_tiles; + + g_object_notify (G_OBJECT (effect), "y-tiles"); + + tiles_changed = TRUE; + } + + if (tiles_changed) + { + clutter_deform_effect_init_arrays (effect); + clutter_deform_effect_invalidate (effect); + } + + g_object_thaw_notify (G_OBJECT (effect)); +} + +/** + * clutter_deform_effect_get_n_tiles: + * @effect: a #ClutterDeformEffect + * @x_tiles: (out): return location for the number of horizontal tiles, + * or %NULL + * @y_tiles: (out): return location for the number of vertical tiles, + * or %NULL + * + * Retrieves the number of horizontal and vertical tiles used to sub-divide + * the actor's geometry during the effect + * + * Since: 1.4 + */ +void +clutter_deform_effect_get_n_tiles (ClutterDeformEffect *effect, + guint *x_tiles, + guint *y_tiles) +{ + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + + if (x_tiles != NULL) + *x_tiles = effect->priv->x_tiles; + + if (y_tiles != NULL) + *y_tiles = effect->priv->y_tiles; +} + +/** + * clutter_deform_effect_invalidate: + * @effect: a #ClutterDeformEffect + * + * Invalidates the @effect's vertices and, if it is associated + * to an actor, it will queue a redraw + * + * Since: 1.4 + */ +void +clutter_deform_effect_invalidate (ClutterDeformEffect *effect) +{ + ClutterActor *actor; + + g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect)); + + if (effect->priv->is_dirty) + return; + + effect->priv->is_dirty = TRUE; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + if (actor != NULL) + clutter_actor_queue_redraw (actor); +} diff --git a/clutter/clutter-deform-effect.h b/clutter/clutter-deform-effect.h new file mode 100644 index 000000000..63ccd4c5a --- /dev/null +++ b/clutter/clutter-deform-effect.h @@ -0,0 +1,111 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * 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 . + * + * Author: + * Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_DEFORM_EFFECT_H__ +#define __CLUTTER_DEFORM_EFFECT_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DEFORM_EFFECT (clutter_deform_effect_get_type ()) +#define CLUTTER_DEFORM_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEFORM_EFFECT, ClutterDeformEffect)) +#define CLUTTER_IS_DEFORM_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEFORM_EFFECT)) +#define CLUTTER_DEFORM_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEFORM_EFFECT, ClutterDeformEffectClass)) +#define CLUTTER_IS_DEFORM_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEFORM_EFFECT)) +#define CLUTTER_DEFORM_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEFORM_EFFECT, ClutterDeformEffectClass)) + +typedef struct _ClutterDeformEffect ClutterDeformEffect; +typedef struct _ClutterDeformEffectPrivate ClutterDeformEffectPrivate; +typedef struct _ClutterDeformEffectClass ClutterDeformEffectClass; + +/** + * ClutterDeformEffect: + * + * The ClutterDeformEffect structure contains + * only private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterDeformEffect +{ + /*< private >*/ + ClutterOffscreenEffect parent_instance; + + ClutterDeformEffectPrivate *priv; +}; + +/** + * ClutterDeformEffectClass: + * @deform_vertex: virtual function; sub-classes should override this + * function to compute the deformation of each vertex + * + * The ClutterDeformEffectClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterDeformEffectClass +{ + /*< private >*/ + ClutterOffscreenEffectClass parent_class; + + /*< public >*/ + void (* deform_vertex) (ClutterDeformEffect *effect, + gfloat width, + gfloat height, + CoglTextureVertex *vertex); + + /*< private >*/ + void (*_clutter_deform1) (void); + void (*_clutter_deform2) (void); + void (*_clutter_deform3) (void); + void (*_clutter_deform4) (void); + void (*_clutter_deform5) (void); + void (*_clutter_deform6) (void); + void (*_clutter_deform7) (void); +}; + +GType clutter_deform_effect_get_type (void) G_GNUC_CONST; + +void clutter_deform_effect_set_back_material (ClutterDeformEffect *effect, + CoglHandle material); +CoglHandle clutter_deform_effect_get_back_material (ClutterDeformEffect *effect); +void clutter_deform_effect_set_n_tiles (ClutterDeformEffect *effect, + guint x_tiles, + guint y_tiles); +void clutter_deform_effect_get_n_tiles (ClutterDeformEffect *effect, + guint *x_tiles, + guint *y_tiles); + +void clutter_deform_effect_invalidate (ClutterDeformEffect *effect); + +G_END_DECLS + +#endif /* __CLUTTER_DEFORM_EFFECT_H__ */ diff --git a/clutter/clutter.h b/clutter/clutter.h index 0b948af95..70c8fa37b 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -60,6 +60,7 @@ #include "clutter-colorize-effect.h" #include "clutter-constraint.h" #include "clutter-container.h" +#include "clutter-deform-effect.h" #include "clutter-desaturate-effect.h" #include "clutter-device-manager.h" #include "clutter-drag-action.h"