2008-11-18 Emmanuele Bassi <ebassi@linux.intel.com>

Bug 1049 - Clutter doesn't support most GLSL uniforms (patch
	by Chris Lord and Neil Roberts)

	* README: Update release notes.

	* clutter/Makefile.am:
	* clutter/clutter-shader-types.[ch]: Add GValue types for
	shader values.

	* clutter/clutter-actor.[ch]: Update the shader API to use
	the newly added GValue support for GLSL shader uniform
	setters.

	* clutter/clutter-shader.[ch]: Add float and integer convenience
	API for single value GLSL uniform setters.

	* clutter/cogl/cogl-shader.h: Add new uniform setters.

	* clutter/cogl/gl/cogl-context.c:
	* clutter/cogl/gl/cogl-context.h:
	* clutter/cogl/gl/cogl-defines.h.in:
	* clutter/cogl/gl/cogl-program.c:
	* clutter/cogl/gl/cogl.c: Update the GL implementation of COGL
	to handle the GLSL uniform setters.

	* clutter/cogl/gles/cogl-gles2-wrapper.c:
	* clutter/cogl/gles/cogl-gles2-wrapper.h:
	* clutter/cogl/gles/cogl-internal.h:
	* clutter/cogl/gles/cogl-program.c: Update the GLES 2.0 implementation
	of COGL to handle the GLSL uniform setters.

	* doc/reference/clutter/clutter-sections.txt:
	* doc/reference/cogl/cogl-sections.txt: Update the documentation.

	* tests/interactive/test-fbo.c:
	* tests/interactive/test-shader.c: Update the shader tests.
This commit is contained in:
Emmanuele Bassi 2008-11-18 15:08:40 +00:00
parent 25d9773e15
commit af0cb47570
23 changed files with 1595 additions and 100 deletions

View File

@ -1,3 +1,42 @@
2008-11-18 Emmanuele Bassi <ebassi@linux.intel.com>
Bug 1049 - Clutter doesn't support most GLSL uniforms (patch
by Chris Lord and Neil Roberts)
* README: Update release notes.
* clutter/Makefile.am:
* clutter/clutter-shader-types.[ch]: Add GValue types for
shader values.
* clutter/clutter-actor.[ch]: Update the shader API to use
the newly added GValue support for GLSL shader uniform
setters.
* clutter/clutter-shader.[ch]: Add float and integer convenience
API for single value GLSL uniform setters.
* clutter/cogl/cogl-shader.h: Add new uniform setters.
* clutter/cogl/gl/cogl-context.c:
* clutter/cogl/gl/cogl-context.h:
* clutter/cogl/gl/cogl-defines.h.in:
* clutter/cogl/gl/cogl-program.c:
* clutter/cogl/gl/cogl.c: Update the GL implementation of COGL
to handle the GLSL uniform setters.
* clutter/cogl/gles/cogl-gles2-wrapper.c:
* clutter/cogl/gles/cogl-gles2-wrapper.h:
* clutter/cogl/gles/cogl-internal.h:
* clutter/cogl/gles/cogl-program.c: Update the GLES 2.0 implementation
of COGL to handle the GLSL uniform setters.
* doc/reference/clutter/clutter-sections.txt:
* doc/reference/cogl/cogl-sections.txt: Update the documentation.
* tests/interactive/test-fbo.c:
* tests/interactive/test-shader.c: Update the shader tests.
2008-11-18 Emmanuele Bassi <ebassi@linux.intel.com>
* clutter/clutter-texture.c:

6
README
View File

@ -170,6 +170,12 @@ wanting to port to newer releases (See NEWS for general new feature info).
Release Notes for Clutter 1.0
-------------------------------
* The clutter_actor_set_shader_param() function now takes a
GValue, which can be set using the clutter_value_set_shader()
family of functions. The floating point wrapper has been
rename clutter_actor_set_shader_param_float() to match the newly
added clutter_actor_set_shader_param_int().
* The Pango renderer API has been exposed as public API, after
a full rename from PangoClutter to CoglPango, to avoid namespace
collisions with upstream Pango. The Pango font map, renderer and

View File

@ -81,6 +81,7 @@ source_h = \
$(srcdir)/clutter-script.h \
$(srcdir)/clutter-scriptable.h \
$(srcdir)/clutter-shader.h \
$(srcdir)/clutter-shader-types.h \
$(srcdir)/clutter-stage.h \
$(srcdir)/clutter-stage-manager.h \
$(srcdir)/clutter-texture.h \
@ -171,6 +172,7 @@ source_c = \
clutter-script-parser.c \
clutter-scriptable.c \
clutter-shader.c \
clutter-shader-types.c \
clutter-stage.c \
clutter-stage-manager.c \
clutter-stage-window.c \

View File

