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 x_step;
|
||||||
gfloat y_step;
|
gfloat y_step;
|
||||||
|
|
||||||
guint source_set : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBlurEffectClass
|
struct _ClutterBlurEffectClass
|
||||||
@ -147,16 +145,7 @@ clutter_blur_effect_pre_paint (ClutterEffect *effect)
|
|||||||
|
|
||||||
shader_effect = CLUTTER_SHADER_EFFECT (effect);
|
shader_effect = CLUTTER_SHADER_EFFECT (effect);
|
||||||
|
|
||||||
if (!self->source_set)
|
clutter_shader_effect_set_shader_source (shader_effect, box_blur_glsl_shader);
|
||||||
{
|
|
||||||
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,
|
clutter_shader_effect_set_uniform (shader_effect,
|
||||||
"tex",
|
"tex",
|
||||||
|
@ -65,8 +65,6 @@ struct _ClutterColorizeEffect
|
|||||||
|
|
||||||
/* the tint of the colorization */
|
/* the tint of the colorization */
|
||||||
ClutterColor tint;
|
ClutterColor tint;
|
||||||
|
|
||||||
guint source_set : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterColorizeEffectClass
|
struct _ClutterColorizeEffectClass
|
||||||
@ -114,17 +112,12 @@ clutter_colorize_effect_pre_paint (ClutterEffect *effect)
|
|||||||
ClutterEffectClass *parent_class;
|
ClutterEffectClass *parent_class;
|
||||||
float tint_r, tint_g, tint_b;
|
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);
|
shader_effect = CLUTTER_SHADER_EFFECT (effect);
|
||||||
if (!self->source_set)
|
|
||||||
{
|
|
||||||
CoglHandle shader = clutter_shader_effect_get_shader (shader_effect);
|
|
||||||
|
|
||||||
if (shader == COGL_INVALID_HANDLE)
|
clutter_shader_effect_set_shader_source (shader_effect, colorize_glsl_shader);
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
cogl_shader_source (shader, colorize_glsl_shader);
|
|
||||||
self->source_set = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we want normalized values here */
|
/* we want normalized values here */
|
||||||
tint_r = self->tint.red / 255.0f;
|
tint_r = self->tint.red / 255.0f;
|
||||||
|
@ -67,8 +67,6 @@ struct _ClutterDesaturateEffect
|
|||||||
|
|
||||||
/* the desaturation factor, also known as "strength" */
|
/* the desaturation factor, also known as "strength" */
|
||||||
gdouble factor;
|
gdouble factor;
|
||||||
|
|
||||||
guint source_set : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterDesaturateEffectClass
|
struct _ClutterDesaturateEffectClass
|
||||||
@ -129,18 +127,7 @@ clutter_desaturate_effect_pre_paint (ClutterEffect *effect)
|
|||||||
|
|
||||||
shader_effect = CLUTTER_SHADER_EFFECT (effect);
|
shader_effect = CLUTTER_SHADER_EFFECT (effect);
|
||||||
|
|
||||||
if (!self->source_set)
|
clutter_shader_effect_set_shader_source (shader_effect, desaturate_glsl_shader);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
factor = (float) self->factor;
|
factor = (float) self->factor;
|
||||||
|
|
||||||
|
@ -38,51 +38,14 @@
|
|||||||
* <refsect2 id="ClutterShaderEffect-implementing">
|
* <refsect2 id="ClutterShaderEffect-implementing">
|
||||||
* <title>Implementing a ClutterShaderEffect</title>
|
* <title>Implementing a ClutterShaderEffect</title>
|
||||||
* <para>Creating a sub-class of #ClutterShaderEffect requires the
|
* <para>Creating a sub-class of #ClutterShaderEffect requires the
|
||||||
* overriding of the <function>set_actor()</function> virtual function
|
* overriding of the <function>pre_paint()</function> virtual function
|
||||||
* from the #ClutterActorMeta class, and the <function>pre_paint()</function>
|
* from the #ClutterEffect class.</para>
|
||||||
* virtual functions from the #ClutterEffect class.</para>
|
* <para>The <function>pre_paint()</function> should set the shader's
|
||||||
* <para>The <function>set_actor()</function> must chain up to the
|
* source and eventually set the uniforms. The sub-class should call
|
||||||
* #ClutterShaderEffect implementation; if the effect has not been disabled
|
* clutter_shader_effect_set_shader_source() to set the shader source
|
||||||
* by the super class implementation, then the sub-class should get the
|
* code, and clutter_shader_effect_set_uniform_value() or
|
||||||
* #CoglHandle for the fragment shader using
|
* clutter_shader_effect_set_uniform() to set the values of the shader
|
||||||
* clutter_shader_effect_get_shader() and call cogl_shader_source() to set
|
* uniforms, if any; the sub-class should then chain up to the
|
||||||
* 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
|
|
||||||
* #ClutterShaderEffect implementation.</para>
|
* #ClutterShaderEffect implementation.</para>
|
||||||
* <example id="ClutterShaderEffect-example-uniforms">
|
* <example id="ClutterShaderEffect-example-uniforms">
|
||||||
* <title>Setting uniforms on a ClutterShaderEffect</title>
|
* <title>Setting uniforms on a ClutterShaderEffect</title>
|
||||||
@ -98,11 +61,13 @@
|
|||||||
* ClutterEffectClass *parent_class;
|
* ClutterEffectClass *parent_class;
|
||||||
* gfloat component_r, component_g, component_b;
|
* gfloat component_r, component_g, component_b;
|
||||||
*
|
*
|
||||||
* /* chain up to the parent's implementation */
|
* /* if the effect is not enabled we can bail out now */
|
||||||
* parent_class = CLUTTER_EFFECT_CLASS (my_effect_parent_class);
|
* if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||||
* if (!parent_class->pre_paint (effect))
|
|
||||||
* return FALSE;
|
* 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:
|
* /* the "tex" uniform is declared in the shader as:
|
||||||
* *
|
* *
|
||||||
* * uniform int tex;
|
* * uniform int tex;
|
||||||
@ -127,7 +92,9 @@
|
|||||||
* component_g,
|
* component_g,
|
||||||
* component_b);
|
* 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>
|
* </programlisting>
|
||||||
* </example>
|
* </example>
|
||||||
@ -167,6 +134,7 @@ struct _ClutterShaderEffectPrivate
|
|||||||
GHashTable *uniforms;
|
GHashTable *uniforms;
|
||||||
|
|
||||||
guint is_compiled : 1;
|
guint is_compiled : 1;
|
||||||
|
guint source_set : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE (ClutterShaderEffect,
|
G_DEFINE_ABSTRACT_TYPE (ClutterShaderEffect,
|
||||||
@ -199,6 +167,7 @@ clutter_shader_effect_clear (ClutterShaderEffect *effect,
|
|||||||
|
|
||||||
priv->actor = NULL;
|
priv->actor = NULL;
|
||||||
priv->is_compiled = FALSE;
|
priv->is_compiled = FALSE;
|
||||||
|
priv->source_set = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -289,8 +258,6 @@ clutter_shader_effect_set_actor (ClutterActorMeta *meta,
|
|||||||
ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (meta);
|
ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (meta);
|
||||||
ClutterShaderEffectPrivate *priv = self->priv;
|
ClutterShaderEffectPrivate *priv = self->priv;
|
||||||
ClutterActorMetaClass *parent;
|
ClutterActorMetaClass *parent;
|
||||||
ClutterActorBox allocation;
|
|
||||||
gfloat width, height;
|
|
||||||
|
|
||||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
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'",
|
CLUTTER_NOTE (SHADER, "Preparing shader effect of type '%s'",
|
||||||
G_OBJECT_TYPE_NAME (meta));
|
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->program = cogl_create_program ();
|
||||||
|
|
||||||
priv->shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
|
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)
|
priv->shader == COGL_INVALID_HANDLE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!priv->source_set)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!priv->is_compiled)
|
if (!priv->is_compiled)
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (SHADER, "Compiling shader effect");
|
CLUTTER_NOTE (SHADER, "Compiling shader effect");
|
||||||
@ -757,3 +724,44 @@ clutter_shader_effect_set_uniform (ClutterShaderEffect *effect,
|
|||||||
&args);
|
&args);
|
||||||
va_end (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;
|
GType clutter_shader_effect_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
void clutter_shader_effect_set_uniform (ClutterShaderEffect *effect,
|
gboolean clutter_shader_effect_set_shader_source (ClutterShaderEffect *effect,
|
||||||
const gchar *name,
|
const gchar *source);
|
||||||
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);
|
void clutter_shader_effect_set_uniform (ClutterShaderEffect *effect,
|
||||||
CoglHandle clutter_shader_effect_get_program (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
|
G_END_DECLS
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user