diff options
author | Emmanuele Bassi <ebassi@linux.intel.com> | 2010-05-17 12:55:46 +0100 |
---|---|---|
committer | Emmanuele Bassi <ebassi@linux.intel.com> | 2010-06-03 14:10:55 +0100 |
commit | 0e9a1dee6dde18e7fe6d92960987baa933826937 (patch) | |
tree | f6218c1e7221670f92e6b3e15298966c4e28ceb8 /clutter/clutter-shader-effect.c | |
parent | f2caafa127a42f5b10454407d52eb6b8bd64876d (diff) | |
download | clutter-0e9a1dee6dde18e7fe6d92960987baa933826937.tar.gz |
shader-effect: Simplify setting the shader source
Sub-classes of ShaderEffect currently have to get the handle for the
Cogl shader and call cogl_shader_source(); this makes it awkward to
implement a ShaderEffect, and it exposes handles and Cogl API that we
might want to change in the future.
We should provide a ClutterShaderEffect method that allows to (safely)
set the shader source at the right time for sub-classes to use.
Diffstat (limited to 'clutter/clutter-shader-effect.c')
-rw-r--r-- | clutter/clutter-shader-effect.c | 116 |
1 files changed, 62 insertions, 54 deletions
diff --git a/clutter/clutter-shader-effect.c b/clutter/clutter-shader-effect.c index 2a48df786..0f68151a1 100644 --- a/clutter/clutter-shader-effect.c +++ b/clutter/clutter-shader-effect.c @@ -38,51 +38,14 @@ * <refsect2 id="ClutterShaderEffect-implementing"> * <title>Implementing a ClutterShaderEffect</title> * <para>Creating a sub-class of #ClutterShaderEffect requires the - * overriding of the <function>set_actor()</function> virtual function - * from the #ClutterActorMeta class, and the <function>pre_paint()</function> - * virtual functions from the #ClutterEffect class.</para> - * <para>The <function>set_actor()</function> must chain up to the - * #ClutterShaderEffect implementation; if the effect has not been disabled - * by the super class implementation, then the sub-class should get the - * #CoglHandle for the fragment shader using - * clutter_shader_effect_get_shader() and call cogl_shader_source() to set - * the source of the program.</para> - * <example id="ClutterShaderEffect-example-preparing"> - * <title>Preparing a ClutterShaderEffect</title> - * <para>The example below shows the typical implementation of the - * <function>set_actor()</function> phase of a #ClutterShaderEffect - * sub-class.</para> - * <programlisting> - * static void - * my_effect_set_actor (ClutterActorMeta *meta, - * ClutterActor *actor) - * { - * MyEffect *self = MY_EFFECT (meta); - * ClutterActorMetaClass *parent_class; - * CoglHandle handle; - * - * /* chain up to the parent's implementation */ - * parent_class = CLUTTER_EFFECT_CLASS (my_effect_parent_class); - * parent_class->set_actor (meta, actor)); - * - * /* if the parent class disabled the effect then we return * - * if (!clutter_actor_meta_get_enabled (meta)) - * return; - * - * /* we should have a handle to the shader at this point */ - * handle = clutter_shader_effect_get_shader (CLUTTER_SHADER_EFFECT (self)); - * if (handle == COGL_INVALID_HANDLE) - * return; - * - * /* set the source of the shader */ - * cogl_shader_source (handle, my_effect_glsl_source); - * } - * </programlisting> - * </example> - * <para>The <function>pre_paint()</function> is optional and it depends on - * whether the fragment shader has uniforms to set. The sub-class should call - * clutter_shader_effect_set_uniform_value() or - * clutter_shader_effect_set_uniform() and then chain up to the + * overriding of the <function>pre_paint()</function> virtual function + * from the #ClutterEffect class.</para> + * <para>The <function>pre_paint()</function> should set the shader's + * source and eventually set the uniforms. The sub-class should call + * clutter_shader_effect_set_shader_source() to set the shader source + * code, and clutter_shader_effect_set_uniform_value() or + * clutter_shader_effect_set_uniform() to set the values of the shader + * uniforms, if any; the sub-class should then chain up to the * #ClutterShaderEffect implementation.</para> * <example id="ClutterShaderEffect-example-uniforms"> * <title>Setting uniforms on a ClutterShaderEffect</title> @@ -98,11 +61,13 @@ * ClutterEffectClass *parent_class; * gfloat component_r, component_g, component_b; * - * /* chain up to the parent's implementation */ - * parent_class = CLUTTER_EFFECT_CLASS (my_effect_parent_class); - * if (!parent_class->pre_paint (effect)) + * /* if the effect is not enabled we can bail out now */ + * if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) * return FALSE; * + * /* this function is a no-op after the first call */ + * clutter_shader_effect_set_shader_source (shader, shader_source); + * * /* the "tex" uniform is declared in the shader as: * * * * uniform int tex; @@ -127,7 +92,9 @@ * component_g, * component_b); * - * return TRUE; + * /* chain up to the parent's implementation */ + * parent_class = CLUTTER_EFFECT_CLASS (my_effect_parent_class); + * return parent_class->pre_paint (effect); * } * </programlisting> * </example> @@ -167,6 +134,7 @@ struct _ClutterShaderEffectPrivate GHashTable *uniforms; guint is_compiled : 1; + guint source_set : 1; }; G_DEFINE_ABSTRACT_TYPE (ClutterShaderEffect, @@ -199,6 +167,7 @@ clutter_shader_effect_clear (ClutterShaderEffect *effect, priv->actor = NULL; priv->is_compiled = FALSE; + priv->source_set = FALSE; } static void @@ -289,8 +258,6 @@ clutter_shader_effect_set_actor (ClutterActorMeta *meta, ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (meta); ClutterShaderEffectPrivate *priv = self->priv; ClutterActorMetaClass *parent; - ClutterActorBox allocation; - gfloat width, height; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { @@ -318,9 +285,6 @@ clutter_shader_effect_set_actor (ClutterActorMeta *meta, CLUTTER_NOTE (SHADER, "Preparing shader effect of type '%s'", G_OBJECT_TYPE_NAME (meta)); - clutter_actor_get_allocation_box (priv->actor, &allocation); - clutter_actor_box_get_size (&allocation, &width, &height); - priv->program = cogl_create_program (); priv->shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); @@ -340,6 +304,9 @@ clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect) priv->shader == COGL_INVALID_HANDLE) return; + if (!priv->source_set) + return; + if (!priv->is_compiled) { CLUTTER_NOTE (SHADER, "Compiling shader effect"); @@ -757,3 +724,44 @@ clutter_shader_effect_set_uniform (ClutterShaderEffect *effect, &args); va_end (args); } + +/** + * clutter_shader_effect_set_shader_source: + * @effect: a #ClutterShaderEffect + * @source: the source of a GLSL shader + * + * Sets the source of the GLSL shader used by @effect + * + * This function should only be called by implementations of + * the #ClutterShaderEffect class, and not by application code. + * + * This function can only be called once; subsequent calls will + * yield no result. + * + * Return value: %TRUE if the source was set + * + * Since: 1.4 + */ +gboolean +clutter_shader_effect_set_shader_source (ClutterShaderEffect *effect, + const gchar *source) +{ + ClutterShaderEffectPrivate *priv; + + g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect), FALSE); + g_return_val_if_fail (source != NULL && *source != '\0', FALSE); + + priv = effect->priv; + + if (priv->source_set) + return TRUE; + + if (priv->shader == COGL_INVALID_HANDLE) + return FALSE; + + cogl_shader_source (priv->shader, source); + + priv->source_set = TRUE; + + return TRUE; +} |