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.
This commit is contained in:
parent
f2caafa127
commit
0e9a1dee6d
@ -94,8 +94,6 @@ struct _ClutterBlurEffect
|
||||
*/
|
||||
gfloat x_step;
|
||||
gfloat y_step;
|
||||
|
||||
guint source_set : 1;
|
||||
};
|
||||
|
||||
struct _ClutterBlurEffectClass
|
||||
@ -147,16 +145,7 @@ clutter_blur_effect_pre_paint (ClutterEffect *effect)
|
||||
|
||||
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_shader_source (shader_effect, box_blur_glsl_shader);
|
||||
|
||||
clutter_shader_effect_set_uniform (shader_effect,
|
||||
"tex",
|
||||
|
@ -65,8 +65,6 @@ struct _ClutterColorizeEffect
|
||||
|
||||
/* the tint of the colorization */
|
||||
ClutterColor tint;
|
||||
|
||||
guint source_set : 1;
|
||||
};
|
||||
|
||||
struct _ClutterColorizeEffectClass
|
||||
@ -114,17 +112,12 @@ clutter_colorize_effect_pre_paint (ClutterEffect *effect)
|
||||
ClutterEffectClass *parent_class;
|
||||
float tint_r, tint_g, tint_b;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
|
||||
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, colorize_glsl_shader);
|
||||
self->source_set = TRUE;
|
||||
}
|
||||
clutter_shader_effect_set_shader_source (shader_effect, colorize_glsl_shader);
|
||||
|
||||
/* we want normalized values here */
|
||||
tint_r = self->tint.red / 255.0f;
|
||||
|
@ -67,8 +67,6 @@ struct _ClutterDesaturateEffect
|
||||
|
||||
/* the desaturation factor, also known as "strength" */
|
||||
gdouble factor;
|
||||
|
||||
guint source_set : 1;
|
||||
};
|
||||
|
||||
struct _ClutterDesaturateEffectClass
|
||||
@ -129,18 +127,7 @@ clutter_desaturate_effect_pre_paint (ClutterEffect *effect)
|
||||
|
||||
shader_effect = CLUTTER_SHADER_EFFECT (effect);
|
||||
|
||||
if (!self->source_set)
|
||||
{
|
||||
CoglHandle shader;
|
||||
|
||||
/* get the CoglShader handle to set the source */
|
||||
shader = clutter_shader_effect_get_shader (shader_effect);
|
||||
if (shader == COGL_INVALID_HANDLE)
|
||||
return FALSE;
|
||||
|
||||
cogl_shader_source (shader, desaturate_glsl_shader);
|
||||
self->source_set = TRUE;
|
||||
}
|
||||
clutter_shader_effect_set_shader_source (shader_effect, desaturate_glsl_shader);
|
||||
|
||||
factor = (float) self->factor;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -84,17 +84,20 @@ struct _ClutterShaderEffectClass
|
||||
|
||||
GType clutter_shader_effect_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void clutter_shader_effect_set_uniform (ClutterShaderEffect *effect,
|
||||
const gchar *name,
|
||||
GType gtype,
|
||||
gsize size,
|
||||
...);
|
||||
void clutter_shader_effect_set_uniform_value (ClutterShaderEffect *effect,
|
||||
const gchar *name,
|
||||
const GValue *value);
|
||||
gboolean clutter_shader_effect_set_shader_source (ClutterShaderEffect *effect,
|
||||
const gchar *source);
|
||||
|
||||
CoglHandle clutter_shader_effect_get_shader (ClutterShaderEffect *effect);
|
||||
CoglHandle clutter_shader_effect_get_program (ClutterShaderEffect *effect);
|
||||
void clutter_shader_effect_set_uniform (ClutterShaderEffect *effect,
|
||||
const gchar *name,
|
||||
GType gtype,
|
||||
gsize size,
|
||||
...);
|
||||
void clutter_shader_effect_set_uniform_value (ClutterShaderEffect *effect,
|
||||
const gchar *name,
|
||||
const GValue *value);
|
||||
|
||||
CoglHandle clutter_shader_effect_get_shader (ClutterShaderEffect *effect);
|
||||
CoglHandle clutter_shader_effect_get_program (ClutterShaderEffect *effect);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user