mirror of
https://github.com/brl/mutter.git
synced 2025-01-03 16:22:15 +00:00
Support for shaders in clutter. At the moment limited to drivers
providing GLSL support. * clutter/cogl/cogl.h: added rather direct binding of needed for glsl shaders. * clutter/cogl/gl/cogl-defines.h.in: * clutter/cogl/gl/cogl.c: * clutter/cogl/gles/cogl-defines.h: added stubs. * clutter/cogl/gles/cogl.c: added stubs. * clutter/glx/clutter-stage-glx.c: (clutter_stage_glx_realize): unrelated memory management sanity fix. (clutter_stage_glx_unrealize): unbind all shaders on stage unrealize. * clutter/Makefile.am: added clutter-shader.[ch] * clutter/clutter-actor.[ch]: adding shader capability to actors. * clutter/clutter-feature.h: added CLUTTER_FEATURE_SHADERS_GLSL * clutter/clutter-private.h: added stack of shaders to context. * clutter/clutter-shader.[ch]: new. * tests/Makefile.am: added shader test. * tests/test-shader.c: (frame_cb), (main): simple shader test, cycle through the inline shader with right/left mouse buttons.
This commit is contained in:
parent
ace69e71b3
commit
e92b864dff
27
ChangeLog
27
ChangeLog
@ -1,3 +1,30 @@
|
|||||||
|
2007-12-03 Øyvind Kolås <pippin@o-hand.com>
|
||||||
|
|
||||||
|
Support for shaders in clutter. At the moment limited to drivers
|
||||||
|
providing GLSL support.
|
||||||
|
|
||||||
|
* clutter/cogl/cogl.h: added rather direct binding of needed for glsl
|
||||||
|
shaders.
|
||||||
|
* clutter/cogl/gl/cogl-defines.h.in:
|
||||||
|
* clutter/cogl/gl/cogl.c:
|
||||||
|
* clutter/cogl/gles/cogl-defines.h: added stubs.
|
||||||
|
* clutter/cogl/gles/cogl.c: added stubs.
|
||||||
|
|
||||||
|
* clutter/glx/clutter-stage-glx.c:
|
||||||
|
(clutter_stage_glx_realize): unrelated memory management sanity fix.
|
||||||
|
(clutter_stage_glx_unrealize): unbind all shaders on stage unrealize.
|
||||||
|
|
||||||
|
* clutter/Makefile.am: added clutter-shader.[ch]
|
||||||
|
* clutter/clutter-actor.[ch]: adding shader capability to
|
||||||
|
actors.
|
||||||
|
* clutter/clutter-feature.h: added CLUTTER_FEATURE_SHADERS_GLSL
|
||||||
|
* clutter/clutter-private.h: added stack of shaders to context.
|
||||||
|
* clutter/clutter-shader.[ch]: new.
|
||||||
|
|
||||||
|
* tests/Makefile.am: added shader test.
|
||||||
|
* tests/test-shader.c: (frame_cb), (main): simple shader test,
|
||||||
|
cycle through the inline shader with right/left mouse buttons.
|
||||||
|
|
||||||
2007-12-03 Øyvind Kolås <pippin@o-hand.com>
|
2007-12-03 Øyvind Kolås <pippin@o-hand.com>
|
||||||
|
|
||||||
* clutter/glx/clutter-stage-glx.c: for extra sanity, set
|
* clutter/glx/clutter-stage-glx.c: for extra sanity, set
|
||||||
|
@ -69,6 +69,7 @@ source_h = \
|
|||||||
$(srcdir)/clutter-score.h \
|
$(srcdir)/clutter-score.h \
|
||||||
$(srcdir)/clutter-script.h \
|
$(srcdir)/clutter-script.h \
|
||||||
$(srcdir)/clutter-scriptable.h \
|
$(srcdir)/clutter-scriptable.h \
|
||||||
|
$(srcdir)/clutter-shader.h \
|
||||||
$(srcdir)/clutter-stage.h \
|
$(srcdir)/clutter-stage.h \
|
||||||
$(srcdir)/clutter-texture.h \
|
$(srcdir)/clutter-texture.h \
|
||||||
$(srcdir)/clutter-timeline.h \
|
$(srcdir)/clutter-timeline.h \
|
||||||
@ -153,6 +154,7 @@ source_c = \
|
|||||||
clutter-script.c \
|
clutter-script.c \
|
||||||
clutter-script-parser.c \
|
clutter-script-parser.c \
|
||||||
clutter-scriptable.c \
|
clutter-scriptable.c \
|
||||||
|
clutter-shader.c \
|
||||||
clutter-stage.c \
|
clutter-stage.c \
|
||||||
clutter-texture.c \
|
clutter-texture.c \
|
||||||
clutter-timeline.c \
|
clutter-timeline.c \
|
||||||
|
@ -156,6 +156,8 @@ static guint32 __id = 0;
|
|||||||
#define CLUTTER_ACTOR_GET_PRIVATE(obj) \
|
#define CLUTTER_ACTOR_GET_PRIVATE(obj) \
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_ACTOR, ClutterActorPrivate))
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_ACTOR, ClutterActorPrivate))
|
||||||
|
|
||||||
|
typedef struct _ShaderData ShaderData;
|
||||||
|
|
||||||
struct _ClutterActorPrivate
|
struct _ClutterActorPrivate
|
||||||
{
|
{
|
||||||
ClutterActorBox coords;
|
ClutterActorBox coords;
|
||||||
@ -170,6 +172,8 @@ struct _ClutterActorPrivate
|
|||||||
gchar *name;
|
gchar *name;
|
||||||
ClutterFixed scale_x, scale_y;
|
ClutterFixed scale_x, scale_y;
|
||||||
guint32 id; /* Unique ID */
|
guint32 id; /* Unique ID */
|
||||||
|
|
||||||
|
ShaderData *shader_data;
|
||||||
ClutterUnit anchor_x, anchor_y;
|
ClutterUnit anchor_x, anchor_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -221,6 +225,11 @@ static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
|
|||||||
static void _clutter_actor_apply_modelview_transform (ClutterActor *self);
|
static void _clutter_actor_apply_modelview_transform (ClutterActor *self);
|
||||||
static void _clutter_actor_apply_modelview_transform_recursive (ClutterActor *self);
|
static void _clutter_actor_apply_modelview_transform_recursive (ClutterActor *self);
|
||||||
|
|
||||||
|
static void clutter_actor_shader_pre_paint (ClutterActor *actor,
|
||||||
|
gboolean repeat);
|
||||||
|
static void clutter_actor_shader_post_paint (ClutterActor *actor);
|
||||||
|
static void destroy_shader_data (ClutterActor *self);
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterActor,
|
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterActor,
|
||||||
clutter_actor,
|
clutter_actor,
|
||||||
G_TYPE_INITIALLY_UNOWNED,
|
G_TYPE_INITIALLY_UNOWNED,
|
||||||
@ -907,8 +916,10 @@ clutter_actor_paint (ClutterActor *self)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
clutter_actor_shader_pre_paint (self, FALSE);
|
||||||
if (G_LIKELY(klass->paint))
|
if (G_LIKELY(klass->paint))
|
||||||
(klass->paint) (self);
|
(klass->paint) (self);
|
||||||
|
clutter_actor_shader_post_paint (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->has_clip)
|
if (priv->has_clip)
|
||||||
@ -1175,6 +1186,8 @@ clutter_actor_dispose (GObject *object)
|
|||||||
g_type_name (G_OBJECT_TYPE (self)),
|
g_type_name (G_OBJECT_TYPE (self)),
|
||||||
object->ref_count);
|
object->ref_count);
|
||||||
|
|
||||||
|
destroy_shader_data (self);
|
||||||
|
|
||||||
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_DESTRUCTION))
|
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_DESTRUCTION))
|
||||||
{
|
{
|
||||||
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_DESTRUCTION);
|
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_IN_DESTRUCTION);
|
||||||
@ -1730,6 +1743,7 @@ clutter_actor_init (ClutterActor *self)
|
|||||||
priv->id = __id++;
|
priv->id = __id++;
|
||||||
priv->scale_x = CFX_ONE;
|
priv->scale_x = CFX_ONE;
|
||||||
priv->scale_y = CFX_ONE;
|
priv->scale_y = CFX_ONE;
|
||||||
|
priv->shader_data = NULL;
|
||||||
|
|
||||||
clutter_actor_request_coords (self, &box);
|
clutter_actor_request_coords (self, &box);
|
||||||
}
|
}
|
||||||
@ -4036,3 +4050,175 @@ clutter_actor_box_get_type (void)
|
|||||||
(GBoxedFreeFunc) clutter_actor_box_free);
|
(GBoxedFreeFunc) clutter_actor_box_free);
|
||||||
return our_type;
|
return our_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
typedef struct _BoxedFloat BoxedFloat;
|
||||||
|
struct _BoxedFloat
|
||||||
|
{
|
||||||
|
gfloat value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ShaderData
|
||||||
|
{
|
||||||
|
ClutterShader *shader;
|
||||||
|
GHashTable *float1f_hash; /*< list of values that should be set
|
||||||
|
* on the shader before each paint cycle
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_shader_data (ClutterActor *self)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *actor_priv = self->priv;
|
||||||
|
ShaderData *shader_data = actor_priv->shader_data;
|
||||||
|
|
||||||
|
if (!shader_data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (shader_data->shader)
|
||||||
|
{
|
||||||
|
g_object_unref (shader_data->shader);
|
||||||
|
}
|
||||||
|
shader_data->shader = NULL;
|
||||||
|
if (shader_data->float1f_hash)
|
||||||
|
{
|
||||||
|
g_hash_table_destroy (shader_data->float1f_hash);
|
||||||
|
shader_data->float1f_hash = NULL;
|
||||||
|
}
|
||||||
|
g_free (shader_data);
|
||||||
|
actor_priv->shader_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean clutter_actor_apply_shader (ClutterActor *self,
|
||||||
|
ClutterShader *shader)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *actor_priv;
|
||||||
|
ShaderData *shader_data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
||||||
|
|
||||||
|
actor_priv = self->priv;
|
||||||
|
shader_data = actor_priv->shader_data;
|
||||||
|
|
||||||
|
if (shader_data == NULL)
|
||||||
|
{
|
||||||
|
actor_priv->shader_data = shader_data = g_new0 (ShaderData, 1);
|
||||||
|
shader_data->float1f_hash = g_hash_table_new_full (
|
||||||
|
g_str_hash, g_str_equal,
|
||||||
|
g_free, g_free);
|
||||||
|
}
|
||||||
|
if (shader_data->shader)
|
||||||
|
{
|
||||||
|
g_object_unref (shader_data->shader);
|
||||||
|
}
|
||||||
|
if (shader)
|
||||||
|
{
|
||||||
|
shader_data->shader = g_object_ref (shader);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shader_data->shader = NULL;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
each_param (gpointer key,
|
||||||
|
gpointer value,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
ClutterShader *shader = CLUTTER_SHADER (user_data);
|
||||||
|
BoxedFloat *box = value;
|
||||||
|
clutter_shader_set_uniform_1f (shader, key, box->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_actor_shader_pre_paint (ClutterActor *actor,
|
||||||
|
gboolean repeat)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *actor_priv;
|
||||||
|
ShaderData *shader_data;
|
||||||
|
ClutterShader *shader;
|
||||||
|
ClutterMainContext *context;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||||
|
|
||||||
|
actor_priv = actor->priv;
|
||||||
|
shader_data = actor_priv->shader_data;
|
||||||
|
|
||||||
|
if (!shader_data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
context = clutter_context_get_default ();
|
||||||
|
shader = shader_data->shader;
|
||||||
|
|
||||||
|
if (shader)
|
||||||
|
{
|
||||||
|
clutter_shader_enable (shader);
|
||||||
|
|
||||||
|
g_hash_table_foreach (shader_data->float1f_hash, each_param, shader);
|
||||||
|
|
||||||
|
if (!repeat)
|
||||||
|
{
|
||||||
|
context->shaders = g_slist_prepend (context->shaders, actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_actor_shader_post_paint (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *actor_priv;
|
||||||
|
ShaderData *shader_data;
|
||||||
|
ClutterShader *shader;
|
||||||
|
ClutterMainContext *context;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||||
|
|
||||||
|
actor_priv = actor->priv;
|
||||||
|
shader_data = actor_priv->shader_data;
|
||||||
|
|
||||||
|
if (!shader_data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
context = clutter_context_get_default ();
|
||||||
|
shader = shader_data->shader;
|
||||||
|
|
||||||
|
if (shader)
|
||||||
|
{
|
||||||
|
clutter_shader_disable (shader);
|
||||||
|
|
||||||
|
context->shaders = g_slist_remove (context->shaders, actor);
|
||||||
|
if (context->shaders)
|
||||||
|
{
|
||||||
|
/* call pre-paint again, this time with the second argument being
|
||||||
|
* TRUE, indicating that we are reapplying the shader and thus
|
||||||
|
* should not be prepended to the stack
|
||||||
|
*/
|
||||||
|
clutter_actor_shader_pre_paint (context->shaders->data, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_actor_set_shader_param (ClutterActor *actor,
|
||||||
|
const gchar *param,
|
||||||
|
gfloat value)
|
||||||
|
{
|
||||||
|
ClutterActorPrivate *actor_priv;
|
||||||
|
ShaderData *shader_data;
|
||||||
|
BoxedFloat *box;
|
||||||
|
|
||||||
|
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||||
|
|
||||||
|
actor_priv = actor->priv;
|
||||||
|
shader_data = actor_priv->shader_data;
|
||||||
|
|
||||||
|
if (!shader_data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
box = g_malloc (sizeof (BoxedFloat));
|
||||||
|
box->value = value;
|
||||||
|
g_hash_table_insert (shader_data->float1f_hash, g_strdup (param), box);
|
||||||
|
}
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <clutter/clutter-types.h>
|
#include <clutter/clutter-types.h>
|
||||||
#include <clutter/clutter-units.h>
|
#include <clutter/clutter-units.h>
|
||||||
#include <clutter/clutter-event.h>
|
#include <clutter/clutter-event.h>
|
||||||
|
#include <clutter/clutter-shader.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -216,9 +217,10 @@ struct _ClutterActorClass
|
|||||||
void (* focus_in) (ClutterActor *actor);
|
void (* focus_in) (ClutterActor *actor);
|
||||||
void (* focus_out) (ClutterActor *actor);
|
void (* focus_out) (ClutterActor *actor);
|
||||||
|
|
||||||
|
gboolean shadable;
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
/* padding for future expansion */
|
/* padding for future expansion */
|
||||||
gpointer _padding_dummy[32];
|
gpointer _padding_dummy[31];
|
||||||
};
|
};
|
||||||
|
|
||||||
GType clutter_actor_get_type (void) G_GNUC_CONST;
|
GType clutter_actor_get_type (void) G_GNUC_CONST;
|
||||||
@ -390,6 +392,14 @@ ClutterActor * clutter_get_actor_by_gid (guint32 id);
|
|||||||
|
|
||||||
gboolean clutter_actor_should_pick_paint (ClutterActor *self);
|
gboolean clutter_actor_should_pick_paint (ClutterActor *self);
|
||||||
|
|
||||||
|
gboolean clutter_actor_apply_shader (ClutterActor *self,
|
||||||
|
ClutterShader *shader);
|
||||||
|
|
||||||
|
void clutter_actor_set_shader_param (ClutterActor *self,
|
||||||
|
const gchar *param,
|
||||||
|
gfloat value);
|
||||||
|
|
||||||
|
|
||||||
void clutter_actor_set_anchor_point (ClutterActor *self,
|
void clutter_actor_set_anchor_point (ClutterActor *self,
|
||||||
gint anchor_x,
|
gint anchor_x,
|
||||||
gint anchor_y);
|
gint anchor_y);
|
||||||
|
@ -46,6 +46,7 @@ G_BEGIN_DECLS
|
|||||||
* @CLUTTER_FEATURE_STAGE_STATIC: Set if stage size if fixed (i.e framebuffer)
|
* @CLUTTER_FEATURE_STAGE_STATIC: Set if stage size if fixed (i.e framebuffer)
|
||||||
* @CLUTTER_FEATURE_STAGE_USER_RESIZE: Set if stage is able to be user resized.
|
* @CLUTTER_FEATURE_STAGE_USER_RESIZE: Set if stage is able to be user resized.
|
||||||
* @CLUTTER_FEATURE_STAGE_CURSOR: Set if stage has a graphical cursor.
|
* @CLUTTER_FEATURE_STAGE_CURSOR: Set if stage has a graphical cursor.
|
||||||
|
* @CLUTTER_FEATURE_SHADER_GLSL: Set if the backend supports GLSL shaders.
|
||||||
*
|
*
|
||||||
* Runtime flags indicating specific features available via Clutter window
|
* Runtime flags indicating specific features available via Clutter window
|
||||||
* sysytem and graphics backend.
|
* sysytem and graphics backend.
|
||||||
@ -60,7 +61,8 @@ typedef enum
|
|||||||
CLUTTER_FEATURE_TEXTURE_READ_PIXELS = (1 << 4),
|
CLUTTER_FEATURE_TEXTURE_READ_PIXELS = (1 << 4),
|
||||||
CLUTTER_FEATURE_STAGE_STATIC = (1 << 5),
|
CLUTTER_FEATURE_STAGE_STATIC = (1 << 5),
|
||||||
CLUTTER_FEATURE_STAGE_USER_RESIZE = (1 << 6),
|
CLUTTER_FEATURE_STAGE_USER_RESIZE = (1 << 6),
|
||||||
CLUTTER_FEATURE_STAGE_CURSOR = (1 << 7)
|
CLUTTER_FEATURE_STAGE_CURSOR = (1 << 7),
|
||||||
|
CLUTTER_FEATURE_SHADERS_GLSL = (1 << 8)
|
||||||
} ClutterFeatureFlags;
|
} ClutterFeatureFlags;
|
||||||
|
|
||||||
gboolean clutter_feature_available (ClutterFeatureFlags feature);
|
gboolean clutter_feature_available (ClutterFeatureFlags feature);
|
||||||
|
@ -93,6 +93,7 @@ struct _ClutterMainContext
|
|||||||
ClutterActor *keyboard_grab_actor; /* The actor having the pointer grab
|
ClutterActor *keyboard_grab_actor; /* The actor having the pointer grab
|
||||||
(or NULL if there is no pointer grab)
|
(or NULL if there is no pointer grab)
|
||||||
*/
|
*/
|
||||||
|
GSList *shaders; /* stack of overridden shaders */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLUTTER_CONTEXT() (clutter_context_get_default ())
|
#define CLUTTER_CONTEXT() (clutter_context_get_default ())
|
||||||
|
433
clutter/clutter-shader.c
Normal file
433
clutter/clutter-shader.c
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
* Øyvind Kolås <pippin@o-hand.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "clutter.h"
|
||||||
|
#include "clutter-private.h"
|
||||||
|
#include "clutter-shader.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define CLUTTER_SHADER_GET_PRIVATE(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
|
||||||
|
CLUTTER_TYPE_SHADER, ClutterShaderPrivate))
|
||||||
|
|
||||||
|
static GList *shader_list;
|
||||||
|
|
||||||
|
static void clutter_shader_class_init (ClutterShaderClass *klass);
|
||||||
|
static void clutter_shader_init (ClutterShader *sp);
|
||||||
|
static void clutter_shader_finalize (GObject *object);
|
||||||
|
static GObject *clutter_shader_constructor (GType type,
|
||||||
|
guint n_params,
|
||||||
|
GObjectConstructParam *params);
|
||||||
|
static void clutter_shader_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
static void clutter_shader_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
|
||||||
|
struct _ClutterShaderPrivate
|
||||||
|
{
|
||||||
|
gboolean glsl; /* The shader is a GLSL shader */
|
||||||
|
gboolean bound; /* The shader is bound to the GL context */
|
||||||
|
|
||||||
|
gchar *vertex_shader_source; /* source (or asm) for vertex shader */
|
||||||
|
gchar *fragment_shader_source;/* source (or asm) for fragment shader*/
|
||||||
|
|
||||||
|
GLhandleARB program;
|
||||||
|
|
||||||
|
GLhandleARB vertex_shader;
|
||||||
|
GLhandleARB fragment_shader;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_VERTEX_SOURCE,
|
||||||
|
PROP_FRAGMENT_SOURCE
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ClutterShader, clutter_shader, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_shader_class_init (ClutterShaderClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
clutter_shader_parent_class = g_type_class_peek_parent (klass);
|
||||||
|
object_class->finalize = clutter_shader_finalize;
|
||||||
|
object_class->set_property = clutter_shader_set_property;
|
||||||
|
object_class->get_property = clutter_shader_get_property;
|
||||||
|
object_class->constructor = clutter_shader_constructor;
|
||||||
|
g_type_class_add_private (klass, sizeof (ClutterShaderPrivate));
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_VERTEX_SOURCE,
|
||||||
|
g_param_spec_string ("vertex-source",
|
||||||
|
"Vertex Source",
|
||||||
|
"Source of vertex shader",
|
||||||
|
NULL,
|
||||||
|
CLUTTER_PARAM_READWRITE|
|
||||||
|
G_PARAM_CONSTRUCT_ONLY));
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_FRAGMENT_SOURCE,
|
||||||
|
g_param_spec_string ("fragment-source",
|
||||||
|
"Fragment Source",
|
||||||
|
"Source of fragment shader",
|
||||||
|
NULL,
|
||||||
|
CLUTTER_PARAM_READWRITE|
|
||||||
|
G_PARAM_CONSTRUCT_ONLY));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_shader_init (ClutterShader *self)
|
||||||
|
{
|
||||||
|
ClutterShaderPrivate *priv;
|
||||||
|
|
||||||
|
priv = self->priv = CLUTTER_SHADER_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
priv->glsl = FALSE;
|
||||||
|
priv->bound = FALSE;
|
||||||
|
priv->vertex_shader_source = NULL;
|
||||||
|
priv->fragment_shader_source = NULL;
|
||||||
|
priv->program = 0;
|
||||||
|
priv->vertex_shader = 0;
|
||||||
|
priv->fragment_shader = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean bind_glsl_shader (ClutterShader *self)
|
||||||
|
{
|
||||||
|
ClutterShaderPrivate *priv;
|
||||||
|
priv = self->priv;
|
||||||
|
|
||||||
|
cogl_enable (CGL_FRAGMENT_SHADER);
|
||||||
|
cogl_enable (CGL_VERTEX_SHADER);
|
||||||
|
|
||||||
|
priv->glsl = TRUE;
|
||||||
|
priv->program = cogl_create_program ();
|
||||||
|
|
||||||
|
if (priv->vertex_shader_source)
|
||||||
|
{
|
||||||
|
priv->vertex_shader = cogl_create_shader (CGL_VERTEX_SHADER);
|
||||||
|
cogl_shader_source (priv->vertex_shader, priv->vertex_shader_source);
|
||||||
|
cogl_shader_compile (priv->vertex_shader);
|
||||||
|
cogl_program_attach_shader (priv->program, priv->vertex_shader);
|
||||||
|
}
|
||||||
|
if (priv->fragment_shader_source)
|
||||||
|
{
|
||||||
|
GLint compiled = CGL_FALSE;
|
||||||
|
priv->fragment_shader = cogl_create_shader (CGL_FRAGMENT_SHADER);
|
||||||
|
cogl_shader_source (priv->fragment_shader, priv->fragment_shader_source);
|
||||||
|
cogl_shader_compile (priv->fragment_shader);
|
||||||
|
|
||||||
|
cogl_shader_get_parameteriv (priv->fragment_shader,
|
||||||
|
CGL_OBJECT_COMPILE_STATUS,
|
||||||
|
&compiled);
|
||||||
|
if (compiled != CGL_TRUE)
|
||||||
|
{
|
||||||
|
GLcharARB *buffer;
|
||||||
|
gint max_length = 512;
|
||||||
|
buffer = g_malloc (max_length);
|
||||||
|
cogl_shader_get_info_log (priv->fragment_shader, max_length, buffer);
|
||||||
|
g_print ("Shader compilation failed:\n%s", buffer);
|
||||||
|
g_free (buffer);
|
||||||
|
g_object_unref (self);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
cogl_program_attach_shader (priv->program, priv->fragment_shader);
|
||||||
|
}
|
||||||
|
cogl_program_link (priv->program);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_shader_bind (ClutterShader *self)
|
||||||
|
{
|
||||||
|
ClutterShaderPrivate *priv;
|
||||||
|
|
||||||
|
priv = self->priv;
|
||||||
|
if (priv->bound)
|
||||||
|
return priv->bound;
|
||||||
|
|
||||||
|
if (priv->glsl)
|
||||||
|
{
|
||||||
|
priv->bound = bind_glsl_shader (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
return priv->bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_shader_release (ClutterShader *self)
|
||||||
|
{
|
||||||
|
ClutterShaderPrivate *priv;
|
||||||
|
|
||||||
|
priv = self->priv;
|
||||||
|
if (!priv->bound)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_assert (priv->program);
|
||||||
|
|
||||||
|
if (priv->glsl)
|
||||||
|
{
|
||||||
|
if (priv->vertex_shader)
|
||||||
|
cogl_shader_destroy (priv->vertex_shader);
|
||||||
|
if (priv->fragment_shader)
|
||||||
|
cogl_shader_destroy (priv->fragment_shader);
|
||||||
|
if (priv->program)
|
||||||
|
cogl_program_destroy (priv->program);
|
||||||
|
priv->vertex_shader = 0;
|
||||||
|
priv->fragment_shader = 0;
|
||||||
|
priv->program = 0;
|
||||||
|
}
|
||||||
|
priv->bound = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_shader_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
ClutterShader *shader;
|
||||||
|
ClutterShaderPrivate *priv;
|
||||||
|
|
||||||
|
shader = CLUTTER_SHADER (object);
|
||||||
|
priv = shader->priv;
|
||||||
|
|
||||||
|
clutter_shader_release (shader);
|
||||||
|
|
||||||
|
shader_list = g_list_remove (shader_list, object);
|
||||||
|
|
||||||
|
if (priv->fragment_shader_source)
|
||||||
|
g_free (priv->fragment_shader_source);
|
||||||
|
if (priv->vertex_shader_source)
|
||||||
|
g_free (priv->vertex_shader_source);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_shader_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_shader_enable (ClutterShader *self)
|
||||||
|
{
|
||||||
|
ClutterShaderPrivate *priv = self->priv;
|
||||||
|
|
||||||
|
clutter_shader_bind (self);
|
||||||
|
|
||||||
|
cogl_program_use (priv->program);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_shader_disable (ClutterShader *self)
|
||||||
|
{
|
||||||
|
cogl_program_use (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_shader_set_uniform_1f (ClutterShader *self,
|
||||||
|
const gchar *name,
|
||||||
|
gfloat value)
|
||||||
|
{
|
||||||
|
ClutterShaderPrivate *priv = self->priv;
|
||||||
|
GLint location = 0;
|
||||||
|
GLfloat foo = value;
|
||||||
|
|
||||||
|
location =cogl_program_get_uniform_location (priv->program, name);
|
||||||
|
cogl_program_uniform_1f (location, foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_shader_release_all (void)
|
||||||
|
{
|
||||||
|
GList *iter;
|
||||||
|
for (iter = shader_list; iter; iter = g_list_next (iter))
|
||||||
|
{
|
||||||
|
clutter_shader_release (iter->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_shader_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterShader *shader;
|
||||||
|
ClutterShaderPrivate *priv;
|
||||||
|
|
||||||
|
shader = CLUTTER_SHADER(object);
|
||||||
|
priv = shader->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_VERTEX_SOURCE:
|
||||||
|
if (priv->vertex_shader_source)
|
||||||
|
{
|
||||||
|
g_free (priv->vertex_shader_source);
|
||||||
|
priv->vertex_shader_source = NULL;
|
||||||
|
}
|
||||||
|
priv->vertex_shader_source = g_value_dup_string (value);
|
||||||
|
break;
|
||||||
|
case PROP_FRAGMENT_SOURCE:
|
||||||
|
if (priv->fragment_shader_source)
|
||||||
|
{
|
||||||
|
g_free (priv->fragment_shader_source);
|
||||||
|
priv->fragment_shader_source = NULL;
|
||||||
|
}
|
||||||
|
priv->fragment_shader_source = g_value_dup_string (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_shader_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ClutterShader *shader;
|
||||||
|
ClutterShaderPrivate *priv;
|
||||||
|
|
||||||
|
shader = CLUTTER_SHADER(object);
|
||||||
|
priv = shader->priv;
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_VERTEX_SOURCE:
|
||||||
|
g_value_set_string (value, priv->vertex_shader_source);
|
||||||
|
break;
|
||||||
|
case PROP_FRAGMENT_SOURCE:
|
||||||
|
g_value_set_string (value, priv->fragment_shader_source);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GObject *
|
||||||
|
clutter_shader_constructor (GType type,
|
||||||
|
guint n_params,
|
||||||
|
GObjectConstructParam *params)
|
||||||
|
{
|
||||||
|
GObject *object;
|
||||||
|
ClutterShader *shader;
|
||||||
|
ClutterShaderPrivate *priv;
|
||||||
|
|
||||||
|
object = G_OBJECT_CLASS (clutter_shader_parent_class)->constructor (
|
||||||
|
type, n_params, params);
|
||||||
|
shader = CLUTTER_SHADER (object);
|
||||||
|
priv = shader->priv;
|
||||||
|
|
||||||
|
priv->glsl = !((priv->vertex_shader_source &&
|
||||||
|
g_str_has_prefix (priv->vertex_shader_source, "!!ARBvp")) ||
|
||||||
|
(priv->fragment_shader_source &&
|
||||||
|
g_str_has_prefix (priv->fragment_shader_source, "!!ARBfp")));
|
||||||
|
if (!priv->glsl)
|
||||||
|
{
|
||||||
|
g_warning ("ASM shader support not available");
|
||||||
|
g_object_unref (object);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (priv->glsl && !clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||||
|
{
|
||||||
|
g_warning ("GLSL shaders not supported\n");
|
||||||
|
g_object_unref (object);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader_list = g_list_prepend (shader_list, object);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterShader *
|
||||||
|
clutter_shader_new_from_strings (const gchar *vertex_shader_program,
|
||||||
|
const gchar *fragment_shader_program)
|
||||||
|
{
|
||||||
|
/* evil hack, since g_object_new would interpret a NULL passed as
|
||||||
|
* a argument termination
|
||||||
|
*/
|
||||||
|
if (vertex_shader_program &&
|
||||||
|
fragment_shader_program)
|
||||||
|
return g_object_new (CLUTTER_TYPE_SHADER,
|
||||||
|
"vertex-source", vertex_shader_program,
|
||||||
|
"fragment-source", fragment_shader_program,
|
||||||
|
NULL);
|
||||||
|
else if (fragment_shader_program)
|
||||||
|
return g_object_new (CLUTTER_TYPE_SHADER,
|
||||||
|
"fragment-source", fragment_shader_program,
|
||||||
|
NULL);
|
||||||
|
else if (vertex_shader_program)
|
||||||
|
return g_object_new (CLUTTER_TYPE_SHADER,
|
||||||
|
"vertex-source", vertex_shader_program,
|
||||||
|
NULL);
|
||||||
|
else {
|
||||||
|
g_warning ("neither fragment nor vertex shader provided");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterShader *
|
||||||
|
clutter_shader_new_from_files (const gchar *vertex_file,
|
||||||
|
const gchar *fragment_file)
|
||||||
|
{
|
||||||
|
ClutterShader *shader;
|
||||||
|
gchar *vertex_shader_program = NULL;
|
||||||
|
gchar *fragment_shader_program = NULL;
|
||||||
|
|
||||||
|
g_assert (vertex_file != NULL ||
|
||||||
|
fragment_file != NULL);
|
||||||
|
|
||||||
|
if (vertex_file)
|
||||||
|
{
|
||||||
|
g_file_get_contents (vertex_file, &vertex_shader_program,
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
if (fragment_file)
|
||||||
|
{
|
||||||
|
g_file_get_contents (fragment_file, &fragment_shader_program,
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
shader = clutter_shader_new_from_strings (vertex_shader_program,
|
||||||
|
fragment_shader_program);
|
||||||
|
|
||||||
|
if (vertex_shader_program)
|
||||||
|
{
|
||||||
|
g_free (vertex_shader_program);
|
||||||
|
}
|
||||||
|
if (fragment_shader_program)
|
||||||
|
{
|
||||||
|
g_free (fragment_shader_program);
|
||||||
|
}
|
||||||
|
return shader;
|
||||||
|
}
|
80
clutter/clutter-shader.h
Normal file
80
clutter/clutter-shader.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
* Øyvind Kolås <pippin@o-hand.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CLUTTER_SHADER_H
|
||||||
|
#define CLUTTER_SHADER_H
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define CLUTTER_TYPE_SHADER (clutter_shader_get_type ())
|
||||||
|
#define CLUTTER_SHADER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CLUTTER_TYPE_SHADER, ClutterShader))
|
||||||
|
#define CLUTTER_SHADER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CLUTTER_TYPE_SHADER, ClutterShaderClass))
|
||||||
|
#define CLUTTER_IS_SHADER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CLUTTER_TYPE_SHADER))
|
||||||
|
#define CLUTTER_IS_SHADER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CLUTTER_TYPE_SHADER))
|
||||||
|
#define CLUTTER_SHADER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CLUTTER_TYPE_SHADER, ClutterShaderClass))
|
||||||
|
|
||||||
|
typedef struct _ClutterShader ClutterShader;
|
||||||
|
typedef struct _ClutterShaderPrivate ClutterShaderPrivate;
|
||||||
|
typedef struct _ClutterShaderClass ClutterShaderClass;
|
||||||
|
|
||||||
|
struct _ClutterShader
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
ClutterShaderPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ClutterShaderClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType clutter_shader_get_type ();
|
||||||
|
|
||||||
|
ClutterShader * clutter_shader_new_from_files (const gchar *vertex_file,
|
||||||
|
const gchar *fragment_file);
|
||||||
|
ClutterShader * clutter_shader_new_from_strings (const gchar *vertex_file,
|
||||||
|
const gchar *fragment_file);
|
||||||
|
void clutter_shader_enable (ClutterShader *self);
|
||||||
|
void clutter_shader_disable (ClutterShader *self);
|
||||||
|
|
||||||
|
gboolean clutter_shader_bind (ClutterShader *self);
|
||||||
|
void clutter_shader_release (ClutterShader *self);
|
||||||
|
void clutter_shader_set_uniform_1f (ClutterShader *self,
|
||||||
|
const gchar *name,
|
||||||
|
gfloat value);
|
||||||
|
/* should be private and internal */
|
||||||
|
void clutter_shader_release_all (void);
|
||||||
|
gboolean clutter_shader_has_glsl (void);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* CLUTTER_SHADER_H */
|
@ -207,6 +207,58 @@ cogl_fog_set (const ClutterColor *fog_color,
|
|||||||
ClutterFixed z_near,
|
ClutterFixed z_near,
|
||||||
ClutterFixed z_far);
|
ClutterFixed z_far);
|
||||||
|
|
||||||
|
|
||||||
|
COGLint
|
||||||
|
cogl_create_shader (COGLenum shaderType);
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_shader_destroy (COGLint handle);
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_shader_source (COGLint shader,
|
||||||
|
const gchar *source);
|
||||||
|
void
|
||||||
|
cogl_shader_compile (COGLint shader_handle);
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_shader_get_info_log (COGLint handle,
|
||||||
|
guint size,
|
||||||
|
gchar *buffer);
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_shader_get_parameteriv (COGLint handle,
|
||||||
|
COGLenum pname,
|
||||||
|
COGLint *dest);
|
||||||
|
|
||||||
|
|
||||||
|
COGLint
|
||||||
|
cogl_create_program (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_program_destroy (COGLint handle);
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_program_attach_shader (COGLint program_handle,
|
||||||
|
COGLint shader_handle);
|
||||||
|
|
||||||
|
/* 0 to use none */
|
||||||
|
void
|
||||||
|
cogl_program_link (COGLint program_handle);
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_program_use (COGLint program_handle);
|
||||||
|
|
||||||
|
COGLint
|
||||||
|
cogl_program_get_uniform_location (COGLint program_int,
|
||||||
|
const gchar *uniform_name);
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_program_uniform_1f (COGLint uniform_no,
|
||||||
|
gfloat value);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __COGL_H__ */
|
#endif /* __COGL_H__ */
|
||||||
|
@ -698,6 +698,12 @@ typedef GLuint COGLuint;
|
|||||||
#define CGL_UNSIGNED_SHORT_8_8_MESA 0
|
#define CGL_UNSIGNED_SHORT_8_8_MESA 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CGL_FRAGMENT_SHADER GL_FRAGMENT_SHADER_ARB
|
||||||
|
#define CGL_VERTEX_SHADER GL_VERTEX_SHADER_ARB
|
||||||
|
|
||||||
|
#define CGL_OBJECT_COMPILE_STATUS GL_OBJECT_COMPILE_STATUS_ARB
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -621,6 +621,12 @@ cogl_get_features ()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (cogl_check_extension ("GL_ARB_vertex_shader", gl_extensions) &&
|
||||||
|
cogl_check_extension ("GL_ARB_fragment_shader", gl_extensions))
|
||||||
|
{
|
||||||
|
flags |= CLUTTER_FEATURE_SHADERS_GLSL;
|
||||||
|
}
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,3 +752,134 @@ cogl_fog_set (const ClutterColor *fog_color,
|
|||||||
glFogf (GL_FOG_START, CLUTTER_FIXED_TO_FLOAT (start));
|
glFogf (GL_FOG_START, CLUTTER_FIXED_TO_FLOAT (start));
|
||||||
glFogf (GL_FOG_END, CLUTTER_FIXED_TO_FLOAT (stop));
|
glFogf (GL_FOG_END, CLUTTER_FIXED_TO_FLOAT (stop));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
|
||||||
|
#define PROC(rettype, retval, procname, args...) \
|
||||||
|
static rettype (*proc) (args) = NULL; \
|
||||||
|
if (proc == NULL) \
|
||||||
|
{ \
|
||||||
|
proc = (void*)cogl_get_proc_address (#procname);\
|
||||||
|
if (!proc)\
|
||||||
|
{\
|
||||||
|
g_warning ("failed to lookup proc: %s", #procname);\
|
||||||
|
return retval;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define PROC(rettype, retval, procname, ...) \
|
||||||
|
static rettype (*proc) (__VA_ARGS__) = NULL; \
|
||||||
|
if (proc == NULL) \
|
||||||
|
{ \
|
||||||
|
proc = (void*)cogl_get_proc_address (#procname);\
|
||||||
|
if (!proc)\
|
||||||
|
{\
|
||||||
|
g_warning ("failed to lookup proc: %s", #procname);\
|
||||||
|
return retval;\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
COGLint
|
||||||
|
cogl_create_program (void)
|
||||||
|
{
|
||||||
|
PROC (GLhandleARB, 0, glCreateProgramObjectARB, void);
|
||||||
|
return proc ();
|
||||||
|
}
|
||||||
|
|
||||||
|
COGLint
|
||||||
|
cogl_create_shader (COGLenum shaderType)
|
||||||
|
{
|
||||||
|
PROC (GLhandleARB, 0, glCreateShaderObjectARB, GLenum);
|
||||||
|
return proc (shaderType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_shader_source (COGLint shader,
|
||||||
|
const gchar *source)
|
||||||
|
{
|
||||||
|
PROC (GLvoid,, glShaderSourceARB, GLhandleARB, GLsizei, const GLcharARB **, const GLint *)
|
||||||
|
proc (shader, 1, &source, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_shader_compile (COGLint shader_handle)
|
||||||
|
{
|
||||||
|
PROC (GLvoid,, glCompileShaderARB, GLhandleARB);
|
||||||
|
proc (shader_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_program_attach_shader (COGLint program_handle,
|
||||||
|
COGLint shader_handle)
|
||||||
|
{
|
||||||
|
PROC (GLvoid,, glAttachObjectARB, GLhandleARB, GLhandleARB);
|
||||||
|
proc (program_handle, shader_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_program_link (COGLint program_handle)
|
||||||
|
{
|
||||||
|
PROC (GLvoid,, glLinkProgramARB, GLhandleARB);
|
||||||
|
proc (program_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_program_use (COGLint program_handle)
|
||||||
|
{
|
||||||
|
PROC (GLvoid,, glUseProgramObjectARB, GLhandleARB);
|
||||||
|
proc (program_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
COGLint
|
||||||
|
cogl_program_get_uniform_location (COGLint program_handle,
|
||||||
|
const gchar *uniform_name)
|
||||||
|
{
|
||||||
|
PROC (GLint,0, glGetUniformLocationARB, GLhandleARB, const GLcharARB *)
|
||||||
|
return proc (program_handle, uniform_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_program_destroy (COGLint handle)
|
||||||
|
{
|
||||||
|
PROC (GLvoid,, glDeleteObjectARB, GLhandleARB);
|
||||||
|
proc (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_shader_destroy (COGLint handle)
|
||||||
|
{
|
||||||
|
PROC (GLvoid,, glDeleteObjectARB, GLhandleARB);
|
||||||
|
proc (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_shader_get_info_log (COGLint handle,
|
||||||
|
guint size,
|
||||||
|
gchar *buffer)
|
||||||
|
{
|
||||||
|
gint len;
|
||||||
|
PROC (GLvoid,, glGetInfoLogARB, GLhandleARB, GLsizei, GLsizei *, GLcharARB *);
|
||||||
|
proc (handle, size-1, &len, buffer);
|
||||||
|
buffer[len]='\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_shader_get_parameteriv (COGLint handle,
|
||||||
|
COGLenum pname,
|
||||||
|
COGLint *dest)
|
||||||
|
{
|
||||||
|
PROC (GLvoid,, glGetObjectParameterivARB, GLhandleARB, GLenum, GLint*)
|
||||||
|
proc (handle, pname, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_program_uniform_1f (COGLint uniform_no,
|
||||||
|
gfloat value)
|
||||||
|
{
|
||||||
|
PROC (GLvoid,, glUniform1fARB, GLint, GLfloat);
|
||||||
|
proc (uniform_no, value);
|
||||||
|
}
|
||||||
|
@ -460,6 +460,24 @@ typedef GLuint COGLuint;
|
|||||||
#define CGL_UNSIGNED_SHORT_8_8_REV_MESA 0
|
#define CGL_UNSIGNED_SHORT_8_8_REV_MESA 0
|
||||||
#define CGL_UNSIGNED_SHORT_8_8_MESA 0
|
#define CGL_UNSIGNED_SHORT_8_8_MESA 0
|
||||||
|
|
||||||
|
#ifdef GL_FRAGMENT_SHADER
|
||||||
|
#define CGL_FRAGMENT_SHADER GL_FRAGMENT_SHADER
|
||||||
|
#else
|
||||||
|
#define CGL_FRAGMENT_SHADER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GL_VERTEX_SHADER
|
||||||
|
#define CGL_VERTEX_SHADER GL_VERTEX_SHADER
|
||||||
|
#else
|
||||||
|
#define CGL_VERTEX_SHADER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GL_OBJECT_COMPILE_STATUS
|
||||||
|
#define CGL_OBJECT_COMPILE_STATUS GL_OBJECT_COMPILE_STATUS
|
||||||
|
#else
|
||||||
|
#define CGL_OBJECT_COMPILE_STATUS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -214,13 +214,13 @@ cogl_enable (gulong flags)
|
|||||||
if (flags & CGL_ENABLE_TEXTURE_RECT)
|
if (flags & CGL_ENABLE_TEXTURE_RECT)
|
||||||
{
|
{
|
||||||
if (!(__enable_flags & CGL_ENABLE_TEXTURE_RECT))
|
if (!(__enable_flags & CGL_ENABLE_TEXTURE_RECT))
|
||||||
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
glEnable (GL_TEXTURE_RECTANGLE_);
|
||||||
|
|
||||||
__enable_flags |= CGL_ENABLE_TEXTURE_RECT;
|
__enable_flags |= CGL_ENABLE_TEXTURE_RECT;
|
||||||
}
|
}
|
||||||
else if (__enable_flags & CGL_ENABLE_TEXTURE_RECT)
|
else if (__enable_flags & CGL_ENABLE_TEXTURE_RECT)
|
||||||
{
|
{
|
||||||
glDisable (GL_TEXTURE_RECTANGLE_ARB);
|
glDisable (GL_TEXTURE_RECTANGLE_);
|
||||||
__enable_flags &= ~CGL_ENABLE_TEXTURE_RECT;
|
__enable_flags &= ~CGL_ENABLE_TEXTURE_RECT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -630,3 +630,67 @@ cogl_fog_set (const ClutterColor *fog_color,
|
|||||||
glFogx (GL_FOG_START, (GLfixed) z_near);
|
glFogx (GL_FOG_START, (GLfixed) z_near);
|
||||||
glFogx (GL_FOG_END, (GLfixed) z_far);
|
glFogx (GL_FOG_END, (GLfixed) z_far);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COGLint cogl_create_program (void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
COGLint cogl_create_shader (COGLenum shaderType)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cogl_shader_source (COGLint shader,
|
||||||
|
const gchar *source)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cogl_shader_compile (COGLint shader_handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cogl_program_attach_shader (COGLint program_handle,
|
||||||
|
COGLint shader_handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cogl_program_link (COGLint program_handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cogl_program_use (COGLint program_handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
COGLint cogl_program_get_uniform_location (COGLint program_handle,
|
||||||
|
const gchar *uniform_name)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cogl_program_destroy (COGLint handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cogl_shader_destroy (COGLint handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cogl_shader_get_info_log (COGLint handle,
|
||||||
|
guint size,
|
||||||
|
gchar *buffer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void cogl_shader_get_parameteriv (COGLint handle,
|
||||||
|
COGLenum pname,
|
||||||
|
COGLint *dest)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cogl_program_uniform_1f (COGLint uniform_no,
|
||||||
|
gfloat value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "../clutter-private.h"
|
#include "../clutter-private.h"
|
||||||
#include "../clutter-debug.h"
|
#include "../clutter-debug.h"
|
||||||
#include "../clutter-units.h"
|
#include "../clutter-units.h"
|
||||||
|
#include "../clutter-shader.h"
|
||||||
|
|
||||||
#include "cogl.h"
|
#include "cogl.h"
|
||||||
|
|
||||||
@ -60,6 +61,9 @@ clutter_stage_glx_unrealize (ClutterActor *actor)
|
|||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
|
/* Unrealize all shaders, since the GL context is going away */
|
||||||
|
clutter_shader_release_all ();
|
||||||
|
|
||||||
if (G_UNLIKELY (was_offscreen))
|
if (G_UNLIKELY (was_offscreen))
|
||||||
{
|
{
|
||||||
if (stage_glx->glxpixmap)
|
if (stage_glx->glxpixmap)
|
||||||
|
@ -2,7 +2,7 @@ noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \
|
|||||||
test-actors test-behave test-text test-entry test-project \
|
test-actors test-behave test-text test-entry test-project \
|
||||||
test-perspective test-rotate test-depth \
|
test-perspective test-rotate test-depth \
|
||||||
test-threads test-timeline test-score test-script \
|
test-threads test-timeline test-score test-script \
|
||||||
test-model test-grab test-effects test-fullscreen
|
test-model test-grab test-effects test-fullscreen test-shader
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/
|
INCLUDES = -I$(top_srcdir)/
|
||||||
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
|
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
|
||||||
@ -24,6 +24,7 @@ test_rotate_SOURCES = test-rotate.c
|
|||||||
test_depth_SOURCES = test-depth.c
|
test_depth_SOURCES = test-depth.c
|
||||||
test_threads_SOURCES = test-threads.c
|
test_threads_SOURCES = test-threads.c
|
||||||
test_timeline_SOURCES = test-timeline.c
|
test_timeline_SOURCES = test-timeline.c
|
||||||
|
test_shader_SOURCES = test-shader.c
|
||||||
test_score_SOURCES = test-score.c
|
test_score_SOURCES = test-score.c
|
||||||
test_script_SOURCES = test-script.c
|
test_script_SOURCES = test-script.c
|
||||||
test_model_SOURCES = test-model.c
|
test_model_SOURCES = test-model.c
|
||||||
|
246
tests/test-shader.c
Normal file
246
tests/test-shader.c
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
/* #define TEST_GROUP 1 */
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gchar *name;
|
||||||
|
gchar *source;
|
||||||
|
} ShaderSource;
|
||||||
|
|
||||||
|
static ShaderSource shaders[]=
|
||||||
|
{
|
||||||
|
{"brightness-contrast",
|
||||||
|
|
||||||
|
"uniform float brightness;"
|
||||||
|
"uniform float contrast;"
|
||||||
|
"uniform sampler2DRect pend_s3_tex;"
|
||||||
|
""
|
||||||
|
"void main()"
|
||||||
|
"{"
|
||||||
|
" vec4 pend_s4_result;"
|
||||||
|
" pend_s4_result = texture2DRect(pend_s3_tex, gl_TexCoord[0].xy);"
|
||||||
|
" pend_s4_result.x = (pend_s4_result.x - 0.5)*contrast + brightness + 0.5;"
|
||||||
|
" pend_s4_result.y = (pend_s4_result.y - 0.5)*contrast + brightness + 0.5;"
|
||||||
|
" pend_s4_result.z = (pend_s4_result.z - 0.5)*contrast + brightness + 0.5;"
|
||||||
|
" gl_FragColor = pend_s4_result;"
|
||||||
|
"}",
|
||||||
|
},
|
||||||
|
{"box-blur",
|
||||||
|
|
||||||
|
"uniform float radius ;"
|
||||||
|
"uniform sampler2DRect rectTexture;"
|
||||||
|
""
|
||||||
|
"void main()"
|
||||||
|
"{"
|
||||||
|
" vec4 color = texture2DRect(rectTexture, gl_TexCoord[0].st);"
|
||||||
|
" float u;"
|
||||||
|
" float v;"
|
||||||
|
" int count = 1;"
|
||||||
|
" for (u=-radius;u<radius;u++)"
|
||||||
|
" for (v=-radius;v<radius;v++)"
|
||||||
|
" {"
|
||||||
|
" color += texture2DRect(rectTexture, vec2(gl_TexCoord[0].s + u * 2, gl_TexCoord[0].t +v * 2));"
|
||||||
|
" count ++;"
|
||||||
|
" }"
|
||||||
|
""
|
||||||
|
" gl_FragColor = color / count;"
|
||||||
|
"}"
|
||||||
|
},
|
||||||
|
{"brightness-contrast.asm",
|
||||||
|
|
||||||
|
"!!ARBfp1.0\n"
|
||||||
|
"PARAM brightness = program.local[0];\n"
|
||||||
|
"PARAM contrast = program.local[1];\n"
|
||||||
|
"\n"
|
||||||
|
"TEMP R0;\n"
|
||||||
|
"TEX R0, fragment.texcoord[0], texture[0], RECT;\n"
|
||||||
|
"ADD R0.z, R0, -0.5;\n"
|
||||||
|
"MUL R0.z, R0, contrast.x;\n"
|
||||||
|
"ADD R0.z, R0, brightness.x;\n"
|
||||||
|
"ADD R0.y, R0, -0.5;\n"
|
||||||
|
"ADD R0.x, R0, -0.5;\n"
|
||||||
|
"MUL R0.y, R0, contrast.x;\n"
|
||||||
|
"MUL R0.x, R0, contrast.x;\n"
|
||||||
|
"ADD R0.y, R0, brightness.x;\n"
|
||||||
|
"ADD R0.x, R0, brightness.x;\n"
|
||||||
|
"ADD result.color.z, R0, 0.5;\n"
|
||||||
|
"ADD result.color.y, R0, 0.5;\n"
|
||||||
|
"ADD result.color.x, R0, 0.5;\n"
|
||||||
|
"MOV result.color.w, R0;\n"
|
||||||
|
"END ",
|
||||||
|
},
|
||||||
|
{"invert",
|
||||||
|
|
||||||
|
"uniform sampler2DRect tex;\n"
|
||||||
|
"void main ()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec4 color = texture2DRect (tex, vec2(gl_TexCoord[0].st));\n"
|
||||||
|
" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0) - color;\n"
|
||||||
|
" gl_FragColor.a = color.a;\n"
|
||||||
|
"}"
|
||||||
|
},
|
||||||
|
{"brightness-contrast",
|
||||||
|
|
||||||
|
"uniform sampler2DRect tex;"
|
||||||
|
"uniform float brightness;"
|
||||||
|
"uniform float contrast;"
|
||||||
|
"void main ()"
|
||||||
|
"{"
|
||||||
|
" vec4 color = texture2DRect (tex, vec2(gl_TexCoord[0].st));"
|
||||||
|
" color.r = (color.r - 0.5) * contrast + brightness + 0.5;"
|
||||||
|
" color.g = (color.g - 0.5) * contrast + brightness + 0.5;"
|
||||||
|
" color.b = (color.b - 0.5) * contrast + brightness + 0.5;"
|
||||||
|
" gl_FragColor = color;"
|
||||||
|
"}",
|
||||||
|
},
|
||||||
|
{"gray",
|
||||||
|
"uniform sampler2DRect tex;"
|
||||||
|
"void main ()"
|
||||||
|
"{"
|
||||||
|
" vec4 color = texture2DRect (tex, vec2(gl_TexCoord[0].st));"
|
||||||
|
" float avg = (color.r + color.g + color.b) / 3;"
|
||||||
|
" color.r = avg;"
|
||||||
|
" color.g = avg;"
|
||||||
|
" color.b = avg;"
|
||||||
|
" gl_FragColor = color;"
|
||||||
|
"}",
|
||||||
|
},
|
||||||
|
{"combined-mirror",
|
||||||
|
"uniform sampler2DRect tex;"
|
||||||
|
"void main ()"
|
||||||
|
"{"
|
||||||
|
" vec4 color = texture2DRect (tex, vec2(gl_TexCoord[0].st));"
|
||||||
|
" vec4 colorB = texture2DRect (tex, vec2(gl_TexCoord[0].ts));"
|
||||||
|
" float avg = (color.r + color.g + color.b) / 3;"
|
||||||
|
" color.r = avg;"
|
||||||
|
" color.g = avg;"
|
||||||
|
" color.b = avg;"
|
||||||
|
" color = (color + colorB)/2;"
|
||||||
|
" gl_FragColor = color;"
|
||||||
|
"}",
|
||||||
|
},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static gint shader_no=0;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
button_release_cb (ClutterActor *actor,
|
||||||
|
ClutterEvent *event,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
gint new_no;
|
||||||
|
if (event->button.button == 1)
|
||||||
|
{
|
||||||
|
new_no = shader_no-1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_no = shader_no+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_no >= 0 && shaders[new_no].name)
|
||||||
|
{
|
||||||
|
ClutterShader *shader;
|
||||||
|
shader_no = new_no;
|
||||||
|
|
||||||
|
g_print ("setting shaders[%i] named '%s'\n", shader_no, shaders[shader_no].name);
|
||||||
|
shader = clutter_shader_new_from_strings (NULL, shaders[shader_no].source);
|
||||||
|
clutter_actor_apply_shader (actor, shader);
|
||||||
|
|
||||||
|
clutter_actor_set_shader_param (actor, "radius", 3.0);
|
||||||
|
clutter_redraw();
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gint
|
||||||
|
main (gint argc,
|
||||||
|
gchar *argv[])
|
||||||
|
{
|
||||||
|
ClutterTimeline *timeline;
|
||||||
|
ClutterAlpha *alpha;
|
||||||
|
ClutterActor *actor;
|
||||||
|
ClutterActor *stage;
|
||||||
|
ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
|
GError *error;
|
||||||
|
ClutterShader *shader;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
|
||||||
|
clutter_init (&argc, &argv);
|
||||||
|
g_print ("applying shaders[%i] named '%s'\n", shader_no, shaders[shader_no].name);
|
||||||
|
shader = clutter_shader_new_from_strings (NULL, shaders[shader_no].source);
|
||||||
|
|
||||||
|
stage = clutter_stage_get_default ();
|
||||||
|
clutter_actor_set_size (stage, 512, 384);
|
||||||
|
|
||||||
|
pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL);
|
||||||
|
|
||||||
|
if (!pixbuf)
|
||||||
|
g_error("pixbuf load failed");
|
||||||
|
|
||||||
|
clutter_stage_set_title (CLUTTER_STAGE (stage), "Shader Test");
|
||||||
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||||
|
|
||||||
|
/* Create a timeline to manage animation */
|
||||||
|
timeline = clutter_timeline_new (360, 60); /* num frames, fps */
|
||||||
|
g_object_set (timeline, "loop", TRUE, NULL); /* have it loop */
|
||||||
|
|
||||||
|
#ifndef TEST_GROUP
|
||||||
|
actor = clutter_texture_new_from_pixbuf (pixbuf);
|
||||||
|
#else
|
||||||
|
actor = clutter_group_new ();
|
||||||
|
{
|
||||||
|
ClutterActor *child1, *child2, *child3, *child4;
|
||||||
|
ClutterColor color={0xff, 0x22, 0x66, 0x99};
|
||||||
|
|
||||||
|
child1 = clutter_texture_new_from_pixbuf (pixbuf);
|
||||||
|
child2 = clutter_texture_new_from_pixbuf (pixbuf);
|
||||||
|
child3 = clutter_rectangle_new ();
|
||||||
|
child4 = clutter_label_new_with_text ("Sans 20px", "Shady stuff");
|
||||||
|
|
||||||
|
clutter_rectangle_set_color (child3, &color);
|
||||||
|
clutter_actor_set_size (child3, 50, 50);
|
||||||
|
clutter_actor_set_position (child1, 0, 0);
|
||||||
|
clutter_actor_set_position (child2, 50, 100);
|
||||||
|
clutter_actor_set_position (child3, 30, -30);
|
||||||
|
clutter_actor_set_position (child4, -50, 20);
|
||||||
|
|
||||||
|
clutter_group_add (CLUTTER_GROUP (actor), child1);
|
||||||
|
clutter_group_add (CLUTTER_GROUP (actor), child2);
|
||||||
|
clutter_group_add (CLUTTER_GROUP (actor), child3);
|
||||||
|
clutter_group_add (CLUTTER_GROUP (actor), child4);
|
||||||
|
clutter_actor_show_all (actor);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
clutter_actor_set_position (actor, 100, 100);
|
||||||
|
|
||||||
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor);
|
||||||
|
|
||||||
|
clutter_actor_apply_shader (actor, shader);
|
||||||
|
|
||||||
|
clutter_actor_set_shader_param (actor, "brightness", 0.4);
|
||||||
|
clutter_actor_set_shader_param (actor, "contrast", -1.9);
|
||||||
|
|
||||||
|
clutter_actor_set_reactive (actor, TRUE);
|
||||||
|
g_signal_connect (actor, "button-release-event",
|
||||||
|
G_CALLBACK (button_release_cb), NULL);
|
||||||
|
|
||||||
|
/* Show everying ( and map window ) */
|
||||||
|
clutter_actor_show_all (stage);
|
||||||
|
|
||||||
|
/* and start it */
|
||||||
|
clutter_timeline_start (timeline);
|
||||||
|
|
||||||
|
clutter_main ();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user