@ -7085,28 +7085,22 @@ clutter_actor_box_get_type (void)
/******************************************************************************/
typedef struct _BoxedFloat BoxedFloat;
struct _BoxedFloat
{
gfloat value;
};
static void
boxed_float_free (gpointer data)
{
if (G_LIKELY (data))
g_slice_free (BoxedFloat, data);
}
struct _ShaderData
{
ClutterShader *shader;
GHashTable *float1f_hash; /*< list of values that should be set
GHashTable *value_hash; /*< list of GValue's that should be set
* on the shader before each paint cycle
*/
};
static void
shader_value_free (gpointer data)
{
GValue *var = data;
g_value_unset (var);
g_slice_free (GValue, var);
}
static void
destroy_shader_data (ClutterActor *self)
{
@ -7122,10 +7116,10 @@ destroy_shader_data (ClutterActor *self)
shader_data->shader = NULL;
}
if (shader_data->float1f_hash)
if (shader_data->value_hash)
{
g_hash_table_destroy (shader_data->float1f_hash);
shader_data->float1f_hash = NULL;
g_hash_table_destroy (shader_data->value_hash);
shader_data->value_hash = NULL;
}
g_free (shader_data);
@ -7196,10 +7190,10 @@ clutter_actor_set_shader (ClutterActor *self,
if (!shader_data)
{
actor_priv->shader_data = shader_data = g_new0 (ShaderData, 1);
shader_data->float1f_hash =
shader_data->value_hash =
g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
boxed_float_free);
shader_value_free);
}
if (shader_data->shader)
{
@ -7224,10 +7218,10 @@ set_each_param (gpointer key,
gpointer value,
gpointer user_data)
{
ClutterShader *shader = CLUTTER_SHADER (user_data);
BoxedFloat *box = value;
ClutterShader *shader = user_data;
GValue *var = value;
clutter_shader_set_uniform_1f (shader, key, box->value);
clutter_shader_set_uniform (shader, (const gchar *)key, var);
}
static void
@ -7252,7 +7246,7 @@ clutter_actor_shader_pre_paint (ClutterActor *actor,
{
clutter_shader_set_is_enabled (shader, TRUE);
g_hash_table_foreach (shader_data->float1f_hash, set_each_param, shader);
g_hash_table_foreach (shader_data->value_hash, set_each_param, shader);
if (!repeat)
context->shaders = g_slist_prepend (context->shaders, actor);
@ -7301,19 +7295,24 @@ clutter_actor_shader_post_paint (ClutterActor *actor)
* Sets the value for a named parameter of the shader applied
* to @actor.
*
* Since: 0.6
* Since: 1.0
*/
void
clutter_actor_set_shader_param (ClutterActor *self,
const gchar *param,
gfloat value)
const GValue *value)
{
ClutterActorPrivate *priv;
ShaderData *shader_data;
BoxedFloat *box;
GValue *var;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (param != NULL);
g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value) ||
CLUTTER_VALUE_HOLDS_SHADER_INT (value) ||
CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value) ||
G_VALUE_HOLDS_FLOAT (value) ||
G_VALUE_HOLDS_INT (value));
priv = self->priv;
shader_data = priv->shader_data;
@ -7321,14 +7320,67 @@ clutter_actor_set_shader_param (ClutterActor *self,
if (!shader_data)
return;
box = g_slice_new (BoxedFloat);
box->value = value;
g_hash_table_insert (shader_data->float1f_hash, g_strdup (param), box);
var = g_slice_new0 (GValue);
g_value_init (var, G_VALUE_TYPE (value));
g_value_copy (value, var);
g_hash_table_insert (shader_data->value_hash, g_strdup (param), var);
if (CLUTTER_ACTOR_IS_VISIBLE (self))
clutter_actor_queue_redraw (self);
}
/**
* clutter_actor_set_shader_param_float:
* @self: a #ClutterActor
* @param: the name of the parameter
* @value: the value of the parameter
*
* Sets the value for a named float parameter of the shader applied
* to @actor.
*
* Since: 0.8
*/
void
clutter_actor_set_shader_param_float (ClutterActor *self,
const gchar *param,
gfloat value)
{
GValue var = { 0, };
g_value_init (&var, G_TYPE_FLOAT);
g_value_set_float (&var, value);
clutter_actor_set_shader_param (self, param, &var);
g_value_unset (&var);
}
/**
* clutter_actor_set_shader_param_int:
* @self: a #ClutterActor
* @param: the name of the parameter
* @value: the value of the parameter
*
* Sets the value for a named int parameter of the shader applied to
* @actor.
*
* Since: 0.8
*/
void
clutter_actor_set_shader_param_int (ClutterActor *self,
const gchar *param,
gint value)
{
GValue var = { 0, };
g_value_init (&var, G_TYPE_INT);
g_value_set_int (&var, value);
clutter_actor_set_shader_param (self, param, &var);
g_value_unset (&var);
}
/**
* clutter_actor_is_rotated:
* @self: a #ClutterActor

View File

@ -504,6 +504,12 @@ gboolean clutter_actor_set_shader (ClutterActor
ClutterShader *shader);
ClutterShader * clutter_actor_get_shader (ClutterActor *self);
void clutter_actor_set_shader_param (ClutterActor *self,
const gchar *param,
const GValue *value);
void clutter_actor_set_shader_param_int (ClutterActor *self,
const gchar *param,
gint value);
void clutter_actor_set_shader_param_float (ClutterActor *self,
const gchar *param,
gfloat value);

View File

@ -0,0 +1,563 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Chris Lord <chris@openedhand.com>
*
* Copyright (C) 2008 OpenedHand
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <glib-object.h>
#include <gobject/gvaluecollector.h>
#include "clutter-shader-types.h"
#include "clutter-private.h"
static GTypeInfo shader_float_info = {
0,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
0,
NULL,
NULL,
};
static GTypeFundamentalInfo shader_float_finfo = { 0, };
static GTypeInfo shader_int_info = {
0,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
0,
NULL,
NULL,
};
static GTypeFundamentalInfo shader_int_finfo = { 0, };
static GTypeInfo shader_matrix_info = {
0,
NULL,
NULL,
NULL,
NULL,
NULL,
0,
0,
NULL,
NULL,
};
static GTypeFundamentalInfo shader_matrix_finfo = { 0, };
struct _ClutterShaderFloat
{
gint size;
GLfloat value[4];
};
struct _ClutterShaderInt
{
gint size;
COGLint value[4];
};
struct _ClutterShaderMatrix
{
gint size;
GLfloat value[16];
};
static gpointer
clutter_value_peek_pointer (const GValue *value)
{
return value->data[0].v_pointer;
}
/* Float */
static void
clutter_value_init_shader_float (GValue *value)
{
value->data[0].v_pointer = g_slice_new0 (ClutterShaderFloat);
}
static void
clutter_value_free_shader_float (GValue *value)
{
g_slice_free (ClutterShaderFloat, value->data[0].v_pointer);
}
static void
clutter_value_copy_shader_float (const GValue *src,
GValue *dest)
{
dest->data[0].v_pointer =
g_slice_dup (ClutterShaderFloat, src->data[0].v_pointer);
}
static gchar *
clutter_value_collect_shader_float (GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
gint float_count = collect_values[0].v_int;
const float *floats = collect_values[1].v_pointer;
if (!floats)
return g_strdup_printf ("value location for `%s' passed as NULL",
G_VALUE_TYPE_NAME (value));
clutter_value_init_shader_float (value);
clutter_value_set_shader_float (value, float_count, floats);
return NULL;
}
static gchar *
clutter_value_lcopy_shader_float (const GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
gint *float_count = collect_values[0].v_pointer;
float **floats = collect_values[1].v_pointer;
ClutterShaderFloat *shader_float = value->data[0].v_pointer;
if (!float_count || !floats)
return g_strdup_printf ("value location for `%s' passed as NULL",
G_VALUE_TYPE_NAME (value));
*float_count = shader_float->size;
*floats = g_memdup (shader_float->value, shader_float->size * sizeof (float));
return NULL;
}
static const GTypeValueTable _clutter_shader_float_value_table = {
clutter_value_init_shader_float,
clutter_value_free_shader_float,
clutter_value_copy_shader_float,
clutter_value_peek_pointer,
"ip",
clutter_value_collect_shader_float,
"pp",
clutter_value_lcopy_shader_float
};
GType
clutter_shader_float_get_type (void)
{
static GType _clutter_shader_float_type = 0;
if (G_UNLIKELY (_clutter_shader_float_type == 0))
{
shader_float_info.value_table = & _clutter_shader_float_value_table;
_clutter_shader_float_type =
g_type_register_fundamental (g_type_fundamental_next (),
I_("ClutterShaderFloat"),
&shader_float_info,
&shader_float_finfo, 0);
}
return _clutter_shader_float_type;
}
/* Integer */
static void
clutter_value_init_shader_int (GValue *value)
{
value->data[0].v_pointer = g_slice_new0 (ClutterShaderInt);
}
static void
clutter_value_free_shader_int (GValue *value)
{
g_slice_free (ClutterShaderInt, value->data[0].v_pointer);
}
static void
clutter_value_copy_shader_int (const GValue *src,
GValue *dest)
{
dest->data[0].v_pointer =
g_slice_dup (ClutterShaderInt, src->data[0].v_pointer);
}
static gchar *
clutter_value_collect_shader_int (GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
gint int_count = collect_values[0].v_int;
const COGLint *ints = collect_values[1].v_pointer;
if (!ints)
return g_strdup_printf ("value location for `%s' passed as NULL",
G_VALUE_TYPE_NAME (value));
clutter_value_init_shader_int (value);
clutter_value_set_shader_int (value, int_count, ints);
return NULL;
}
static gchar *
clutter_value_lcopy_shader_int (const GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
gint *int_count = collect_values[0].v_pointer;
COGLint **ints = collect_values[1].v_pointer;
ClutterShaderInt *shader_int = value->data[0].v_pointer;
if (!int_count || !ints)
return g_strdup_printf ("value location for `%s' passed as NULL",
G_VALUE_TYPE_NAME (value));
*int_count = shader_int->size;
*ints = g_memdup (shader_int->value, shader_int->size * sizeof (COGLint));
return NULL;
}
static const GTypeValueTable _clutter_shader_int_value_table = {
clutter_value_init_shader_int,
clutter_value_free_shader_int,
clutter_value_copy_shader_int,
clutter_value_peek_pointer,
"ip",
clutter_value_collect_shader_int,
"pp",
clutter_value_lcopy_shader_int
};
GType
clutter_shader_int_get_type (void)
{
static GType _clutter_shader_int_type = 0;
if (G_UNLIKELY (_clutter_shader_int_type == 0))
{
shader_int_info.value_table = & _clutter_shader_int_value_table;
_clutter_shader_int_type =
g_type_register_fundamental (g_type_fundamental_next (),
I_("ClutterShaderInt"),
&shader_int_info,
&shader_int_finfo, 0);
}
return _clutter_shader_int_type;
}
/* Matrix */
static void
clutter_value_init_shader_matrix (GValue *value)
{
value->data[0].v_pointer = g_slice_new0 (ClutterShaderMatrix);
}
static void
clutter_value_free_shader_matrix (GValue *value)
{
g_slice_free (ClutterShaderMatrix, value->data[0].v_pointer);
}
static void
clutter_value_copy_shader_matrix (const GValue *src,
GValue *dest)
{
dest->data[0].v_pointer =
g_slice_dup (ClutterShaderMatrix, src->data[0].v_pointer);
}
static gchar *
clutter_value_collect_shader_matrix (GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
gint float_count = collect_values[0].v_int;
const float *floats = collect_values[1].v_pointer;
if (!floats)
return g_strdup_printf ("value location for `%s' passed as NULL",
G_VALUE_TYPE_NAME (value));
clutter_value_init_shader_matrix (value);
clutter_value_set_shader_matrix (value, float_count, floats);
return NULL;
}
static gchar *
clutter_value_lcopy_shader_matrix (const GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
gint *float_count = collect_values[0].v_pointer;
float **floats = collect_values[1].v_pointer;
ClutterShaderFloat *shader_float = value->data[0].v_pointer;
if (!float_count || !floats)
return g_strdup_printf ("value location for `%s' passed as NULL",
G_VALUE_TYPE_NAME (value));
*float_count = shader_float->size;
*floats = g_memdup (shader_float->value,
shader_float->size * shader_float->size * sizeof (float));
return NULL;
}
static const GTypeValueTable _clutter_shader_matrix_value_table = {
clutter_value_init_shader_matrix,
clutter_value_free_shader_matrix,
clutter_value_copy_shader_matrix,
clutter_value_peek_pointer,
"ip",
clutter_value_collect_shader_matrix,
"pp",
clutter_value_lcopy_shader_matrix
};
GType
clutter_shader_matrix_get_type (void)
{
static GType _clutter_shader_matrix_type = 0;
if (G_UNLIKELY (_clutter_shader_matrix_type == 0))
{
shader_matrix_info.value_table = & _clutter_shader_matrix_value_table;
_clutter_shader_matrix_type =
g_type_register_fundamental (g_type_fundamental_next (),
I_("ClutterShaderMatrix"),
&shader_matrix_info,
&shader_matrix_finfo, 0);
}
return _clutter_shader_matrix_type;
}
/* Utility functions */
/**
* clutter_value_set_shader_float:
* @value: a #GValue
* @size: number of floating point values in @floats
* @floats: an array of floating point values
*
* Sets @floats as the contents of @value. The passed #GValue
* must have been initialized using %CLUTTER_TYPE_SHADER_FLOAT.
*
* Since: 0.8
*/
void
clutter_value_set_shader_float (GValue *value,
gint size,
const gfloat *floats)
{
ClutterShaderFloat *shader_float;
gint i;
g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value));
shader_float = value->data[0].v_pointer;
shader_float->size = size;
for (i = 0; i < size; i++)
shader_float->value[i] = floats[i];
}
/**
* clutter_value_set_shader_int:
* @value: a #GValue
* @size: number of integer values in @ints
* @ints: an array of integer values
*
* Sets @ints as the contents of @value. The passed #GValue
* must have been initialized using %CLUTTER_TYPE_SHADER_INT.
*
* Since: 0.8
*/
void
clutter_value_set_shader_int (GValue *value,
gint size,
const gint *ints)
{
ClutterShaderInt *shader_int;
gint i;
g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_INT (value));
shader_int = value->data[0].v_pointer;
shader_int->size = size;
for (i = 0; i < size; i++)
shader_int->value[i] = ints[i];
}
/**
* clutter_value_set_shader_matrix:
* @value: a #GValue
* @size: number of floating point values in @floats
* @matrix: a matrix of floating point values
*
* Sets @matrix as the contents of @value. The passed #GValue
* must have been initialized using %CLUTTER_TYPE_SHADER_MATRIX.
*
* Since: 0.8
*/
void
clutter_value_set_shader_matrix (GValue *value,
gint size,
const gfloat *matrix)
{
ClutterShaderMatrix *shader_matrix;
gint i;
g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value));
shader_matrix = value->data[0].v_pointer;
shader_matrix->size = size;
for (i = 0; i < size * size; i++)
shader_matrix->value[i] = matrix[i];
}
/**
* clutter_value_get_shader_float:
* @value: a #GValue
* @length: return location for the number of returned floating
* point values, or %NULL
*
* Retrieves the list of floating point values stored inside
* the passed #GValue. @value must have been initialized with
* %CLUTTER_TYPE_SHADER_FLOAT.
*
* Return value: the pointer to a list of floating point values.
* The returned value is owned by the #GValue and should never
* be modified or freed.
*
* Since: 0.8
*/
G_CONST_RETURN gfloat *
clutter_value_get_shader_float (const GValue *value,
gsize *length)
{
ClutterShaderFloat *shader_float;
g_return_val_if_fail (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value), 0);
shader_float = value->data[0].v_pointer;
if (length)
*length = shader_float->size;
return shader_float->value;
}
/**
* clutter_value_get_shader_int:
* @value: a #GValue
* @length: return location for the number of returned integer
* values, or %NULL
*
* Retrieves the list of integer values stored inside the passed
* #GValue. @value must have been initialized with
* %CLUTTER_TYPE_SHADER_INT.
*
* Return value: the pointer to a list of integer values.
* The returned value is owned by the #GValue and should never
* be modified or freed.
*
* Since: 0.8
*/
G_CONST_RETURN COGLint *
clutter_value_get_shader_int (const GValue *value,
gsize *length)
{
ClutterShaderInt *shader_int;
g_return_val_if_fail (CLUTTER_VALUE_HOLDS_SHADER_INT (value), 0);
shader_int = value->data[0].v_pointer;
if (length)
*length = shader_int->size;
return shader_int->value;
}
/**
* clutter_value_get_shader_matrix:
* @value: a #GValue
* @length: return location for the number of returned floating
* point values, or %NULL
*
* Retrieves a matrix of floating point values stored inside
* the passed #GValue. @value must have been initialized with
* %CLUTTER_TYPE_SHADER_MATRIX.
*
* Return value: the pointer to a matrix of floating point values.
* The returned value is owned by the #GValue and should never
* be modified or freed.
*
* Since: 0.8
*/
G_CONST_RETURN gfloat *
clutter_value_get_shader_matrix (const GValue *value,
gsize *length)
{
ClutterShaderMatrix *shader_matrix;
g_return_val_if_fail (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value), 0);
shader_matrix = value->data[0].v_pointer;
if (length)
*length = shader_matrix->size;
return shader_matrix->value;
}

