diff --git a/clutter/Makefile.am b/clutter/Makefile.am index 0cb1dffb5..fa82005ad 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -84,6 +84,7 @@ source_h = \ $(srcdir)/clutter-bind-constraint.h \ $(srcdir)/clutter-binding-pool.h \ $(srcdir)/clutter-bin-layout.h \ + $(srcdir)/clutter-blur-effect.h \ $(srcdir)/clutter-box.h \ $(srcdir)/clutter-box-layout.h \ $(srcdir)/clutter-cairo-texture.h \ @@ -169,6 +170,7 @@ source_c = \ $(srcdir)/clutter-bind-constraint.c \ $(srcdir)/clutter-binding-pool.c \ $(srcdir)/clutter-bin-layout.c \ + $(srcdir)/clutter-blur-effect.c \ $(srcdir)/clutter-box.c \ $(srcdir)/clutter-box-layout.c \ $(srcdir)/clutter-cairo-texture.c \ diff --git a/clutter/clutter-blur-effect.c b/clutter/clutter-blur-effect.c new file mode 100644 index 000000000..8b1d0ddef --- /dev/null +++ b/clutter/clutter-blur-effect.c @@ -0,0 +1,244 @@ +/* + * 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 + */ + +/** + * SECTION:clutter-blur-effect + * @short_description: A blur effect + * @see_also: #ClutterEffect, #ClutterOffscreenEffect + * + * #ClutterBlurEffect is a sub-class of #ClutterEffect that allows blurring a + * actor and its contents. + * + * #ClutterBlurEffect uses the programmable pipeline of the GPU and an + * offscreen buffer, so it is only available on graphics hardware that supports + * these two features. + * + * #ClutterBlurEffect is available since Clutter 1.4 + */ + +#define CLUTTER_BLUR_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BLUR_EFFECT, ClutterBlurEffectClass)) +#define CLUTTER_IS_BLUR_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BLUR_EFFECT)) +#define CLUTTER_BLUR_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BLUR_EFFECT, ClutterBlurEffectClass)) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-blur-effect.h" + +#include "cogl/cogl.h" + +#include "clutter-debug.h" +#include "clutter-private.h" +#include "clutter-shader-effect.h" + +typedef struct _ClutterBlurEffectClass ClutterBlurEffectClass; + +/* FIXME - lame shader; we should really have a decoupled + * horizontal/vertical two pass shader for the gaussian blur + */ +static const gchar *box_blur_glsl_shader = +"uniform sampler2D tex;\n" +"uniform float x_step, y_step;\n" +"\n" +"vec4 get_rgba_rel (sampler2D source, float dx, float dy)\n" +"{\n" +" return texture2D (tex, gl_TexCoord[0].st + vec2 (dx, dy) * 2.0);\n" +"}\n" +"\n" +"void main ()\n" +"{\n" +" vec4 color = gl_Color * texture2D (tex, vec2 (gl_TexCoord[0].xy));\n" +" float count = 1.0;\n" +" color += get_rgba_rel (tex, -x_step, -y_step); count++;\n" +" color += get_rgba_rel (tex, -x_step, 0.0); count++;\n" +" color += get_rgba_rel (tex, 0.0, -y_step); count++;\n" +" color += get_rgba_rel (tex, 0.0, 0.0); count++;\n" +" color += get_rgba_rel (tex, 0.0, y_step); count++;\n" +" color += get_rgba_rel (tex, x_step, -y_step); count++;\n" +" color += get_rgba_rel (tex, x_step, 0.0); count++;\n" +" color += get_rgba_rel (tex, x_step, y_step); count++;\n" +" gl_FragColor = color / count;\n" +"}"; + +struct _ClutterBlurEffect +{ + ClutterShaderEffect parent_instance; + + /* a back pointer to our actor, so that we can query it */ + ClutterActor *actor; + + /* the parameters; x_step and y_step depend on + * the actor's allocation + */ + gfloat x_step; + gfloat y_step; + + guint source_set : 1; +}; + +struct _ClutterBlurEffectClass +{ + ClutterShaderEffectClass parent_class; +}; + +enum +{ + PROP_0 +}; + +G_DEFINE_TYPE (ClutterBlurEffect, + clutter_blur_effect, + CLUTTER_TYPE_SHADER_EFFECT); + +static int +next_p2 (int a) +{ + int rval = 1; + + while (rval < a) + rval <<= 1; + + return rval; +} + +static gboolean +clutter_blur_effect_pre_paint (ClutterEffect *effect) +{ + ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect); + ClutterShaderEffect *shader_effect; + ClutterEffectClass *parent_class; + ClutterActorBox allocation; + gfloat width, height; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) + return FALSE; + + self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); + if (self->actor == NULL) + return FALSE; + + clutter_actor_get_allocation_box (self->actor, &allocation); + clutter_actor_box_get_size (&allocation, &width, &height); + + self->x_step = 1.0f / (float) next_p2 (width); + self->y_step = 1.0f / (float) next_p2 (height); + + shader_effect = CLUTTER_SHADER_EFFECT (effect); + + if (!self->source_set) + { + CoglHandle shader = clutter_shader_effect_get_shader (shader_effect); + + if (shader == COGL_INVALID_HANDLE) + return FALSE; + + cogl_shader_source (shader, box_blur_glsl_shader); + self->source_set = TRUE; + } + + clutter_shader_effect_set_uniform (shader_effect, + "tex", + G_TYPE_INT, 1, + 0); + clutter_shader_effect_set_uniform (shader_effect, + "x_step", + G_TYPE_FLOAT, 1, + self->x_step); + clutter_shader_effect_set_uniform (shader_effect, + "y_step", + G_TYPE_FLOAT, 1, + self->y_step); + + parent_class = CLUTTER_EFFECT_CLASS (clutter_blur_effect_parent_class); + return parent_class->pre_paint (effect); +} + +static void +clutter_blur_effect_finalize (GObject *gobject) +{ + G_OBJECT_CLASS (clutter_blur_effect_parent_class)->finalize (gobject); +} + +static void +clutter_blur_effect_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_blur_effect_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_blur_effect_class_init (ClutterBlurEffectClass *klass) +{ + ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + effect_class->pre_paint = clutter_blur_effect_pre_paint; + + gobject_class->set_property = clutter_blur_effect_set_property; + gobject_class->get_property = clutter_blur_effect_get_property; + gobject_class->finalize = clutter_blur_effect_finalize; +} + +static void +clutter_blur_effect_init (ClutterBlurEffect *self) +{ +} + +/** + * clutter_blur_effect_new: + * + * Creates a new #ClutterBlurEffect to be used with + * clutter_actor_set_effect() + * + * Return value: the newly created #ClutterBlurEffect or %NULL + * + * Since: 1.4 + */ +ClutterEffect * +clutter_blur_effect_new (void) +{ + return g_object_new (CLUTTER_TYPE_BLUR_EFFECT, NULL); +} diff --git a/clutter/clutter-blur-effect.h b/clutter/clutter-blur-effect.h new file mode 100644 index 000000000..130fd0977 --- /dev/null +++ b/clutter/clutter-blur-effect.h @@ -0,0 +1,56 @@ +/* + * 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_BLUR_EFFECT_H__ +#define __CLUTTER_BLUR_EFFECT_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BLUR_EFFECT (clutter_blur_effect_get_type ()) +#define CLUTTER_BLUR_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BLUR_EFFECT, ClutterBlurEffect)) +#define CLUTTER_IS_BLUR_EFFECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BLUR_EFFECT)) + +/** + * ClutterBlurEffect: + * + * ClutterBlurEffect is an opaque structure + * whose members cannot be accessed directly + * + * Since: 1.4 + */ +typedef struct _ClutterBlurEffect ClutterBlurEffect; + +GType clutter_blur_effect_get_type (void) G_GNUC_CONST; + +ClutterEffect *clutter_blur_effect_new (void); + +G_END_DECLS + +#endif /* __CLUTTER_BLUR_EFFECT_H__ */ diff --git a/clutter/clutter.h b/clutter/clutter.h index 53e2c163a..1cdf0628d 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -49,6 +49,7 @@ #include "clutter-bind-constraint.h" #include "clutter-binding-pool.h" #include "clutter-bin-layout.h" +#include "clutter-blur-effect.h" #include "clutter-box.h" #include "clutter-box-layout.h" #include "clutter-cairo-texture.h"