--- /dev/null
+#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <cogl/cogl.h> can be included directly."
+#endif
+
+#ifndef __COGL_MATERIAL_H__
+#define __COGL_MATERIAL_H__
+
+G_BEGIN_DECLS
+
+#include <cogl/cogl-types.h>
+#include <cogl/cogl-matrix.h>
+
+/**
+ * SECTION:cogl-material
+ * @short_description: Fuctions for creating and manipulating materials
+ *
+ * COGL allows creating and manipulating materials used to fill in
+ * geometry. Materials may simply be lighting attributes (such as an
+ * ambient and diffuse colour) or might represent one or more textures
+ * blended together.
+ */
+
+G_END_DECLS
+
+typedef enum _CoglMaterialAlphaFunc
+{
+ COGL_MATERIAL_ALPHA_FUNC_NEVER = GL_NEVER,
+ COGL_MATERIAL_ALPHA_FUNC_LESS = GL_LESS,
+ COGL_MATERIAL_ALPHA_FUNC_EQUAL = GL_EQUAL,
+ COGL_MATERIAL_ALPHA_FUNC_LEQUAL = GL_LEQUAL,
+ COGL_MATERIAL_ALPHA_FUNC_GREATER = GL_GREATER,
+ COGL_MATERIAL_ALPHA_FUNC_NOTEQUAL = GL_NOTEQUAL,
+ COGL_MATERIAL_ALPHA_FUNC_GEQUAL = GL_GEQUAL,
+ COGL_MATERIAL_ALPHA_FUNC_ALWAYS = GL_ALWAYS
+} CoglMaterialAlphaFunc;
+
+typedef enum _CoglMaterialBlendFactor
+{
+ COGL_MATERIAL_BLEND_FACTOR_ZERO = GL_ZERO,
+ COGL_MATERIAL_BLEND_FACTOR_ONE = GL_ONE,
+ COGL_MATERIAL_BLEND_FACTOR_DST_COLOR = GL_DST_COLOR,
+ COGL_MATERIAL_BLEND_FACTOR_SRC_COLOR = GL_SRC_COLOR,
+ COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_COLOR = GL_ONE_MINUS_DST_COLOR,
+ COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR,
+ COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA = GL_SRC_ALPHA,
+ COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA,
+ COGL_MATERIAL_BLEND_FACTOR_DST_ALPHA = GL_DST_ALPHA,
+ COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = GL_ONE_MINUS_DST_ALPHA,
+ COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA_SATURATE = GL_SRC_ALPHA_SATURATE,
+ COGL_MATERIAL_BLEND_FACTOR_CONSTANT_COLOR = GL_CONSTANT_COLOR,
+ COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR =
+ GL_ONE_MINUS_CONSTANT_COLOR,
+ COGL_MATERIAL_BLEND_FACTOR_CONSTANT_ALPHA = GL_CONSTANT_ALPHA,
+ COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA =
+ GL_ONE_MINUS_CONSTANT_ALPHA
+} CoglMaterialBlendFactor;
+
+typedef enum _CoglMaterialLayerType
+{
+ COGL_MATERIAL_LAYER_TYPE_TEXTURE
+} CoglMaterialLayerType;
+
+typedef enum _CoglMaterialLayerCombineFunc
+{
+ COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE = GL_REPLACE,
+ COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE = GL_MODULATE,
+ COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD = GL_ADD,
+ COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED = GL_ADD_SIGNED,
+ COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE = GL_INTERPOLATE,
+ COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT = GL_SUBTRACT,
+ COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB = GL_DOT3_RGB,
+ COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA = GL_DOT3_RGBA
+} CoglMaterialLayerCombineFunc;
+
+typedef enum _CoglMaterialLayerCombineChannels
+{
+ COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
+ COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA,
+ COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA
+} CoglMaterialLayerCombineChannels;
+
+typedef enum _CoglMaterialLayerCombineSrc
+{
+ COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE = GL_TEXTURE,
+
+ /* Can we find a nicer way... */
+ COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE0 = GL_TEXTURE0,
+ COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE1 = GL_TEXTURE1,
+ COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE2 = GL_TEXTURE2,
+ COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE3 = GL_TEXTURE3,
+ COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE4 = GL_TEXTURE4,
+ COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE5 = GL_TEXTURE5,
+ COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE6 = GL_TEXTURE6,
+ COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE7 = GL_TEXTURE7,
+ /* .. who would ever need more than 8 texture layers.. :-) */
+
+ COGL_MATERIAL_LAYER_COMBINE_SRC_CONSTANT = GL_CONSTANT,
+ COGL_MATERIAL_LAYER_COMBINE_SRC_PRIMARY_COLOR = GL_PRIMARY_COLOR,
+ COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS = GL_PREVIOUS
+} CoglMaterialLayerCombineSrc;
+
+typedef enum _CoglMaterialLayerCombineOp
+{
+ COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR = GL_SRC_COLOR,
+ COGL_MATERIAL_LAYER_COMBINE_OP_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR,
+
+ COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA = GL_SRC_ALPHA,
+ COGL_MATERIAL_LAYER_COMBINE_OP_ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA
+} CoglMaterialLayerCombineOp;
+
+/**
+ * cogl_material_new:
+ *
+ * Allocates and initializes blank white material
+ */
+CoglHandle cogl_material_new (void);
+
+/**
+ * cogl_material_ref:
+ * @handle: a @CoglHandle.
+ *
+ * Increment the reference count for a cogl material.
+ *
+ * Returns: the @handle.
+ */
+CoglHandle cogl_material_ref (CoglHandle handle);
+
+/**
+ * cogl_material_unref:
+ * @handle: a @CoglHandle.
+ *
+ * Deccrement the reference count for a cogl material.
+ */
+void cogl_material_unref (CoglHandle handle);
+
+/**
+ * cogl_material_set_diffuse:
+ * @material: A CoglMaterial object
+ * @diffuse: The components of the desired diffuse color
+ *
+ * Exposing the standard OpenGL lighting model; this function sets
+ * the material's diffuse color. The diffuse color is most intense
+ * where the light hits the surface directly; perpendicular to the
+ * surface.
+ */
+void cogl_material_set_diffuse (CoglHandle material,
+ const CoglColor *diffuse);
+
+/**
+ * cogl_material_set_ambient:
+ * @material: A CoglMaterial object
+ * @ambient: The components of the desired ambient color
+ *
+ * Exposing the standard OpenGL lighting model; this function sets
+ * the material's ambient color. The ambient color affects the overall
+ * color of the object. Since the diffuse color will be intense when
+ * the light hits the surface directly, the ambient will most aparent
+ * where the light hits at a slant.
+ */
+void cogl_material_set_ambient (CoglHandle material,
+ const CoglColor *ambient);
+
+/**
+ * cogl_material_set_ambient_and_diffuse:
+ * @material: A CoglMaterial object
+ * @color: The components of the desired ambient and diffuse colors
+ *
+ * This is a convenience for setting the diffuse and ambient color
+ * of the material at the same time.
+ */
+void cogl_material_set_ambient_and_diffuse (CoglHandle material,
+ const CoglColor *color);
+
+/**
+ * cogl_material_set_specular:
+ * @material: A CoglMaterial object
+ * @specular: The components of the desired specular color
+ *
+ * Exposing the standard OpenGL lighting model; this function sets
+ * the material's specular color. The intensity of the specular color
+ * depends on the viewport position, and is brightest along the lines
+ * of reflection.
+ */
+void cogl_material_set_specular (CoglHandle material,
+ const CoglColor *specular);
+
+/**
+ * cogl_material_set_shininess:
+ * @material: A CoglMaterial object
+ * shininess: The desired shininess; range: [0.0, 1.0]
+ *
+ * This function sets the materials shininess which determines how
+ * specular highlights are calculated. A higher shininess will produce
+ * smaller brigher highlights.
+ */
+void cogl_material_set_shininess (CoglHandle material,
+ float shininess);
+
+/**
+ * cogl_material_set_emission:
+ * @material: A CoglMaterial object
+ * @emission: The components of the desired emissive color
+ *
+ * Exposing the standard OpenGL lighting model; this function sets
+ * the material's emissive color. It will look like the surface is
+ * a light source emitting this color.
+ */
+void cogl_material_set_emission (CoglHandle material,
+ const CoglColor *emission);
+
+/**
+ * cogl_set_source:
+ * @material: A CoglMaterial object
+ *
+ * This function sets the source material that will be used to fill
+ * subsequent geometry emitted via the cogl API.
+ *
+ * XXX: This doesn't really belong to the cogl-material API, it should
+ * move to cogl.h
+ */
+void cogl_set_source (CoglHandle material);
+
+/**
+ * cogl_material_set_alpha_test_func:
+ * @material: A CoglMaterial object
+ *
+ * Before a primitive is blended with the framebuffer, it goes through an
+ * alpha test stage which lets you discard fragments based on the current
+ * alpha value. This function lets you change the function used to evaluate
+ * the alpha channel, and thus determine which fragments are discarded
+ * and which continue on to the blending stage.
+ * TODO: expand on this
+ */
+void cogl_material_set_alpha_test_func (CoglHandle material,
+ CoglMaterialAlphaFunc alpha_func,
+ float alpha_reference);
+
+/**
+ * cogl_material_set_blend_function:
+ * @material: A CoglMaterial object
+ * @src_factor: Chooses the source factor you want plugged in to the blend
+ * equation.
+ * @dst_factor: Chooses the source factor you want plugged in to the blend
+ * equation.
+ *
+ * This function lets you control how primitives using this material will get
+ * blended with the contents of your framebuffer. The blended RGBA components
+ * are calculated like this:
+ *
+ * (RsSr+RdDr, GsSg+GdDg, BsSb+BsSb, AsSa+AdDa)
+ *
+ * Where (Rs,Gs,Bs,As) represents your source - material- color,
+ * (Rd,Gd,Bd,Ad) represents your destination - framebuffer - color,
+ * (Sr,Sg,Sb,Sa) represents your source blend factor and
+ * (Dr,Dg,Db,Da) represents you destination blend factor.
+ *
+ * All factors lie in the range [0,1] and incoming color components are also
+ * normalized to the range [0,1]
+ *
+ * The factors are selected with the following constants:
+ * <itemizedlist>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_ZERO: (0,0,0,0)</listitem>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_ONE: (1,1,1,1)</listitem>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_DST_COLOR: (Rd,Gd,Bd,Ad)</listitem>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_SRC_COLOR: (Rs,Gs,Bs,As)</listitem>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
+ * (1,1,1,1)-(Rd,Gd,Bd,Ad) [Only valid for src_factor]</listitem>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
+ * (1,1,1,1)-(Rs,Gs,Bs,As)</listitem>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA: (As,As,As,As)</listitem>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
+ * (1,1,1,1)-(As,As,As,As) [Only valid for dst_factor]</listitem>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_DST_ALPHA: (Ad,Ad,Ad,Ad)</listitem>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
+ * (1,1,1,1)-(Ad,Ad,Ad,Ad)</listitem>
+ * <listitem>COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA_SATURATE:
+ * (f,f,f,1) where f=MIN(As,1-Ad)</listitem>
+ * </itemizedlist>
+ */
+void cogl_material_set_blend_function (CoglHandle material,
+ CoglMaterialBlendFactor src_factor,
+ CoglMaterialBlendFactor dst_factor);
+
+/**
+ * cogl_material_set_layer:
+ * @material: A CoglMaterial object
+ *
+ * In addition to the standard OpenGL lighting model a Cogl material may have
+ * one or more layers comprised of textures that can be blended together in
+ * order with a number of different texture combine modes. This function
+ * defines a new texture layer.
+ *
+ * The index values of multiple layers do not have to be consecutive; it is
+ * only their relative order that is important.
+ *
+ * XXX: In the future, we may define other types of material layers, such
+ * as purely GLSL based layers.
+ */
+void cogl_material_set_layer (CoglHandle material,
+ gint layer_index,
+ CoglHandle texture);
+
+/**
+ * cogl_material_add_texture:
+ * @material: A CoglMaterial object
+ *
+ *
+ */
+void cogl_material_remove_layer (CoglHandle material,
+ gint layer_index);
+
+/**
+ * cogl_material_set_layer_alpha_combine_func:
+ * @material: A CoglMaterial object
+ *
+ * TODO: Brew, a nice hot cup of tea, and document these functions...
+ */
+void cogl_material_set_layer_combine_func (
+ CoglHandle material,
+ gint layer_index,
+ CoglMaterialLayerCombineChannels channels,
+ CoglMaterialLayerCombineFunc func);
+
+void cogl_material_set_layer_combine_arg_src (
+ CoglHandle material,
+ gint layer_index,
+ gint argument,
+ CoglMaterialLayerCombineChannels channels,
+ CoglMaterialLayerCombineSrc src);
+
+void cogl_material_set_layer_combine_arg_op (
+ CoglHandle material,
+ gint layer_index,
+ gint argument,
+ CoglMaterialLayerCombineChannels channels,
+ CoglMaterialLayerCombineOp op);
+
+/* TODO: */
+#if 0
+ I think it would be be really neat to support a simple string description
+ of the fixed function texture combine modes exposed above. I think we can
+ consider this stuff to be set in stone from the POV that more advanced
+ texture combine functions are catered for with GLSL, so it seems reasonable
+ to find a concise string representation that can represent all the above
+ modes in a *much* more readable/useable fashion. I think somthing like
+ this would be quite nice:
+
+ "MODULATE(TEXTURE[RGB], PREVIOUS[A])"
+ "ADD(TEXTURE[A],PREVIOUS[RGB])"
+ "INTERPOLATE(TEXTURE[1-A], PREVIOUS[RGB])"
+
+void cogl_material_set_layer_rgb_combine (CoglHandle material
+ gint layer_index,
+ const char *combine_description);
+void cogl_material_set_layer_alpha_combine (CoglHandle material
+ gint layer_index,
+ const char *combine_description);
+#endif
+
+/**
+ * cogl_material_set_layer_matrix:
+ * @material: A CoglMaterial object
+ *
+ * This function lets you set a matrix that can be used to e.g. translate
+ * and rotate a single layer of a material used to fill your geometry.
+ */
+void cogl_material_set_layer_matrix (CoglHandle material,
+ gint layer_index,
+ CoglMatrix *matrix);
+
+/**
+ * cogl_material_get_cogl_enable_flags:
+ * @material: A CoglMaterial object
+ *
+ * This determines what flags need to be passed to cogl_enable before
+ * this material can be used. Normally you shouldn't need to use this
+ * function directly since Cogl will do this internally, but if you are
+ * developing custom primitives directly with OpenGL you may want to use
+ * this.
+ *
+ * Note: This API is hopfully just a stop-gap solution. Ideally
+ * cogl_enable will be replaced.
+ */
+gulong
+cogl_material_get_cogl_enable_flags (CoglHandle handle);
+
+/**
+ * cogl_material_flush_gl_material_state:
+ * @material: A CoglMaterial object
+ *
+ * This commits the glMaterial state to the OpenGL driver. Normally you
+ * shouldn't need to use this function directly, since Cogl will do this
+ * internally, but if you are developing custom primitives directly with
+ * OpenGL you may want to use this.
+ */
+void cogl_material_flush_gl_material_state (CoglHandle material_handle);
+
+/**
+ * cogl_material_flush_gl_alpha_func:
+ * @material: A CoglMaterial object
+ *
+ */
+void cogl_material_flush_gl_alpha_func (CoglHandle material_handle);
+
+/**
+ * cogl_material_flush_gl_blend_func:
+ * @material: A CoglMaterial object
+ *
+ */
+void cogl_material_flush_gl_blend_func (CoglHandle material_handle);
+
+/**
+ * cogl_material_get_layers:
+ * @material: A CoglMaterial object
+ *
+ * This function lets you access a materials internal list of layers
+ * for iteration.
+ *
+ * Note: Normally you shouldn't need to use this function directly since
+ * Cogl will do this internally, but if you are developing custom primitives
+ * directly with OpenGL, you will need to iterate the layers that you want
+ * to texture with.
+ *
+ * Note: This function may return more layers than OpenGL can use at once
+ * so it's your responsability limit yourself to
+ * CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS.
+ *
+ * Note: It's a bit out of the ordinary to return a const GList *, but it
+ * was considered sensible to try and avoid list manipulation for every
+ * primitive emitted in a scene, every frame.
+ */
+const GList *cogl_material_get_layers (CoglHandle material_handle);
+
+/**
+ * cogl_material_layer_get_type:
+ * @material: A CoglMaterial object
+ *
+ * Currently there is only one type of layer defined:
+ * COGL_MATERIAL_LAYER_TYPE_TEXTURE, but considering we may add purely GLSL
+ * based layers in the future, you should write code that checks the type
+ * first.
+ *
+ * Note: Normally you shouldn't need to use this function directly since
+ * Cogl will do this internally, but if you are developing custom primitives
+ * directly with OpenGL, you will need to iterate the layers that you want
+ * to texture with, and thus should be checking the layer types.
+ */
+CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle);
+
+/**
+ * cogl_material_layer_get_texture:
+ * @material: A CoglMaterial object
+ *
+ * This lets you extract a CoglTexture handle for a specific layer. Normally
+ * you shouldn't need to use this function directly since Cogl will do this
+ * internally, but if you are developing custom primitives directly with
+ * OpenGL you may need this.
+ *
+ * Note: In the future, we may support purely GLSL based layers which will
+ * likley return COGL_INVALID_HANDLE if you try to get the texture.
+ * Considering this, you should always call cogl_material_layer_get_type
+ * first, to check it is of type COGL_MATERIAL_LAYER_TYPE_TEXTURE.
+ */
+CoglHandle cogl_material_layer_get_texture (CoglHandle layer_handle);
+
+/**
+ * cogl_material_layer_flush_gl_sampler_state:
+ * @material: A CoglMaterial object
+ *
+ * This commits the sampler state for a single material layer to the OpenGL
+ * driver. Normally you shouldn't need to use this function directly since
+ * Cogl will do this internally, but if you are developing custom primitives
+ * directly with OpenGL you may want to use this.
+ *
+ * Note: It assumes you have already activated the appropriate sampler
+ * by calling glActiveTexture ();
+ */
+void cogl_material_layer_flush_gl_sampler_state (CoglHandle layer_handle);
+
+#endif /* __COGL_MATERIAL_H__ */
+
#include <cogl/cogl-defines-@CLUTTER_COGL@.h>
#include <cogl/cogl-mesh.h>
+#include <cogl/cogl-matrix.h>
#include <cogl/cogl-fixed.h>
#include <cogl/cogl-color.h>
#include <cogl/cogl-offscreen.h>
+#include <cogl/cogl-material.h>
#include <cogl/cogl-path.h>
#include <cogl/cogl-shader.h>
#include <cogl/cogl-texture.h>
cogl-fixed.c \
cogl-color.c \
cogl-mesh.c \
- cogl-matrix.c
+ cogl-matrix.c \
+ cogl-material.c
--- /dev/null
+#ifndef __COGL_MATERIAL_PRIVATE_H
+#define __COGL_MATERIAL_PRIVATE_H
+
+#include "cogl-material.h"
+#include "cogl-matrix.h"
+
+#include <glib.h>
+
+typedef struct _CoglMaterial CoglMaterial;
+typedef struct _CoglMaterialLayer CoglMaterialLayer;
+
+typedef enum _CoglMaterialLayerFlags
+{
+ COGL_MATERIAL_LAYER_FLAG_USER_MATRIX = 1L<<0,
+} CoglMaterialLayerFlags;
+
+struct _CoglMaterialLayer
+{
+ guint ref_count;
+ guint index; /*!< lowest index is blended first then others
+ on top */
+ gulong flags;
+ CoglHandle texture; /*!< The texture for this layer, or COGL_INVALID_HANDLE
+ for an empty layer */
+
+ /* Determines how the color of individual texture fragments
+ * are calculated. */
+ CoglMaterialLayerCombineFunc texture_combine_rgb_func;
+ CoglMaterialLayerCombineSrc texture_combine_rgb_src[3];
+ CoglMaterialLayerCombineOp texture_combine_rgb_op[3];
+
+ CoglMaterialLayerCombineFunc texture_combine_alpha_func;
+ CoglMaterialLayerCombineSrc texture_combine_alpha_src[3];
+ CoglMaterialLayerCombineOp texture_combine_alpha_op[3];
+
+ /* TODO: Support purely GLSL based material layers */
+
+ CoglMatrix matrix;
+};
+
+typedef enum _CoglMaterialFlags
+{
+ COGL_MATERIAL_FLAG_ENABLE_BLEND = 1L<<0,
+ COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING = 1L<<1
+} CoglMaterialFlags;
+
+struct _CoglMaterial
+{
+ guint ref_count;
+
+ gulong flags;
+
+ /* Standard OpenGL lighting model attributes */
+ GLfloat ambient[4];
+ GLfloat diffuse[4];
+ GLfloat specular[4];
+ GLfloat emission[4];
+ GLfloat shininess;
+
+ /* Determines what fragments are discarded based on their alpha */
+ CoglMaterialAlphaFunc alpha_func;
+ GLfloat alpha_func_reference;
+
+ /* Determines how this material is blended with other primitives */
+ CoglMaterialBlendFactor blend_src_factor;
+ CoglMaterialBlendFactor blend_dst_factor;
+
+ GList *layers;
+};
+
+#endif /* __COGL_MATERIAL_PRIVATE_H */
+
--- /dev/null
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl.h"
+#include "cogl-internal.h"
+#include "cogl-context.h"
+#include "cogl-handle.h"
+
+#include "cogl-material-private.h"
+
+#include <glib.h>
+
+static void _cogl_material_free (CoglMaterial *tex);
+static void _cogl_material_layer_free (CoglMaterialLayer *layer);
+
+COGL_HANDLE_DEFINE (Material, material, material_handles);
+COGL_HANDLE_DEFINE (MaterialLayer,
+ material_layer,
+ material_layer_handles);
+
+CoglHandle
+cogl_material_new (void)
+{
+ /* Create new - blank - material */
+ CoglMaterial *material = g_new0 (CoglMaterial, 1);
+ GLfloat *ambient = material->ambient;
+ GLfloat *diffuse = material->diffuse;
+ GLfloat *specular = material->specular;
+ GLfloat *emission = material->emission;
+
+ material->ref_count = 1;
+ COGL_HANDLE_DEBUG_NEW (material, material);
+
+ /* Use the same defaults as the GL spec... */
+ ambient[0] = 0.2; ambient[1] = 0.2; ambient[2] = 0.2; ambient[3] = 1.0;
+ diffuse[0] = 0.8; diffuse[1] = 0.8; diffuse[2] = 0.8; diffuse[3] = 1.0;
+ specular[0] = 0; specular[1] = 0; specular[2] = 0; specular[3] = 1.0;
+ emission[0] = 0; emission[1] = 0; emission[2] = 0; emission[3] = 1.0;
+
+ /* Use the same defaults as the GL spec... */
+ material->alpha_func = COGL_MATERIAL_ALPHA_FUNC_ALWAYS;
+ material->alpha_func_reference = 0.0;
+
+ /* Not the same as the GL default, but seems saner... */
+ material->blend_src_factor = COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA;
+ material->blend_dst_factor = COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ material->layers = NULL;
+
+ return _cogl_material_handle_new (material);
+}
+
+static void
+_cogl_material_free (CoglMaterial *material)
+{
+ /* Frees material resources but its handle is not
+ released! Do that separately before this! */
+
+ g_list_foreach (material->layers,
+ (GFunc)cogl_material_layer_unref, NULL);
+ g_free (material);
+}
+
+void
+cogl_material_set_ambient (CoglHandle handle,
+ const CoglColor *ambient_color)
+{
+ CoglMaterial *material;
+ GLfloat *ambient;
+
+ g_return_if_fail (cogl_is_material (handle));
+
+ material = _cogl_material_pointer_from_handle (handle);
+
+ ambient = material->ambient;
+ ambient[0] = cogl_color_get_red_float (ambient_color);
+ ambient[1] = cogl_color_get_green_float (ambient_color);
+ ambient[2] = cogl_color_get_blue_float (ambient_color);
+ ambient[3] = cogl_color_get_alpha_float (ambient_color);
+ /* material->ambient = *ambient_color; */
+}
+
+void
+cogl_material_set_diffuse (CoglHandle handle,
+ const CoglColor *diffuse_color)
+{
+ CoglMaterial *material;
+ GLfloat *diffuse;
+
+ g_return_if_fail (cogl_is_material (handle));
+
+ material = _cogl_material_pointer_from_handle (handle);
+
+ diffuse = material->diffuse;
+ diffuse[0] = cogl_color_get_red_float (diffuse_color);
+ diffuse[1] = cogl_color_get_green_float (diffuse_color);
+ diffuse[2] = cogl_color_get_blue_float (diffuse_color);
+ diffuse[3] = cogl_color_get_alpha_float (diffuse_color);
+ /* material->diffuse = *diffuse_color; */
+}
+
+void
+cogl_material_set_ambient_and_diffuse (CoglHandle handle,
+ const CoglColor *color)
+{
+ cogl_material_set_ambient (handle, color);
+ cogl_material_set_diffuse (handle, color);
+}
+
+void
+cogl_material_set_specular (CoglHandle handle,
+ const CoglColor *specular_color)
+{
+ CoglMaterial *material;
+ GLfloat *specular;
+
+ g_return_if_fail (cogl_is_material (handle));
+
+ material = _cogl_material_pointer_from_handle (handle);
+
+ specular = material->specular;
+ specular[0] = cogl_color_get_red_float (specular_color);
+ specular[1] = cogl_color_get_green_float (specular_color);
+ specular[2] = cogl_color_get_blue_float (specular_color);
+ specular[3] = cogl_color_get_alpha_float (specular_color);
+ /* material->specular = *specular_color; */
+}
+
+void
+cogl_material_set_shininess (CoglHandle handle,
+ float shininess)
+{
+ CoglMaterial *material;
+
+ g_return_if_fail (cogl_is_material (handle));
+
+ if (shininess < 0.0 || shininess > 1.0)
+ g_warning ("Out of range shininess %f supplied for material\n",
+ shininess);
+
+ material = _cogl_material_pointer_from_handle (handle);
+
+ material->shininess = (GLfloat)shininess * 128.0;
+}
+
+void
+cogl_material_set_emission (CoglHandle handle,
+ const CoglColor *emission_color)
+{
+ CoglMaterial *material;
+ GLfloat *emission;
+
+ g_return_if_fail (cogl_is_material (handle));
+
+ material = _cogl_material_pointer_from_handle (handle);
+
+ emission = material->emission;
+ emission[0] = cogl_color_get_red_float (emission_color);
+ emission[1] = cogl_color_get_green_float (emission_color);
+ emission[2] = cogl_color_get_blue_float (emission_color);
+ emission[3] = cogl_color_get_alpha_float (emission_color);
+ /* material->emission = *emission_color; */
+}
+
+/* TODO: Should go in cogl.c */
+void
+cogl_set_source (CoglHandle material_handle)
+{
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ g_return_if_fail (cogl_is_material (material_handle));
+
+ if (ctx->source_material)
+ cogl_material_unref (ctx->source_material);
+
+ cogl_material_ref (material_handle);
+ ctx->source_material = material_handle;
+}
+
+void
+cogl_material_set_alpha_test_func (CoglHandle handle,
+ CoglMaterialAlphaFunc alpha_func,
+ float alpha_reference)
+{
+ CoglMaterial *material;
+
+ g_return_if_fail (cogl_is_material (handle));
+
+ material = _cogl_material_pointer_from_handle (handle);
+ material->alpha_func = alpha_func;
+ material->alpha_func_reference = (GLfloat)alpha_reference;
+}
+
+void
+cogl_material_set_blend_function (CoglHandle handle,
+ CoglMaterialBlendFactor src_factor,
+ CoglMaterialBlendFactor dst_factor)
+{
+ CoglMaterial *material;
+
+ g_return_if_fail (cogl_is_material (handle));
+
+ material = _cogl_material_pointer_from_handle (handle);
+ material->blend_src_factor = src_factor;
+ material->blend_dst_factor = dst_factor;
+}
+
+/* Asserts that a layer corresponding to the given index exists. If no
+ * match is found, then a new empty layer is added.
+ */
+static CoglMaterialLayer *
+_cogl_material_get_layer (CoglMaterial *material,
+ gint index,
+ gboolean create_if_not_found)
+{
+ CoglMaterialLayer *layer;
+ GList *tmp;
+ CoglHandle layer_handle;
+
+ for (tmp = material->layers; tmp != NULL; tmp = tmp->next)
+ {
+ layer =
+ _cogl_material_layer_pointer_from_handle ((CoglHandle)tmp->data);
+ if (layer->index == index)
+ return layer;
+
+ /* The layers are always sorted, so at this point we know this layer
+ * doesn't exist */
+ if (layer->index > index)
+ break;
+ }
+ /* NB: if we now insert a new layer before tmp, that will maintain order.
+ */
+
+ if (!create_if_not_found)
+ return NULL;
+
+ layer = g_new0 (CoglMaterialLayer, 1);
+
+ layer->ref_count = 1;
+ layer->index = index;
+ layer->texture = COGL_INVALID_HANDLE;
+
+ /* Choose the same default combine mode as OpenGL:
+ * MODULATE(PREVIOUS[RGBA],TEXTURE[RGBA]) */
+ layer->texture_combine_rgb_func = COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE;
+ layer->texture_combine_rgb_src[0] = COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS;
+ layer->texture_combine_rgb_src[1] = COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE;
+ layer->texture_combine_rgb_op[0] = COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR;
+ layer->texture_combine_rgb_op[1] = COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR;
+ layer->texture_combine_alpha_func =
+ COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE;
+ layer->texture_combine_alpha_src[0] =
+ COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS;
+ layer->texture_combine_alpha_src[1] =
+ COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE;
+ layer->texture_combine_alpha_op[0] =
+ COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA;
+ layer->texture_combine_alpha_op[1] =
+ COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA;
+
+ layer_handle = _cogl_material_layer_handle_new (layer);
+ /* Note: see comment after for() loop above */
+ material->layers =
+ g_list_insert_before (material->layers, tmp, layer_handle);
+
+ return layer;
+}
+
+void
+cogl_material_set_layer (CoglHandle material_handle,
+ gint layer_index,
+ CoglHandle texture_handle)
+{
+ CoglMaterial *material;
+ CoglMaterialLayer *layer;
+ int n_layers;
+
+ g_return_if_fail (cogl_is_material (material_handle));
+ g_return_if_fail (cogl_is_texture (texture_handle));
+
+ material = _cogl_material_pointer_from_handle (material_handle);
+ layer = _cogl_material_get_layer (material_handle, layer_index, TRUE);
+
+ /* XXX: If we expose manual control over ENABLE_BLEND, we'll add
+ * a flag to know when it's user configured, so we don't trash it */
+ if (cogl_texture_get_format (texture_handle) & COGL_A_BIT)
+ material->flags |= COGL_MATERIAL_FLAG_ENABLE_BLEND;
+
+ n_layers = g_list_length (material->layers);
+ if (n_layers >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
+ {
+ if (!(material->flags & COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING))
+ {
+ g_warning ("Your hardware doesnot have enough texture samplers"
+ "to handle this many texture layers");
+ material->flags |= COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING;
+ }
+ /* Note: We always make a best effort attempt to display as many
+ * layers as possible, so this isn't an _error_ */
+ /* Note: in the future we may support enabling/disabling layers
+ * too, so it may become valid to add more than
+ * MAX_COMBINED_TEXTURE_IMAGE_UNITS layers. */
+ }
+
+ if (layer->texture)
+ cogl_texture_unref (layer->texture);
+
+ cogl_texture_ref (texture_handle);
+ layer->texture = texture_handle;
+}
+
+void
+cogl_material_set_layer_combine_func (
+ CoglHandle handle,
+ gint layer_index,
+ CoglMaterialLayerCombineChannels channels,
+ CoglMaterialLayerCombineFunc func)
+{
+ CoglMaterial *material;
+ CoglMaterialLayer *layer;
+ gboolean set_alpha_func = FALSE;
+ gboolean set_rgb_func = FALSE;
+
+ g_return_if_fail (cogl_is_material (handle));
+
+ material = _cogl_material_pointer_from_handle (handle);
+ layer = _cogl_material_get_layer (material, layer_index, FALSE);
+ if (!layer)
+ return;
+
+ if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA)
+ set_alpha_func = set_rgb_func = TRUE;
+ else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB)
+ set_rgb_func = TRUE;
+ else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA)
+ set_alpha_func = TRUE;
+
+ if (set_rgb_func)
+ layer->texture_combine_rgb_func = func;
+ if (set_alpha_func)
+ layer->texture_combine_alpha_func = func;
+}
+
+void
+cogl_material_set_layer_combine_arg_src (
+ CoglHandle handle,
+ gint layer_index,
+ gint argument,
+ CoglMaterialLayerCombineChannels channels,
+ CoglMaterialLayerCombineSrc src)
+{
+ CoglMaterial *material;
+ CoglMaterialLayer *layer;
+ gboolean set_arg_alpha_src = FALSE;
+ gboolean set_arg_rgb_src = FALSE;
+
+ g_return_if_fail (cogl_is_material (handle));
+ g_return_if_fail (argument >=0 && argument <= 3);
+
+ material = _cogl_material_pointer_from_handle (handle);
+ layer = _cogl_material_get_layer (material, layer_index, FALSE);
+ if (!layer)
+ return;
+
+ if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA)
+ set_arg_alpha_src = set_arg_rgb_src = TRUE;
+ else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB)
+ set_arg_rgb_src = TRUE;
+ else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA)
+ set_arg_alpha_src = TRUE;
+
+ if (set_arg_rgb_src)
+ layer->texture_combine_rgb_src[argument] = src;
+ if (set_arg_alpha_src)
+ layer->texture_combine_alpha_src[argument] = src;
+}
+
+void
+cogl_material_set_layer_combine_arg_op (
+ CoglHandle material_handle,
+ gint layer_index,
+ gint argument,
+ CoglMaterialLayerCombineChannels channels,
+ CoglMaterialLayerCombineOp op)
+{
+ CoglMaterial *material;
+ CoglMaterialLayer *layer;
+ gboolean set_arg_alpha_op = FALSE;
+ gboolean set_arg_rgb_op = FALSE;
+
+ g_return_if_fail (cogl_is_material (material_handle));
+ g_return_if_fail (argument >=0 && argument <= 3);
+
+ material = _cogl_material_pointer_from_handle (material_handle);
+ layer = _cogl_material_get_layer (material, layer_index, FALSE);
+ if (!layer)
+ return;
+
+ if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA)
+ set_arg_alpha_op = set_arg_rgb_op = TRUE;
+ else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB)
+ set_arg_rgb_op = TRUE;
+ else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA)
+ set_arg_alpha_op = TRUE;
+
+ if (set_arg_rgb_op)
+ layer->texture_combine_rgb_op[argument] = op;
+ if (set_arg_alpha_op)
+ layer->texture_combine_alpha_op[argument] = op;
+}
+
+void
+cogl_material_set_layer_matrix (CoglHandle material_handle,
+ gint layer_index,
+ CoglMatrix *matrix)
+{
+ CoglMaterial *material;
+ CoglMaterialLayer *layer;
+
+ g_return_if_fail (cogl_is_material (material_handle));
+
+ material = _cogl_material_pointer_from_handle (material_handle);
+ layer = _cogl_material_get_layer (material, layer_index, FALSE);
+ if (!layer)
+ return;
+
+ layer->matrix = *matrix;
+ layer->flags |= COGL_MATERIAL_LAYER_FLAG_USER_MATRIX;
+}
+
+static void
+_cogl_material_layer_free (CoglMaterialLayer *layer)
+{
+ cogl_texture_unref (layer->texture);
+ g_free (layer);
+}
+
+void
+cogl_material_remove_layer (CoglHandle material_handle,
+ gint layer_index)
+{
+ CoglMaterial *material;
+ CoglMaterialLayer *layer;
+ GList *tmp;
+
+ g_return_if_fail (cogl_is_material (material_handle));
+
+ material = _cogl_material_pointer_from_handle (material_handle);
+ material->flags &= ~COGL_MATERIAL_FLAG_ENABLE_BLEND;
+ for (tmp = material->layers; tmp != NULL; tmp = tmp->next)
+ {
+ layer = tmp->data;
+ if (layer->index == layer_index)
+ {
+ CoglHandle handle =
+ _cogl_material_layer_handle_from_pointer (layer);
+ cogl_material_layer_unref (handle);
+ material->layers = g_list_remove (material->layers, layer);
+ continue;
+ }
+
+ /* XXX: If we expose manual control over ENABLE_BLEND, we'll add
+ * a flag to know when it's user configured, so we don't trash it */
+ if (cogl_texture_get_format (layer->texture) & COGL_A_BIT)
+ material->flags |= COGL_MATERIAL_FLAG_ENABLE_BLEND;
+ }
+}
+
+/* XXX: This API is hopfully just a stop-gap solution. Ideally cogl_enable
+ * will be replaced. */
+gulong
+cogl_material_get_cogl_enable_flags (CoglHandle material_handle)
+{
+ CoglMaterial *material;
+ gulong enable_flags = 0;
+
+ _COGL_GET_CONTEXT (ctx, 0);
+
+ g_return_val_if_fail (cogl_is_material (material_handle), 0);
+
+ material = _cogl_material_pointer_from_handle (material_handle);
+
+ /* Enable blending if the geometry has an associated alpha color,
+ * or the material wants blending enabled. */
+ if (material->flags & COGL_MATERIAL_FLAG_ENABLE_BLEND
+ || ctx->color_alpha < 255)
+ enable_flags |= COGL_ENABLE_BLEND;
+
+ return enable_flags;
+}
+
+void
+cogl_material_flush_gl_material_state (CoglHandle material_handle)
+{
+ CoglMaterial *material;
+
+ g_return_if_fail (cogl_is_material (material_handle));
+
+ material = _cogl_material_pointer_from_handle (material_handle);
+
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, material->ambient));
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, material->diffuse));
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, material->specular));
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, material->emission));
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &material->shininess));
+}
+
+void
+cogl_material_flush_gl_alpha_func (CoglHandle material_handle)
+{
+ CoglMaterial *material;
+
+ g_return_if_fail (cogl_is_material (material_handle));
+
+ material = _cogl_material_pointer_from_handle (material_handle);
+
+ /* NB: Currently the Cogl defines are compatible with the GL ones: */
+ GE (glAlphaFunc (material->alpha_func, material->alpha_func_reference));
+}
+
+void
+cogl_material_flush_gl_blend_func (CoglHandle material_handle)
+{
+ CoglMaterial *material;
+
+ g_return_if_fail (cogl_is_material (material_handle));
+ GE (glBlendFunc (material->blend_src_factor, material->blend_dst_factor));
+}
+
+/* It's a bit out of the ordinary to return a const GList *, but it's
+ * probably sensible to try and avoid list manipulation for every
+ * primitive emitted in a scene, every frame.
+ *
+ * Alternativly; we could either add a _foreach function, or maybe
+ * a function that gets a passed a buffer (that may be stack allocated)
+ * by the caller.
+ */
+const GList *
+cogl_material_get_layers (CoglHandle material_handle)
+{
+ CoglMaterial *material;
+
+ g_return_val_if_fail (cogl_is_material (material_handle), NULL);
+
+ material = _cogl_material_pointer_from_handle (material_handle);
+
+ return material->layers;
+}
+
+CoglMaterialLayerType
+cogl_material_layer_get_type (CoglHandle layer_handle)
+{
+ return COGL_MATERIAL_LAYER_TYPE_TEXTURE;
+}
+
+CoglHandle
+cogl_material_layer_get_texture (CoglHandle layer_handle)
+{
+ CoglMaterialLayer *layer;
+
+ g_return_val_if_fail (cogl_is_material_layer (layer_handle),
+ COGL_INVALID_HANDLE);
+
+ layer = _cogl_material_layer_pointer_from_handle (layer_handle);
+ return layer->texture;
+}
+
+static guint
+get_n_args_for_combine_func (CoglMaterialLayerCombineFunc func)
+{
+ switch (func)
+ {
+ case COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE:
+ return 1;
+ case COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE:
+ case COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD:
+ case COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED:
+ case COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT:
+ case COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB:
+ case COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA:
+ return 2;
+ case COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE:
+ return 3;
+ }
+ return 0;
+}
+
+void
+cogl_material_layer_flush_gl_sampler_state (CoglHandle layer_handle)
+{
+ CoglMaterialLayer *layer;
+ int n_rgb_func_args;
+ int n_alpha_func_args;
+
+ g_return_if_fail (cogl_is_material_layer (layer_handle));
+
+ layer = _cogl_material_layer_pointer_from_handle (layer_handle);
+
+ /* XXX: We really want some kind of cache/dirty flag mechanism
+ * somewhere here so we can avoid as much mucking about with
+ * the texture units per primitive as possible!
+ *
+ * E.g. some recent profiling of clutter-actor suggested that
+ * validating/updating the texture environment may currently
+ * be a significant bottleneck. Given that all the actors should
+ * have the same texture environment, that implies we could do a
+ * much better job of avoiding redundant glTexEnv calls.
+ */
+
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE));
+
+ /* Set the combiner functions... */
+ GE (glTexEnvi (GL_TEXTURE_ENV,
+ GL_COMBINE_RGB,
+ layer->texture_combine_rgb_func));
+ GE (glTexEnvi (GL_TEXTURE_ENV,
+ GL_COMBINE_ALPHA,
+ layer->texture_combine_alpha_func));
+
+ /*
+ * Setup the function arguments...
+ */
+
+ /* For the RGB components... */
+ n_rgb_func_args =
+ get_n_args_for_combine_func (layer->texture_combine_rgb_func);
+
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB,
+ layer->texture_combine_rgb_src[0]));
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
+ layer->texture_combine_rgb_op[0]));
+ if (n_rgb_func_args > 1)
+ {
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB,
+ layer->texture_combine_rgb_src[1]));
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB,
+ layer->texture_combine_rgb_op[1]));
+ }
+ if (n_rgb_func_args > 2)
+ {
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_RGB,
+ layer->texture_combine_rgb_src[2]));
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB,
+ layer->texture_combine_rgb_op[2]));
+ }
+
+ /* For the Alpha component */
+ n_alpha_func_args =
+ get_n_args_for_combine_func (layer->texture_combine_alpha_func);
+
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA,
+ layer->texture_combine_alpha_src[0]));
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA,
+ layer->texture_combine_alpha_op[0]));
+ if (n_alpha_func_args > 1)
+ {
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA,
+ layer->texture_combine_alpha_src[1]));
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA,
+ layer->texture_combine_alpha_op[1]));
+ }
+ if (n_alpha_func_args > 2)
+ {
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_ALPHA,
+ layer->texture_combine_alpha_src[2]));
+ GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA,
+ layer->texture_combine_alpha_op[2]));
+ }
+
+ if (layer->flags & COGL_MATERIAL_LAYER_FLAG_USER_MATRIX)
+ {
+ GE (glMatrixMode (GL_TEXTURE));
+ GE (glLoadMatrixf ((GLfloat *)&layer->matrix));
+ GE (glMatrixMode (GL_MODELVIEW));
+ }
+}
+
+++ /dev/null
-#ifndef __COGL_MATRIX_H
-#define __COGL_MATRIX_H
-
-/* Note: This is ordered according to how OpenGL expects to get 4x4 matrices */
-typedef struct {
- /* column 0 */
- float xx;
- float yx;
- float zx;
- float wx;
-
- /* column 1 */
- float xy;
- float yy;
- float zy;
- float wy;
-
- /* column 2 */
- float xz;
- float yz;
- float zz;
- float wz;
-
- /* column 3 */
- float xw;
- float yw;
- float zw;
- float ww;
-
- /* Note: we may want to extend this later with private flags
- * and a cache of the inverse transform matrix. */
-} CoglMatrix;
-
-void cogl_matrix_init_identity (CoglMatrix *matrix);
-
-void cogl_matrix_multiply (CoglMatrix *result,
- const CoglMatrix *a,
- const CoglMatrix *b);
-
-void cogl_matrix_rotate (CoglMatrix *matrix,
- float angle,
- float x,
- float y,
- float z);
-
-void cogl_matrix_translate (CoglMatrix *matrix,
- float x,
- float y,
- float z);
-
-void cogl_matrix_scale (CoglMatrix *matrix,
- float sx,
- float sy,
- float sz);
-
-#endif /* __COGL_MATRIX_H */
-
_context->texture_vertices_size = 0;
_context->texture_vertices = NULL;
- _context->multi_texture_handles = NULL;
- _context->multi_texture_layer_handles = NULL;
+ _context->material_handles = NULL;
+ _context->material_layer_handles = NULL;
+ _context->source_material = NULL;
_context->fbo_handles = NULL;
_context->draw_buffer = COGL_WINDOW_BUFFER;
CoglTextureGLVertex *texture_vertices;
gulong texture_vertices_size;
- /* Multi Textures */
- GArray *multi_texture_handles;
-
- /* Multi Texture Layers */
- GArray *multi_texture_layer_handles;
+ /* Materials */
+ GArray *material_handles;
+ GArray *material_layer_handles;
+ CoglHandle source_material;
/* Framebuffer objects */
GArray *fbo_handles;
typedef struct _CoglTexture CoglTexture;
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
typedef struct _CoglSpanIter CoglSpanIter;
-typedef struct _CoglMultiTexture CoglMultiTexture;
-typedef struct _CoglMultiTextureLayer CoglMultiTextureLayer;
+typedef struct _CoglCompositeTexture CoglCompositeTexture;
+typedef struct _CoglCompositeTextureLayer CoglCompositeTextureLayer;
struct _CoglTexSliceSpan
{
gboolean auto_mipmap;
};
-struct _CoglMultiTextureLayer
+struct _CoglCompositeTextureLayer
{
guint ref_count;
* unit. For example we should support dot3 normal mapping. */
};
-struct _CoglMultiTexture
+struct _CoglCompositeTexture
{
guint ref_count;
GList *layers;
#include "cogl-util.h"
#include "cogl-bitmap.h"
#include "cogl-texture-private.h"
+#include "cogl-material.h"
#include "cogl-context.h"
#include "cogl-handle.h"
} */
static void _cogl_texture_free (CoglTexture *tex);
-static void _cogl_multi_texture_free (CoglMultiTexture *multi_texture);
-static void _cogl_multi_texture_layer_free (CoglMultiTextureLayer *layer);
COGL_HANDLE_DEFINE (Texture, texture, texture_handles);
-COGL_HANDLE_DEFINE (MultiTexture, multi_texture, multi_texture_handles);
-COGL_HANDLE_DEFINE (MultiTextureLayer,
- multi_texture_layer,
- multi_texture_layer_handles);
struct _CoglSpanIter
{
}
}
-CoglHandle
-cogl_multi_texture_new (void)
-{
- CoglMultiTexture *multi_tex = g_new0 (CoglMultiTexture, 1);
- return _cogl_multi_texture_handle_new (multi_tex);
-}
-
-static void
-_cogl_multi_texture_free (CoglMultiTexture *multi_tex)
-{
- g_list_foreach (multi_tex->layers,
- (GFunc)cogl_multi_texture_layer_unref, NULL);
- g_free (multi_tex);
-}
-
-static CoglMultiTextureLayer *
-_cogl_multi_texture_get_layer (CoglMultiTexture *multi_tex, guint index)
-{
- CoglMultiTextureLayer *layer;
- GList *tmp;
-
- for (tmp = multi_tex->layers; tmp != NULL; tmp = tmp->next)
- {
- layer = tmp->data;
- if (layer->index == index)
- return layer;
-
- /* The layers are always sorted, so we know this layer doesn't exists */
- if (layer->index > index)
- break;
- }
- /* NB: if we now insert a new layer before tmp, that will maintain order.
- */
-
- layer = g_new (CoglMultiTextureLayer, 1);
-
- layer->ref_count = 1;
- layer->index = index;
- /* Note: comment after for() loop above */
- multi_tex->layers = g_list_insert_before (multi_tex->layers, tmp, layer);
-
- return layer;
-}
-
-void
-cogl_multi_texture_layer_set_texture (CoglHandle multi_texture_handle,
- guint layer_index,
- CoglHandle tex_handle)
-{
- CoglMultiTexture *multi_tex;
- CoglMultiTextureLayer *layer;
- CoglTexture *tex;
-
- if (!cogl_is_multi_texture (multi_texture_handle)
- || !cogl_is_texture (tex_handle))
- return;
-
- multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
- layer = _cogl_multi_texture_get_layer (multi_tex, layer_index);
- tex = _cogl_texture_pointer_from_handle (tex_handle);
-
- cogl_texture_ref (tex_handle);
-
- layer->tex = tex;
-}
-
-static void
-_cogl_multi_texture_layer_free (CoglMultiTextureLayer *layer)
-{
- cogl_texture_unref (layer->tex);
- g_free (layer);
-}
-
-void
-cogl_multi_texture_layer_remove (CoglHandle multi_texture_handle,
- guint layer_index)
-{
- CoglMultiTexture *multi_tex;
- CoglMultiTextureLayer *layer;
- GList *tmp;
-
- /* Check if valid multi texture */
- if (!cogl_is_multi_texture (multi_texture_handle))
- return;
-
- multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
- for (tmp = multi_tex->layers; tmp != NULL; tmp = tmp->next)
- {
- layer = tmp->data;
- if (layer->index == layer_index)
- {
- CoglHandle handle =
- _cogl_multi_texture_layer_handle_from_pointer (layer);
- cogl_multi_texture_layer_unref (handle);
- multi_tex->layers = g_list_remove (multi_tex->layers, layer);
- return;
- }
- }
-}
-
void
-cogl_multi_texture_rectangle (CoglHandle multi_texture_handle,
- CoglFixed x1,
- CoglFixed y1,
- CoglFixed x2,
- CoglFixed y2,
- CoglFixed *user_tex_coords)
+cogl_material_rectangle (CoglFixed x1,
+ CoglFixed y1,
+ CoglFixed x2,
+ CoglFixed y2,
+ CoglFixed *user_tex_coords)
{
- CoglMultiTexture *multi_tex;
- GLfloat quad_coords[8];
- GList *tmp;
- GList *valid_layers = NULL;
- int count;
- GLfloat *tex_coords_buff;
- gulong enable_flags = 0;
- /* FIXME - currently cogl deals with enabling texturing
- * via enable flags, but that can't scale to n texture
- * units. Currently we have to be carefull how we leave the
- * environment so we don't break things. See the cleanup
+ CoglHandle material;
+ const GList *layers;
+ int n_layers;
+ const GList *tmp;
+ CoglHandle *valid_layers = NULL;
+ int n_valid_layers = 0;
+ gboolean handle_slicing = FALSE;
+ int i;
+ GLfloat *tex_coords_buff;
+ GLfloat quad_coords[8];
+ gulong enable_flags = 0;
+ GLfloat values[4];
+
+ /* FIXME - currently cogl deals with enabling texturing via enable flags,
+ * but that can't scale to n texture units. Currently we have to be carefull
+ * how we leave the environment so we don't break things. See the cleanup
* notes at the end of this function */
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- /* Check if valid multi texture */
- if (!cogl_is_multi_texture (multi_texture_handle))
- return;
-
- multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
-
-#define CFX_F COGL_FIXED_TO_FLOAT
- quad_coords[0] = CFX_F (x1);
- quad_coords[1] = CFX_F (y1);
- quad_coords[2] = CFX_F (x2);
- quad_coords[3] = CFX_F (y1);
- quad_coords[4] = CFX_F (x1);
- quad_coords[5] = CFX_F (y2);
- quad_coords[6] = CFX_F (x2);
- quad_coords[7] = CFX_F (y2);
-#undef CFX_F
+ material = ctx->source_material;
- enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
- GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords));
+ layers = cogl_material_get_layers (material);
+ n_layers = g_list_length ((GList *)layers);
+ valid_layers = alloca (sizeof (CoglHandle) * n_layers);
- for (count = 0, tmp = multi_tex->layers;
- tmp != NULL;
- count++, tmp = tmp->next)
+ for (tmp = layers; tmp != NULL; tmp = tmp->next)
{
- CoglMultiTextureLayer *layer = tmp->data;
-
- /* Skip empty layers */
- if (!layer->tex)
- {
- count--;
- continue;
- }
-
- /* FIXME - currently we don't support sliced textures */
- if (layer->tex->slice_gl_handles == NULL
- || layer->tex->slice_gl_handles->len < 1)
+ CoglHandle layer = tmp->data;
+ CoglHandle texture = cogl_material_layer_get_texture (layer);
+
+ if (cogl_material_layer_get_type (layer)
+ != COGL_MATERIAL_LAYER_TYPE_TEXTURE)
continue;
- if (count >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
+ /* FIXME: support sliced textures. For now if the first layer is
+ * sliced then all other layers are ignored, or if the first layer
+ * is not sliced, we ignore sliced textures in other layers. */
+ if (cogl_texture_is_sliced (texture))
{
- static gboolean shown_warning = FALSE;
-
- if (!shown_warning)
+ if (n_valid_layers == 0)
{
- g_warning ("Your driver does not support enough texture layers"
- "to correctly handle this multi texturing");
- shown_warning = TRUE;
+ valid_layers[n_valid_layers++] = layer;
+ handle_slicing = TRUE;
+ break;
}
- /* NB: We make a best effort attempt to display as many layers as
- * possible. */
- break;
+ continue;
}
+ valid_layers[n_valid_layers++] = tmp->data;
- if (layer->tex->bitmap.format & COGL_A_BIT)
- enable_flags |= COGL_ENABLE_BLEND;
-
- valid_layers = g_list_prepend (valid_layers, layer);
+ if (n_valid_layers >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
+ break;
}
- valid_layers = g_list_reverse (valid_layers);
-
- /* Enable blending if the geometry has an associated alpha color,
- * or - see above - we also check each layer texture and if any has
- * an alpha channel also enable blending. */
- if (ctx->color_alpha < 255)
- enable_flags |= COGL_ENABLE_BLEND;
- cogl_enable (enable_flags);
-
+
/* NB: It could be that no valid texture layers were found, but
* we will still submit a non-textured rectangle in that case. */
- if (count)
- tex_coords_buff = alloca (sizeof(GLfloat) * 8 * count);
+ if (n_valid_layers)
+ tex_coords_buff = alloca (sizeof(GLfloat) * 8 * n_valid_layers);
- /* NB: valid_layers is in order, sorted by index */
- for (count = 0, tmp = valid_layers;
- tmp != NULL;
- count++, tmp = tmp->next)
+ for (i = 0; i < n_valid_layers; i++)
{
- CoglMultiTextureLayer *layer = tmp->data;
- CoglFixed *in_tex_coords = &user_tex_coords[count * 4];
- GLfloat *out_tex_coords = &tex_coords_buff[count * 8];
- GLenum gl_tex_handle;
+ CoglHandle layer = valid_layers[i];
+ CoglHandle texture = cogl_material_layer_get_texture (layer);
+ CoglFixed *in_tex_coords = &user_tex_coords[i * 4];
+ GLfloat *out_tex_coords = &tex_coords_buff[i * 8];
+ GLuint gl_tex_handle;
#define CFX_F COGL_FIXED_TO_FLOAT
/* IN LAYOUT: [ tx1:0, ty1:1, tx2:2, ty2:3 ] */
#undef CFX_F
/* TODO - support sliced textures */
- gl_tex_handle = g_array_index (layer->tex->slice_gl_handles, GLuint, 0);
+ cogl_texture_get_gl_texture (texture, &gl_tex_handle, NULL);
+ //gl_tex_handle = g_array_index (layer->tex->slice_gl_handles, GLuint, 0);
- GE (glActiveTexture (GL_TEXTURE0 + count));
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
+ GE (glActiveTexture (GL_TEXTURE0 + i));
+ cogl_material_layer_flush_gl_sampler_state (layer);
GE (glBindTexture (GL_TEXTURE_2D, gl_tex_handle));
/* GE (glEnable (GL_TEXTURE_2D)); */
- GE (glClientActiveTexture (GL_TEXTURE0 + count));
+ GE (glClientActiveTexture (GL_TEXTURE0 + i));
GE (glTexCoordPointer (2, GL_FLOAT, 0, out_tex_coords));
/* GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY)); */
/* FIXME - cogl only knows about one texture unit a.t.m
* (Also see cleanup note below) */
- if (count == 0)
- {
- enable_flags |= COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_TEXCOORD_ARRAY;
- cogl_enable (enable_flags);
- }
+ if (i == 0)
+ enable_flags |= COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_TEXCOORD_ARRAY;
else
{
GE (glEnable (GL_TEXTURE_2D));
}
}
+#define CFX_F COGL_FIXED_TO_FLOAT
+ quad_coords[0] = CFX_F (x1);
+ quad_coords[1] = CFX_F (y1);
+ quad_coords[2] = CFX_F (x2);
+ quad_coords[3] = CFX_F (y1);
+ quad_coords[4] = CFX_F (x1);
+ quad_coords[5] = CFX_F (y2);
+ quad_coords[6] = CFX_F (x2);
+ quad_coords[7] = CFX_F (y2);
+#undef CFX_F
+
+ enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
+ GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords));
+
+ /* Setup the remaining GL state according to this material... */
+ cogl_material_flush_gl_material_state (material);
+ cogl_material_flush_gl_alpha_func (material);
+ cogl_material_flush_gl_blend_func (material);
+ /* FIXME: This api is a bit yukky, ideally it will be removed if we
+ * re-work the cogl_enable mechanism */
+ enable_flags |= cogl_material_get_cogl_enable_flags (material);
+
+ /* FIXME - cogl only knows about one texture unit so assumes that unit 0
+ * is always active...*/
+ GE (glActiveTexture (GL_TEXTURE0));
+ GE (glClientActiveTexture (GL_TEXTURE0));
+ cogl_enable (enable_flags);
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
/* FIXME - cogl doesn't currently have a way of caching the
* enable states for more than one texture unit so for now,
* we just disable anything relating to additional units once
* we are done with them. */
- while (--count > 0)
+ for (i = 1; i < n_valid_layers; i++)
{
- GE (glActiveTexture (GL_TEXTURE0 + count));
- GE (glClientActiveTexture (GL_TEXTURE0 + count));
+ GE (glActiveTexture (GL_TEXTURE0 + i));
+ GE (glClientActiveTexture (GL_TEXTURE0 + i));
GE (glDisable (GL_TEXTURE_2D));
GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY));
}
+
+ /* FIXME - CoglMaterials aren't yet used pervasively throughout
+ * the cogl API, so we currently need to cleanup material state
+ * that will confuse other parts of the API.
+ * Other places to tweak, include the primitives API and lite
+ * GL wrappers like cogl_rectangle */
+ values[0] = 0.2; values[1] = 0.2; values[2] = 0.2; values[3] = 1.0;
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, values));
+ values[0] = 0.8; values[1] = 0.8; values[2] = 0.8; values[3] = 1.0;
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, values));
+ values[0] = 0; values[1] = 0; values[2] = 0; values[3] = 1.0;
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, values));
+ values[0] = 0; values[1] = 0; values[2] = 0; values[3] = 1.0;
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, values));
+ values[0] = 0;
+ GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, values));
}
redhand.png \
redhand_alpha.png \
light0.png \
- light1.png \
test-script.json
test-cogl-tex-getset.c \
test-cogl-offscreen.c \
test-cogl-tex-polygon.c \
- test-cogl-multi-texture.c \
+ test-cogl-material.c \
test-stage-read-pixels.c \
test-random-text.c \
test-clip.c \
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+#include <clutter/clutter.h>
+#include <cogl/cogl.h>
+
+#define TIMELINE_FRAME_COUNT 200
+
+typedef struct _TestMultiLayerMaterialState
+{
+ ClutterActor *group;
+ CoglHandle material;
+ CoglHandle alpha_tex;
+ CoglHandle redhand_tex;
+ CoglHandle light_tex0;
+ ClutterFixed *tex_coords;
+
+ CoglMatrix tex_matrix;
+ CoglMatrix rot_matrix;
+
+} TestMultiLayerMaterialState;
+
+
+static void
+frame_cb (ClutterTimeline *timeline,
+ gint frame_no,
+ gpointer data)
+{
+ TestMultiLayerMaterialState *state = data;
+
+ cogl_matrix_multiply (&state->tex_matrix,
+ &state->tex_matrix,
+ &state->rot_matrix);
+ cogl_material_set_layer_matrix (state->material, 2, &state->tex_matrix);
+}
+
+static gboolean
+material_rectangle_paint (ClutterActor *actor, gpointer data)
+{
+ TestMultiLayerMaterialState *state = data;
+
+ cogl_set_source (state->material);
+ cogl_material_rectangle (CLUTTER_INT_TO_FIXED(0),
+ CLUTTER_INT_TO_FIXED(0),
+ CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT),
+ CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT),
+ state->tex_coords);
+}
+
+G_MODULE_EXPORT int
+test_cogl_material_main (int argc, char *argv[])
+{
+ ClutterTimeline *timeline;
+ ClutterAlpha *alpha;
+ ClutterBehaviour *r_behave;
+ ClutterActor *stage;
+ ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff };
+ TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1);
+ ClutterGeometry geom;
+ ClutterFixed tex_coords[] =
+ {
+ /* tx1 ty1 tx2 ty2 */
+ 0, 0, CLUTTER_INT_TO_FIXED (1), CLUTTER_INT_TO_FIXED (1),
+ 0, 0, CLUTTER_INT_TO_FIXED (1), CLUTTER_INT_TO_FIXED (1),
+ 0, 0, CLUTTER_INT_TO_FIXED (1), CLUTTER_INT_TO_FIXED (1)
+ };
+
+ clutter_init (&argc, &argv);
+
+ stage = clutter_stage_get_default ();
+ clutter_actor_get_geometry (stage, &geom);
+
+ clutter_stage_set_color (CLUTTER_STAGE (stage),
+ &stage_color);
+
+ /* We create a non-descript actor that we know doesn't have a
+ * default paint handler, so that we can easily control
+ * painting in a paint signal handler, without having to
+ * sub-class anything etc. */
+ state->group = clutter_group_new ();
+ clutter_actor_set_position (state->group, geom.width/2, geom.height/2);
+ g_signal_connect (state->group, "paint",
+ G_CALLBACK(material_rectangle_paint), state);
+
+ state->alpha_tex =
+ cogl_texture_new_from_file ("./redhand_alpha.png",
+ -1, /* disable slicing */
+ TRUE,
+ COGL_PIXEL_FORMAT_ANY,
+ NULL);
+ state->redhand_tex =
+ cogl_texture_new_from_file ("./redhand.png",
+ -1, /* disable slicing */
+ TRUE,
+ COGL_PIXEL_FORMAT_ANY,
+ NULL);
+ state->light_tex0 =
+ cogl_texture_new_from_file ("./light0.png",
+ -1, /* disable slicing */
+ TRUE,
+ COGL_PIXEL_FORMAT_ANY,
+ NULL);
+
+ state->material = cogl_material_new ();
+ cogl_material_set_layer (state->material, 0, state->alpha_tex);
+ cogl_material_set_layer (state->material, 1, state->redhand_tex);
+ cogl_material_set_layer (state->material, 2, state->light_tex0);
+
+ state->tex_coords = tex_coords;
+
+ cogl_matrix_init_identity (&state->tex_matrix);
+ cogl_matrix_init_identity (&state->rot_matrix);
+
+ cogl_matrix_translate (&state->rot_matrix, 0.5, 0.5, 0);
+ cogl_matrix_rotate (&state->rot_matrix, 10.0, 0, 0, 1.0);
+ cogl_matrix_translate (&state->rot_matrix, -0.5, -0.5, 0);
+
+ clutter_actor_set_anchor_point (state->group, 86, 125);
+ clutter_container_add_actor (CLUTTER_CONTAINER(stage),
+ state->group);
+
+ timeline = clutter_timeline_new (TIMELINE_FRAME_COUNT, 26 /* fps */);
+ g_object_set (timeline, "loop", TRUE, NULL);
+
+ g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), state);
+
+ /* Set an alpha func to power behaviour - ramp is constant rise/fall */
+ alpha = clutter_alpha_new_for_mode (CLUTTER_LINEAR);
+ clutter_alpha_set_timeline (alpha, timeline);
+
+ /* Create a behaviour for that alpha */
+ r_behave = clutter_behaviour_rotate_new (alpha,
+ CLUTTER_Y_AXIS,
+ CLUTTER_ROTATE_CW,
+ 0.0, 360.0);
+
+ /* Apply it to our actor */
+ clutter_behaviour_apply (r_behave, state->group);
+
+ /* start the timeline and thus the animations */
+ clutter_timeline_start (timeline);
+
+ clutter_actor_show_all (stage);
+
+ clutter_main();
+
+ cogl_material_unref (state->material);
+ cogl_texture_unref (state->alpha_tex);
+ cogl_texture_unref (state->redhand_tex);
+ cogl_texture_unref (state->light_tex0);
+ g_free (state);
+
+ g_object_unref (r_behave);
+
+ return 0;
+}
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gmodule.h>
-
-#include <clutter/clutter.h>
-#include <cogl/cogl.h>
-
-#define TIMELINE_FRAME_COUNT 200
-
-typedef struct _MultiTextureState
-{
- ClutterActor *group;
- CoglHandle multi_tex;
- CoglHandle alpha_tex;
- CoglHandle redhand_tex;
- CoglHandle light_tex0;
- CoglHandle light_tex1;
- ClutterFixed *tex_coords;
-
- /* For handling light switching */
- guint last_light_change;
- gboolean light_on;
-
- /* For handling texture coord sliding */
- guint last_frame_no;
- gint light_x_dir;
- gint light_y_dir;
- gint light_x_pos;
- gint light_y_pos;
-
-} MultiTextureState;
-
-
-static void
-frame_cb (ClutterTimeline *timeline,
- gint frame_no,
- gpointer data)
-{
- MultiTextureState *state = data;
- ClutterFixed *tex_coords = &state->tex_coords[8];
- int prev_frame_delta;
- int light_duration;
-
- light_duration = frame_no - state->last_light_change;
- if (light_duration < 0)
- light_duration += TIMELINE_FRAME_COUNT;
-
- if (light_duration > 10)
- {
- if (state->light_on)
- {
- cogl_multi_texture_layer_set_texture (state->multi_tex,
- 2,
- state->light_tex1);
- state->light_on = FALSE;
- }
- else
- {
- cogl_multi_texture_layer_set_texture (state->multi_tex,
- 2,
- state->light_tex0);
- state->light_on = TRUE;
- }
- state->last_light_change = frame_no;
- }
-
- /* slide the texture coordinates */
-
- /* This is worked out as if the texture has a virtual resolution
- * of TIMELINE_FRAME_COUNT x TIMELINE_FRAME_COUNT.
- *
- * We are always showing an apature of the texture that is
- * (TIMELINE_FRAME_COUNT/2) x (TIMELINE_FRAME_COUNT/2)
- *
- * To remain within the texture we don't let the tx1, ty1 positions
- * go past ((TIMELINE_FRAME_COUNT/2), (TIMELINE_FRAME_COUNT/2))
- */
- prev_frame_delta = frame_no - state->last_frame_no;
- if (prev_frame_delta < 0)
- prev_frame_delta += TIMELINE_FRAME_COUNT;
-
- state->light_x_pos += prev_frame_delta * state->light_x_dir;
- if (state->light_x_pos > TIMELINE_FRAME_COUNT/2)
- {
- state->light_x_pos = TIMELINE_FRAME_COUNT/2;
- state->light_x_dir = -state->light_x_dir;
- }
- else if (state->light_x_pos < 0)
- {
- state->light_x_pos = 0;
- state->light_x_dir = 1;
- }
-
- state->light_y_pos += prev_frame_delta * state->light_y_dir;
- if (state->light_y_pos > TIMELINE_FRAME_COUNT/2)
- {
- state->light_y_pos = TIMELINE_FRAME_COUNT/2;
- state->light_y_dir = -state->light_y_dir;
- }
- else if (state->light_y_pos < 0)
- {
- state->light_y_pos = 0;
- state->light_y_dir = 1;
- }
-
-#define CI_F CLUTTER_INT_TO_FIXED
- tex_coords[0] = (CI_F(1)/TIMELINE_FRAME_COUNT) * state->light_x_pos;
- tex_coords[1] = (CI_F(1)/TIMELINE_FRAME_COUNT) * state->light_y_pos;
- tex_coords[2] = tex_coords[0] + CI_F(1)/2;
- tex_coords[3] = tex_coords[1] + CI_F(1)/2;
-#undef CI_F
-
- state->last_frame_no = frame_no;
-}
-
-static gboolean
-multi_texture_paint (ClutterActor *actor, gpointer data)
-{
- MultiTextureState *state = data;
-
- cogl_multi_texture_rectangle (state->multi_tex,
- CLUTTER_INT_TO_FIXED(0),
- CLUTTER_INT_TO_FIXED(0),
- CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT),
- CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT),
- state->tex_coords);
-}
-
-G_MODULE_EXPORT int
-test_cogl_multi_texture_main (int argc, char *argv[])
-{
- ClutterTimeline *timeline;
- ClutterAlpha *alpha;
- ClutterBehaviour *r_behave;
- ClutterActor *stage;
- ClutterColor stage_color = { 0x15, 0x93, 0x15, 0xff };
- MultiTextureState *state = g_new0 (MultiTextureState, 1);
- CoglHandle layer;
- ClutterGeometry geom;
- ClutterFixed tex_coords[] =
- {
- /* tx1 ty1 tx2 ty2 */
- 0, 0, CLUTTER_INT_TO_FIXED (1), CLUTTER_INT_TO_FIXED (1),
- 0, 0, CLUTTER_INT_TO_FIXED (1), CLUTTER_INT_TO_FIXED (1),
- 0, 0, CLUTTER_INT_TO_FIXED (1), CLUTTER_INT_TO_FIXED (1)
- };
-
-
- clutter_init (&argc, &argv);
-
- stage = clutter_stage_get_default ();
- clutter_actor_get_geometry (stage, &geom);
-
- clutter_stage_set_color (CLUTTER_STAGE (stage),
- &stage_color);
-
- /* We create a non-descript actor that we know doesn't have a
- * default paint handler, so that we can easily control
- * painting in a paint signal handler, without having to
- * sub-class anything etc. */
- state->group = clutter_group_new ();
- clutter_actor_set_position (state->group, geom.width/2, geom.height/2);
- g_signal_connect (state->group, "paint",
- G_CALLBACK(multi_texture_paint), state);
-
- state->alpha_tex =
- cogl_texture_new_from_file ("./redhand_alpha.png",
- -1, /* disable slicing */
- TRUE,
- COGL_PIXEL_FORMAT_ANY,
- NULL);
- state->redhand_tex =
- cogl_texture_new_from_file ("./redhand.png",
- -1, /* disable slicing */
- TRUE,
- COGL_PIXEL_FORMAT_ANY,
- NULL);
- state->light_tex0 =
- cogl_texture_new_from_file ("./light0.png",
- -1, /* disable slicing */
- TRUE,
- COGL_PIXEL_FORMAT_ANY,
- NULL);
- state->light_tex1 =
- cogl_texture_new_from_file ("./light1.png",
- -1, /* disable slicing */
- TRUE,
- COGL_PIXEL_FORMAT_ANY,
- NULL);
-
- state->multi_tex = cogl_multi_texture_new ();
-
- cogl_multi_texture_layer_set_texture (state->multi_tex, 0,
- state->alpha_tex);
- cogl_multi_texture_layer_set_texture (state->multi_tex, 1,
- state->redhand_tex);
- cogl_multi_texture_layer_set_texture (state->multi_tex, 2,
- state->light_tex0);
-
- state->tex_coords = tex_coords;
-
- /* pick a random starting direction */
- state->light_x_dir = rand() % 5;
- state->light_y_dir = rand() % 5;
-
- clutter_actor_set_anchor_point (state->group, 86, 125);
- clutter_container_add_actor (CLUTTER_CONTAINER(stage),
- state->group);
-
-
- timeline = clutter_timeline_new (TIMELINE_FRAME_COUNT, 26); /* num frames, fps */
- g_object_set (timeline, "loop", TRUE, NULL);
-
- g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), state);
-
- /* Set an alpha func to power behaviour - ramp is constant rise/fall */
- alpha = clutter_alpha_new_for_mode (CLUTTER_LINEAR);
- clutter_alpha_set_timeline (alpha, timeline);
-
- /* Create a behaviour for that alpha */
- r_behave = clutter_behaviour_rotate_new (alpha,
- CLUTTER_Y_AXIS,
- CLUTTER_ROTATE_CW,
- 0.0, 360.0);
-
- /* Apply it to our actor */
- clutter_behaviour_apply (r_behave, state->group);
-
- /* start the timeline and thus the animations */
- clutter_timeline_start (timeline);
-
- clutter_actor_show_all (stage);
-
- clutter_main();
-
- cogl_multi_texture_unref (state->multi_tex);
- cogl_texture_unref (state->alpha_tex);
- cogl_texture_unref (state->redhand_tex);
- cogl_texture_unref (state->light_tex0);
- cogl_texture_unref (state->light_tex1);
- g_free (state);
-
- g_object_unref (r_behave);
-
- return 0;
-}