View File

@ -0,0 +1,96 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2008 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 <http://www.gnu.org/licenses/>.
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_SHADER_TYPES_H__
#define __CLUTTER_SHADER_TYPES_H__
#include <glib-object.h>
#include <cogl/cogl.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_SHADER_FLOAT (clutter_shader_float_get_type ())
#define CLUTTER_TYPE_SHADER_INT (clutter_shader_int_get_type ())
#define CLUTTER_TYPE_SHADER_MATRIX (clutter_shader_matrix_get_type ())
typedef struct _ClutterShaderFloat ClutterShaderFloat;
typedef struct _ClutterShaderInt ClutterShaderInt;
typedef struct _ClutterShaderMatrix ClutterShaderMatrix;
/**
* CLUTTER_VALUE_HOLDS_SHADER_FLOAT:
* @x: a #GValue
*
* Evaluates to %TRUE if @x holds a #ClutterShaderFloat.
*
* Since: 1.0
*/
#define CLUTTER_VALUE_HOLDS_SHADER_FLOAT(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_SHADER_FLOAT))
/**
* CLUTTER_VALUE_HOLDS_SHADER_INT:
* @x: a #GValue
*
* Evaluates to %TRUE if @x holds a #ClutterShaderInt.
*
* Since: 1.0
*/
#define CLUTTER_VALUE_HOLDS_SHADER_INT(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_SHADER_INT))
/**
* CLUTTER_VALUE_HOLDS_SHADER_MATRIX:
* @x: a #GValue
*
* Evaluates to %TRUE if @x holds a #ClutterShaderMatrix.
*
* Since: 1.0
*/
#define CLUTTER_VALUE_HOLDS_SHADER_MATRIX(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_SHADER_MATRIX))
GType clutter_shader_float_get_type (void) G_GNUC_CONST;
GType clutter_shader_int_get_type (void) G_GNUC_CONST;
GType clutter_shader_matrix_get_type (void) G_GNUC_CONST;
void clutter_value_set_shader_float (GValue *value,
gint size,
const gfloat *floats);
void clutter_value_set_shader_int (GValue *value,
gint size,
const gint *ints);
void clutter_value_set_shader_matrix (GValue *value,
gint size,
const gfloat *matrix);
G_CONST_RETURN gfloat * clutter_value_get_shader_float (const GValue *value,
gsize *length);
G_CONST_RETURN COGLint *clutter_value_get_shader_int (const GValue *value,
gsize *length);
G_CONST_RETURN GLfloat *clutter_value_get_shader_matrix (const GValue *value,
gsize *length);
G_END_DECLS
#endif /* __CLUTTER_SHADER_TYPES_H__ */

View File

@ -70,7 +70,6 @@ struct _ClutterShaderPrivate
{
guint compiled : 1; /* Shader is bound to the GL context */
guint is_enabled : 1;
guint vertex_is_glsl : 1;
guint fragment_is_glsl : 1;
@ -95,9 +94,6 @@ enum
G_DEFINE_TYPE (ClutterShader, clutter_shader, G_TYPE_OBJECT);
G_CONST_RETURN gchar *clutter_shader_get_source (ClutterShader *shader,
ClutterShaderType type);
static void
clutter_shader_finalize (GObject *object)
{
@ -193,7 +189,6 @@ clutter_shader_constructor (GType type,
return object;
}
static void
clutter_shader_class_init (ClutterShaderClass *klass)
{
@ -341,8 +336,8 @@ clutter_shader_set_fragment_source (ClutterShader *shader,
g_free (priv->fragment_source);
CLUTTER_NOTE (SHADER, "setting fragment shader (GLSL:%s, len:%"
G_GSSIZE_FORMAT ")",
CLUTTER_NOTE (SHADER,
"setting fragment shader (GLSL:%s, len:%" G_GSSIZE_FORMAT ")",
is_glsl ? "yes" : "no",
length);
@ -387,8 +382,8 @@ clutter_shader_set_vertex_source (ClutterShader *shader,
g_free (priv->vertex_source);
CLUTTER_NOTE (SHADER, "setting vertex shader (GLSL:%s, len:%"
G_GSSIZE_FORMAT ")",
CLUTTER_NOTE (SHADER,
"setting vertex shader (GLSL:%s, len:%" G_GSSIZE_FORMAT ")",
is_glsl ? "yes" : "no",
length);
@ -668,6 +663,7 @@ clutter_shader_set_uniform_1f (ClutterShader *shader,
GLfloat foo = value;
g_return_if_fail (CLUTTER_IS_SHADER (shader));
g_return_if_fail (name != NULL);
priv = shader->priv;
@ -675,13 +671,83 @@ clutter_shader_set_uniform_1f (ClutterShader *shader,
cogl_program_uniform_1f (location, foo);
}
/**
* clutter_shader_set_uniform:
* @shader: a #ClutterShader.
* @name: name of uniform in GLSL shader program to set.
* @value: a #ClutterShaderFloat, #ClutterShaderInt or #ClutterShaderMatrix
* #GValue.
*
* Sets a user configurable variable in the GLSL shader programs attached to
* a #ClutterShader.
*
* Since: 1.0
*/
void
clutter_shader_set_uniform (ClutterShader *shader,
const gchar *name,
const GValue *value)
{
ClutterShaderPrivate *priv;
GLint location = 0;
gsize size;
g_return_if_fail (CLUTTER_IS_SHADER (shader));
g_return_if_fail (name != NULL);
g_return_if_fail (value != NULL);
g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value) ||
CLUTTER_VALUE_HOLDS_SHADER_INT (value) ||
CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value) ||
G_VALUE_HOLDS_FLOAT (value) ||
G_VALUE_HOLDS_INT (value));
priv = shader->priv;
g_return_if_fail (priv->program != COGL_INVALID_HANDLE);
location = cogl_program_get_uniform_location (priv->program, name);
if (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value))
{
const GLfloat *floats;
floats = clutter_value_get_shader_float (value, &size);
cogl_program_uniform_float (location, size, 1, floats);
}
else if (CLUTTER_VALUE_HOLDS_SHADER_INT (value))
{
const COGLint *ints;
ints = clutter_value_get_shader_int (value, &size);
cogl_program_uniform_int (location, size, 1, ints);
}
else if (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value))
{
const GLfloat *matrix;
matrix = clutter_value_get_shader_matrix (value, &size);
cogl_program_uniform_matrix (location, size, 1, FALSE, matrix);
}
else if (G_VALUE_HOLDS_FLOAT (value))
{
GLfloat float_val = g_value_get_float (value);
cogl_program_uniform_float (location, 1, 1, &float_val);
}
else if (G_VALUE_HOLDS_INT (value))
{
COGLint int_val = g_value_get_int (value);
cogl_program_uniform_int (location, 1, 1, &int_val);
}
else
g_assert_not_reached ();
}
/*
* _clutter_shader_release_all:
*
* Iterate through all #ClutterShaders and tell them to release GL context
* related sources.
*
* Since: 0.6
*/
void
_clutter_shader_release_all (void)
@ -730,6 +796,57 @@ clutter_shader_get_vertex_source (ClutterShader *shader)
return shader->priv->vertex_source;
}
/**
* clutter_shader_get_cogl_program:
* @shader: a #ClutterShader
*
* Retrieves the underlying #CoglHandle for the shader program.
*
* Return value: A #CoglHandle for the shader program, or %NULL
*
* Since: 1.0
*/
CoglHandle
clutter_shader_get_cogl_program (ClutterShader *shader)
{
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL);
return shader->priv->program;
}
/**
* clutter_shader_get_cogl_fragment_shader:
* @shader: a #ClutterShader
*
* Retrieves the underlying #CoglHandle for the fragment shader.
*
* Return value: A #CoglHandle for the fragment shader, or %NULL
*
* Since: 1.0
*/
CoglHandle
clutter_shader_get_cogl_fragment_shader (ClutterShader *shader)
{
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL);
return shader->priv->fragment_shader;
}
/**
* clutter_shader_get_cogl_vertex_shader:
* @shader: a #ClutterShader
*
* Retrieves the underlying #CoglHandle for the vertex shader.
*
* Return value: A #CoglHandle for the vertex shader, or %NULL
*
* Since: 1.0
*/
CoglHandle
clutter_shader_get_cogl_vertex_shader (ClutterShader *shader)
{
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL);
return shader->priv->vertex_shader;
}
GQuark
clutter_shader_error_quark (void)
{

View File

@ -29,7 +29,7 @@
#ifndef __CLUTTER_SHADER_H__
#define __CLUTTER_SHADER_H__
#include <glib-object.h>
#include <clutter/clutter-shader-types.h>
G_BEGIN_DECLS
@ -99,10 +99,21 @@ void clutter_shader_set_fragment_source (ClutterShader *sh
G_CONST_RETURN gchar *clutter_shader_get_vertex_source (ClutterShader *shader);
G_CONST_RETURN gchar *clutter_shader_get_fragment_source (ClutterShader *shader);
void clutter_shader_set_uniform (ClutterShader *shader,
const gchar *name,
const GValue *value);
CoglHandle clutter_shader_get_cogl_program (ClutterShader *shader);
CoglHandle clutter_shader_get_cogl_fragment_shader (ClutterShader *shader);
CoglHandle clutter_shader_get_cogl_vertex_shader (ClutterShader *shader);
#ifndef CLUTTER_DISABLE_DEPRECATED
void clutter_shader_set_uniform_1f (ClutterShader *shader,
const gchar *name,
gfloat value);
/* should be private and internal */
#endif
/* private */
void _clutter_shader_release_all (void);
G_END_DECLS

View File

@ -188,10 +188,10 @@ void cogl_program_link (CoglHandle handle);
/**
* cogl_program_use:
* @handle: a #CoglHandle for a shader program or COGL_INVALID_HANDLE.
* @handle: a #CoglHandle for a shader program or %COGL_INVALID_HANDLE.
*
* Activate a specific shader program replacing that part of the GL
* rendering pipeline, if passed in COGL_INVALID_HANDLE the default
* rendering pipeline, if passed in %COGL_INVALID_HANDLE the default
* behavior of GL is reinstated.
*/
void cogl_program_use (CoglHandle handle);
@ -201,29 +201,77 @@ void cogl_program_use (CoglHandle handle);
* @handle: a #CoglHandle for a shader program.
* @uniform_name: the name of a uniform.
*
* Retrieve the location (offset) of a uniform variable in a shader program, a
* uniform is a variable that is constant for all vertices/fragments for a
* Retrieve the location (offset) of a uniform variable in a shader program,
* a uniform is a variable that is constant for all vertices/fragments for a
* shader object and is possible to modify as an external parameter.
*
* Returns: the offset of a uniform in a specified program, this uniform can be
* set using #cogl_program_uniform_1f when the program is in use.
* Return value: the offset of a uniform in a specified program.
* This uniform can be set using cogl_program_uniform_1f() when the
* program is in use.
*/
COGLint cogl_program_get_uniform_location
(CoglHandle handle,
const gchar *uniform_name);
/**
* cogl_program_uniform_1f:
* @uniform_no: the unform to set.
* @value: the new value of the uniform.
*
* Changes the value of a uniform in the currently used (see #cogl_program_use)
* shader program.
* Changes the value of a uniform in the currently used (see
* cogl_program_use()) shader program.
*/
void cogl_program_uniform_1f (COGLint uniform_no,
gfloat value);
/**
* cogl_program_uniform_float:
* @uniform_no: the uniform to set.
* @size: Size of float vector.
* @count: Size of array of uniforms.
* @value: the new value of the uniform.
*
* Changes the value of a float vector uniform, or uniform array in the
* currently used (see #cogl_program_use) shader program.
*/
void cogl_program_uniform_float (COGLint uniform_no,
gint size,
gint count,
const GLfloat *value);
/**
* cogl_program_uniform_int:
* @uniform_no: the uniform to set.
* @size: Size of int vector.
* @count: Size of array of uniforms.
* @value: the new value of the uniform.
*
* Changes the value of a int vector uniform, or uniform array in the
* currently used (see cogl_program_use()) shader program.
*/
void cogl_program_uniform_int (COGLint uniform_no,
gint size,
gint count,
const COGLint *value);
/**
* cogl_program_uniform_matrix:
* @uniform_no: the uniform to set.
* @size: Size of matrix.
* @count: Size of array of uniforms.
* @transpose: Whether to transpose the matrix when setting the uniform.
* @value: the new value of the uniform.
*
* Changes the value of a matrix uniform, or uniform array in the
* currently used (see cogl_program_use()) shader program. The @size
* parameter is used to determine the square size of the matrix.
*/
void cogl_program_uniform_matrix (COGLint uniform_no,
gint size,
gint count,
gboolean transpose,
const GLfloat *value);
G_END_DECLS
#endif /* __COGL_SHADER_H__ */

View File

@ -94,6 +94,24 @@ cogl_create_context ()
_context->pf_glGetInfoLogARB = NULL;
_context->pf_glGetObjectParameterivARB = NULL;
_context->pf_glUniform1fARB = NULL;
_context->pf_glUniform2fARB = NULL;
_context->pf_glUniform3fARB = NULL;
_context->pf_glUniform4fARB = NULL;
_context->pf_glUniform1fvARB = NULL;
_context->pf_glUniform2fvARB = NULL;
_context->pf_glUniform3fvARB = NULL;
_context->pf_glUniform4fvARB = NULL;
_context->pf_glUniform1iARB = NULL;
_context->pf_glUniform2iARB = NULL;
_context->pf_glUniform3iARB = NULL;
_context->pf_glUniform4iARB = NULL;
_context->pf_glUniform1ivARB = NULL;
_context->pf_glUniform2ivARB = NULL;
_context->pf_glUniform3ivARB = NULL;
_context->pf_glUniform4ivARB = NULL;
_context->pf_glUniformMatrix2fvARB = NULL;
_context->pf_glUniformMatrix3fvARB = NULL;
_context->pf_glUniformMatrix4fvARB = NULL;
/* Init OpenGL state */
GE( glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) );

View File

@ -96,7 +96,7 @@ typedef struct
COGL_PFNGLDELETEOBJECTARBPROC pf_glDeleteObjectARB;
COGL_PFNGLGETINFOLOGARBPROC pf_glGetInfoLogARB;
COGL_PFNGLGETOBJECTPARAMETERIVARBPROC pf_glGetObjectParameterivARB;
COGL_PFNGLUNIFORM1FARBPROC pf_glUniform1fARB;
COGL_PFNGLVERTEXATTRIBPOINTERARBPROC pf_glVertexAttribPointerARB;
COGL_PFNGLENABLEVERTEXATTRIBARRAYARBPROC pf_glEnableVertexAttribArrayARB;
COGL_PFNGLDISABLEVERTEXATTRIBARRAYARBPROC pf_glDisableVertexAttribArrayARB;
@ -109,6 +109,25 @@ typedef struct
COGL_PFNGLUNMAPBUFFERARBPROC pf_glUnmapBufferARB;
COGL_PFNGLDELETEBUFFERSARBPROC pf_glDeleteBuffersARB;
COGL_PFNGLUNIFORM1FARBPROC pf_glUniform1fARB;
COGL_PFNGLUNIFORM2FARBPROC pf_glUniform2fARB;
COGL_PFNGLUNIFORM3FARBPROC pf_glUniform3fARB;
COGL_PFNGLUNIFORM4FARBPROC pf_glUniform4fARB;
COGL_PFNGLUNIFORM1FVARBPROC pf_glUniform1fvARB;
COGL_PFNGLUNIFORM2FVARBPROC pf_glUniform2fvARB;
COGL_PFNGLUNIFORM3FVARBPROC pf_glUniform3fvARB;
COGL_PFNGLUNIFORM4FVARBPROC pf_glUniform4fvARB;
COGL_PFNGLUNIFORM1IARBPROC pf_glUniform1iARB;
COGL_PFNGLUNIFORM2IARBPROC pf_glUniform2iARB;
COGL_PFNGLUNIFORM3IARBPROC pf_glUniform3iARB;
COGL_PFNGLUNIFORM4IARBPROC pf_glUniform4iARB;
COGL_PFNGLUNIFORM1IVARBPROC pf_glUniform1ivARB;
COGL_PFNGLUNIFORM2IVARBPROC pf_glUniform2ivARB;
COGL_PFNGLUNIFORM3IVARBPROC pf_glUniform3ivARB;
COGL_PFNGLUNIFORM4IVARBPROC pf_glUniform4ivARB;
COGL_PFNGLUNIFORMMATRIX2FVARBPROC pf_glUniformMatrix2fvARB;
COGL_PFNGLUNIFORMMATRIX3FVARBPROC pf_glUniformMatrix3fvARB;
COGL_PFNGLUNIFORMMATRIX4FVARBPROC pf_glUniformMatrix4fvARB;
} CoglContext;
CoglContext *

View File

@ -837,11 +837,6 @@ typedef void
GLenum pname,
GLint *params);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM1FARBPROC)
(GLint location,
GLfloat v0);
typedef void
(APIENTRYP COGL_PFNGLVERTEXATTRIBPOINTERARBPROC)
(GLuint index,
@ -897,6 +892,127 @@ typedef void
(GLsizei n,
const GLuint *buffers);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM1FARBPROC)
(GLint location,
GLfloat v0);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM2FARBPROC)
(GLint location,
GLfloat v0,
GLfloat v1);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM3FARBPROC)
(GLint location,
GLfloat v0,
GLfloat v1,
GLfloat v2);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM4FARBPROC)
(GLint location,
GLfloat v0,
GLfloat v1,
GLfloat v2,
GLfloat v3);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM1FVARBPROC)
(GLint location,
GLsizei count,
const GLfloat * value);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM2FVARBPROC)
(GLint location,
GLsizei count,
const GLfloat * value);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM3FVARBPROC)
(GLint location,
GLsizei count,
const GLfloat * value);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM4FVARBPROC)
(GLint location,
GLsizei count,
const GLfloat * value);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM1IARBPROC)
(GLint location,
GLint v0);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM2IARBPROC)
(GLint location,
GLint v0,
GLint v1);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM3IARBPROC)
(GLint location,
GLint v0,
GLint v1,
GLint v2);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM4IARBPROC)
(GLint location,
GLint v0,
GLint v1,
GLint v2,
GLint v3);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM1IVARBPROC)
(GLint location,
GLsizei count,
const GLint * value);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM2IVARBPROC)
(GLint location,
GLsizei count,
const GLint * value);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM3IVARBPROC)
(GLint location,
GLsizei count,
const GLint * value);
typedef void
(APIENTRYP COGL_PFNGLUNIFORM4IVARBPROC)
(GLint location,
GLsizei count,
const GLint * value);
typedef void
(APIENTRYP COGL_PFNGLUNIFORMMATRIX2FVARBPROC)
(GLint location,
GLsizei count,
GLboolean transpose,
const GLfloat *value);
typedef void
(APIENTRYP COGL_PFNGLUNIFORMMATRIX3FVARBPROC)
(GLint location,
GLsizei count,
GLboolean transpose,
const GLfloat *value);
typedef void
(APIENTRYP COGL_PFNGLUNIFORMMATRIX4FVARBPROC)
(GLint location,
GLsizei count,
GLboolean transpose,
const GLfloat *value);
G_END_DECLS
#endif

View File

@ -43,6 +43,24 @@
#define glLinkProgramARB ctx->pf_glLinkProgramARB
#define glGetUniformLocationARB ctx->pf_glGetUniformLocationARB
#define glUniform1fARB ctx->pf_glUniform1fARB
#define glUniform2fARB ctx->pf_glUniform2fARB
#define glUniform3fARB ctx->pf_glUniform3fARB
#define glUniform4fARB ctx->pf_glUniform4fARB
#define glUniform1fvARB ctx->pf_glUniform1fvARB
#define glUniform2fvARB ctx->pf_glUniform2fvARB
#define glUniform3fvARB ctx->pf_glUniform3fvARB
#define glUniform4fvARB ctx->pf_glUniform4fvARB
#define glUniform1iARB ctx->pf_glUniform1iARB
#define glUniform2iARB ctx->pf_glUniform2iARB
#define glUniform3iARB ctx->pf_glUniform3iARB
#define glUniform4iARB ctx->pf_glUniform4iARB
#define glUniform1ivARB ctx->pf_glUniform1ivARB
#define glUniform2ivARB ctx->pf_glUniform2ivARB
#define glUniform3ivARB ctx->pf_glUniform3ivARB
#define glUniform4ivARB ctx->pf_glUniform4ivARB
#define glUniformMatrix2fvARB ctx->pf_glUniformMatrix2fvARB
#define glUniformMatrix3fvARB ctx->pf_glUniformMatrix3fvARB
#define glUniformMatrix4fvARB ctx->pf_glUniformMatrix4fvARB
#define glDeleteObjectARB ctx->pf_glDeleteObjectARB
static void _cogl_program_free (CoglProgram *program);
@ -148,3 +166,82 @@ cogl_program_uniform_1f (COGLint uniform_no,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
glUniform1fARB (uniform_no, value);
}
void
cogl_program_uniform_float (COGLint uniform_no,
gint size,
gint count,
const GLfloat *value)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
switch (size)
{
case 1:
glUniform1fvARB (uniform_no, count, value);
break;
case 2:
glUniform2fvARB (uniform_no, count, value);
break;
case 3:
glUniform3fvARB (uniform_no, count, value);
break;
case 4:
glUniform4fvARB (uniform_no, count, value);
break;
default:
g_warning ("%s called with invalid size parameter", G_STRFUNC);
}
}
void
cogl_program_uniform_int (COGLint uniform_no,
gint size,
gint count,
const COGLint *value)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
switch (size)
{
case 1:
glUniform1ivARB (uniform_no, count, value);
break;
case 2:
glUniform2ivARB (uniform_no, count, value);
break;
case 3:
glUniform3ivARB (uniform_no, count, value);
break;
case 4:
glUniform4ivARB (uniform_no, count, value);
break;
default:
g_warning ("%s called with invalid size parameter", G_STRFUNC);
}
}
void
cogl_program_uniform_matrix (COGLint uniform_no,
gint size,
gint count,
gboolean transpose,
const GLfloat *value)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
switch (size)
{
case 2 :
glUniformMatrix2fvARB (uniform_no, count, transpose, value);
break;
case 3 :
glUniformMatrix3fvARB (uniform_no, count, transpose, value);
break;
case 4 :
glUniformMatrix4fvARB (uniform_no, count, transpose, value);
break;
default :
g_warning ("%s called with invalid size parameter", G_STRFUNC);
}
}

View File

@ -1028,6 +1028,78 @@ _cogl_features_init ()
(COGL_PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)
cogl_get_proc_address ("glDisableVertexAttribArrayARB");
ctx->pf_glUniform2fARB =
(COGL_PFNGLUNIFORM2FARBPROC)
cogl_get_proc_address ("glUniform2fARB");
ctx->pf_glUniform3fARB =
(COGL_PFNGLUNIFORM3FARBPROC)
cogl_get_proc_address ("glUniform3fARB");
ctx->pf_glUniform4fARB =
(COGL_PFNGLUNIFORM4FARBPROC)
cogl_get_proc_address ("glUniform4fARB");
ctx->pf_glUniform1fvARB =
(COGL_PFNGLUNIFORM1FVARBPROC)
cogl_get_proc_address ("glUniform1fvARB");
ctx->pf_glUniform2fvARB =
(COGL_PFNGLUNIFORM2FVARBPROC)
cogl_get_proc_address ("glUniform2fvARB");
ctx->pf_glUniform3fvARB =
(COGL_PFNGLUNIFORM3FVARBPROC)
cogl_get_proc_address ("glUniform3fvARB");
ctx->pf_glUniform4fvARB =
(COGL_PFNGLUNIFORM4FVARBPROC)
cogl_get_proc_address ("glUniform4fvARB");
ctx->pf_glUniform1iARB =
(COGL_PFNGLUNIFORM1IARBPROC)
cogl_get_proc_address ("glUniform1iARB");
ctx->pf_glUniform2iARB =
(COGL_PFNGLUNIFORM2IARBPROC)
cogl_get_proc_address ("glUniform2iARB");
ctx->pf_glUniform3iARB =
(COGL_PFNGLUNIFORM3IARBPROC)
cogl_get_proc_address ("glUniform3iARB");
ctx->pf_glUniform4iARB =
(COGL_PFNGLUNIFORM4IARBPROC)
cogl_get_proc_address ("glUniform4iARB");
ctx->pf_glUniform1ivARB =
(COGL_PFNGLUNIFORM1IVARBPROC)
cogl_get_proc_address ("glUniform1ivARB");
ctx->pf_glUniform2ivARB =
(COGL_PFNGLUNIFORM2IVARBPROC)
cogl_get_proc_address ("glUniform2ivARB");
ctx->pf_glUniform3ivARB =
(COGL_PFNGLUNIFORM3IVARBPROC)
cogl_get_proc_address ("glUniform3ivARB");
ctx->pf_glUniform4ivARB =
(COGL_PFNGLUNIFORM4IVARBPROC)
cogl_get_proc_address ("glUniform4ivARB");
ctx->pf_glUniformMatrix2fvARB =
(COGL_PFNGLUNIFORMMATRIX2FVARBPROC)
cogl_get_proc_address ("glUniformMatrix2fvARB");
ctx->pf_glUniformMatrix3fvARB =
(COGL_PFNGLUNIFORMMATRIX3FVARBPROC)
cogl_get_proc_address ("glUniformMatrix3fvARB");
ctx->pf_glUniformMatrix4fvARB =
(COGL_PFNGLUNIFORMMATRIX4FVARBPROC)
cogl_get_proc_address ("glUniformMatrix4fvARB");
if (ctx->pf_glCreateProgramObjectARB &&
ctx->pf_glCreateShaderObjectARB &&
ctx->pf_glShaderSourceARB &&
@ -1040,13 +1112,30 @@ _cogl_features_init ()
ctx->pf_glGetInfoLogARB &&
ctx->pf_glGetObjectParameterivARB &&
ctx->pf_glUniform1fARB &&
ctx->pf_glUniform2fARB &&
ctx->pf_glUniform3fARB &&
ctx->pf_glUniform4fARB &&
ctx->pf_glUniform1fvARB &&
ctx->pf_glUniform2fvARB &&
ctx->pf_glUniform3fvARB &&
ctx->pf_glUniform4fvARB &&
ctx->pf_glUniform1iARB &&
ctx->pf_glUniform2iARB &&
ctx->pf_glUniform3iARB &&
ctx->pf_glUniform4iARB &&
ctx->pf_glUniform1ivARB &&
ctx->pf_glUniform2ivARB &&
ctx->pf_glUniform3ivARB &&
ctx->pf_glUniform4ivARB &&
ctx->pf_glUniformMatrix2fvARB &&
ctx->pf_glUniformMatrix3fvARB &&
ctx->pf_glUniformMatrix4fvARB &&
ctx->pf_glVertexAttribPointerARB &&
ctx->pf_glEnableVertexAttribArrayARB &&
ctx->pf_glDisableVertexAttribArrayARB)
flags |= COGL_FEATURE_SHADERS_GLSL;
}
if (cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions) ||
cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions))
{

View File

@ -462,6 +462,7 @@ void
cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper)
{
GSList *node, *next;
int i;
for (node = wrapper->compiled_programs; node; node = next)
{
@ -486,6 +487,10 @@ cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper)
g_slist_free1 (node);
}
wrapper->compiled_fragment_shaders = NULL;
for (i = 0; i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++)
if (wrapper->custom_uniforms[i].count > 1)
g_free (wrapper->custom_uniforms[i].v.array);
}
void
@ -814,6 +819,78 @@ cogl_wrap_glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer)
GL_FALSE, stride, pointer);
}
static void
cogl_gles2_do_set_uniform (GLint location, CoglBoxedValue *value)
{
switch (value->type)
{
case COGL_BOXED_NONE:
break;
case COGL_BOXED_INT:
{
gint *ptr;
if (value->count == 1)
ptr = value->v.int_value;
else
ptr = value->v.int_array;
switch (value->size)
{
case 1: glUniform1iv (location, value->count, ptr); break;
case 2: glUniform2iv (location, value->count, ptr); break;
case 3: glUniform3iv (location, value->count, ptr); break;
case 4: glUniform4iv (location, value->count, ptr); break;
}
}
break;
case COGL_BOXED_FLOAT:
{
gfloat *ptr;
if (value->count == 1)
ptr = value->v.float_value;
else
ptr = value->v.float_array;
switch (value->size)
{
case 1: glUniform1fv (location, value->count, ptr); break;
case 2: glUniform2fv (location, value->count, ptr); break;
case 3: glUniform3fv (location, value->count, ptr); break;
case 4: glUniform4fv (location, value->count, ptr); break;
}
}
break;
case COGL_BOXED_MATRIX:
{
gfloat *ptr;
if (value->count == 1)
ptr = value->v.matrix;
else
ptr = value->v.float_array;
switch (value->size)
{
case 2:
glUniformMatrix2fv (location, value->count, value->transpose, ptr);
break;
case 3:
glUniformMatrix3fv (location, value->count, value->transpose, ptr);
break;
case 4:
glUniformMatrix4fv (location, value->count, value->transpose, ptr);
break;
}
}
break;
}
}
void
cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count)
{
@ -914,8 +991,8 @@ cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count)
program->custom_uniforms[i]
= glGetUniformLocation (program->program, uniform_name);
if (program->custom_uniforms[i] >= 0)
glUniform1f (program->custom_uniforms[i],
w->custom_uniforms[i]);
cogl_gles2_do_set_uniform (program->custom_uniforms[i],
&w->custom_uniforms[i]);
}
}

View File

@ -26,6 +26,8 @@
#ifndef __COGL_GLES2_WRAPPER_H__
#define __COGL_GLES2_WRAPPER_H__
#include "cogl-internal.h"
G_BEGIN_DECLS
#ifdef HAVE_COGL_GLES2
@ -131,7 +133,7 @@ struct _CoglGles2Wrapper
GLfloat fog_start;
GLfloat fog_end;
GLfloat fog_color[4];
GLfloat custom_uniforms[COGL_GLES2_NUM_CUSTOM_UNIFORMS];
CoglBoxedValue custom_uniforms[COGL_GLES2_NUM_CUSTOM_UNIFORMS];
};
struct _CoglGles2WrapperProgram

View File

@ -26,6 +26,30 @@
#ifndef __COGL_INTERNAL_H
#define __COGL_INTERNAL_H
typedef enum {
COGL_BOXED_NONE,
COGL_BOXED_INT,
COGL_BOXED_FLOAT,
COGL_BOXED_MATRIX
} CoglBoxedType;
typedef struct _CoglBoxedValue
{
CoglBoxedType type;
int size, count;
gboolean transpose;
union {
gfloat float_value[4];
gint int_value[4];
gfloat matrix[16];
gfloat *float_array;
gint *int_array;
gpointer array;
} v;
} CoglBoxedValue;
#define COGL_DEBUG 0
#if COGL_DEBUG

View File

@ -162,16 +162,95 @@ cogl_program_get_uniform_location (CoglHandle handle,
void
cogl_program_uniform_1f (COGLint uniform_no,
gfloat value)
{
cogl_program_uniform_float (uniform_no, 1, 1, &value);
}
static void
cogl_program_uniform_x (COGLint uniform_no,
gint size,
gint count,
CoglBoxedType type,
size_t value_size,
gconstpointer value)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (uniform_no >= 0 && uniform_no < COGL_GLES2_NUM_CUSTOM_UNIFORMS)
if (uniform_no >= 0 && uniform_no < COGL_GLES2_NUM_CUSTOM_UNIFORMS
&& size >= 1 && size <= 4 && count >= 1)
{
ctx->gles2.custom_uniforms[uniform_no] = value;
CoglBoxedValue *bv = ctx->gles2.custom_uniforms + uniform_no;
if (count == 1)
{
if (bv->count > 1)
g_free (bv->v.array);
memcpy (bv->v.float_value, value, value_size);
}
else
{
if (bv->count > 1)
{
if (bv->count != count || bv->size != size || bv->type != type)
{
g_free (bv->v.array);
bv->v.array = g_malloc (count * value_size);
}
}
else
bv->v.array = g_malloc (count * value_size);
memcpy (bv->v.array, value, count * value_size);
}
bv->type = type;
bv->size = size;
bv->count = count;
ctx->gles2.dirty_custom_uniforms |= 1 << uniform_no;
}
}
void
cogl_program_uniform_float (COGLint uniform_no,
gint size,
gint count,
const GLfloat *value)
{
cogl_program_uniform_x (uniform_no, size, count, COGL_BOXED_FLOAT,
sizeof (float) * size, value);
}
void
cogl_program_uniform_int (COGLint uniform_no,
gint size,
gint count,
const GLint *value)
{
cogl_program_uniform_x (uniform_no, size, count, COGL_BOXED_INT,
sizeof (gint) * size, value);
}
void
cogl_program_uniform_matrix (COGLint uniform_no,
gint size,
gint count,
gboolean transpose,
const GLfloat *value)
{
CoglBoxedValue *bv;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
bv = ctx->gles2.custom_uniforms + uniform_no;
cogl_program_uniform_x (uniform_no, size, count, COGL_BOXED_MATRIX,
sizeof (float) * size * size, value);
bv->transpose = transpose;
}
#else /* HAVE_COGL_GLES2 */
/* No support on regular OpenGL 1.1 */
@ -228,4 +307,30 @@ cogl_program_uniform_1f (COGLint uniform_no,
{
}
void
cogl_program_uniform_float (COGLint uniform_no,
gint size,
gint count,
const GLfloat *value)
{
}
void
cogl_program_uniform_int (COGLint uniform_no,
gint size,
gint count,
const COGLint *value)
{
}
void
cogl_program_uniform_matrix (COGLint uniform_no,
gint size,
gint count,
gboolean transpose,
const GLfloat *value)
{
}
#endif /* HAVE_COGL_GLES2 */

View File

@ -1503,6 +1503,10 @@ clutter_shader_is_compiled
clutter_shader_set_is_enabled
clutter_shader_get_is_enabled
clutter_shader_set_uniform_1f
clutter_shader_set_uniform
clutter_shader_get_cogl_program
clutter_shader_get_cogl_fragment_shader
clutter_shader_get_cogl_vertex_shader
<SUBSECTION Standard>
CLUTTER_IS_SHADER

View File

@ -138,6 +138,9 @@ cogl_program_link
cogl_program_use
cogl_program_get_uniform_location
cogl_program_uniform_1f
cogl_program_uniform_float
cogl_program_uniform_int
cogl_program_uniform_matrix
</SECTION>
<SECTION>

View File

@ -142,10 +142,10 @@ test_fbo_main (gint argc, gchar *argv[])
/* apply a shader to it */
shader = make_shader();
clutter_actor_set_shader (fbo, shader);
clutter_actor_set_shader_param (fbo, "radius", 2.0);
clutter_actor_set_shader_param (fbo, "x_step",
clutter_actor_set_shader_param_float (fbo, "radius", 2.0);
clutter_actor_set_shader_param_float (fbo, "x_step",
1.0f / clutter_util_next_p2 (fbo_width));
clutter_actor_set_shader_param (fbo, "y_step",
clutter_actor_set_shader_param_float (fbo, "y_step",
1.0f / clutter_util_next_p2 (fbo_height));
/* Third from cloning the fbo texture */

View File

@ -238,9 +238,10 @@ set_shader_num (ClutterActor *actor, gint new_no)
{
clutter_actor_set_shader (actor, NULL);
clutter_actor_set_shader (actor, shader);
clutter_actor_set_shader_param (actor, "radius", 3.0);
clutter_actor_set_shader_param (actor, "brightness", 0.4);
clutter_actor_set_shader_param (actor, "contrast", -1.9);
clutter_actor_set_shader_param_int (actor, "tex", 0);
clutter_actor_set_shader_param_float (actor, "radius", 3.0);
clutter_actor_set_shader_param_float (actor, "brightness", 0.4);
clutter_actor_set_shader_param_float (actor, "contrast", -1.9);
if (CLUTTER_IS_TEXTURE (actor))
{
@ -249,9 +250,9 @@ set_shader_num (ClutterActor *actor, gint new_no)
tex_height = clutter_actor_get_height (actor);
tex_height = clutter_util_next_p2 (tex_height);
clutter_actor_set_shader_param (actor, "x_step",
clutter_actor_set_shader_param_float (actor, "x_step",
1.0f / tex_width);
clutter_actor_set_shader_param (actor, "y_step",
clutter_actor_set_shader_param_float (actor, "y_step",
1.0f / tex_height);
}
}
@ -376,9 +377,9 @@ test_shader_main (gint argc, gchar *argv[])
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
clutter_actor_set_shader_param (actor, "brightness", 0.4);
clutter_actor_set_shader_param (actor, "contrast", -1.9);
clutter_actor_set_shader_param_int (actor, "tex", 0);
clutter_actor_set_shader_param_float (actor, "brightness", 0.4);
clutter_actor_set_shader_param_float (actor, "contrast", -1.9);
clutter_actor_set_reactive (actor, TRUE);
g_signal_connect (actor, "button-release-event",