diff --git a/Makefile.am b/Makefile.am
index 225b66100..cae798703 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,9 @@
+NULL =
+
+V = @
+Q = $(V:1=)
+QUIET_GEN = $(Q:@=@echo ' GEN '$@;)
+
SUBDIRS = common $(CLUTTER_COGL)
BUILT_SOURCES = cogl.h
@@ -23,29 +29,42 @@ CLEANFILES = $(pc_files)
AM_CPPFLAGS = $(CLUTTER_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
+# COGL installed headers
cogl_headers = \
- $(top_srcdir)/clutter/cogl/cogl-bitmap.h \
- $(top_srcdir)/clutter/cogl/cogl-color.h \
- $(top_srcdir)/clutter/cogl/cogl-debug.h \
- $(top_srcdir)/clutter/cogl/cogl-fixed.h \
- $(top_srcdir)/clutter/cogl/cogl-material.h \
- $(top_srcdir)/clutter/cogl/cogl-matrix.h \
- $(top_srcdir)/clutter/cogl/cogl-offscreen.h \
- $(top_srcdir)/clutter/cogl/cogl-path.h \
- $(top_srcdir)/clutter/cogl/cogl-shader.h \
- $(top_srcdir)/clutter/cogl/cogl-texture.h \
- $(top_srcdir)/clutter/cogl/cogl-types.h \
- $(top_srcdir)/clutter/cogl/cogl-vertex-buffer.h
+ $(top_srcdir)/clutter/cogl/cogl-bitmap.h \
+ $(top_srcdir)/clutter/cogl/cogl-color.h \
+ $(top_srcdir)/clutter/cogl/cogl-debug.h \
+ $(top_srcdir)/clutter/cogl/cogl-deprecated.h \
+ $(top_srcdir)/clutter/cogl/cogl-fixed.h \
+ $(top_srcdir)/clutter/cogl/cogl-material.h \
+ $(top_srcdir)/clutter/cogl/cogl-matrix.h \
+ $(top_srcdir)/clutter/cogl/cogl-offscreen.h \
+ $(top_srcdir)/clutter/cogl/cogl-path.h \
+ $(top_srcdir)/clutter/cogl/cogl-shader.h \
+ $(top_srcdir)/clutter/cogl/cogl-texture.h \
+ $(top_srcdir)/clutter/cogl/cogl-types.h \
+ $(top_srcdir)/clutter/cogl/cogl-vertex-buffer.h \
+ $(top_builddir)/clutter/cogl/cogl-defines-@CLUTTER_COGL@.h \
+ $(top_builddir)/clutter/cogl/cogl-enum-types.h \
+ $(top_builddir)/clutter/cogl/cogl.h \
+ $(NULL)
+
+# this is copied in from common/ to make cogl.h work, but we
+# need to clean it up ourselves once we're done
+DISTCLEANFILES = cogl-enum-types.h
# HACK - gobject-introspection can't scan a library in another directory
# so we create a libclutter-cogl.la that's just identical to the one
# in the subdir
noinst_LTLIBRARIES = libclutter-cogl.la
-libclutter_cogl_la_LIBADD = $(CLUTTER_COGL)/libclutter-cogl.la
+libclutter_cogl_la_LIBADD = $(CLUTTER_COGL)/libclutter-cogl-$(CLUTTER_COGL).la
libclutter_cogl_la_SOURCES = $(cogl_headers)
+coglincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/cogl
+coglinclude_HEADERS = $(cogl_headers)
+
if HAVE_INTROSPECTION
-Cogl-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) $(CLUTTER_COGL)/libclutter-cogl.la
+Cogl-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libclutter-cogl.la
$(QUIET_GEN)$(INTROSPECTION_SCANNER) -v \
--namespace Cogl --nsversion=@CLUTTER_API_VERSION@ \
-I$(top_srcdir)/clutter/cogl \
@@ -59,8 +78,6 @@ Cogl-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) $(CLUTTER_COGL)/libclut
--libtool="$(top_builddir)/doltlibtool" \
--pkg gobject-2.0 \
--output $@ \
- $(top_builddir)/clutter/cogl/cogl-defines-@CLUTTER_COGL@.h \
- $(top_builddir)/clutter/cogl/cogl.h \
$(cogl_headers)
BUILT_GIRSOURCES = Cogl-@CLUTTER_API_VERSION@.gir
diff --git a/cogl-debug.h b/cogl-debug.h
index b31a36c52..8aa1e8f87 100644
--- a/cogl-debug.h
+++ b/cogl-debug.h
@@ -29,15 +29,16 @@
G_BEGIN_DECLS
typedef enum {
- COGL_DEBUG_MISC = 1 << 0,
- COGL_DEBUG_TEXTURE = 1 << 1,
- COGL_DEBUG_MATERIAL = 1 << 2,
- COGL_DEBUG_SHADER = 1 << 3,
- COGL_DEBUG_OFFSCREEN = 1 << 4,
- COGL_DEBUG_DRAW = 1 << 5,
- COGL_DEBUG_PANGO = 1 << 6,
- COGL_DEBUG_RECTANGLES = 1 << 7,
- COGL_DEBUG_HANDLE = 1 << 8
+ COGL_DEBUG_MISC = 1 << 0,
+ COGL_DEBUG_TEXTURE = 1 << 1,
+ COGL_DEBUG_MATERIAL = 1 << 2,
+ COGL_DEBUG_SHADER = 1 << 3,
+ COGL_DEBUG_OFFSCREEN = 1 << 4,
+ COGL_DEBUG_DRAW = 1 << 5,
+ COGL_DEBUG_PANGO = 1 << 6,
+ COGL_DEBUG_RECTANGLES = 1 << 7,
+ COGL_DEBUG_HANDLE = 1 << 8,
+ COGL_DEBUG_BLEND_STRINGS = 1 << 9
} CoglDebugFlags;
#ifdef COGL_ENABLE_DEBUG
@@ -69,3 +70,4 @@ extern guint cogl_debug_flags;
G_END_DECLS
#endif /* __COGL_DEBUG_H__ */
+
diff --git a/cogl-deprecated.h b/cogl-deprecated.h
index 2111e48b4..24dc5b28b 100644
--- a/cogl-deprecated.h
+++ b/cogl-deprecated.h
@@ -23,6 +23,14 @@
#ifndef COGL_DEPRECATED_H
-#define cogl_color cogl_color_REPLACED_BY_cogl_set_source_color
+#define cogl_color cogl_color_REPLACED_BY_cogl_set_source_color
+#define cogl_enable_depth_test cogl_enable_depth_test_RENAMED_TO_cogl_set_depth_test_enabled
+#define cogl_enable_backface_culling cogl_enable_backface_culling_RENAMED_TO_cogl_set_backface_culling_enabled
+
+#define cogl_texture_rectangle cogl_texture_rectangle_REPLACE_BY_cogl_set_source_texture_AND_cogl_rectangle_with_texture_coords
+
+#define cogl_texture_multiple_rectangles cogl_texture_multiple_rectangles_REPLACED_BY_cogl_set_source_texture_AND_cogl_rectangles_with_texture_coords
+
+#define cogl_texture_polygon cogl_texture_polygon_REPLACED_BY_cogl_set_source_texture_AND_cogl_polygon
#endif
diff --git a/cogl-material.h b/cogl-material.h
index 95a474831..66fbd8d5c 100644
--- a/cogl-material.h
+++ b/cogl-material.h
@@ -43,6 +43,51 @@ G_BEGIN_DECLS
* blended together.
*/
+/**
+ * CoglMaterialFilter:
+ * @COGL_MATERIAL_FILTER_NEAREST: Measuring in manhatten distance from the,
+ * current pixel center, use the nearest texture
+ * texel.
+ * @COGL_MATERIAL_FILTER_LINEAR: Use the weighted average of the 4 texels
+ * nearest the current pixel center.
+ * @COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose
+ * texel size most closely matches
+ * the current pixel, and use the
+ * COGL_MATERIAL_FILTER_NEAREST
+ * criterion.
+ * @COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose
+ * texel size most closely matches
+ * the current pixel, and use the
+ * COGL_MATERIAL_FILTER_LINEAR
+ * criterion.
+ * @COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels
+ * whose texel size most closely
+ * matches the current pixel, use
+ * the COGL_MATERIAL_FILTER_NEAREST
+ * criterion on each one and take
+ * their weighted average.
+ * @COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels
+ * whose texel size most closely
+ * matches the current pixel, use
+ * the COGL_MATERIAL_FILTER_LINEAR
+ * criterion on each one and take
+ * their weighted average.
+ *
+ * Texture filtering is used whenever the current pixel maps either to more
+ * than one texture element (texel) or less than one. These filter enums
+ * correspond to different strategies used to come up with a pixel color, by
+ * possibly referring to multiple neighbouring texels and taking a weighted
+ * average or simply using the nearest texel.
+ */
+typedef enum _CoglMaterialFilter
+{
+ COGL_MATERIAL_FILTER_NEAREST = GL_NEAREST,
+ COGL_MATERIAL_FILTER_LINEAR = GL_LINEAR,
+ COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST,
+ COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST,
+ COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR,
+ COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR
+} CoglMaterialFilter;
/**
* cogl_material_new:
@@ -367,80 +412,90 @@ void cogl_material_set_alpha_test_function (CoglHandle material,
float alpha_reference);
/**
- * CoglMaterialBlendFactor:
- * @COGL_MATERIAL_BLEND_FACTOR_ZERO: (0, 0, 0, 0)
- * @COGL_MATERIAL_BLEND_FACTOR_ONE: (1, 1, 1, 1)
- * @COGL_MATERIAL_BLEND_FACTOR_SRC_COLOR: (Rs, Gs, Bs, As)
- * @COGL_MATERIAL_BLEND_FACTOR_DST_COLOR: (Rd, Gd, Bd, Ad)
- * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: (1-Rs, 1-Gs, 1-Bs, 1-As)
- * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_COLOR: (1-Rd, 1-Gd, 1-Bd, 1-Ad)
- * @COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA: (As, As, As, As)
- * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: (1-As, 1-As, 1-As, 1-As)
- * @COGL_MATERIAL_BLEND_FACTOR_DST_ALPHA: (Ad, Ad, Ad, Ad)
- * @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: (1-Ad, 1-Ad, 1-Ad, 1-Ad)
- * @COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA_SATURATE: (f,f,f,1) where f=MIN(As,1-Ad)
+ * cogl_material_set_blend:
+ * @material: A CoglMaterial object
+ * @blend_string: A Cogl blend string
+ * describing the desired blend function.
+ * @error: A GError that may report lack of driver support if you give
+ * separate blend string statements for the alpha channel and RGB
+ * channels since some drivers or backends such as GLES 1.1 dont
+ * support this.
+ *
+ * If not already familiar; please refer
+ * here for an overview of what blend
+ * strings are and there syntax.
*
* Blending occurs after the alpha test function, and combines fragments with
* the framebuffer.
- *
- * A fixed function is used to determine the blended color, which is based on
- * the incoming source color of your fragment (Rs, Gs, Bs, As), a source
- * factor (Sr, Sg, Sb, Sa), a destination color (Rd, Rg, Rb, Ra) and
- * a destination factor (Dr, Dg, Db, Da), and is given by these equations:
- *
+
+ * Currently the only blend function Cogl exposes is ADD(). So any valid
+ * blend statements will be of the form:
+ *
*
- * R = Rs*Sr + Rd*Dr
- * G = Gs*Sg + Gd*Dg
- * B = Bs*Sb + Bd*Db
- * A = As*Sa + Ad*Da
+ * <channel-mask>=ADD(SRC_COLOR*(<factor>), DST_COLOR*(<factor>))
*
*
- * All factors have a range [0, 1]
+ * NOTE: The brackets around blend factors are currently not optional!
*
- * The factors are selected with the following constants:
+ * This is the list of source-names usable as blend factors:
+ *
+ * SRC_COLOR: The color of the in comming fragment
+ * DST_COLOR: The color of the framebuffer
+ *
+ * CONSTANT: The constant set via cogl_material_set_blend_constant()
+ *
+ * The source names can be used according to the
+ * color-source and factor syntax,
+ * so for example "(1-SRC_COLOR[A])" would be a valid factor, as would
+ * "(CONSTANT[RGB])"
+ *
+ * These can also be used as factors:
+ *
+ * 0: (0, 0, 0, 0)
+ * 1: (1, 1, 1, 1)
+ * SRC_ALPHA_SATURATE_FACTOR: (f,f,f,1)
+ * where f=MIN(SRC_COLOR[A],1-DST_COLOR[A])
+ *
+ *
+ * Remember; all color components are normalized to the range [0, 1] before
+ * computing the result of blending.
+ *
+ *
+ * Examples
+ * Blend a non-premultiplied source over a destination with
+ * premultiplied alpha:
+ *
+ * "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))"
+ * "A = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
+ *
+ * Blend a premultiplied source over a destination with premultiplied alpha:
+ *
+ * "RGBA = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
+ *
+ *
+ *
+ * Returns: TRUE if the blend string was successfully parsed, and the described
+ * blending is supported by the underlying driver/hardware. If there
+ * was an error, it returns FALSE.
+ *
+ * Since: 1.0
*/
-typedef enum _CoglMaterialBlendFactor
-{
- COGL_MATERIAL_BLEND_FACTOR_ZERO = GL_ZERO,
- COGL_MATERIAL_BLEND_FACTOR_ONE = GL_ONE,
- COGL_MATERIAL_BLEND_FACTOR_SRC_COLOR = GL_SRC_COLOR,
- COGL_MATERIAL_BLEND_FACTOR_DST_COLOR = GL_DST_COLOR,
- COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR,
- COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_COLOR = GL_ONE_MINUS_DST_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,
-} CoglMaterialBlendFactor;
+gboolean cogl_material_set_blend (CoglHandle material,
+ const char *blend_string,
+ GError **error);
/**
- * cogl_material_set_blend_factors:
+ * cogl_material_set_blend_constant:
* @material: A CoglMaterial object
- * @src_factor: Chooses the @CoglMaterialBlendFactor you want plugged in to
- * the blend equation.
- * @dst_factor: Chooses the @CoglMaterialBlendFactor you want plugged in to
- * the blend equation.
+ * @constant_color: The constant color you want
*
- * 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:
+ * When blending is setup to reference a CONSTANT blend factor then
+ * blending will depend on the constant set with this function.
*
- * (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]
- *
- * Since 1.0
+ * Since: 1.0
*/
-void cogl_material_set_blend_factors (CoglHandle material,
- CoglMaterialBlendFactor src_factor,
- CoglMaterialBlendFactor dst_factor);
+void cogl_material_set_blend_constant (CoglHandle material,
+ CoglColor *constant_color);
/**
* cogl_material_set_layer:
@@ -460,7 +515,7 @@ void cogl_material_set_blend_factors (CoglHandle material,
* Since 1.0
*/
void cogl_material_set_layer (CoglHandle material,
- gint layer_index,
+ int layer_index,
CoglHandle texture);
/**
@@ -473,233 +528,112 @@ void cogl_material_set_layer (CoglHandle material,
void cogl_material_remove_layer (CoglHandle material,
gint layer_index);
+
/**
- * CoglMaterialLayerCombineFunc:
- * @COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE: Arg0
- * @COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE: Arg0 x Arg1
- * @COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD: Arg0 + Arg1
- * @COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED: Arg0 + Arg1 - 0.5
- * @COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE: Arg0 x Arg + Arg1 x (1-Arg2)
- * @COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT: Arg0 - Arg1
- * @COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB: 4 x ((Arg0r - 0.5) x (Arg1r - 0.5)) +
- * @COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA: ((Arg0b - 0.5) x (Arg1b - 0.5)) +
+ * cogl_material_set_layer_combine:
+ * @material: A CoglMaterial object
+ * @layer_index: Specifies the layer you want define a combine function for
+ * @blend_string: A Cogl blend string
+ * describing the desired texture combine function.
+ * @error: A GError that may report parse errors or lack of GPU/driver support.
*
- * A material may comprise of 1 or more layers that can be combined using a
- * number of different functions. By default layers are modulated, which is
- * to say the components of the current source layer S are simply multipled
- * together with the combined results of the previous layer P like this:
+ * If not already familiar; you can refer
+ * here for an overview of what blend
+ * strings are and there syntax.
*
+ * These are all the functions available for texture combining:
+ *
+ * REPLACE(arg0) = arg0
+ * MODULATE(arg0, arg1) = arg0 x arg1
+ * ADD(arg0, arg1) = arg0 + arg1
+ * ADD_SIGNED(arg0, arg1) = arg0 + arg1 - 0.5
+ * INTERPOLATE(arg0, arg1, arg2) =
+ * arg0 x arg2 + arg1 x (1 - arg2)
+ * SUBTRACT(arg0, arg1) = arg0 - arg1
+ *
+ * DOT3_RGB(arg0, arg1) =
*
- * (Rs*Rp, Gs*Gp, Bs*Bp, As*Ap)
+ * 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) +
+ * (arg0[G] - 0.5)) * (arg1[G] - 0.5) +
+ * (arg0[B] - 0.5)) * (arg1[B] - 0.5))
*
- *
- * For more advanced techniques, Cogl exposes the fixed function texture
- * combining capabilities of your GPU to give you greater control.
- */
-typedef enum _CoglMaterialLayerCombineFunc
-{
- COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE = CGL_REPLACE,
- COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE = CGL_MODULATE,
- COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD = CGL_ADD,
- COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED = CGL_ADD_SIGNED,
- COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE = CGL_INTERPOLATE,
- COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT = CGL_SUBTRACT,
- COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB = CGL_DOT3_RGB,
- COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA = CGL_DOT3_RGBA
-} CoglMaterialLayerCombineFunc;
-
-/**
- * CoglMaterialLayerCombineChannels:
- * @COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB: Modify the function or argument
- * src/op for the RGB components of a
- * layer
- * @COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA: Modify the function or argument
- * src/op for the Alpha component of a
- * layer
- * @COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA: Modify the function or argument
- * src/op for all the components of a
- * layer
- *
- * Cogl optionally lets you describe 2 seperate combine modes for a single
- * layer; 1 for the RGB components, and 1 for the Alpha component, so in this
- * case you would repeat the 3 steps documented with the
- * @cogl_material_set_layer_combine_function function for each channel
- * selector.
- *
- * (Note: you can't have different modes for each channel, so if you need more
- * control you will need to use a glsl fragment shader)
- */
-typedef enum _CoglMaterialLayerCombineChannels
-{
- COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
- COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA,
- COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA
-} CoglMaterialLayerCombineChannels;
-
-/**
- * cogl_material_set_layer_combine_function:
- * @material: A CoglMaterial object
- * @layer_index: Specifies the layer whos combine mode you want to modify
- * @channels: Specifies which channels combine mode you want to modify
- * (RGB, ALPHA, or RGBA)
- * @func: Specifies the function you want to use for combining fragments
- * of the specified layer with the results of previously combined
- * layers.
- *
- * There are three basic steps to describing how a layer should be combined:
- *
- *
- * Choose a function.
*
- *
- * Specify the source color for each argument of the chosen function. (Note
- * the functions don't all take the same number of arguments)
- *
- *
- * Specify an operator for each argument that can modify the corresponding
- * source color before the function is applied.
- *
- *
- *
- * Cogl optionally lets you describe 2 seperate combine modes for a single
- * layer; 1 for the RGB components, and 1 for the Alpha component, so in this
- * case you would repeat the 3 steps for each channel selector.
- *
- * (Note: you can't have different modes for each channel, so if you need more
- * control you will need to use a glsl fragment shader)
- *
- * For example here is how you could elect to use the ADD function for all
- * components of layer 1 in your material:
+ * DOT3_RGBA(arg0, arg1) =
*
- * //Step 1: Choose a function. Note the ADD function takes 2 arguments...
- * cogl_material_set_layer_combine_function (material,
- * 1,
- * COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA)
- * COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD);
- * //Step 2: Specify the source color for the 2 ADD function arguments...
- * cogl_material_set_layer_combine_arg_src (material,
- * 1,//layer index
- * 0,//argument index
- * COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS);
- * cogl_material_set_layer_combine_arg_src (material,
- * 1,//layer index
- * 1,//argument index
- * COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA)
- * COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE);
- * //Step 3: Specify the operators used to modify the arguments...
- * cogl_material_set_layer_combine_arg_op (material,
- * 1,//layer index
- * 0,//argument index
- * COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA,
- * COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR);
- * cogl_material_set_layer_combine_arg_op (material,
- * 1,//layer index
- * 1,//argument index
- * COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA,
- * COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR);
+ * 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) +
+ * (arg0[G] - 0.5)) * (arg1[G] - 0.5) +
+ * (arg0[B] - 0.5)) * (arg1[B] - 0.5))
*
- */
-void cogl_material_set_layer_combine_function (CoglHandle material,
- gint layer_index,
- CoglMaterialLayerCombineChannels channels,
- CoglMaterialLayerCombineFunc func);
-
-/**
- * CoglMaterialLayerCombineSrc:
- * @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE: The fragment color of the current texture layer
- * @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE0: The fragment color of texture unit 0
- * @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE1: The fragment color of texture unit 1
- * @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE2: The fragment color of texture unit 2..7
- * @COGL_MATERIAL_LAYER_COMBINE_SRC_CONSTANT: A fixed constant color (TODO: no API yet to specify the actual color!)
- * @COGL_MATERIAL_LAYER_COMBINE_SRC_PRIMARY_COLOR: The basic color of the primitive ignoring texturing
- * @COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS: The result of combining all previous layers
+ *
+ *
*
- * Note for the constants @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE0..n the
- * numbers may not correspond to the indices you choose for your layers since
- * your layer indices don't need to be contiguous. If you need to use these
- * it would probably be sensible to ensure the layer indices do infact
- * correspond.
+ * Refer to the
+ * color-source syntax for
+ * describing the arguments. The valid source names for texture combining
+ * are:
+ *
+ *
+ * TEXTURE: Use the color from the current texture layer
+ *
+ *
+ * TEXTURE_0, TEXTURE_1, etc: Use the color from the specified texture layer
+ *
+ *
+ * CONSTANT: Use the color from the constant given with
+ * cogl_material_set_layer_constant()
+ *
+ *
+ * PRIMARY: Use the color of the material as set with cogl_material_set_color()
+ *
+ *
+ * PREVIOUS: Either use the texture color from the previous layer, or if this
+ * is layer 0, use the color of the material as set with
+ * cogl_material_set_color()
+ *
+ *
+ *
+ * Example
+ * This is effectively what the default blending is:
+ *
+ * "RGBA = MODULATE (PREVIOUS, TEXTURE)"
+ *
+ * This could be used to cross-fade between two images, using the alpha
+ * component of a constant as the interpolator. The constant color
+ * is given by calling cogl_material_set_layer_constant.
+ *
+ * RGBA = INTERPOLATE (PREVIOUS, TEXTURE, CONSTANT[A])
+ *
+ *
+ * Note: you can't give a multiplication factor for arguments as you can
+ * with blending.
+ *
+ * Returns: TRUE if the blend string was successfully parsed, and the described
+ * texture combining is supported by the underlying driver/hardware.
+ * If there was an error, it returns FALSE.
+ *
+ * Since: 1.0
*/
-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 = CGL_CONSTANT,
- COGL_MATERIAL_LAYER_COMBINE_SRC_PRIMARY_COLOR = CGL_PRIMARY_COLOR,
- COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS = CGL_PREVIOUS
-} CoglMaterialLayerCombineSrc;
+gboolean
+cogl_material_set_layer_combine (CoglHandle material,
+ gint layer_index,
+ const char *blend_string,
+ GError **error);
/**
- * cogl_material_set_layer_combine_arg_src:
+ * cogl_material_set_layer_combine_constant:
* @material: A CoglMaterial object
- * @layer_index:
- * @argument:
- * @channels:
- * @src:
+ * @layer_index: Specifies the layer you want to specify a constant used
+ * for texture combining
+ * @color_constant: The constant color you want
*
- */
-void cogl_material_set_layer_combine_arg_src (CoglHandle material,
- gint layer_index,
- gint argument,
- CoglMaterialLayerCombineChannels channels,
- CoglMaterialLayerCombineSrc src);
-
-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_set_layer_combine_arg_op:
- * @material: A CoglMaterial object
- * @layer_index:
- * @argument:
- * @channels:
- * @op:
+ * When you are using the 'CONSTANT' color source in a layer combine
+ * description then you can use this function to define its value.
*
+ * Since 1.0
*/
-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
+void cogl_material_set_layer_combine_constant (CoglHandle material,
+ int layer_index,
+ CoglColor *constant);
/**
* cogl_material_set_layer_matrix:
@@ -709,38 +643,9 @@ void cogl_material_set_layer_alpha_combine (CoglHandle material
* and rotate a single layer of a material used to fill your geometry.
*/
void cogl_material_set_layer_matrix (CoglHandle material,
- gint layer_index,
+ int layer_index,
CoglMatrix *matrix);
-
-/**
- * SECTION:cogl-material-internals
- * @short_description: Functions for creating custom primitives that make use
- * of Cogl materials for filling.
- *
- * Normally you shouldn't need to use this API directly, but if you need to
- * developing a custom/specialised primitive - probably using raw OpenGL - then
- * this API aims to expose enough of the material internals to support being
- * able to fill your geometry according to a given Cogl material.
- */
-
-
-/**
- * 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.
- */
-/* TODO: find a nicer solution! */
-gulong
-cogl_material_get_cogl_enable_flags (CoglHandle handle);
-
/**
* cogl_material_get_layers:
* @material: A CoglMaterial object
@@ -748,24 +653,20 @@ cogl_material_get_cogl_enable_flags (CoglHandle handle);
* 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.
+ * Returns: A list of #CoglHandle's that can be passed to the
+ * cogl_material_layer_* functions.
*/
const GList *cogl_material_get_layers (CoglHandle material_handle);
/**
* CoglMaterialLayerType:
- * @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a CoglTexture
+ * @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a
+ * Cogl texture
+ *
+ * Available types of layers for a #CoglMaterial. This enumeration
+ * might be expanded in later versions.
+ *
+ * Since: 1.0
*/
typedef enum _CoglMaterialLayerType
{
@@ -774,17 +675,12 @@ typedef enum _CoglMaterialLayerType
/**
* cogl_material_layer_get_type:
- * @layer_handle: A CoglMaterialLayer handle
+ * @layer_handle: A Cogl material layer handle
*
* 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);
@@ -792,75 +688,58 @@ CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle);
* cogl_material_layer_get_texture:
* @layer_handle: A CoglMaterialLayer handle
*
- * 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.
+ * This lets you extract a CoglTexture handle for a specific layer.
*
* 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.
+ * likely return COGL_INVALID_HANDLE if you try to get the texture.
+ * Considering this, you can call cogl_material_layer_get_type first,
+ * to check it is of type COGL_MATERIAL_LAYER_TYPE_TEXTURE.
+ *
+ * Note: It is possible for a layer object of type
+ * COGL_MATERIAL_LAYER_TYPE_TEXTURE to be realized before a texture
+ * object has been associated with the layer. For example this happens
+ * if you setup layer combining for a given layer index before calling
+ * cogl_material_set_layer for that index.
+ *
+ * Returns: A CoglHandle to the layers texture object or COGL_INVALID_HANDLE
+ * if a texture has not been set yet.
*/
CoglHandle cogl_material_layer_get_texture (CoglHandle layer_handle);
/**
- * CoglMaterialLayerFlags:
- * @COGL_MATERIAL_LAYER_FLAG_USER_MATRIX: Means the user has supplied a
- * custom texture matrix.
+ * cogl_material_layer_get_min_filter:
+ * @layer_handle: a #CoglHandle for a material layer.
+ *
+ * Query the currently set downscaling filter for a cogl material layer.
+ *
+ * Returns: the current downscaling filter for a cogl material layer.
*/
-typedef enum _CoglMaterialLayerFlags
-{
- COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX = 1L<<0
-} CoglMaterialLayerFlags;
-/* XXX: NB: if you add flags here you will need to update
- * CoglMaterialLayerPrivFlags!!! */
+CoglMaterialFilter cogl_material_layer_get_min_filter (CoglHandle layer_handle);
/**
- * cogl_material_layer_get_flags:
- * @layer_handle: A CoglMaterialLayer layer handle
+ * cogl_material_layer_get_mag_filter:
+ * @layer_handle: a #CoglHandle for a material layer.
*
- * This lets you get a number of flag attributes about the 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.
+ * Query the currently set downscaling filter for a cogl material layer.
+ *
+ * Returns: the current downscaling filter for a cogl material layer.
*/
-gulong cogl_material_layer_get_flags (CoglHandle layer_handle);
+CoglMaterialFilter cogl_material_layer_get_mag_filter (CoglHandle layer_handle);
/**
- * CoglMaterialFlushOption:
- * @COGL_MATERIAL_FLUSH_FALLBACK_MASK: Follow this by a guin32 mask
- * of the layers that can't be supported with the user supplied texture
- * and need to be replaced with fallback textures. (1 = fallback, and the
- * least significant bit = layer 0)
- * @COGL_MATERIAL_FLUSH_DISABLE_MASK: Follow this by a guint32 mask
- * of the layers that you want to completly disable texturing for
- * (1 = fallback, and the least significant bit = layer 0)
- * @COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE: Follow this by a GLuint OpenGL texture
- * name to override the texture used for layer 0 of the material. This is
- * intended for dealing with sliced textures where you will need to point
- * to each of the texture slices in turn when drawing your geometry.
- * Passing a value of 0 is the same as not passing the option at all.
- */
-typedef enum _CoglMaterialFlushOption
-{
- COGL_MATERIAL_FLUSH_FALLBACK_MASK = 1,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
-} CoglMaterialFlushOption;
-
-/**
- * cogl_material_flush_gl_state:
- * @material: A CoglMaterial object
- * @...: A NULL terminated list of (CoglMaterialFlushOption, data) pairs
+ * cogl_material_set_layer_filters:
+ * @handle: a #CoglHandle to a material.
+ * @layer_index: the layer number to change.
+ * @min_filter: the filter used when scaling a texture down.
+ * @mag_filter: the filter used when magnifying a texture.
*
- * This function commits the state of the specified CoglMaterial - including
- * the texture state for all the layers - to the OpenGL[ES] driver.
- *
- * Since 1.0
+ * Changes the decimation and interpolation filters used when a texture is
+ * drawn at other scales than 100%.
*/
-void cogl_material_flush_gl_state (CoglHandle material,
- ...) G_GNUC_NULL_TERMINATED;
+void cogl_material_set_layer_filters (CoglHandle handle,
+ gint layer_index,
+ CoglMaterialFilter min_filter,
+ CoglMaterialFilter mag_filter);
G_END_DECLS
diff --git a/cogl-matrix.h b/cogl-matrix.h
index ca643f146..3ee94aeb5 100644
--- a/cogl-matrix.h
+++ b/cogl-matrix.h
@@ -199,22 +199,50 @@ void cogl_matrix_frustum (CoglMatrix *matrix,
float z_far);
/**
- * cogl_matrix_transform_point:
+ * cogl_matrix_perspective:
* @matrix: A 4x4 transformation matrix
- * @x: The X component of your points position [in:out]
- * @y: The Y component of your points position [in:out]
- * @z: The Z component of your points position [in:out]
- * @w: The W component of your points position [in:out]
+ * @fov_y: A field of view angle for the Y axis
+ * @aspect: The ratio of width to height determining the field of view angle
+ * for the x axis.
+ * @z_near: The distance to the near clip plane.
+ * Never pass 0 and always pass a positive number.
+ * @z_far: The distance to the far clip plane. (Should always be positive)
*
- * This transforms a point whos position is given and returned
- * as four float components.
+ * Multiplies the matrix by the described perspective matrix
+ *
+ * Note: you should be careful not to have to great a z_far / z_near ratio
+ * since that will reduce the effectiveness of depth testing since there wont
+ * be enough precision to identify the depth of objects near to each other.
*/
void
-cogl_matrix_transform_point (const CoglMatrix *matrix,
- float *x,
- float *y,
- float *z,
- float *w);
+cogl_matrix_perspective (CoglMatrix *matrix,
+ float fov_y,
+ float aspect,
+ float z_near,
+ float z_far);
+
+/**
+ * cogl_matrix_ortho:
+ * @matrix: A 4x4 transformation matrix
+ * @left: The coordinate for the left clipping plane
+ * @right: The coordinate for the right clipping plane
+ * @bottom: The coordinate for the bottom clipping plane
+ * @top: The coordinate for the top clipping plane
+ * @z_near: The coordinate for the near clipping plane (may be negative if
+ * the plane is behind the viewer)
+ * @z_far: The coordinate for the far clipping plane (may be negative if
+ * the plane is behind the viewer)
+ *
+ * Multiples the matrix by a parallel projection matrix.
+ */
+void
+cogl_matrix_ortho (CoglMatrix *matrix,
+ float left,
+ float right,
+ float bottom,
+ float top,
+ float z_near,
+ float z_far);
/**
* cogl_matrix_init_from_array:
@@ -234,6 +262,24 @@ void cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array);
*/
const float *cogl_matrix_get_array (const CoglMatrix *matrix);
+/**
+ * cogl_matrix_transform_point:
+ * @matrix: A 4x4 transformation matrix
+ * @x: The X component of your points position [in:out]
+ * @y: The Y component of your points position [in:out]
+ * @z: The Z component of your points position [in:out]
+ * @w: The W component of your points position [in:out]
+ *
+ * This transforms a point whos position is given and returned
+ * as four float components.
+ */
+void
+cogl_matrix_transform_point (const CoglMatrix *matrix,
+ float *x,
+ float *y,
+ float *z,
+ float *w);
+
G_END_DECLS
#endif /* __COGL_MATRIX_H */
diff --git a/cogl-shader.h b/cogl-shader.h
index 59c75ede6..9eec9bb40 100644
--- a/cogl-shader.h
+++ b/cogl-shader.h
@@ -46,9 +46,12 @@ G_BEGIN_DECLS
* CoglShaderType:
* @COGL_SHADER_TYPE_VERTEX: A program for proccessing vertices
* @COGL_SHADER_TYPE_FRAGMENT: A program for processing fragments
+ *
+ * Types of shaders
+ *
+ * Since: 1.0
*/
-typedef enum _CoglShaderType
-{
+typedef enum {
COGL_SHADER_TYPE_VERTEX,
COGL_SHADER_TYPE_FRAGMENT
} CoglShaderType;
@@ -103,7 +106,7 @@ gboolean cogl_is_shader (CoglHandle handle);
* one.
*/
void cogl_shader_source (CoglHandle shader,
- const char *source);
+ const gchar *source);
/**
* cogl_shader_compile:
* @handle: #CoglHandle for a shader.
@@ -111,29 +114,30 @@ void cogl_shader_source (CoglHandle shader,
* Compiles the shader, no return value, but the shader is now ready for
* linking into a program.
*/
-void cogl_shader_compile (CoglHandle handle);
+void cogl_shader_compile (CoglHandle handle);
/**
* cogl_shader_get_info_log:
* @handle: #CoglHandle for a shader.
- * @size: maximum number of bytes to retrieve.
- * @buffer: location for info log.
*
* Retrieves the information log for a coglobject, can be used in conjunction
- * with #cogl_shader_get_parameteriv to retrieve the compiler warnings/error
+ * with cogl_shader_get_parameteriv() to retrieve the compiler warnings/error
* messages that caused a shader to not compile correctly, mainly useful for
* debugging purposes.
+ *
+ * Return value: a newly allocated string containing the info log. Use
+ * g_free() to free it
*/
-void cogl_shader_get_info_log (CoglHandle handle,
- size_t size,
- char *buffer);
+gchar * cogl_shader_get_info_log (CoglHandle handle);
/**
* cogl_shader_get_type:
* @handle: #CoglHandle for a shader.
*
- * Returns: COGL_SHADER_TYPE_VERTEX if the shader is a vertex processor
- * or COGL_SHADER_TYPE_FRAGMENT if the shader is a frament processor
+ * Retrieves the type of a shader #CoglHandle
+ *
+ * Return value: %COGL_SHADER_TYPE_VERTEX if the shader is a vertex processor
+ * or %COGL_SHADER_TYPE_FRAGMENT if the shader is a frament processor
*/
CoglShaderType cogl_shader_get_type (CoglHandle handle);
@@ -141,7 +145,9 @@ CoglShaderType cogl_shader_get_type (CoglHandle handle);
* cogl_shader_is_compiled:
* @handle: #CoglHandle for a shader.
*
- * Returns: TRUE if the shader object has sucessfully be compiled else FALSE
+ * Retrieves whether a shader #CoglHandle has been compiled
+ *
+ * Return value: %TRUE if the shader object has sucessfully be compiled
*/
gboolean cogl_shader_is_compiled (CoglHandle handle);
diff --git a/cogl-texture.h b/cogl-texture.h
index 6a8b00a01..15cadc879 100644
--- a/cogl-texture.h
+++ b/cogl-texture.h
@@ -41,12 +41,12 @@ G_BEGIN_DECLS
* loading and manipulating textures.
*/
+#define COGL_TEXTURE_MAX_WASTE 127
+
/**
* cogl_texture_new_with_size:
* @width: width of texture in pixels.
* @height: height of texture in pixels.
- * @max_waste: maximum extra horizontal and|or vertical margin pixels
- * to make the texture fit GPU limitations
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
* @internal_format: the #CoglPixelFormat to use for the GPU storage of the
* texture.
@@ -60,15 +60,12 @@ G_BEGIN_DECLS
*/
CoglHandle cogl_texture_new_with_size (guint width,
guint height,
- gint max_waste,
CoglTextureFlags flags,
CoglPixelFormat internal_format);
/**
* cogl_texture_new_from_file:
* @filename: the file to load
- * @max_waste: maximum extra horizontal and|or vertical margin pixels
- * to make the texture fit GPU limitations
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
* @internal_format: the #CoglPixelFormat to use for the GPU storage of the
* texture
@@ -82,7 +79,6 @@ CoglHandle cogl_texture_new_with_size (guint width,
* Since: 0.8
*/
CoglHandle cogl_texture_new_from_file (const gchar *filename,
- gint max_waste,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
GError **error);
@@ -91,8 +87,6 @@ CoglHandle cogl_texture_new_from_file (const gchar *filename,
* cogl_texture_new_from_data:
* @width: width of texture in pixels
* @height: height of texture in pixels
- * @max_waste: maximum extra horizontal and|or vertical margin pixels
- * to make the texture fit GPU limitations
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
* @format: the #CoglPixelFormat the buffer is stored in in RAM
* @internal_format: the #CoglPixelFormat that will be used for storing
@@ -110,7 +104,6 @@ CoglHandle cogl_texture_new_from_file (const gchar *filename,
*/
CoglHandle cogl_texture_new_from_data (guint width,
guint height,
- gint max_waste,
CoglTextureFlags flags,
CoglPixelFormat format,
CoglPixelFormat internal_format,
@@ -136,19 +129,17 @@ CoglHandle cogl_texture_new_from_data (guint width,
*
* Since: 0.8
*/
-CoglHandle cogl_texture_new_from_foreign (GLuint gl_handle,
- GLenum gl_target,
- GLuint width,
- GLuint height,
- GLuint x_pot_waste,
- GLuint y_pot_waste,
- CoglPixelFormat format);
+CoglHandle cogl_texture_new_from_foreign (GLuint gl_handle,
+ GLenum gl_target,
+ GLuint width,
+ GLuint height,
+ GLuint x_pot_waste,
+ GLuint y_pot_waste,
+ CoglPixelFormat format);
/**
* cogl_texture_new_from_bitmap:
* @bmp_handle: A CoglBitmap handle
- * @max_waste: maximum extra horizontal and|or vertical margin pixels
- * to make the texture fit GPU limitations
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
* @internal_format: the #CoglPixelFormat to use for the GPU storage of the
* texture
@@ -160,10 +151,9 @@ CoglHandle cogl_texture_new_from_foreign (GLuint gl_handle,
*
* Since: 1.0
*/
-CoglHandle cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
- gint max_waste,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
+CoglHandle cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
+ CoglTextureFlags flags,
+ CoglPixelFormat internal_format);
/**
* cogl_is_texture:
@@ -228,72 +218,6 @@ guint cogl_texture_get_rowstride (CoglHandle handle);
*/
gint cogl_texture_get_max_waste (CoglHandle handle);
-/**
- * CoglTextureFilter:
- * @COGL_TEXTURE_FILTER_NEAREST: Measuring in manhatten distance from the,
- * current pixel center, use the nearest texture
- * texel.
- * @COGL_TEXTURE_FILTER_LINEAR: Use the weighted average of the 4 texels
- * nearest the current pixel center.
- * @COGL_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose
- * texel size most closely matches
- * the current pixel, and use the
- * COGL_TEXTURE_FILTER_NEAREST
- * criterion.
- * @COGL_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose
- * texel size most closely matches
- * the current pixel, and use the
- * COGL_TEXTURE_FILTER_LINEAR
- * criterion.
- * @COGL_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels
- * whose texel size most closely
- * matches the current pixel, use
- * the COGL_TEXTURE_FILTER_NEAREST
- * criterion on each one and take
- * their weighted average.
- * @COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels
- * whose texel size most closely
- * matches the current pixel, use
- * the COGL_TEXTURE_FILTER_LINEAR
- * criterion on each one and take
- * their weighted average.
- *
- * Texture filtering is used whenever the current pixel maps either to more
- * than one texture element (texel) or less than one. These filter enums
- * correspond to different strategies used to come up with a pixel color, by
- * possibly referring to multiple neighbouring texels and taking a weighted
- * average or simply using the nearest texel.
- */
-typedef enum _CoglTextureFilter
-{
- COGL_TEXTURE_FILTER_NEAREST = GL_NEAREST,
- COGL_TEXTURE_FILTER_LINEAR = GL_LINEAR,
- COGL_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST,
- COGL_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST,
- COGL_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR,
- COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR
-} CoglTextureFilter;
-
-/**
- * cogl_texture_get_min_filter:
- * @handle: a #CoglHandle for a texture.
- *
- * Query the currently set downscaling filter for a cogl texture.
- *
- * Returns: the current downscaling filter for a cogl texture.
- */
-CoglTextureFilter cogl_texture_get_min_filter (CoglHandle handle);
-
-/**
- * cogl_texture_get_mag_filter:
- * @handle: a #CoglHandle for a texture.
- *
- * Query the currently set downscaling filter for a cogl texture.
- *
- * Returns: the current downscaling filter for a cogl texture.
- */
-CoglTextureFilter cogl_texture_get_mag_filter (CoglHandle handle);
-
/**
* cogl_texture_is_sliced:
* @handle: a #CoglHandle for a texture.
@@ -343,20 +267,6 @@ gint cogl_texture_get_data (CoglHandle handle,
guint rowstride,
guchar *data);
-/**
- * cogl_texture_set_filters:
- * @handle: a #CoglHandle.
- * @min_filter: the filter used when scaling the texture down.
- * @mag_filter: the filter used when magnifying the texture.
- *
- * Changes the decimation and interpolation filters used when the texture is
- * drawn at other scales than 100%.
- */
-void cogl_texture_set_filters (CoglHandle handle,
- CoglTextureFilter min_filter,
- CoglTextureFilter mag_filter);
-
-
/**
* cogl_texture_set_region:
* @handle: a #CoglHandle.
diff --git a/cogl-types.h b/cogl-types.h
index a4ecd4193..0a1360dde 100644
--- a/cogl-types.h
+++ b/cogl-types.h
@@ -123,8 +123,7 @@ typedef struct _CoglTextureVertex CoglTextureVertex;
*
* Since: 0.8
*/
-typedef enum
-{
+typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
COGL_PIXEL_FORMAT_ANY = 0,
COGL_PIXEL_FORMAT_A_8 = 1 | COGL_A_BIT,
@@ -135,60 +134,21 @@ typedef enum
COGL_PIXEL_FORMAT_G_8 = 8,
COGL_PIXEL_FORMAT_RGB_888 = COGL_PIXEL_FORMAT_24,
+ COGL_PIXEL_FORMAT_BGR_888 = (COGL_PIXEL_FORMAT_24 | COGL_BGR_BIT),
- COGL_PIXEL_FORMAT_BGR_888 = (COGL_PIXEL_FORMAT_24 |
- COGL_BGR_BIT),
-
- COGL_PIXEL_FORMAT_RGBA_8888 = COGL_PIXEL_FORMAT_32 |
- COGL_A_BIT,
-
- COGL_PIXEL_FORMAT_BGRA_8888 = (COGL_PIXEL_FORMAT_32 |
- COGL_A_BIT |
- COGL_BGR_BIT),
-
- COGL_PIXEL_FORMAT_ARGB_8888 = (COGL_PIXEL_FORMAT_32 |
- COGL_A_BIT |
- COGL_AFIRST_BIT),
-
- COGL_PIXEL_FORMAT_ABGR_8888 = (COGL_PIXEL_FORMAT_32 |
- COGL_A_BIT |
- COGL_BGR_BIT |
- COGL_AFIRST_BIT),
-
- COGL_PIXEL_FORMAT_RGBA_8888_PRE = (COGL_PIXEL_FORMAT_32 |
- COGL_A_BIT |
- COGL_PREMULT_BIT),
-
- COGL_PIXEL_FORMAT_BGRA_8888_PRE = (COGL_PIXEL_FORMAT_32 |
- COGL_A_BIT |
- COGL_PREMULT_BIT |
- COGL_BGR_BIT),
-
- COGL_PIXEL_FORMAT_ARGB_8888_PRE = (COGL_PIXEL_FORMAT_32 |
- COGL_A_BIT |
- COGL_PREMULT_BIT |
- COGL_AFIRST_BIT),
-
- COGL_PIXEL_FORMAT_ABGR_8888_PRE = (COGL_PIXEL_FORMAT_32 |
- COGL_A_BIT |
- COGL_PREMULT_BIT |
- COGL_BGR_BIT |
- COGL_AFIRST_BIT),
-
- COGL_PIXEL_FORMAT_RGBA_4444_PRE = (COGL_PIXEL_FORMAT_RGBA_4444 |
- COGL_A_BIT |
- COGL_PREMULT_BIT),
-
- COGL_PIXEL_FORMAT_RGBA_5551_PRE = (COGL_PIXEL_FORMAT_RGBA_5551 |
- COGL_A_BIT |
- COGL_PREMULT_BIT),
-
+ COGL_PIXEL_FORMAT_RGBA_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT),
+ COGL_PIXEL_FORMAT_BGRA_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_BGR_BIT),
+ COGL_PIXEL_FORMAT_ARGB_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_AFIRST_BIT),
+ COGL_PIXEL_FORMAT_ABGR_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT),
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT),
+ COGL_PIXEL_FORMAT_BGRA_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_BGR_BIT),
+ COGL_PIXEL_FORMAT_ARGB_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_AFIRST_BIT),
+ COGL_PIXEL_FORMAT_ABGR_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT),
+ COGL_PIXEL_FORMAT_RGBA_4444_PRE = (COGL_PIXEL_FORMAT_RGBA_4444 | COGL_A_BIT | COGL_PREMULT_BIT),
+ COGL_PIXEL_FORMAT_RGBA_5551_PRE = (COGL_PIXEL_FORMAT_RGBA_5551 | COGL_A_BIT | COGL_PREMULT_BIT),
} CoglPixelFormat;
-#define COGL_TYPE_PIXEL_FORMAT (cogl_pixel_format_get_type ())
-GType cogl_pixel_format_get_type (void) G_GNUC_CONST;
-
/**
* CoglFeatureFlags:
* @COGL_FEATURE_TEXTURE_RECTANGLE: ARB_texture_rectangle support
@@ -222,9 +182,6 @@ typedef enum
COGL_FEATURE_VBOS = (1 << 11)
} CoglFeatureFlags;
-#define COGL_TYPE_FEATURE_FLAGS (cogl_feature_flags_get_type ())
-GType cogl_feature_flags_get_type (void) G_GNUC_CONST;
-
/**
* CoglBufferTarget:
* @COGL_WINDOW_BUFFER: FIXME
@@ -240,9 +197,6 @@ typedef enum
COGL_OFFSCREEN_BUFFER = (1 << 2)
} CoglBufferTarget;
-#define COGL_TYPE_BUFFER_TARGET (cogl_buffer_target_get_type ())
-GType cogl_buffer_target_get_type (void) G_GNUC_CONST;
-
/**
* CoglColor:
*
@@ -290,21 +244,23 @@ struct _CoglTextureVertex
/**
* CoglTextureFlags:
* @COGL_TEXTURE_NONE: No flags specified
- * @COGL_TEXTURE_AUTO_MIPMAP: Enables the automatic generation of the
- * mipmap pyramid from the base level image whenever it is updated
+ * @COGL_TEXTURE_NO_AUTO_MIPMAP: Disables the automatic generation of
+ * the mipmap pyramid from the base level image whenever it is
+ * updated. The mipmaps are only generated when the texture is
+ * rendered with a mipmap filter so it should be free to leave out
+ * this flag when using other filtering modes.
+ * @COGL_TEXTURE_NO_SLICING: Disables the slicing of the texture
*
* Flags to pass to the cogl_texture_new_* family of functions.
*
* Since: 1.0
*/
typedef enum {
- COGL_TEXTURE_NONE = 0,
- COGL_TEXTURE_AUTO_MIPMAP = 1 << 0
+ COGL_TEXTURE_NONE = 0,
+ COGL_TEXTURE_NO_AUTO_MIPMAP = 1 << 0,
+ COGL_TEXTURE_NO_SLICING = 1 << 1
} CoglTextureFlags;
-#define COGL_TYPE_TEXTURE_FLAGS (cogl_texture_flags_get_type ())
-GType cogl_texture_flags_get_type (void) G_GNUC_CONST;
-
/**
* CoglFogMode:
* @COGL_FOG_MODE_LINEAR: Calculates the fog blend factor as:
@@ -333,16 +289,12 @@ GType cogl_texture_flags_get_type (void) G_GNUC_CONST;
*
* Since: 1.0
*/
-typedef enum _CoglFogMode
-{
+typedef enum {
COGL_FOG_MODE_LINEAR,
COGL_FOG_MODE_EXPONENTIAL,
COGL_FOG_MODE_EXPONENTIAL_SQUARED
} CoglFogMode;
-#define COGL_TYPE_FOG_MODE (cogl_fog_mode_get_type ())
-GType cogl_fog_mode_get_type (void) G_GNUC_CONST;
-
G_END_DECLS
#endif /* __COGL_TYPES_H__ */
diff --git a/cogl-vertex-buffer.h b/cogl-vertex-buffer.h
index 717281db0..f01b5d3dd 100644
--- a/cogl-vertex-buffer.h
+++ b/cogl-vertex-buffer.h
@@ -94,6 +94,29 @@ cogl_vertex_buffer_new (guint n_vertices);
guint
cogl_vertex_buffer_get_n_vertices (CoglHandle handle);
+/**
+ * CoglAttributeType:
+ * @COGL_ATTRIBUTE_TYPE_BYTE: Data is the same size of a byte
+ * @COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE: Data is the same size of an
+ * unsigned byte
+ * @COGL_ATTRIBUTE_TYPE_SHORT: Data is the same size of a short integer
+ * @COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT: Data is the same size of
+ * an unsigned short integer
+ * @COGL_ATTRIBUTE_TYPE_FLOAT: Data is the same size of a float
+ *
+ * Data types for the components of cogl_vertex_buffer_add()
+ *
+ * Since: 1.0
+ */
+typedef enum _CoglAttributeType
+{
+ COGL_ATTRIBUTE_TYPE_BYTE = GL_BYTE,
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE = GL_UNSIGNED_BYTE,
+ COGL_ATTRIBUTE_TYPE_SHORT = GL_SHORT,
+ COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT = GL_UNSIGNED_SHORT,
+ COGL_ATTRIBUTE_TYPE_FLOAT = GL_FLOAT
+} CoglAttributeType;
+
/**
* cogl_vertex_buffer_add:
* @handle: A vertex buffer handle
@@ -111,10 +134,9 @@ cogl_vertex_buffer_get_n_vertices (CoglHandle handle);
* the name can have a detail component, E.g.
* "gl_Color::active" or "gl_Color::inactive"
* @n_components: The number of components per attribute and must be 1,2,3 or 4
- * @gl_type: Specifies the data type of each component (GL_BYTE, GL_UNSIGNED_BYTE,
- * GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT or GL_FLOAT)
+ * @type: a #CoglAttributeType specifying the data type of each component.
* @normalized: If GL_TRUE, this specifies that values stored in an integer
- * format should be mapped into the range [-1.0, 1.0] or [0.1, 1.0]
+ * format should be mapped into the range [-1.0, 1.0] or [0.0, 1.0]
* for unsigned values. If GL_FALSE they are converted to floats
* directly.
* @stride: This specifies the number of bytes from the start of one attribute
@@ -156,13 +178,13 @@ cogl_vertex_buffer_get_n_vertices (CoglHandle handle);
* (Though you can have multiple groups of interleved attributes)
*/
void
-cogl_vertex_buffer_add (CoglHandle handle,
- const char *attribute_name,
- guint8 n_components,
- GLenum gl_type,
- gboolean normalized,
- guint16 stride,
- const void *pointer);
+cogl_vertex_buffer_add (CoglHandle handle,
+ const char *attribute_name,
+ guint8 n_components,
+ CoglAttributeType type,
+ gboolean normalized,
+ guint16 stride,
+ const void *pointer);
/**
* cogl_vertex_buffer_delete:
@@ -226,21 +248,37 @@ void
cogl_vertex_buffer_enable (CoglHandle handle,
const char *attribute_name);
+/**
+ * CoglVerticesMode:
+ * @COGL_VERTICES_MODE_POINTS: FIXME, equivalent to %GL_POINTS
+ * @COGL_VERTICES_MODE_LINE_STRIP: FIXME, equivalent to %GL_LINE_STRIP
+ * @COGL_VERTICES_MODE_LINE_LOOP: FIXME, equivalent to %GL_LINE_LOOP
+ * @COGL_VERTICES_MODE_LINES: FIXME, equivalent to %GL_LINES
+ * @COGL_VERTICES_MODE_TRIANGLE_STRIP: FIXME, equivalent to %GL_TRIANGLE_STRIP
+ * @COGL_VERTICES_MODE_TRIANGLE_FAN: FIXME, equivalent to %GL_TRIANGLE_FAN
+ * @COGL_VERTICES_MODE_TRIANGLES: FIXME, equivalent to %GL_TRIANGLES
+ *
+ * How vertices passed to cogl_vertex_buffer_draw() and
+ * cogl_vertex_buffer_draw_elements() should be interpreted
+ *
+ * Since: 1.0
+ */
+typedef enum _CoglVerticesMode
+{
+ COGL_VERTICES_MODE_POINTS = GL_POINTS,
+ COGL_VERTICES_MODE_LINE_STRIP = GL_LINE_STRIP,
+ COGL_VERTICES_MODE_LINE_LOOP = GL_LINE_LOOP,
+ COGL_VERTICES_MODE_LINES = GL_LINES,
+ COGL_VERTICES_MODE_TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
+ COGL_VERTICES_MODE_TRIANGLE_FAN = GL_TRIANGLE_FAN,
+ COGL_VERTICES_MODE_TRIANGLES = GL_TRIANGLES
+} CoglVerticesMode;
+
/**
* cogl_vertex_buffer_draw:
* @handle: A vertex buffer handle
- * @mode: Specifies how the vertices should be interpreted, and should be
- * a valid GL primitive type:
- *
- * GL_POINTS
- * GL_LINE_STRIP
- * GL_LINE_LOOP
- * GL_LINES
- * GL_TRIANGLE_STRIP
- * GL_TRIANGLE_FAN
- * GL_TRIANGLES
- *
- * (Note: only types available in GLES are listed)
+ * @mode: A #CoglVerticesMode specifying how the vertices should be
+ * interpreted.
* @first: Specifies the index of the first vertex you want to draw with
* @count: Specifies the number of vertices you want to draw.
*
@@ -251,52 +289,90 @@ cogl_vertex_buffer_enable (CoglHandle handle,
* drawing.
*/
void
-cogl_vertex_buffer_draw (CoglHandle handle,
- GLenum mode,
- GLint first,
- GLsizei count);
+cogl_vertex_buffer_draw (CoglHandle handle,
+ CoglVerticesMode mode,
+ int first,
+ int count);
+
+/**
+ * CoglIndicesType:
+ * @COGL_INDICES_TYPE_UNSIGNED_BYTE: Your indices are unsigned bytes
+ * @COGL_INDICES_TYPE_UNSIGNED_SHORT: Your indices are unsigned shorts
+ * @COGL_INDICES_TYPE_UNSIGNED_INT: You indices are unsigned integers
+ *
+ * You should aim to use the smallest data type that gives you enough
+ * range, since it reduces the size of your index array and can help
+ * reduce the demand on memory bandwidth.
+ */
+typedef enum _CoglIndicesType
+{
+ COGL_INDICES_TYPE_UNSIGNED_BYTE,
+ COGL_INDICES_TYPE_UNSIGNED_SHORT,
+ COGL_INDICES_TYPE_UNSIGNED_INT
+} CoglIndicesType;
+
+/**
+ * cogl_vertex_buffer_indices_new:
+ * @indices_type: a #CoglIndicesType specifying the data type used for
+ * the indices.
+ * @indices_array: Specifies the address of your array of indices
+ * @indices_len: The number of indices in indices_array
+ *
+ * Depending on how much geometry you are submitting it can be worthwhile
+ * optimizing the number of redundant vertices you submit. Using an index
+ * array allows you to reference vertices multiple times, for example
+ * during triangle strips.
+ *
+ * Returns: A CoglHandle for the indices which you can pass to
+ * cogl_vertex_buffer_draw_elements().
+ */
+CoglHandle
+cogl_vertex_buffer_indices_new (CoglIndicesType indices_type,
+ const void *indices_array,
+ int indices_len);
+
+/**
+ * cogl_vertex_buffer_delete_indices:
+ * @handle: A vertex buffer handle
+ * @indices_id: The identifier for a an array of indices previously added to
+ * the given Cogl vertex buffer using
+ * cogl_vertex_buffer_add_indices().
+ *
+ * Frees the resources associated with a previously added array of vertex
+ * indices.
+ */
+void
+cogl_vertex_buffer_delete_indices (CoglHandle handle,
+ int indices_id);
/**
* cogl_vertex_buffer_draw_elements:
* @handle: A vertex buffer handle
- * @mode: Specifies how the vertices should be interpreted, and should be
- * a valid GL primitive type:
- *
- * GL_POINTS
- * GL_LINE_STRIP
- * GL_LINE_LOOP
- * GL_LINES
- * GL_TRIANGLE_STRIP
- * GL_TRIANGLE_FAN
- * GL_TRIANGLES
- *
- * (Note: only types available in GLES are listed)
+ * @mode: A #CoglVerticesMode specifying how the vertices should be
+ * interpreted.
+ * @indices: A CoglHandle for a set of indices allocated via
+ * cogl_vertex_buffer_indices_new ()
* @min_index: Specifies the minimum vertex index contained in indices
* @max_index: Specifies the maximum vertex index contained in indices
+ * @indices_offset: An offset into named indices. The offset marks the first
+ * index to use for drawing.
* @count: Specifies the number of vertices you want to draw.
- * @indices_type: Specifies the data type used for the indices, and must be
- * one of:
- *
- * GL_UNSIGNED_BYTE
- * GL_UNSIGNED_SHORT
- * GL_UNSIGNED_INT
- *
- * @indices: Specifies the address of your array of indices
*
* This function lets you use an array of indices to specify the vertices
- * within your vertex buffer that you want to draw.
+ * within your vertex buffer that you want to draw. The indices themselves
+ * are created by calling cogl_vertex_buffer_indices_new ()
*
* Any un-submitted attribute changes are automatically submitted before
* drawing.
*/
void
-cogl_vertex_buffer_draw_elements (CoglHandle handle,
- GLenum mode,
- GLuint min_index,
- GLuint max_index,
- GLsizei count,
- GLenum indices_type,
- const GLvoid *indices);
+cogl_vertex_buffer_draw_elements (CoglHandle handle,
+ CoglVerticesMode mode,
+ CoglHandle indices,
+ int min_index,
+ int max_index,
+ int indices_offset,
+ int count);
/**
* cogl_vertex_buffer_ref:
@@ -318,6 +394,46 @@ cogl_vertex_buffer_ref (CoglHandle handle);
void
cogl_vertex_buffer_unref (CoglHandle handle);
+/**
+ * cogl_vertex_buffer_indices_get_for_quads:
+ * @n_indices: the number of indices in the vertex buffer.
+ *
+ * Creates a vertex buffer containing the indices needed to draw pairs
+ * of triangles from a list of vertices grouped as quads. There will
+ * be at least @n_indices entries in the buffer (but there may be
+ * more).
+ *
+ * The indices will follow this pattern:
+ *
+ * 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7 ... etc
+ *
+ * For example, if you submit vertices for a quad like this:
+ *
+ * |[
+ * 0 3
+ * ########
+ * # #
+ * # #
+ * ########
+ * 1 2
+ * ]|
+ *
+ * Then you can request 6 indices to render two triangles like this:
+ *
+ * |[
+ * 0 0 3
+ * ## ########
+ * # ## ## #
+ * # ## ## #
+ * ######## ##
+ * 1 2 2
+ * ]|
+ *
+ * Returns: A %CoglHandle containing the indices. The handled is
+ * owned by Cogl and should not be modified or unref'd.
+ */
+CoglHandle
+cogl_vertex_buffer_indices_get_for_quads (guint n_indices);
G_END_DECLS
diff --git a/cogl.h.in b/cogl.h.in
index bd3698312..a468cf717 100644
--- a/cogl.h.in
+++ b/cogl.h.in
@@ -45,6 +45,7 @@
#include
#include
#include
+#include
G_BEGIN_DECLS
@@ -55,22 +56,6 @@ G_BEGIN_DECLS
* General utility functions for COGL.
*/
-/* Context manipulation */
-
-/**
- * cogl_create_context:
- *
- * FIXME
- */
-gboolean cogl_create_context (void);
-
-/**
- * cogl_destroy_context:
- *
- * FIXME
- */
-void cogl_destroy_context (void);
-
/**
* cogl_get_option_group:
*
@@ -187,7 +172,30 @@ void cogl_frustum (float left,
float z_far);
/**
- * cogl_setup_viewport:
+ * cogl_ortho:
+ * @left: The coordinate for the left clipping plane
+ * @right: The coordinate for the right clipping plane
+ * @bottom: The coordinate for the bottom clipping plane
+ * @top: The coordinate for the top clipping plane
+ * @near: The coordinate for the near clipping plane (may be negative if
+ * the plane is behind the viewer)
+ * @far: The coordinate for the far clipping plane (may be negative if
+ * the plane is behind the viewer)
+ *
+ * Replaces the current projection matrix with a parallel projection
+ * matrix.
+ *
+ * Since: 1.0
+ */
+void cogl_ortho (float left,
+ float right,
+ float bottom,
+ float top,
+ float near,
+ float far);
+
+/*
+ * _cogl_setup_viewport:
* @width: Width of the viewport
* @height: Height of the viewport
* @fovy: Field of view angle in degrees
@@ -201,9 +209,11 @@ void cogl_frustum (float left,
* with one that has a viewing angle of @fovy along the y-axis and a
* view scaled according to @aspect along the x-axis. The view is
* clipped according to @z_near and @z_far on the z-axis.
+ *
+ * This function is used only by Clutter.
*/
-void cogl_setup_viewport (guint width,
- guint height,
+void _cogl_setup_viewport (guint width,
+ guint height,
float fovy,
float aspect,
float z_near,
@@ -288,6 +298,14 @@ void cogl_rotate (float angle,
*/
void cogl_get_modelview_matrix (CoglMatrix *matrix);
+/**
+ * cogl_set_modelview_matrix:
+ * @matrix: pointer to a CoglMatrix to set as the new model-view matrix
+ *
+ * Loads matrix as the new model-view matrix.
+ */
+void cogl_set_modelview_matrix (CoglMatrix *matrix);
+
/**
* cogl_get_projection_matrix:
* @matrix: pointer to a CoglMatrix to recieve the matrix
@@ -296,6 +314,14 @@ void cogl_get_modelview_matrix (CoglMatrix *matrix);
*/
void cogl_get_projection_matrix (CoglMatrix *matrix);
+/**
+ * cogl_set_projection_matrix:
+ * @matrix: pointer to a CoglMatrix to set as the new projection matrix
+ *
+ * Loads matrix as the new projection matrix.
+ */
+void cogl_set_projection_matrix (CoglMatrix *matrix);
+
/**
* cogl_get_viewport:
* @v: pointer to a 4 element array of #floats to
@@ -308,7 +334,7 @@ void cogl_get_projection_matrix (CoglMatrix *matrix);
void cogl_get_viewport (float v[4]);
/**
- * cogl_enable_depth_test:
+ * cogl_set_depth_test_enable:
* @setting: %TRUE to enable depth testing or %FALSE to disable.
*
* Sets whether depth testing is enabled. If it is disabled then the
@@ -317,10 +343,19 @@ void cogl_get_viewport (float v[4]);
* clutter_actor_lower(), otherwise it will also take into account the
* actor's depth. Depth testing is disabled by default.
*/
-void cogl_enable_depth_test (gboolean setting);
+void cogl_set_depth_test_enable (gboolean setting);
/**
- * cogl_enable_backface_culling:
+ * cogl_get_depth_test_enable:
+ *
+ * Queries if depth testing has been enabled via cogl_set_depth_test_enable()
+ *
+ * Returns: TRUE if depth testing is enabled else FALSE
+ */
+gboolean cogl_get_depth_test_enable (void);
+
+/**
+ * cogl_set_backface_culling_enabled:
* @setting: %TRUE to enable backface culling or %FALSE to disable.
*
* Sets whether textures positioned so that their backface is showing
@@ -329,7 +364,17 @@ void cogl_enable_depth_test (gboolean setting);
* only affects calls to the cogl_rectangle* family of functions and
* cogl_vertex_buffer_draw*. Backface culling is disabled by default.
*/
-void cogl_enable_backface_culling (gboolean setting);
+void cogl_set_backface_culling_enabled (gboolean setting);
+
+/**
+ * cogl_get_backface_culling_enabled:
+ *
+ * Queries if backface culling has been enabled via
+ * cogl_set_backface_culling_enabled()
+ *
+ * Returns: TRUE if backface culling is enabled else FALSE
+ */
+gboolean cogl_get_backface_culling_enabled (void);
/**
* cogl_set_fog:
@@ -368,9 +413,12 @@ void cogl_disable_fog (void);
* @COGL_BUFFER_BIT_COLOR: Selects the primary color buffer
* @COGL_BUFFER_BIT_DEPTH: Selects the depth buffer
* @COGL_BUFFER_BIT_STENCIL: Selects the stencil buffer
+ *
+ * Types of auxiliary buffers
+ *
+ * Since: 1.0
*/
-typedef enum _CoglBufferBit
-{
+typedef enum {
COGL_BUFFER_BIT_COLOR = 1L<<0,
COGL_BUFFER_BIT_DEPTH = 1L<<1,
COGL_BUFFER_BIT_STENCIL = 1L<<2
@@ -379,13 +427,14 @@ typedef enum _CoglBufferBit
/**
* cogl_clear:
* @color: Background color to clear to
- * @buffers: A mask of @CoglBufferBit's identifying which auxiliary
- * buffers to clear
+ * @buffers: A mask of #CoglBufferBit's identifying which auxiliary
+ * buffers to clear
*
* Clears all the auxiliary buffers identified in the @buffers mask, and if
* that includes the color buffer then the specified @color is used.
*/
-void cogl_clear (const CoglColor *color, gulong buffers);
+void cogl_clear (const CoglColor *color,
+ gulong buffers);
/**
* cogl_set_source:
@@ -628,7 +677,24 @@ void cogl_push_draw_buffer (void);
*/
void cogl_pop_draw_buffer (void);
-/**
+
+/*
+ * Internal API available only to Clutter.
+ *
+ * These are typically only to deal with the poor seperation of
+ * responsabilities that currently exists between Clutter and Cogl.
+ * Eventually a lot of the backend code currently in Clutter will
+ * move down into Cogl and these functions will be removed.
+ */
+
+void _cogl_destroy_context (void);
+
+/* XXX: Removed before we release Clutter 1.0 since the implementation
+ * wasn't complete, and so we assume no one is using this yet. Util we
+ * have some one with a good usecase, we can't pretend to support breaking
+ * out into raw OpenGL. */
+#if 0
+/*
* cogl_flush_gl_state:
* @flags: flags controlling what is flushed; currently unused, pass in 0
*
@@ -642,6 +708,7 @@ void cogl_pop_draw_buffer (void);
* Since: 1.0
*/
void cogl_flush_gl_state (int flags);
+#endif
/* private */
void _cogl_set_indirect_context (gboolean indirect);
diff --git a/common/Makefile.am b/common/Makefile.am
index 138893a14..7a7dd8232 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -1,3 +1,10 @@
+NULL =
+
+V = @
+Q = $(V:1=)
+QUIET_GEN = $(Q:@=@echo ' GEN '$@;)
+QUIET_CP = $(Q:@=@echo ' CP '$@;)
+
INCLUDES = \
-I$(top_srcdir) \
-I$(top_srcdir)/clutter \
@@ -9,12 +16,49 @@ INCLUDES = \
-DG_LOG_DOMAIN=\"Cogl-Common\" \
-DCLUTTER_COMPILATION
+cogl_public_h = \
+ $(top_srcdir)/clutter/cogl/cogl-bitmap.h \
+ $(top_srcdir)/clutter/cogl/cogl-color.h \
+ $(top_srcdir)/clutter/cogl/cogl-debug.h \
+ $(top_srcdir)/clutter/cogl/cogl-fixed.h \
+ $(top_srcdir)/clutter/cogl/cogl-material.h \
+ $(top_srcdir)/clutter/cogl/cogl-matrix.h \
+ $(top_srcdir)/clutter/cogl/cogl-offscreen.h \
+ $(top_srcdir)/clutter/cogl/cogl-path.h \
+ $(top_srcdir)/clutter/cogl/cogl-shader.h \
+ $(top_srcdir)/clutter/cogl/cogl-texture.h \
+ $(top_srcdir)/clutter/cogl/cogl-types.h \
+ $(top_srcdir)/clutter/cogl/cogl-vertex-buffer.h \
+ $(top_builddir)/clutter/cogl/cogl.h \
+ $(NULL)
+
noinst_LTLIBRARIES = libclutter-cogl-common.la
-EXTRA_DIST = stb_image.c
+
+cogl-enum-types.h: stamp-cogl-enum-types.h
+ @true
+stamp-cogl-enum-types.h: $(cogl_public_h) Makefile
+ $(QUIET_GEN)( $(GLIB_MKENUMS) \
+ --template $(srcdir)/cogl-enum-types.h.in \
+ $(cogl_public_h) ) > xgen-ceth \
+ && (cmp -s xgen-ceth cogl-enum-types.h || cp -f xgen-ceth cogl-enum-types.h) \
+ && cp -f cogl-enum-types.h $(top_builddir)/clutter/cogl/cogl-enum-types.h \
+ && rm -f xgen-ceth \
+ && echo timestamp > $(@F)
+
+cogl-enum-types.c: cogl-enum-types.h
+ $(QUIET_GEN)( $(GLIB_MKENUMS) \
+ --template $(srcdir)/cogl-enum-types.c.in \
+ $(cogl_public_h) ) > xgen-cetc \
+ && cp -f xgen-cetc cogl-enum-types.c \
+ && rm -f xgen-cetc
+
+BUILT_SOURCES = cogl-enum-types.h cogl-enum-types.c
libclutter_cogl_common_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
libclutter_cogl_common_la_LIBADD = -lm $(CLUTTER_LIBS)
libclutter_cogl_common_la_SOURCES = \
+ $(top_builddir)/clutter/cogl/common/cogl-enum-types.h \
+ $(top_builddir)/clutter/cogl/common/cogl-enum-types.c \
cogl-handle.h \
cogl-internal.h \
cogl.c \
@@ -39,4 +83,11 @@ libclutter_cogl_common_la_SOURCES = \
cogl-matrix-stack.h \
cogl-material.c \
cogl-material-private.h \
- cogl-debug.c
+ cogl-blend-string.c \
+ cogl-blend-string.h \
+ cogl-debug.c \
+ $(NULL)
+
+EXTRA_DIST = stb_image.c cogl-enum-types.h.in cogl-enum-types.c.in
+CLEANFILES = stamp-cogl-enum-types.h
+DISTCLEANFILES = cogl-enum-types.h cogl-enum-types.c
diff --git a/common/cogl-blend-string.c b/common/cogl-blend-string.c
new file mode 100644
index 000000000..2e7bdd8d3
--- /dev/null
+++ b/common/cogl-blend-string.c
@@ -0,0 +1,999 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2009 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Robert Bragg
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+
+#include
+
+#include "cogl.h"
+#include "cogl-internal.h"
+#include "cogl-context.h"
+#include "cogl-debug.h"
+#include "cogl-blend-string.h"
+
+typedef enum _ParserState
+{
+ PARSER_STATE_EXPECT_DEST_CHANNELS,
+ PARSER_STATE_SCRAPING_DEST_CHANNELS,
+ PARSER_STATE_EXPECT_FUNCTION_NAME,
+ PARSER_STATE_SCRAPING_FUNCTION_NAME,
+ PARSER_STATE_EXPECT_ARG_START,
+ PARSER_STATE_EXPECT_STATEMENT_END
+} ParserState;
+
+typedef enum _ParserArgState
+{
+ PARSER_ARG_STATE_START,
+ PARSER_ARG_STATE_EXPECT_MINUS,
+ PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME,
+ PARSER_ARG_STATE_SCRAPING_COLOR_SRC_NAME,
+ PARSER_ARG_STATE_MAYBE_COLOR_MASK,
+ PARSER_ARG_STATE_SCRAPING_MASK,
+ PARSER_ARG_STATE_MAYBE_MULT,
+ PARSER_ARG_STATE_EXPECT_OPEN_PAREN,
+ PARSER_ARG_STATE_EXPECT_FACTOR,
+ PARSER_ARG_STATE_MAYBE_SRC_ALPHA_SATURATE,
+ PARSER_ARG_STATE_MAYBE_MINUS,
+ PARSER_ARG_STATE_EXPECT_CLOSE_PAREN,
+ PARSER_ARG_STATE_EXPECT_END
+} ParserArgState;
+
+
+#define DEFINE_COLOR_SOURCE(NAME, NAME_LEN) \
+ {.type = COGL_BLEND_STRING_COLOR_SOURCE_ ## NAME, \
+ .name = #NAME, \
+ .name_len = NAME_LEN}
+
+static CoglBlendStringColorSourceInfo blending_color_sources[] = {
+ DEFINE_COLOR_SOURCE (SRC_COLOR, 9),
+ DEFINE_COLOR_SOURCE (DST_COLOR, 9),
+ DEFINE_COLOR_SOURCE (CONSTANT, 8)
+};
+
+static CoglBlendStringColorSourceInfo tex_combine_color_sources[] = {
+ DEFINE_COLOR_SOURCE (TEXTURE, 7),
+ /* DEFINE_COLOR_SOURCE (TEXTURE_N, *) - handled manually */
+ DEFINE_COLOR_SOURCE (PRIMARY, 7),
+ DEFINE_COLOR_SOURCE (CONSTANT, 8),
+ DEFINE_COLOR_SOURCE (PREVIOUS, 8)
+};
+
+static CoglBlendStringColorSourceInfo tex_combine_texture_n_color_source = {
+ .type = COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N,
+ .name = "TEXTURE_N",
+ .name_len = 0
+};
+
+#undef DEFINE_COLOR_SOURCE
+
+#define DEFINE_FUNCTION(NAME, NAME_LEN, ARGC) \
+ { .type = COGL_BLEND_STRING_FUNCTION_ ## NAME, \
+ .name = #NAME, \
+ .name_len = NAME_LEN, \
+ .argc = ARGC }
+
+/* NB: These must be sorted so any name that's a subset of another
+ * comes later than the longer name. */
+static CoglBlendStringFunctionInfo tex_combine_functions[] = {
+ DEFINE_FUNCTION (AUTO_COMPOSITE, 14, 0),
+ DEFINE_FUNCTION (REPLACE, 7, 1),
+ DEFINE_FUNCTION (MODULATE, 8, 2),
+ DEFINE_FUNCTION (ADD_SIGNED, 10, 2),
+ DEFINE_FUNCTION (ADD, 3, 2),
+ DEFINE_FUNCTION (INTERPOLATE, 11, 3),
+ DEFINE_FUNCTION (SUBTRACT, 8, 2),
+ DEFINE_FUNCTION (DOT3_RGBA, 9, 2),
+ DEFINE_FUNCTION (DOT3_RGB, 8, 2)
+};
+
+static CoglBlendStringFunctionInfo blend_functions[] = {
+ DEFINE_FUNCTION (AUTO_COMPOSITE, 14, 0),
+ DEFINE_FUNCTION (ADD, 3, 2)
+};
+
+#undef DEFINE_FUNCTION
+
+GQuark
+_cogl_blend_string_error_quark (void)
+{
+ return g_quark_from_static_string ("cogl-blend-string-error-quark");
+}
+
+void
+_cogl_blend_string_split_rgba_statement (CoglBlendStringStatement *statement,
+ CoglBlendStringStatement *rgb,
+ CoglBlendStringStatement *a)
+{
+ int i;
+
+ memcpy (rgb, statement, sizeof (CoglBlendStringStatement));
+ memcpy (a, statement, sizeof (CoglBlendStringStatement));
+
+ rgb->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB;
+ a->mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA;
+
+ for (i = 0; i < statement->function->argc; i++)
+ {
+ CoglBlendStringArgument *arg = &statement->args[i];
+ CoglBlendStringArgument *rgb_arg = &rgb->args[i];
+ CoglBlendStringArgument *a_arg = &a->args[i];
+
+ if (arg->source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA)
+ {
+ rgb_arg->source.mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB;
+ a_arg->source.mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA;
+ }
+
+ if (arg->factor.is_color &&
+ arg->factor.source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA)
+ {
+ rgb_arg->factor.source.mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB;
+ a_arg->factor.source.mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA;
+ }
+ }
+}
+
+static gboolean
+validate_tex_combine_statements (CoglBlendStringStatement *statements,
+ int n_statements,
+ GError **error)
+{
+ int i, j;
+ const char *error_string;
+ CoglBlendStringError detail = COGL_BLEND_STRING_ERROR_INVALID_ERROR;
+
+ for (i = 0; i < n_statements; i++)
+ {
+#ifdef HAVE_COGL_GLES2
+ if (statements[i].function->type != COGL_BLEND_STRING_FUNCTION_MODULATE)
+ {
+ error_string = "Using anything but MODULATE() for texture combining"
+ " under GLES 2 is currently unsupported";
+ detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
+ goto error;
+ }
+#endif
+ for (j = 0; j < statements[i].function->argc; j++)
+ {
+ CoglBlendStringArgument *arg = &statements[i].args[j];
+ if (arg->source.is_zero)
+ {
+ error_string = "You can't use the constant '0' as a texture "
+ "combine argument";
+ goto error;
+ }
+ if (!arg->factor.is_one)
+ {
+ error_string = "Argument factors are only relevant to blending "
+ "not texture combining";
+ goto error;
+ }
+#ifdef HAVE_COGL_GLES2
+ if (arg->source.info->type == COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
+ {
+ error_string = "Using a constant for texture combining isn't "
+ "currently supported with GLES 2 "
+ "(TODO: glTexEnvf)";
+ detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
+ goto error;
+ }
+#endif
+ }
+ }
+
+ return TRUE;
+
+error:
+ g_set_error (error,
+ COGL_BLEND_STRING_ERROR,
+ detail,
+ "Invalid texture combine string: %s",
+ error_string);
+
+ if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ {
+ g_debug ("Invalid texture combine string: %s",
+ error_string);
+ }
+ return FALSE;
+}
+
+static gboolean
+validate_blend_statements (CoglBlendStringStatement *statements,
+ int n_statements,
+ GError **error)
+{
+ int i, j;
+ const char *error_string;
+ CoglBlendStringError detail = COGL_BLEND_STRING_ERROR_INVALID_ERROR;
+
+#ifdef HAVE_COGL_GL
+ _COGL_GET_CONTEXT (ctx, 0);
+#endif
+
+#ifdef HAVE_COGL_GL
+ if (n_statements == 2)
+ {
+ /* glBlendEquationSeperate is GL 2.0 only */
+ if (!ctx->pf_glBlendEquationSeparate &&
+ statements[0].function->type != statements[1].function->type)
+ {
+ error_string = "Separate blend functions for the RGB an A "
+ "channels isn't supported by the driver";
+ detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
+ goto error;
+ }
+ }
+#elif defined(HAVE_COGL_GLES)
+ if (n_statements != 1)
+ {
+ error_string = "Separate blend functions for the RGB an A "
+ "channels isn't supported by the GLES 1";
+ detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
+ goto error;
+ }
+#endif
+
+ for (i = 0; i < n_statements; i++)
+ for (j = 0; j < statements[i].function->argc; j++)
+ {
+ CoglBlendStringArgument *arg = &statements[i].args[j];
+
+ if (arg->source.is_zero)
+ continue;
+
+ if ((j == 0 &&
+ arg->source.info->type !=
+ COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR)
+ || (j == 1 &&
+ arg->source.info->type !=
+ COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR))
+ {
+ error_string = "For blending you must always use SRC_COLOR "
+ "for arg0 and DST_COLOR for arg1";
+ goto error;
+ }
+
+#ifdef HAVE_COGL_GLES
+ if (arg->factor.is_color &&
+ arg->factor.source.info->type == COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
+ {
+ error_string = "GLES Doesn't support constant blend factors";
+ detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
+ goto error;
+ }
+#endif
+ }
+
+ return TRUE;
+
+error:
+ g_set_error (error,
+ COGL_BLEND_STRING_ERROR,
+ detail,
+ "Invalid blend string: %s",
+ error_string);
+ return FALSE;
+}
+
+static gboolean
+validate_statements_for_context (CoglBlendStringStatement *statements,
+ int n_statements,
+ CoglBlendStringContext context,
+ GError **error)
+{
+ const char *error_string;
+
+ if (n_statements == 1)
+ {
+ if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
+ {
+ error_string = "You need to also give a blend statement for the RGB"
+ "channels";
+ goto error;
+ }
+ else if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB)
+ {
+ error_string = "You need to also give a blend statement for the "
+ "Alpha channel";
+ goto error;
+ }
+ }
+
+ if (context == COGL_BLEND_STRING_CONTEXT_BLENDING)
+ return validate_blend_statements (statements, n_statements, error);
+ else
+ return validate_tex_combine_statements (statements, n_statements, error);
+
+error:
+ g_set_error (error,
+ COGL_BLEND_STRING_ERROR,
+ COGL_BLEND_STRING_ERROR_INVALID_ERROR,
+ "Invalid %s string: %s",
+ context == COGL_BLEND_STRING_CONTEXT_BLENDING ?
+ "blend" : "texture combine",
+ error_string);
+
+ if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ {
+ g_debug ("Invalid %s string: %s",
+ context == COGL_BLEND_STRING_CONTEXT_BLENDING ?
+ "blend" : "texture combine",
+ error_string);
+ }
+
+ return FALSE;
+}
+
+static void
+print_argument (CoglBlendStringArgument *arg)
+{
+ const char *mask_names[] = {
+ "RGB",
+ "A",
+ "RGBA"
+ };
+
+ g_print (" Arg:\n");
+ g_print (" is zero = %s\n", arg->source.is_zero ? "yes" : "no");
+ if (!arg->source.is_zero)
+ {
+ g_print (" color source = %s\n", arg->source.info->name);
+ g_print (" one minus = %s\n", arg->source.one_minus ? "yes" : "no");
+ g_print (" mask = %s\n", mask_names[arg->source.mask]);
+ g_print (" texture = %d\n", arg->source.texture);
+ g_print ("\n");
+ g_print (" factor is_one = %s\n", arg->factor.is_one ? "yes" : "no");
+ g_print (" factor is_src_alpha_saturate = %s\n",
+ arg->factor.is_src_alpha_saturate ? "yes" : "no");
+ g_print (" factor is_color = %s\n", arg->factor.is_color ? "yes" : "no");
+ if (arg->factor.is_color)
+ {
+ g_print (" factor color:is zero = %s\n",
+ arg->factor.source.is_zero ? "yes" : "no");
+ g_print (" factor color:color source = %s\n",
+ arg->factor.source.info->name);
+ g_print (" factor color:one minus = %s\n",
+ arg->factor.source.one_minus ? "yes" : "no");
+ g_print (" factor color:mask = %s\n",
+ mask_names[arg->factor.source.mask]);
+ g_print (" factor color:texture = %d\n",
+ arg->factor.source.texture);
+ }
+ }
+}
+
+static void
+print_statement (int num, CoglBlendStringStatement *statement)
+{
+ const char *mask_names[] = {
+ "RGB",
+ "A",
+ "RGBA"
+ };
+ int i;
+ g_print ("Statement %d:\n", num);
+ g_print (" Destination channel mask = %s\n",
+ mask_names[statement->mask]);
+ g_print (" Function = %s\n", statement->function->name);
+ for (i = 0; i < statement->function->argc; i++)
+ print_argument (&statement->args[i]);
+}
+
+static const CoglBlendStringFunctionInfo *
+get_function_info (const char *mark,
+ const char *p,
+ CoglBlendStringContext context)
+{
+ size_t len = p - mark;
+ CoglBlendStringFunctionInfo *functions;
+ size_t array_len;
+ int i;
+
+ if (context == COGL_BLEND_STRING_CONTEXT_BLENDING)
+ {
+ functions = blend_functions;
+ array_len = G_N_ELEMENTS (blend_functions);
+ }
+ else
+ {
+ functions = tex_combine_functions;
+ array_len = G_N_ELEMENTS (tex_combine_functions);
+ }
+
+ for (i = 0; i < array_len; i++)
+ {
+ if (len >= functions[i].name_len
+ && strncmp (mark, functions[i].name, functions[i].name_len) == 0)
+ return &functions[i];
+ }
+ return NULL;
+}
+
+static const CoglBlendStringColorSourceInfo *
+get_color_src_info (const char *mark,
+ const char *p,
+ CoglBlendStringContext context)
+{
+ size_t len = p - mark;
+ CoglBlendStringColorSourceInfo *sources;
+ size_t array_len;
+ int i;
+
+ if (context == COGL_BLEND_STRING_CONTEXT_BLENDING)
+ {
+ sources = blending_color_sources;
+ array_len = G_N_ELEMENTS (blending_color_sources);
+ }
+ else
+ {
+ sources = tex_combine_color_sources;
+ array_len = G_N_ELEMENTS (tex_combine_color_sources);
+ }
+
+ for (i = 0; i < array_len; i++)
+ {
+ if (len >= sources[i].name_len
+ && strncmp (mark, sources[i].name, sources[i].name_len) == 0)
+ return &sources[i];
+ }
+
+ if (len >= 9 &&
+ strncmp (mark, "TEXTURE_", 8) == 0 &&
+ g_ascii_isdigit (mark[8]))
+ {
+ return &tex_combine_texture_n_color_source;
+ }
+
+ return NULL;
+}
+
+static gboolean
+is_symbol_char (const char c)
+{
+ return (g_ascii_isalpha (c) || c == '_') ? TRUE : FALSE;
+}
+
+static gboolean
+parse_argument (const char *string, /* original user string */
+ const char **ret_p, /* start of argument IN:OUT */
+ const CoglBlendStringStatement *statement,
+ int current_arg,
+ CoglBlendStringArgument *arg, /* OUT */
+ CoglBlendStringContext context,
+ GError **error)
+{
+ const char *p = *ret_p;
+ const char *mark;
+ const char *error_string;
+ ParserArgState state = PARSER_ARG_STATE_START;
+ gboolean parsing_factor = FALSE;
+
+ arg->source.is_zero = FALSE;
+ arg->source.info = NULL;
+ arg->source.texture = 0;
+ arg->source.one_minus = FALSE;
+ arg->source.mask = statement->mask;
+
+ arg->factor.is_one = FALSE;
+ arg->factor.is_color = FALSE;
+ arg->factor.is_src_alpha_saturate = FALSE;
+
+ arg->factor.source.is_zero = FALSE;
+ arg->factor.source.info = NULL;
+ arg->factor.source.texture = 0;
+ arg->factor.source.one_minus = FALSE;
+ arg->factor.source.mask = statement->mask;
+
+ do
+ {
+ if (g_ascii_isspace (*p))
+ continue;
+
+ if (*p == '\0')
+ {
+ error_string = "Unexpected end of string while parsing argument";
+ goto error;
+ }
+
+ switch (state)
+ {
+ case PARSER_ARG_STATE_START:
+ if (*p == '1')
+ state = PARSER_ARG_STATE_EXPECT_MINUS;
+ else if (*p == '0')
+ {
+ arg->source.is_zero = TRUE;
+ state = PARSER_ARG_STATE_EXPECT_END;
+ }
+ else
+ {
+ p--; /* backtrack */
+ state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME;
+ }
+ continue;
+
+ case PARSER_ARG_STATE_EXPECT_MINUS:
+ if (*p != '-')
+ {
+ error_string = "expected a '-' following the 1";
+ goto error;
+ }
+ arg->source.one_minus = TRUE;
+ state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME;
+ continue;
+
+ case PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME:
+ if (!is_symbol_char (*p))
+ {
+ error_string = "expected a color source name";
+ goto error;
+ }
+ state = PARSER_ARG_STATE_SCRAPING_COLOR_SRC_NAME;
+ mark = p;
+ if (parsing_factor)
+ arg->factor.is_color = TRUE;
+
+ /* fall through */
+ case PARSER_ARG_STATE_SCRAPING_COLOR_SRC_NAME:
+ if (!is_symbol_char (*p))
+ {
+ CoglBlendStringColorSource *source =
+ parsing_factor ? &arg->factor.source : &arg->source;
+ source->info = get_color_src_info (mark, p, context);
+ if (!source->info)
+ {
+ error_string = "Unknown color source name";
+ goto error;
+ }
+ if (source->info->type ==
+ COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N)
+ {
+ char *endp;
+ source->texture =
+ strtoul (&mark[strlen ("TEXTURE_")], &endp, 10);
+ if (mark == endp)
+ {
+ error_string = "invalid texture number given with "
+ "TEXTURE_N color source";
+ goto error;
+ }
+ p = endp;
+ }
+ state = PARSER_ARG_STATE_MAYBE_COLOR_MASK;
+ }
+ else
+ continue;
+
+ /* fall through */
+ case PARSER_ARG_STATE_MAYBE_COLOR_MASK:
+ if (*p != '[')
+ {
+ p--; /* backtrack */
+ if (!parsing_factor)
+ state = PARSER_ARG_STATE_MAYBE_MULT;
+ else
+ state = PARSER_ARG_STATE_EXPECT_END;
+ continue;
+ }
+ state = PARSER_ARG_STATE_SCRAPING_MASK;
+ mark = p;
+
+ /* fall through */
+ case PARSER_ARG_STATE_SCRAPING_MASK:
+ if (*p == ']')
+ {
+ size_t len = p - mark;
+ CoglBlendStringColorSource *source =
+ parsing_factor ? &arg->factor.source : &arg->source;
+
+ if (len == 5 && strncmp (mark, "[RGBA", len) == 0)
+ {
+ if (statement->mask != COGL_BLEND_STRING_CHANNEL_MASK_RGBA)
+ {
+ error_string = "You can't use an RGBA color mask if the "
+ "statement hasn't also got an RGBA= mask";
+ goto error;
+ }
+ source->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGBA;
+ }
+ else if (len == 4 && strncmp (mark, "[RGB", len) == 0)
+ source->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB;
+ else if (len == 2 && strncmp (mark, "[A", len) == 0)
+ source->mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA;
+ else
+ {
+ error_string = "Expected a channel mask of [RGBA]"
+ "[RGB] or [A]";
+ goto error;
+ }
+ if (parsing_factor)
+ state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN;
+ else
+ state = PARSER_ARG_STATE_MAYBE_MULT;
+ }
+ continue;
+
+ case PARSER_ARG_STATE_EXPECT_OPEN_PAREN:
+ if (*p != '(')
+ {
+ error_string = "Expected '(' before blend factor - the parser "
+ "currently requires that all blend factors "
+ "following a '*' be surrounded in brackets";
+ goto error;
+ }
+ parsing_factor = TRUE;
+ state = PARSER_ARG_STATE_EXPECT_FACTOR;
+ continue;
+
+ case PARSER_ARG_STATE_EXPECT_FACTOR:
+ if (*p == '1')
+ state = PARSER_ARG_STATE_MAYBE_MINUS;
+ else if (*p == '0')
+ {
+ arg->source.is_zero = TRUE;
+ state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN;
+ }
+ else
+ {
+ state = PARSER_ARG_STATE_MAYBE_SRC_ALPHA_SATURATE;
+ mark = p;
+ }
+ continue;
+
+ case PARSER_ARG_STATE_MAYBE_SRC_ALPHA_SATURATE:
+ if (!is_symbol_char (*p))
+ {
+ size_t len = p - mark;
+ if (len >= strlen ("SRC_ALPHA_SATURATE") &&
+ strncmp (mark, "SRC_ALPHA_SATURATE", len) == 0)
+ {
+ arg->factor.is_src_alpha_saturate = TRUE;
+ state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN;
+ }
+ else
+ {
+ state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME;
+ p = mark - 1; /* backtrack */
+ }
+ }
+ continue;
+
+ case PARSER_ARG_STATE_MAYBE_MINUS:
+ if (*p == '-')
+ {
+ arg->factor.source.one_minus = TRUE;
+ state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME;
+ }
+ else
+ {
+ arg->factor.is_one = TRUE;
+ state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN;
+ }
+ continue;
+
+ case PARSER_ARG_STATE_EXPECT_CLOSE_PAREN:
+ if (*p != ')')
+ {
+ error_string = "Expected closing parenthesis after blend factor";
+ goto error;
+ }
+ state = PARSER_ARG_STATE_EXPECT_END;
+ continue;
+
+ case PARSER_ARG_STATE_MAYBE_MULT:
+ if (*p == '*')
+ {
+ state = PARSER_ARG_STATE_EXPECT_OPEN_PAREN;
+ continue;
+ }
+ arg->factor.is_one = TRUE;
+ state = PARSER_ARG_STATE_EXPECT_END;
+
+ /* fall through */
+ case PARSER_ARG_STATE_EXPECT_END:
+ if (*p != ',' && *p != ')')
+ {
+ error_string = "expected , or )";
+ goto error;
+ }
+
+ *ret_p = p - 1;
+ return TRUE;
+ }
+ }
+ while (p++);
+
+error:
+ {
+ int offset = p - string;
+ g_set_error (error,
+ COGL_BLEND_STRING_ERROR,
+ COGL_BLEND_STRING_ERROR_ARGUMENT_PARSE_ERROR,
+ "Syntax error for argument %d at offset %d: %s",
+ current_arg,
+ offset,
+ error_string);
+
+ if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ {
+ g_debug ("Syntax error for argument %d at offset %d: %s",
+ current_arg, offset, error_string);
+ }
+ return FALSE;
+ }
+}
+
+int
+_cogl_blend_string_compile (const char *string,
+ CoglBlendStringContext context,
+ CoglBlendStringStatement *statements,
+ GError **error)
+{
+ const char *p = string;
+ const char *mark;
+ const char *error_string;
+ ParserState state = PARSER_STATE_EXPECT_DEST_CHANNELS;
+ CoglBlendStringStatement *statement = statements;
+ int current_statement = 0;
+ int current_arg = 0;
+ int remaining_argc;
+
+#if 0
+ cogl_debug_flags |= COGL_DEBUG_BLEND_STRINGS;
+#endif
+
+ if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ {
+ COGL_NOTE (BLEND_STRINGS, "Compiling %s string:\n%s\n",
+ context == COGL_BLEND_STRING_CONTEXT_BLENDING ?
+ "blend" : "texture combine",
+ string);
+ }
+
+ do
+ {
+ if (g_ascii_isspace (*p))
+ continue;
+
+ if (*p == '\0')
+ {
+ switch (state)
+ {
+ case PARSER_STATE_EXPECT_DEST_CHANNELS:
+ if (current_statement != 0)
+ goto finished;
+ error_string = "Empty statement";
+ goto error;
+ case PARSER_STATE_SCRAPING_DEST_CHANNELS:
+ error_string = "Expected an '=' following the destination "
+ "channel mask";
+ goto error;
+ case PARSER_STATE_EXPECT_FUNCTION_NAME:
+ error_string = "Expected a function name";
+ goto error;
+ case PARSER_STATE_SCRAPING_FUNCTION_NAME:
+ error_string = "Expected parenthesis after the function name";
+ goto error;
+ case PARSER_STATE_EXPECT_ARG_START:
+ error_string = "Expected to find the start of an argument";
+ goto error;
+ case PARSER_STATE_EXPECT_STATEMENT_END:
+ error_string = "Expected closing parenthesis for statement";
+ goto error;
+ }
+ }
+
+ switch (state)
+ {
+ case PARSER_STATE_EXPECT_DEST_CHANNELS:
+ mark = p;
+ state = PARSER_STATE_SCRAPING_DEST_CHANNELS;
+
+ /* fall through */
+ case PARSER_STATE_SCRAPING_DEST_CHANNELS:
+ if (*p != '=')
+ continue;
+ if (strncmp (mark, "RGBA", 4) == 0)
+ statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGBA;
+ else if (strncmp (mark, "RGB", 3) == 0)
+ statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB;
+ else if (strncmp (mark, "A", 1) == 0)
+ statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA;
+ else
+ {
+ error_string = "Unknown destination channel mask; "
+ "expected RGBA=, RGB= or A=";
+ goto error;
+ }
+ state = PARSER_STATE_EXPECT_FUNCTION_NAME;
+ continue;
+
+ case PARSER_STATE_EXPECT_FUNCTION_NAME:
+ mark = p;
+ state = PARSER_STATE_SCRAPING_FUNCTION_NAME;
+
+ /* fall through */
+ case PARSER_STATE_SCRAPING_FUNCTION_NAME:
+ if (*p != '(')
+ {
+ if (!is_symbol_char (*p))
+ {
+ error_string = "non alpha numeric character in function"
+ "name";
+ goto error;
+ }
+ continue;
+ }
+ statement->function = get_function_info (mark, p, context);
+ if (!statement->function)
+ {
+ error_string = "Unknown function name";
+ goto error;
+ }
+ remaining_argc = statement->function->argc;
+ current_arg = 0;
+ state = PARSER_STATE_EXPECT_ARG_START;
+
+ /* fall through */
+ case PARSER_STATE_EXPECT_ARG_START:
+ if (*p != '(' && *p != ',')
+ continue;
+ if (remaining_argc)
+ {
+ p++; /* parse_argument expects to see the first char of the arg */
+ if (!parse_argument (string, &p, statement,
+ current_arg, &statement->args[current_arg],
+ context, error))
+ return 0;
+ current_arg++;
+ remaining_argc--;
+ }
+ if (!remaining_argc)
+ state = PARSER_STATE_EXPECT_STATEMENT_END;
+ continue;
+
+ case PARSER_STATE_EXPECT_STATEMENT_END:
+ if (*p != ')')
+ {
+ error_string = "Expected end of statement";
+ goto error;
+ }
+ state = PARSER_STATE_EXPECT_DEST_CHANNELS;
+ if (current_statement++ == 1)
+ goto finished;
+ statement = &statements[current_statement];
+ }
+ }
+ while (p++);
+
+finished:
+
+ if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ {
+ if (current_statement > 0)
+ print_statement (0, &statements[0]);
+ if (current_statement > 1)
+ print_statement (1, &statements[1]);
+ }
+
+ if (!validate_statements_for_context (statements,
+ current_statement,
+ context,
+ error))
+ return 0;
+
+ return current_statement;
+
+error:
+ {
+ int offset = p - string;
+ g_set_error (error,
+ COGL_BLEND_STRING_ERROR,
+ COGL_BLEND_STRING_ERROR_PARSE_ERROR,
+ "Syntax error at offset %d: %s",
+ offset,
+ error_string);
+
+ if (cogl_debug_flags & COGL_DEBUG_BLEND_STRINGS)
+ {
+ g_debug ("Syntax error at offset %d: %s",
+ offset, error_string);
+ }
+ return 0;
+ }
+}
+
+/*
+ * INTERNAL TESTING CODE ...
+ */
+
+struct _TestString
+{
+ const char *string;
+ CoglBlendStringContext context;
+};
+
+int
+_cogl_blend_string_test (void)
+{
+ struct _TestString strings[] = {
+ {" A = MODULATE ( TEXTURE[RGB], PREVIOUS[A], PREVIOUS[A] ) ",
+ COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE },
+ {" RGB = MODULATE ( TEXTURE[RGB], PREVIOUS[A] ) ",
+ COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE },
+ {"A=ADD(TEXTURE[A],PREVIOUS[RGB])",
+ COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE },
+ {"A=ADD(TEXTURE[A],PREVIOUS[RGB])",
+ COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE },
+
+ {"RGBA = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))",
+ COGL_BLEND_STRING_CONTEXT_BLENDING },
+ {"RGB = ADD(SRC_COLOR, DST_COLOR*(0))",
+ COGL_BLEND_STRING_CONTEXT_BLENDING },
+ {"RGB = ADD(SRC_COLOR, 0)",
+ COGL_BLEND_STRING_CONTEXT_BLENDING },
+ {"RGB = ADD()",
+ COGL_BLEND_STRING_CONTEXT_BLENDING },
+ {"RGB = ADD(SRC_COLOR, 0, DST_COLOR)",
+ COGL_BLEND_STRING_CONTEXT_BLENDING },
+ {NULL}
+ };
+ int i;
+
+ GError *error = NULL;
+ for (i = 0; strings[i].string; i++)
+ {
+ CoglBlendStringStatement statements[2];
+ int count = _cogl_blend_string_compile (strings[i].string,
+ strings[i].context,
+ statements,
+ &error);
+ if (!count)
+ {
+ g_print ("Failed to parse string:\n%s\n%s\n",
+ strings[i].string,
+ error->message);
+ g_error_free (error);
+ error = NULL;
+ continue;
+ }
+ g_print ("Original:\n");
+ g_print ("%s\n", strings[i].string);
+ if (count > 0)
+ print_statement (0, &statements[0]);
+ if (count > 1)
+ print_statement (1, &statements[1]);
+ }
+
+ return 0;
+}
+
diff --git a/common/cogl-blend-string.h b/common/cogl-blend-string.h
new file mode 100644
index 000000000..a3e3888f8
--- /dev/null
+++ b/common/cogl-blend-string.h
@@ -0,0 +1,151 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2009 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Robert Bragg
+ */
+
+#ifndef COGL_BLEND_STRING_H
+#define COGL_BLEND_STRING_H
+
+#include
+#include
+
+typedef enum _CoglBlendStringContext
+{
+ COGL_BLEND_STRING_CONTEXT_BLENDING,
+ COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE
+} CoglBlendStringContext;
+
+#define COGL_BLEND_STRING_ERROR _cogl_blend_string_error_quark ()
+
+typedef enum _CoglBlendStringError
+{
+ COGL_BLEND_STRING_ERROR_PARSE_ERROR,
+ COGL_BLEND_STRING_ERROR_ARGUMENT_PARSE_ERROR,
+ COGL_BLEND_STRING_ERROR_INVALID_ERROR,
+ COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR
+} CoglBlendStringError;
+
+/* NB: debug stringify code will get upset if these
+ * are re-ordered */
+typedef enum _CoglBlendStringChannelMask
+{
+ COGL_BLEND_STRING_CHANNEL_MASK_RGB,
+ COGL_BLEND_STRING_CHANNEL_MASK_ALPHA,
+ COGL_BLEND_STRING_CHANNEL_MASK_RGBA
+} CoglBlendStringChannelMask;
+
+typedef enum _CoglBlendStringColorSourceType
+{
+ /* blending */
+ COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR,
+ COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR,
+
+ /* shared */
+ COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT,
+
+ /* texture combining */
+ COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE,
+ COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N,
+ COGL_BLEND_STRING_COLOR_SOURCE_PRIMARY,
+ COGL_BLEND_STRING_COLOR_SOURCE_PREVIOUS
+} CoglBlendStringColorSourceType;
+
+typedef struct _CoglBlendStringColorSourceInfo
+{
+ CoglBlendStringColorSourceType type;
+ const char *name;
+ size_t name_len;
+} CoglBlendStringColorSourceInfo;
+
+typedef struct _CoglBlendStringColorSource
+{
+ gboolean is_zero;
+ const CoglBlendStringColorSourceInfo *info;
+ int texture; /* for the TEXTURE_N color source */
+ gboolean one_minus;
+ CoglBlendStringChannelMask mask;
+} CoglBlendStringColorSource;
+
+typedef struct _CoglBlendStringFactor
+{
+ gboolean is_one;
+ gboolean is_src_alpha_saturate;
+ gboolean is_color;
+ CoglBlendStringColorSource source;
+} CoglBlendStringFactor;
+
+typedef struct _CoglBlendStringArgument
+{
+ CoglBlendStringColorSource source;
+ CoglBlendStringFactor factor;
+} CoglBlendStringArgument;
+
+typedef enum _CoglBlendStringFunctionType
+{
+ /* shared */
+ COGL_BLEND_STRING_FUNCTION_AUTO_COMPOSITE,
+ COGL_BLEND_STRING_FUNCTION_ADD,
+
+ /* texture combine only */
+ COGL_BLEND_STRING_FUNCTION_REPLACE,
+ COGL_BLEND_STRING_FUNCTION_MODULATE,
+ COGL_BLEND_STRING_FUNCTION_ADD_SIGNED,
+ COGL_BLEND_STRING_FUNCTION_INTERPOLATE,
+ COGL_BLEND_STRING_FUNCTION_SUBTRACT,
+ COGL_BLEND_STRING_FUNCTION_DOT3_RGB,
+ COGL_BLEND_STRING_FUNCTION_DOT3_RGBA
+} CoglBlendStringFunctionType;
+
+typedef struct _CoglBlendStringFunctionInfo
+{
+ enum _CoglBlendStringFunctionType type;
+ const char *name;
+ size_t name_len;
+ int argc;
+} CoglBlendStringFunctionInfo;
+
+typedef struct _CoglBlendStringStatement
+{
+ CoglBlendStringChannelMask mask;
+ const CoglBlendStringFunctionInfo *function;
+ CoglBlendStringArgument args[3];
+} CoglBlendStringStatement;
+
+
+gboolean
+_cogl_blend_string_compile (const char *string,
+ CoglBlendStringContext context,
+ CoglBlendStringStatement *statements,
+ GError **error);
+
+void
+_cogl_blend_string_split_rgba_statement (CoglBlendStringStatement *statement,
+ CoglBlendStringStatement *rgb,
+ CoglBlendStringStatement *a);
+
+GQuark
+_cogl_blend_string_error_quark (void);
+
+#endif /* COGL_BLEND_STRING_H */
+
diff --git a/common/cogl-current-matrix.c b/common/cogl-current-matrix.c
index 0080af0d1..6d069bc66 100644
--- a/common/cogl-current-matrix.c
+++ b/common/cogl-current-matrix.c
@@ -45,6 +45,9 @@
#define glFrustum(L,R,B,T,N,F) \
glFrustumf((GLfloat)L, (GLfloat)R, (GLfloat)B, \
(GLfloat)T, (GLfloat)N, (GLfloat)F)
+
+#define glOrtho glOrthof
+
#endif
#include
@@ -209,30 +212,57 @@ _cogl_current_matrix_frustum (float left,
}
void
-_cogl_current_matrix_ortho (float left,
- float right,
- float bottom,
- float top,
- float near_val,
- float far_val)
+_cogl_current_matrix_perspective (float fov_y,
+ float aspect,
+ float z_near,
+ float z_far)
+{
+ _COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
+
+ if (current_stack != NULL)
+ _cogl_matrix_stack_perspective (current_stack,
+ fov_y, aspect, z_near, z_far);
+ else
+ {
+ /* NB: There is no glPerspective() (only gluPerspective()) so we use
+ * cogl_matrix_perspective: */
+ CoglMatrix matrix;
+ _cogl_get_matrix (ctx->matrix_mode, &matrix);
+ cogl_matrix_perspective (&matrix,
+ fov_y, aspect, z_near, z_far);
+ _cogl_current_matrix_load (&matrix);
+ }
+}
+
+void
+_cogl_current_matrix_ortho (float left,
+ float right,
+ float bottom,
+ float top,
+ float near_val,
+ float far_val)
{
-#if 0
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
if (current_stack != NULL)
_cogl_matrix_stack_ortho (current_stack,
left, right,
- top, bottom,
+ bottom, top,
near_val,
far_val);
else
- GE (glOrtho (left, right, bottom, top, near_val, far_val));
+ {
+#ifdef HAVE_COGL_GLES2
+ /* NB: GLES 2 has no glOrtho(): */
+ CoglMatrix matrix;
+ _cogl_get_matrix (ctx->matrix_mode, &matrix);
+ cogl_matrix_ortho (&matrix,
+ left, right, bottom, top, near_val, far_val);
+ _cogl_current_matrix_load (&matrix);
#else
- /* Nobody is using glOrtho right now anyway, so not bothering */
- g_warning ("%s not implemented, need to code cogl_matrix_ortho() if you need"
- " this function",
- G_STRFUNC);
+ GE (glOrtho (left, right, bottom, top, near_val, far_val));
#endif
+ }
}
void
@@ -276,6 +306,12 @@ _cogl_get_matrix (CoglMatrixMode mode,
}
}
+void
+_cogl_set_matrix (const CoglMatrix *matrix)
+{
+ _cogl_current_matrix_load (matrix);
+}
+
void
_cogl_current_matrix_state_init (void)
{
@@ -354,85 +390,19 @@ cogl_rotate (float angle, float x, float y, float z)
}
void
-_cogl_set_matrix (const CoglMatrix *matrix)
-{
- _cogl_current_matrix_load (matrix);
-}
-
-void
-cogl_get_modelview_matrix (CoglMatrix *matrix)
-{
- _cogl_get_matrix (COGL_MATRIX_MODELVIEW,
- matrix);
-}
-
-void
-cogl_get_projection_matrix (CoglMatrix *matrix)
-{
- _cogl_get_matrix (COGL_MATRIX_PROJECTION,
- matrix);
-}
-
-void
-cogl_perspective (float fovy,
+cogl_perspective (float fov_y,
float aspect,
- float zNear,
- float zFar)
+ float z_near,
+ float z_far)
{
- float xmax, ymax;
- float x, y, c, d;
- float fovy_rad_half = (fovy * G_PI) / 360;
- CoglMatrix perspective;
- GLfloat m[16];
+ float ymax = z_near * tanf (fov_y * G_PI / 360.0);
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- memset (&m[0], 0, sizeof (m));
-
- _cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
- _cogl_current_matrix_identity ();
-
- /*
- * Based on the original algorithm in perspective():
- *
- * 1) xmin = -xmax => xmax + xmin == 0 && xmax - xmin == 2 * xmax
- * same true for y, hence: a == 0 && b == 0;
- *
- * 2) When working with small numbers, we are loosing significant
- * precision
- */
- ymax = (zNear * (sinf (fovy_rad_half) / cosf (fovy_rad_half)));
- xmax = (ymax * aspect);
-
- x = (zNear / xmax);
- y = (zNear / ymax);
- c = (-(zFar + zNear) / ( zFar - zNear));
- d = (-(2 * zFar) * zNear) / (zFar - zNear);
-
-#define M(row,col) m[col*4+row]
- M(0,0) = x;
- M(1,1) = y;
- M(2,2) = c;
- M(2,3) = d;
- M(3,2) = -1.0;
-
- cogl_matrix_init_from_array (&perspective, m);
- _cogl_current_matrix_multiply (&perspective);
-
- _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
-
- /* Calculate and store the inverse of the matrix */
- memset (ctx->inverse_projection, 0, sizeof (float) * 16);
-
-#define m ctx->inverse_projection
- M(0, 0) = (1.0 / x);
- M(1, 1) = (1.0 / y);
- M(2, 3) = -1.0;
- M(3, 2) = (1.0 / d);
- M(3, 3) = (c / d);
-#undef m
-
-#undef M
+ cogl_frustum (-ymax * aspect, /* left */
+ ymax * aspect, /* right */
+ -ymax, /* bottom */
+ ymax, /* top */
+ z_near,
+ z_far);
}
void
@@ -474,4 +444,65 @@ cogl_frustum (float left,
M(3,2) = 1.0 / d;
M(3,3) = c / d;
#undef M
+
+ _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
}
+
+void
+cogl_ortho (float left,
+ float right,
+ float bottom,
+ float top,
+ float z_near,
+ float z_far)
+{
+ CoglMatrix ortho;
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ cogl_matrix_init_identity (&ortho);
+ cogl_matrix_ortho (&ortho, left, right, bottom, top, z_near, z_far);
+ _cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
+ _cogl_current_matrix_load (&ortho);
+
+ /* Calculate and store the inverse of the matrix */
+ memset (ctx->inverse_projection, 0, sizeof (float) * 16);
+
+#define M(row,col) ctx->inverse_projection[col*4+row]
+ M(0,0) = 1.0 / ortho.xx;
+ M(0,3) = -ortho.xw;
+ M(1,1) = 1.0 / ortho.yy;
+ M(1,3) = -ortho.yw;
+ M(2,2) = 1.0 / ortho.zz;
+ M(2,3) = -ortho.zw;
+ M(3,3) = 1.0;
+#undef M
+}
+
+void
+cogl_get_modelview_matrix (CoglMatrix *matrix)
+{
+ _cogl_get_matrix (COGL_MATRIX_MODELVIEW,
+ matrix);
+}
+
+void
+cogl_set_modelview_matrix (CoglMatrix *matrix)
+{
+ _cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
+ _cogl_current_matrix_load (matrix);
+}
+
+void
+cogl_get_projection_matrix (CoglMatrix *matrix)
+{
+ _cogl_get_matrix (COGL_MATRIX_PROJECTION,
+ matrix);
+}
+
+void
+cogl_set_projection_matrix (CoglMatrix *matrix)
+{
+ _cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
+ _cogl_current_matrix_load (matrix);
+}
+
diff --git a/common/cogl-debug.c b/common/cogl-debug.c
index 85721fc22..b6dfd7559 100644
--- a/common/cogl-debug.c
+++ b/common/cogl-debug.c
@@ -39,7 +39,8 @@ static const GDebugKey cogl_debug_keys[] = {
{ "draw", COGL_DEBUG_DRAW },
{ "pango", COGL_DEBUG_PANGO },
{ "rectangles", COGL_DEBUG_RECTANGLES },
- { "handle", COGL_DEBUG_HANDLE }
+ { "handle", COGL_DEBUG_HANDLE },
+ { "blend-strings", COGL_DEBUG_BLEND_STRINGS }
};
static const gint n_cogl_debug_keys = G_N_ELEMENTS (cogl_debug_keys);
diff --git a/common/cogl-enum-types.c.in b/common/cogl-enum-types.c.in
new file mode 100644
index 000000000..157180dfe
--- /dev/null
+++ b/common/cogl-enum-types.c.in
@@ -0,0 +1,41 @@
+/*** BEGIN file-header ***/
+#include "cogl-enum-types.h"
+#include "cogl.h"
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* enumerations from "@filename@" */
+#include "@filename@"
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+@enum_name@_get_type (void)
+{
+ static volatile gsize g_enum_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_enum_type_id__volatile))
+ {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+ GType g_enum_type_id;
+
+ g_enum_type_id =
+ g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
+
+ g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
+ }
+
+ return g_enum_type_id__volatile;
+}
+/*** END value-tail ***/
diff --git a/common/cogl-enum-types.h.in b/common/cogl-enum-types.h.in
new file mode 100644
index 000000000..23d705dee
--- /dev/null
+++ b/common/cogl-enum-types.h.in
@@ -0,0 +1,25 @@
+/*** BEGIN file-header ***/
+#ifndef __COGL_ENUM_TYPES_H__
+#define __COGL_ENUM_TYPES_H__
+
+#include
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* !__CLUTTER_ENUM_TYPES_H__ */
+/*** END file-tail ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+#define COGL_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
+
+/*** END value-header ***/
diff --git a/common/cogl-handle.h b/common/cogl-handle.h
index 7851932db..6caee0e71 100644
--- a/common/cogl-handle.h
+++ b/common/cogl-handle.h
@@ -82,7 +82,7 @@ typedef struct _CoglHandleObject
static CoglHandleClass _cogl_##type_name##_class; \
\
static GQuark \
-_cogl_##type_name##_get_type (void) \
+_cogl_handle_##type_name##_get_type (void) \
{ \
static GQuark type = 0; \
if (!type) \
@@ -99,13 +99,13 @@ _cogl_##type_name##_handle_new (Cogl##TypeName *new_obj) \
obj->klass = &_cogl_##type_name##_class; \
if (!obj->klass->type) \
{ \
- obj->klass->type = _cogl_##type_name##_get_type (); \
- obj->klass->virt_free = _cogl_##type_name##_free; \
- } \
+ obj->klass->type = _cogl_handle_##type_name##_get_type ();\
+ obj->klass->virt_free = _cogl_##type_name##_free; \
+ } \
\
- _COGL_HANDLE_DEBUG_NEW (TypeName, obj); \
- return (CoglHandle) new_obj; \
- } \
+ _COGL_HANDLE_DEBUG_NEW (TypeName, obj); \
+ return (CoglHandle) new_obj; \
+} \
\
Cogl##TypeName * \
_cogl_##type_name##_pointer_from_handle (CoglHandle handle) \
@@ -121,7 +121,8 @@ cogl_is_##type_name (CoglHandle handle) \
if (handle == COGL_INVALID_HANDLE) \
return FALSE; \
\
- return (obj->klass->type == _cogl_##type_name##_get_type ()); \
+ return (obj->klass->type == \
+ _cogl_handle_##type_name##_get_type ()); \
} \
\
CoglHandle G_GNUC_DEPRECATED \
diff --git a/common/cogl-material-private.h b/common/cogl-material-private.h
index 05d4242dd..e61ab97bd 100644
--- a/common/cogl-material-private.h
+++ b/common/cogl-material-private.h
@@ -68,15 +68,20 @@ struct _CoglMaterialLayer
CoglHandle texture; /*!< The texture for this layer, or COGL_INVALID_HANDLE
for an empty layer */
+ CoglMaterialFilter mag_filter;
+ CoglMaterialFilter min_filter;
+
/* 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];
+ GLint texture_combine_rgb_func;
+ GLint texture_combine_rgb_src[3];
+ GLint texture_combine_rgb_op[3];
- CoglMaterialLayerCombineFunc texture_combine_alpha_func;
- CoglMaterialLayerCombineSrc texture_combine_alpha_src[3];
- CoglMaterialLayerCombineOp texture_combine_alpha_op[3];
+ GLint texture_combine_alpha_func;
+ GLint texture_combine_alpha_src[3];
+ GLint texture_combine_alpha_op[3];
+
+ GLfloat texture_combine_constant[4];
/* TODO: Support purely GLSL based material layers */
@@ -114,11 +119,104 @@ struct _CoglMaterial
GLfloat alpha_func_reference;
/* Determines how this material is blended with other primitives */
- CoglMaterialBlendFactor blend_src_factor;
- CoglMaterialBlendFactor blend_dst_factor;
+#ifndef HAVE_COGL_GLES
+ GLenum blend_equation_rgb;
+ GLenum blend_equation_alpha;
+ GLint blend_src_factor_alpha;
+ GLint blend_dst_factor_alpha;
+ GLfloat blend_constant[4];
+#endif
+ GLint blend_src_factor_rgb;
+ GLint blend_dst_factor_rgb;
GList *layers;
};
+/*
+ * SECTION:cogl-material-internals
+ * @short_description: Functions for creating custom primitives that make use
+ * of Cogl materials for filling.
+ *
+ * Normally you shouldn't need to use this API directly, but if you need to
+ * developing a custom/specialised primitive - probably using raw OpenGL - then
+ * this API aims to expose enough of the material internals to support being
+ * able to fill your geometry according to a given Cogl material.
+ */
+
+
+/*
+ * 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.
+ */
+/* TODO: find a nicer solution! */
+gulong _cogl_material_get_cogl_enable_flags (CoglHandle handle);
+
+/*
+ * CoglMaterialLayerFlags:
+ * @COGL_MATERIAL_LAYER_FLAG_USER_MATRIX: Means the user has supplied a
+ * custom texture matrix.
+ */
+typedef enum _CoglMaterialLayerFlags
+{
+ COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX = 1L<<0
+} CoglMaterialLayerFlags;
+/* XXX: NB: if you add flags here you will need to update
+ * CoglMaterialLayerPrivFlags!!! */
+
+/*
+ * cogl_material_layer_get_flags:
+ * @layer_handle: A CoglMaterialLayer layer handle
+ *
+ * This lets you get a number of flag attributes about the 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.
+ */
+gulong _cogl_material_layer_get_flags (CoglHandle layer_handle);
+
+/*
+ * CoglMaterialFlushOption:
+ * @COGL_MATERIAL_FLUSH_FALLBACK_MASK: Follow this by a guin32 mask
+ * of the layers that can't be supported with the user supplied texture
+ * and need to be replaced with fallback textures. (1 = fallback, and the
+ * least significant bit = layer 0)
+ * @COGL_MATERIAL_FLUSH_DISABLE_MASK: Follow this by a guint32 mask
+ * of the layers that you want to completly disable texturing for
+ * (1 = fallback, and the least significant bit = layer 0)
+ * @COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE: Follow this by a GLuint OpenGL texture
+ * name to override the texture used for layer 0 of the material. This is
+ * intended for dealing with sliced textures where you will need to point
+ * to each of the texture slices in turn when drawing your geometry.
+ * Passing a value of 0 is the same as not passing the option at all.
+ */
+typedef enum _CoglMaterialFlushOption
+{
+ COGL_MATERIAL_FLUSH_FALLBACK_MASK = 1,
+ COGL_MATERIAL_FLUSH_DISABLE_MASK,
+ COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
+} CoglMaterialFlushOption;
+
+/*
+ * cogl_material_flush_gl_state:
+ * @material: A CoglMaterial object
+ * @...: A NULL terminated list of (CoglMaterialFlushOption, data) pairs
+ *
+ * This function commits the state of the specified CoglMaterial - including
+ * the texture state for all the layers - to the OpenGL[ES] driver.
+ *
+ * Since 1.0
+ */
+void _cogl_material_flush_gl_state (CoglHandle material,
+ ...) G_GNUC_NULL_TERMINATED;
+
+
#endif /* __COGL_MATERIAL_PRIVATE_H */
diff --git a/common/cogl-material.c b/common/cogl-material.c
index c456cac6a..66a4b0c96 100644
--- a/common/cogl-material.c
+++ b/common/cogl-material.c
@@ -35,6 +35,7 @@
#include "cogl-material-private.h"
#include "cogl-texture-private.h"
+#include "cogl-blend-string.h"
#include
#include
@@ -50,6 +51,10 @@
#ifdef HAVE_COGL_GL
#define glActiveTexture ctx->pf_glActiveTexture
#define glClientActiveTexture ctx->pf_glClientActiveTexture
+#define glBlendFuncSeparate ctx->pf_glBlendFuncSeparate
+#define glBlendEquation ctx->pf_glBlendEquation
+#define glBlendColor ctx->pf_glBlendColor
+#define glBlendEquationSeparate ctx->pf_glBlendEquationSeparate
#endif
static void _cogl_material_free (CoglMaterial *tex);
@@ -60,6 +65,12 @@ COGL_HANDLE_DEFINE (MaterialLayer, material_layer);
/* #define DISABLE_MATERIAL_CACHE 1 */
+GQuark
+_cogl_material_error_quark (void)
+{
+ return g_quark_from_static_string ("cogl-material-error-quark");
+}
+
CoglHandle
cogl_material_new (void)
{
@@ -88,8 +99,18 @@ cogl_material_new (void)
material->flags |= COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC;
/* 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;
+#ifndef HAVE_COGL_GLES
+ material->blend_equation_rgb = GL_FUNC_ADD;
+ material->blend_equation_alpha = GL_FUNC_ADD;
+ material->blend_src_factor_alpha = GL_SRC_ALPHA;
+ material->blend_dst_factor_alpha = GL_ONE_MINUS_SRC_ALPHA;
+ material->blend_constant[0] = 0;
+ material->blend_constant[1] = 0;
+ material->blend_constant[2] = 0;
+ material->blend_constant[3] = 0;
+#endif
+ material->blend_src_factor_rgb = GL_SRC_ALPHA;
+ material->blend_dst_factor_rgb = GL_ONE_MINUS_SRC_ALPHA;
material->flags |= COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC;
material->layers = NULL;
@@ -408,20 +429,177 @@ cogl_material_set_alpha_test_function (CoglHandle handle,
material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC;
}
+GLenum
+arg_to_gl_blend_factor (CoglBlendStringArgument *arg)
+{
+ if (arg->source.is_zero)
+ return GL_ZERO;
+ if (arg->factor.is_one)
+ return GL_ONE;
+ else if (arg->factor.is_src_alpha_saturate)
+ return GL_SRC_ALPHA_SATURATE;
+ else if (arg->factor.source.info->type ==
+ COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR)
+ {
+ if (arg->factor.source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB)
+ {
+ if (arg->factor.source.one_minus)
+ return GL_ONE_MINUS_SRC_COLOR;
+ else
+ return GL_SRC_COLOR;
+ }
+ else
+ {
+ if (arg->factor.source.one_minus)
+ return GL_ONE_MINUS_SRC_ALPHA;
+ else
+ return GL_SRC_ALPHA;
+ }
+ }
+ else if (arg->factor.source.info->type ==
+ COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR)
+ {
+ if (arg->factor.source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB)
+ {
+ if (arg->factor.source.one_minus)
+ return GL_ONE_MINUS_DST_COLOR;
+ else
+ return GL_DST_COLOR;
+ }
+ else
+ {
+ if (arg->factor.source.one_minus)
+ return GL_ONE_MINUS_DST_ALPHA;
+ else
+ return GL_DST_ALPHA;
+ }
+ }
+#ifndef HAVE_COGL_GLES
+ else if (arg->factor.source.info->type ==
+ COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
+ {
+ if (arg->factor.source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB)
+ {
+ if (arg->factor.source.one_minus)
+ return GL_ONE_MINUS_CONSTANT_COLOR;
+ else
+ return GL_CONSTANT_COLOR;
+ }
+ else
+ {
+ if (arg->factor.source.one_minus)
+ return GL_ONE_MINUS_CONSTANT_ALPHA;
+ else
+ return GL_CONSTANT_ALPHA;
+ }
+ }
+#endif
+
+ g_warning ("Unable to determine valid blend factor from blend string\n");
+ return GL_ONE;
+}
+
void
-cogl_material_set_blend_factors (CoglHandle handle,
- CoglMaterialBlendFactor src_factor,
- CoglMaterialBlendFactor dst_factor)
+setup_blend_state (CoglBlendStringStatement *statement,
+ GLenum *blend_equation,
+ GLint *blend_src_factor,
+ GLint *blend_dst_factor)
+{
+#ifndef HAVE_COGL_GLES
+ switch (statement->function->type)
+ {
+ case COGL_BLEND_STRING_FUNCTION_ADD:
+ *blend_equation = GL_FUNC_ADD;
+ break;
+ /* TODO - add more */
+ default:
+ g_warning ("Unsupported blend function given");
+ *blend_equation = GL_FUNC_ADD;
+ }
+#endif
+
+ *blend_src_factor = arg_to_gl_blend_factor (&statement->args[0]);
+ *blend_dst_factor = arg_to_gl_blend_factor (&statement->args[1]);
+}
+
+gboolean
+cogl_material_set_blend (CoglHandle handle,
+ const char *blend_description,
+ GError **error)
{
CoglMaterial *material;
+ CoglBlendStringStatement statements[2];
+ CoglBlendStringStatement split[2];
+ CoglBlendStringStatement *rgb;
+ CoglBlendStringStatement *a;
+ int count;
+
+ g_return_val_if_fail (cogl_is_material (handle), FALSE);
+
+ material = _cogl_material_pointer_from_handle (handle);
+
+ count =
+ _cogl_blend_string_compile (blend_description,
+ COGL_BLEND_STRING_CONTEXT_BLENDING,
+ statements,
+ error);
+ if (!count)
+ return FALSE;
+
+ if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA)
+ {
+ _cogl_blend_string_split_rgba_statement (statements,
+ &split[0], &split[1]);
+ rgb = &split[0];
+ a = &split[1];
+ }
+ else
+ {
+ rgb = &statements[0];
+ a = &statements[1];
+ }
+
+#ifndef HAVE_COGL_GLES
+ setup_blend_state (rgb,
+ &material->blend_equation_rgb,
+ &material->blend_src_factor_rgb,
+ &material->blend_dst_factor_rgb);
+ setup_blend_state (a,
+ &material->blend_equation_alpha,
+ &material->blend_src_factor_alpha,
+ &material->blend_dst_factor_alpha);
+#else
+ setup_blend_state (rgb,
+ NULL,
+ &material->blend_src_factor_rgb,
+ &material->blend_dst_factor_rgb);
+#endif
+
+ material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC;
+
+ return TRUE;
+}
+
+void
+cogl_material_set_blend_constant (CoglHandle handle,
+ CoglColor *constant_color)
+{
+#ifndef HAVE_COGL_GLES
+ CoglMaterial *material;
+ GLfloat *constant;
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;
+
+ constant = material->blend_constant;
+ constant[0] = cogl_color_get_red_float (constant_color);
+ constant[1] = cogl_color_get_green_float (constant_color);
+ constant[2] = cogl_color_get_blue_float (constant_color);
+ constant[3] = cogl_color_get_alpha_float (constant_color);
material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC;
+#endif
}
/* Asserts that a layer corresponding to the given index exists. If no
@@ -459,25 +637,22 @@ _cogl_material_get_layer (CoglMaterial *material,
layer_handle = _cogl_material_layer_handle_new (layer);
layer->index = index_;
layer->flags = COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE;
+ layer->mag_filter = COGL_MATERIAL_FILTER_LINEAR;
+ layer->min_filter = COGL_MATERIAL_FILTER_LINEAR;
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->texture_combine_rgb_func = GL_MODULATE;
+ layer->texture_combine_rgb_src[0] = GL_PREVIOUS;
+ layer->texture_combine_rgb_src[1] = GL_TEXTURE;
+ layer->texture_combine_rgb_op[0] = GL_SRC_COLOR;
+ layer->texture_combine_rgb_op[1] = GL_SRC_COLOR;
+ layer->texture_combine_alpha_func = GL_MODULATE;
+ layer->texture_combine_alpha_src[0] = GL_PREVIOUS;
+ layer->texture_combine_alpha_src[1] = GL_TEXTURE;
+ layer->texture_combine_alpha_op[0] = GL_SRC_ALPHA;
+ layer->texture_combine_alpha_op[1] = GL_SRC_ALPHA;
cogl_matrix_init_identity (&layer->matrix);
@@ -498,7 +673,8 @@ cogl_material_set_layer (CoglHandle material_handle,
int n_layers;
g_return_if_fail (cogl_is_material (material_handle));
- g_return_if_fail (cogl_is_texture (texture_handle));
+ g_return_if_fail (texture_handle == COGL_INVALID_HANDLE
+ || cogl_is_texture (texture_handle));
material = _cogl_material_pointer_from_handle (material_handle);
layer = _cogl_material_get_layer (material_handle, layer_index, TRUE);
@@ -519,7 +695,8 @@ cogl_material_set_layer (CoglHandle material_handle,
* MAX_COMBINED_TEXTURE_IMAGE_UNITS layers. */
}
- cogl_handle_ref (texture_handle);
+ if (texture_handle)
+ cogl_handle_ref (texture_handle);
if (layer->texture)
cogl_handle_unref (layer->texture);
@@ -530,104 +707,164 @@ cogl_material_set_layer (CoglHandle material_handle,
layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
}
-void
-cogl_material_set_layer_combine_function (
- CoglHandle handle,
- gint layer_index,
- CoglMaterialLayerCombineChannels channels,
- CoglMaterialLayerCombineFunc func)
+static void
+setup_texture_combine_state (CoglBlendStringStatement *statement,
+ GLint *texture_combine_func,
+ GLint *texture_combine_src,
+ GLint *texture_combine_op)
+{
+ int i;
+
+ switch (statement->function->type)
+ {
+ case COGL_BLEND_STRING_FUNCTION_AUTO_COMPOSITE:
+ *texture_combine_func = GL_MODULATE; /* FIXME */
+ break;
+ case COGL_BLEND_STRING_FUNCTION_REPLACE:
+ *texture_combine_func = GL_REPLACE;
+ break;
+ case COGL_BLEND_STRING_FUNCTION_MODULATE:
+ *texture_combine_func = GL_MODULATE;
+ break;
+ case COGL_BLEND_STRING_FUNCTION_ADD:
+ *texture_combine_func = GL_ADD;
+ break;
+ case COGL_BLEND_STRING_FUNCTION_ADD_SIGNED:
+ *texture_combine_func = GL_ADD_SIGNED;
+ break;
+ case COGL_BLEND_STRING_FUNCTION_INTERPOLATE:
+ *texture_combine_func = GL_INTERPOLATE;
+ break;
+ case COGL_BLEND_STRING_FUNCTION_SUBTRACT:
+ *texture_combine_func = GL_SUBTRACT;
+ break;
+ case COGL_BLEND_STRING_FUNCTION_DOT3_RGB:
+ *texture_combine_func = GL_DOT3_RGB;
+ break;
+ case COGL_BLEND_STRING_FUNCTION_DOT3_RGBA:
+ *texture_combine_func = GL_DOT3_RGBA;
+ break;
+ }
+
+ for (i = 0; i < statement->function->argc; i++)
+ {
+ CoglBlendStringArgument *arg = &statement->args[i];
+
+ switch (arg->source.info->type)
+ {
+ case COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT:
+ texture_combine_src[i] = GL_CONSTANT;
+ break;
+ case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE:
+ texture_combine_src[i] = GL_TEXTURE;
+ break;
+ case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N:
+ texture_combine_src[i] =
+ GL_TEXTURE0 + arg->source.texture;
+ break;
+ case COGL_BLEND_STRING_COLOR_SOURCE_PRIMARY:
+ texture_combine_src[i] = GL_PRIMARY_COLOR;
+ break;
+ case COGL_BLEND_STRING_COLOR_SOURCE_PREVIOUS:
+ texture_combine_src[i] = GL_PREVIOUS;
+ break;
+ default:
+ g_warning ("Unexpected texture combine source");
+ texture_combine_src[i] = GL_TEXTURE;
+ }
+
+ if (arg->source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB)
+ {
+ if (statement->args[i].source.one_minus)
+ texture_combine_op[i] = GL_ONE_MINUS_SRC_COLOR;
+ else
+ texture_combine_op[i] = GL_SRC_COLOR;
+ }
+ else
+ {
+ if (statement->args[i].source.one_minus)
+ texture_combine_op[i] = GL_ONE_MINUS_SRC_ALPHA;
+ else
+ texture_combine_op[i] = GL_SRC_ALPHA;
+ }
+ }
+}
+
+gboolean
+cogl_material_set_layer_combine (CoglHandle handle,
+ gint layer_index,
+ const char *combine_description,
+ GError **error)
{
CoglMaterial *material;
CoglMaterialLayer *layer;
- gboolean set_alpha_func = FALSE;
- gboolean set_rgb_func = FALSE;
+ CoglBlendStringStatement statements[2];
+ CoglBlendStringStatement split[2];
+ CoglBlendStringStatement *rgb;
+ CoglBlendStringStatement *a;
+ int count;
+
+ g_return_val_if_fail (cogl_is_material (handle), FALSE);
+
+ material = _cogl_material_pointer_from_handle (handle);
+ layer = _cogl_material_get_layer (material, layer_index, TRUE);
+
+ count =
+ _cogl_blend_string_compile (combine_description,
+ COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE,
+ statements,
+ error);
+ if (!count)
+ return FALSE;
+
+ if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA)
+ {
+ _cogl_blend_string_split_rgba_statement (statements,
+ &split[0], &split[1]);
+ rgb = &split[0];
+ a = &split[1];
+ }
+ else
+ {
+ rgb = &statements[0];
+ a = &statements[1];
+ }
+
+ setup_texture_combine_state (rgb,
+ &layer->texture_combine_rgb_func,
+ layer->texture_combine_rgb_src,
+ layer->texture_combine_rgb_op);
+
+ setup_texture_combine_state (a,
+ &layer->texture_combine_alpha_func,
+ layer->texture_combine_alpha_src,
+ layer->texture_combine_alpha_op);
+
+
+ layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
+ layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE;
+ return TRUE;
+}
+
+void
+cogl_material_set_layer_combine_constant (CoglHandle handle,
+ gint layer_index,
+ CoglColor *constant_color)
+{
+ CoglMaterial *material;
+ CoglMaterialLayer *layer;
+ GLfloat *constant;
g_return_if_fail (cogl_is_material (handle));
material = _cogl_material_pointer_from_handle (handle);
layer = _cogl_material_get_layer (material, layer_index, TRUE);
- 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;
-
- layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
- layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE;
-}
-
-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, TRUE);
-
- 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;
-
- layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
- layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE;
-}
-
-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, TRUE);
-
- 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;
+ constant = layer->texture_combine_constant;
+ constant[0] = cogl_color_get_red_float (constant_color);
+ constant[1] = cogl_color_get_green_float (constant_color);
+ constant[2] = cogl_color_get_blue_float (constant_color);
+ constant[3] = cogl_color_get_alpha_float (constant_color);
layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE;
@@ -690,7 +927,7 @@ cogl_material_remove_layer (CoglHandle material_handle,
/* 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)
+_cogl_material_get_cogl_enable_flags (CoglHandle material_handle)
{
CoglMaterial *material;
gulong enable_flags = 0;
@@ -713,7 +950,7 @@ cogl_material_get_cogl_enable_flags (CoglHandle material_handle)
* 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
+ * Alternatively; 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.
*/
@@ -748,7 +985,7 @@ cogl_material_layer_get_texture (CoglHandle layer_handle)
}
gulong
-cogl_material_layer_get_flags (CoglHandle layer_handle)
+_cogl_material_layer_get_flags (CoglHandle layer_handle)
{
CoglMaterialLayer *layer;
@@ -760,25 +997,34 @@ cogl_material_layer_get_flags (CoglHandle layer_handle)
}
static guint
-get_n_args_for_combine_func (CoglMaterialLayerCombineFunc func)
+get_n_args_for_combine_func (GLint func)
{
switch (func)
{
- case COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE:
+ case GL_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:
+ case GL_MODULATE:
+ case GL_ADD:
+ case GL_ADD_SIGNED:
+ case GL_SUBTRACT:
+ case GL_DOT3_RGB:
+ case GL_DOT3_RGBA:
return 2;
- case COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE:
+ case GL_INTERPOLATE:
return 3;
}
return 0;
}
+static gboolean
+is_mipmap_filter (CoglMaterialFilter filter)
+{
+ return (filter == COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST
+ || filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST
+ || filter == COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR
+ || filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR);
+}
+
static void
_cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer,
CoglLayerInfo *gl_layer_info)
@@ -851,6 +1097,9 @@ _cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer,
GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA,
layer->texture_combine_alpha_op[2]));
}
+
+ GE (glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
+ layer->texture_combine_constant));
}
#ifndef DISABLE_MATERIAL_CACHE
@@ -976,6 +1225,13 @@ _cogl_material_flush_layers_gl_state (CoglMaterial *material,
GE (glActiveTexture (GL_TEXTURE0 + i));
+ _cogl_texture_set_filters (layer->texture,
+ layer->min_filter,
+ layer->mag_filter);
+ if (is_mipmap_filter (layer->min_filter)
+ || is_mipmap_filter (layer->mag_filter))
+ _cogl_texture_ensure_mipmaps (layer->texture);
+
/* FIXME: We could be more clever here and only bind the texture
if it is different from gl_layer_info->gl_texture to avoid
redundant GL calls. However a few other places in Cogl and
@@ -1122,12 +1378,44 @@ _cogl_material_flush_base_gl_state (CoglMaterial *material)
if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC
&& material->flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC))
{
- GE (glBlendFunc (material->blend_src_factor, material->blend_dst_factor));
+#if defined (HAVE_COGL_GLES2)
+ gboolean have_blend_equation_seperate = TRUE;
+#elif defined (HAVE_COGL_GL)
+ gboolean have_blend_equation_seperate = FALSE;
+ if (ctx->pf_glBlendEquationSeparate) /* Only GL 2.0 + */
+ have_blend_equation_seperate = TRUE;
+#endif
+
+#ifndef HAVE_COGL_GLES /* GLES 1 only has glBlendFunc */
+ if (material->blend_src_factor_rgb != material->blend_src_factor_alpha
+ || (material->blend_src_factor_rgb !=
+ material->blend_src_factor_alpha))
+ {
+ if (have_blend_equation_seperate &&
+ material->blend_equation_rgb != material->blend_equation_alpha)
+ GE (glBlendEquationSeparate (material->blend_equation_rgb,
+ material->blend_equation_alpha));
+ else
+ GE (glBlendEquation (material->blend_equation_rgb));
+
+ GE (glBlendFuncSeparate (material->blend_src_factor_rgb,
+ material->blend_dst_factor_rgb,
+ material->blend_src_factor_alpha,
+ material->blend_dst_factor_alpha));
+ GE (glBlendColor (material->blend_constant[0],
+ material->blend_constant[1],
+ material->blend_constant[2],
+ material->blend_constant[3]));
+ }
+ else
+#endif
+ GE (glBlendFunc (material->blend_src_factor_rgb,
+ material->blend_dst_factor_rgb));
}
}
void
-cogl_material_flush_gl_state (CoglHandle handle, ...)
+_cogl_material_flush_gl_state (CoglHandle handle, ...)
{
CoglMaterial *material;
va_list ap;
@@ -1204,3 +1492,44 @@ cogl_set_source_texture (CoglHandle texture_handle)
cogl_set_source (ctx->default_material);
}
+CoglMaterialFilter
+cogl_material_layer_get_min_filter (CoglHandle layer_handle)
+{
+ CoglMaterialLayer *layer;
+
+ g_return_val_if_fail (cogl_is_material_layer (layer_handle), 0);
+
+ layer = _cogl_material_layer_pointer_from_handle (layer_handle);
+
+ return layer->min_filter;
+}
+
+CoglMaterialFilter
+cogl_material_layer_get_mag_filter (CoglHandle layer_handle)
+{
+ CoglMaterialLayer *layer;
+
+ g_return_val_if_fail (cogl_is_material_layer (layer_handle), 0);
+
+ layer = _cogl_material_layer_pointer_from_handle (layer_handle);
+
+ return layer->mag_filter;
+}
+
+void
+cogl_material_set_layer_filters (CoglHandle handle,
+ gint layer_index,
+ CoglMaterialFilter min_filter,
+ CoglMaterialFilter mag_filter)
+{
+ CoglMaterial *material;
+ CoglMaterialLayer *layer;
+
+ g_return_if_fail (cogl_is_material (handle));
+
+ material = _cogl_material_pointer_from_handle (handle);
+ layer = _cogl_material_get_layer (material, layer_index, TRUE);
+
+ layer->min_filter = min_filter;
+ layer->mag_filter = mag_filter;
+}
diff --git a/common/cogl-matrix-stack.c b/common/cogl-matrix-stack.c
index a72af000d..6ba909840 100644
--- a/common/cogl-matrix-stack.c
+++ b/common/cogl-matrix-stack.c
@@ -257,6 +257,59 @@ _cogl_matrix_stack_multiply (CoglMatrixStack *stack,
stack->flushed_state = NULL;
}
+void
+_cogl_matrix_stack_frustum (CoglMatrixStack *stack,
+ float left,
+ float right,
+ float bottom,
+ float top,
+ float z_near,
+ float z_far)
+{
+ CoglMatrixState *state;
+
+ state = _cogl_matrix_stack_top_mutable (stack);
+ cogl_matrix_frustum (&state->matrix,
+ left, right, bottom, top,
+ z_near, z_far);
+ /* mark dirty */
+ stack->flushed_state = NULL;
+}
+
+void
+_cogl_matrix_stack_perspective (CoglMatrixStack *stack,
+ float fov_y,
+ float aspect,
+ float z_near,
+ float z_far)
+{
+ CoglMatrixState *state;
+
+ state = _cogl_matrix_stack_top_mutable (stack);
+ cogl_matrix_perspective (&state->matrix,
+ fov_y, aspect, z_near, z_far);
+ /* mark dirty */
+ stack->flushed_state = NULL;
+}
+
+void
+_cogl_matrix_stack_ortho (CoglMatrixStack *stack,
+ float left,
+ float right,
+ float bottom,
+ float top,
+ float z_near,
+ float z_far)
+{
+ CoglMatrixState *state;
+
+ state = _cogl_matrix_stack_top_mutable (stack);
+ cogl_matrix_ortho (&state->matrix,
+ left, right, bottom, top, z_near, z_far);
+ /* mark dirty */
+ stack->flushed_state = NULL;
+}
+
void
_cogl_matrix_stack_get (CoglMatrixStack *stack,
CoglMatrix *matrix)
@@ -280,25 +333,6 @@ _cogl_matrix_stack_set (CoglMatrixStack *stack,
stack->flushed_state = NULL;
}
-void
-_cogl_matrix_stack_frustum (CoglMatrixStack *stack,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack);
- cogl_matrix_frustum (&state->matrix,
- left, right, bottom, top,
- z_near, z_far);
- /* mark dirty */
- stack->flushed_state = NULL;
-}
-
void
_cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack,
GLenum gl_mode)
diff --git a/common/cogl-matrix-stack.h b/common/cogl-matrix-stack.h
index 00db51685..a766f4bbc 100644
--- a/common/cogl-matrix-stack.h
+++ b/common/cogl-matrix-stack.h
@@ -51,10 +51,6 @@ void _cogl_matrix_stack_rotate (CoglMatrixStack *stack,
float z);
void _cogl_matrix_stack_multiply (CoglMatrixStack *stack,
const CoglMatrix *matrix);
-void _cogl_matrix_stack_get (CoglMatrixStack *stack,
- CoglMatrix *matrix);
-void _cogl_matrix_stack_set (CoglMatrixStack *stack,
- const CoglMatrix *matrix);
void _cogl_matrix_stack_frustum (CoglMatrixStack *stack,
float left,
float right,
@@ -62,6 +58,22 @@ void _cogl_matrix_stack_frustum (CoglMatrixStack *stack,
float top,
float z_near,
float z_far);
+void _cogl_matrix_stack_perspective (CoglMatrixStack *stack,
+ float fov_y,
+ float aspect,
+ float z_near,
+ float z_far);
+void _cogl_matrix_stack_ortho (CoglMatrixStack *stack,
+ float left,
+ float right,
+ float bottom,
+ float top,
+ float z_near,
+ float z_far);
+void _cogl_matrix_stack_get (CoglMatrixStack *stack,
+ CoglMatrix *matrix);
+void _cogl_matrix_stack_set (CoglMatrixStack *stack,
+ const CoglMatrix *matrix);
void _cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack,
GLenum gl_mode);
diff --git a/common/cogl-matrix.c b/common/cogl-matrix.c
index 6b6f20fae..45f367d73 100644
--- a/common/cogl-matrix.c
+++ b/common/cogl-matrix.c
@@ -151,21 +151,6 @@ cogl_matrix_invert (CoglMatrix *matrix)
}
#endif
-void
-cogl_matrix_transform_point (const CoglMatrix *matrix,
- float *x,
- float *y,
- float *z,
- float *w)
-{
- float _x = *x, _y = *y, _z = *z, _w = *w;
-
- *x = matrix->xx * _x + matrix->xy * _y + matrix->xz * _z + matrix->xw * _w;
- *y = matrix->yx * _x + matrix->yy * _y + matrix->yz * _z + matrix->yw * _w;
- *z = matrix->zx * _x + matrix->zy * _y + matrix->zz * _z + matrix->zw * _w;
- *w = matrix->wx * _x + matrix->wy * _y + matrix->wz * _z + matrix->ww * _w;
-}
-
void
cogl_matrix_frustum (CoglMatrix *matrix,
float left,
@@ -208,6 +193,62 @@ cogl_matrix_frustum (CoglMatrix *matrix,
cogl_matrix_multiply (matrix, matrix, &frustum);
}
+void
+cogl_matrix_perspective (CoglMatrix *matrix,
+ float fov_y,
+ float aspect,
+ float z_near,
+ float z_far)
+{
+ float ymax = z_near * tan (fov_y * G_PI / 360.0);
+
+ cogl_matrix_frustum (matrix,
+ -ymax * aspect, /* left */
+ ymax * aspect, /* right */
+ -ymax, /* bottom */
+ ymax, /* top */
+ z_near,
+ z_far);
+}
+
+void
+cogl_matrix_ortho (CoglMatrix *matrix,
+ float left,
+ float right,
+ float bottom,
+ float top,
+ float near,
+ float far)
+{
+ CoglMatrix ortho;
+
+ /* column 0 */
+ ortho.xx = 2.0 / (right - left);
+ ortho.yx = 0.0;
+ ortho.zx = 0.0;
+ ortho.wx = 0.0;
+
+ /* column 1 */
+ ortho.xy = 0.0;
+ ortho.yy = 2.0 / (top - bottom);
+ ortho.zy = 0.0;
+ ortho.wy = 0.0;
+
+ /* column 2 */
+ ortho.xz = 0.0;
+ ortho.yz = 0.0;
+ ortho.zz = -2.0 / (far - near);
+ ortho.wz = 0.0;
+
+ /* column 3 */
+ ortho.xw = -(right + left) / (right - left);
+ ortho.yw = -(top + bottom) / (top - bottom);
+ ortho.zw = -(far + near) / (far - near);
+ ortho.ww = 1.0;
+
+ cogl_matrix_multiply (matrix, matrix, &ortho);
+}
+
void
cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array)
{
@@ -220,3 +261,19 @@ cogl_matrix_get_array (const CoglMatrix *matrix)
return (float *)matrix;
}
+void
+cogl_matrix_transform_point (const CoglMatrix *matrix,
+ float *x,
+ float *y,
+ float *z,
+ float *w)
+{
+ float _x = *x, _y = *y, _z = *z, _w = *w;
+
+ *x = matrix->xx * _x + matrix->xy * _y + matrix->xz * _z + matrix->xw * _w;
+ *y = matrix->yx * _x + matrix->yy * _y + matrix->yz * _z + matrix->yw * _w;
+ *z = matrix->zx * _x + matrix->zy * _y + matrix->zz * _z + matrix->zw * _w;
+ *w = matrix->wx * _x + matrix->wy * _y + matrix->wz * _z + matrix->ww * _w;
+}
+
+
diff --git a/common/cogl-primitives.c b/common/cogl-primitives.c
index 224769ca2..598015521 100644
--- a/common/cogl-primitives.c
+++ b/common/cogl-primitives.c
@@ -29,7 +29,8 @@
#include "cogl-internal.h"
#include "cogl-context.h"
#include "cogl-texture-private.h"
-#include "cogl-material.h"
+#include "cogl-material-private.h"
+#include "cogl-vertex-buffer-private.h"
#include
#include
@@ -39,16 +40,8 @@
#ifdef HAVE_COGL_GL
-#define glDrawRangeElements ctx->pf_glDrawRangeElements
#define glClientActiveTexture ctx->pf_glClientActiveTexture
-#else
-
-/* GLES doesn't have glDrawRangeElements, so we simply pretend it does
- * but that it makes no use of the start, end constraints: */
-#define glDrawRangeElements(mode, start, end, count, type, indices) \
- glDrawElements (mode, count, type, indices)
-
#endif
/* these are defined in the particular backend */
@@ -63,7 +56,6 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
gint batch_len,
GLfloat *vertex_pointer)
{
- int needed_indices;
gsize stride;
int i;
gulong enable_flags = 0;
@@ -72,35 +64,6 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- /* The indices are always the same sequence regardless of the vertices so we
- * only need to change it if there are more vertices than ever before. */
- needed_indices = batch_len * 6;
- if (needed_indices > ctx->static_indices->len)
- {
- int old_len = ctx->static_indices->len;
- int vert_num = old_len / 6 * 4;
- GLushort *q;
-
- /* Add two triangles for each quad to the list of
- indices. That makes six new indices but two of the
- vertices in the triangles are shared. */
- g_array_set_size (ctx->static_indices, needed_indices);
- q = &g_array_index (ctx->static_indices, GLushort, old_len);
-
- for (i = old_len;
- i < ctx->static_indices->len;
- i += 6, vert_num += 4)
- {
- *(q++) = vert_num + 0;
- *(q++) = vert_num + 1;
- *(q++) = vert_num + 3;
-
- *(q++) = vert_num + 1;
- *(q++) = vert_num + 2;
- *(q++) = vert_num + 3;
- }
- }
-
/* XXX NB:
* Our vertex data is arranged as follows:
* 4 vertices per quad: 2 GLfloats per position,
@@ -112,16 +75,16 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
disable_mask = (1 << batch_start->n_layers) - 1;
disable_mask = ~disable_mask;
- cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_FALLBACK_MASK,
- batch_start->fallback_mask,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- disable_mask,
- /* Redundant when dealing with unsliced
- * textures but does no harm... */
- COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
- batch_start->layer0_override_texture,
- NULL);
+ _cogl_material_flush_gl_state (ctx->source_material,
+ COGL_MATERIAL_FLUSH_FALLBACK_MASK,
+ batch_start->fallback_mask,
+ COGL_MATERIAL_FLUSH_DISABLE_MASK,
+ disable_mask,
+ /* Redundant when dealing with unsliced
+ * textures but does no harm... */
+ COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
+ batch_start->layer0_override_texture,
+ NULL);
for (i = 0; i < batch_start->n_layers; i++)
{
@@ -140,7 +103,7 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
/* 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 (ctx->source_material);
+ enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
if (ctx->enable_backface_culling)
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
@@ -150,12 +113,32 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
GE (glVertexPointer (2, GL_FLOAT, stride, vertex_pointer));
_cogl_current_matrix_state_flush ();
- GE (glDrawRangeElements (GL_TRIANGLES,
- 0, ctx->static_indices->len - 1,
- 6 * batch_len,
- GL_UNSIGNED_SHORT,
- ctx->static_indices->data));
+#ifdef HAVE_COGL_GL
+
+ GE( glDrawArrays (GL_QUADS, 0, batch_len * 4) );
+
+#else /* HAVE_COGL_GL */
+
+ /* GLES doesn't support GL_QUADS so we will use GL_TRIANGLES and
+ indices */
+ {
+ int needed_indices = batch_len * 6;
+ CoglHandle indices_handle
+ = cogl_vertex_buffer_indices_get_for_quads (needed_indices);
+ CoglVertexBufferIndices *indices
+ = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
+
+ GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
+ GPOINTER_TO_UINT (indices->vbo_name)));
+ GE (glDrawElements (GL_TRIANGLES,
+ 6 * batch_len,
+ indices->type,
+ NULL));
+ GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
+ }
+
+#endif /* HAVE_COGL_GL */
/* DEBUGGING CODE XXX:
* This path will cause all rectangles to be drawn with a red, green
@@ -177,7 +160,7 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
color == 1 ? 0xff : 0x00,
color == 2 ? 0xff : 0x00,
0xff);
- cogl_material_flush_gl_state (outline, NULL);
+ _cogl_material_flush_gl_state (outline, NULL);
_cogl_current_matrix_state_flush ();
GE( glDrawArrays (GL_LINE_LOOP, 4 * i, 4) );
}
@@ -791,7 +774,7 @@ _cogl_rectangles_with_multitexture_coords (
/* We don't support multi texturing using textures with any waste if the
* user has supplied a custom texture matrix, since we don't know if
* the result will end up trying to texture from the waste area. */
- flags = cogl_material_layer_get_flags (layer);
+ flags = _cogl_material_layer_get_flags (layer);
if (flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX
&& _cogl_texture_span_has_waste (texture, 0, 0))
{
@@ -1041,13 +1024,13 @@ _cogl_texture_sliced_polygon (CoglTextureVertex *vertices,
v += stride;
}
- cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- (guint32)~1, /* disable all except the
+ _cogl_material_flush_gl_state (ctx->source_material,
+ COGL_MATERIAL_FLUSH_DISABLE_MASK,
+ (guint32)~1, /* disable all except the
first layer */
- COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
- gl_handle,
- NULL);
+ COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
+ gl_handle,
+ NULL);
_cogl_current_matrix_state_flush ();
GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) );
@@ -1136,10 +1119,10 @@ _cogl_multitexture_unsliced_polygon (CoglTextureVertex *vertices,
c[3] = cogl_color_get_alpha_float (&vertices[i].color);
}
- cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_FALLBACK_MASK,
- fallback_mask,
- NULL);
+ _cogl_material_flush_gl_state (ctx->source_material,
+ COGL_MATERIAL_FLUSH_FALLBACK_MASK,
+ fallback_mask,
+ NULL);
_cogl_current_matrix_state_flush ();
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices));
@@ -1175,7 +1158,6 @@ cogl_polygon (CoglTextureVertex *vertices,
{
CoglHandle layer = (CoglHandle)tmp->data;
CoglHandle tex_handle = cogl_material_layer_get_texture (layer);
- CoglTexture *tex = _cogl_texture_pointer_from_handle (tex_handle);
if (i == 0 && cogl_texture_is_sliced (tex_handle))
{
@@ -1203,7 +1185,8 @@ cogl_polygon (CoglTextureVertex *vertices,
use_sliced_polygon_fallback = TRUE;
n_layers = 1;
- if (tex->min_filter != GL_NEAREST || tex->mag_filter != GL_NEAREST)
+ if (cogl_material_layer_get_min_filter (layer) != GL_NEAREST
+ || cogl_material_layer_get_mag_filter (layer) != GL_NEAREST)
{
static gboolean warning_seen = FALSE;
if (!warning_seen)
@@ -1217,11 +1200,14 @@ cogl_polygon (CoglTextureVertex *vertices,
}
#ifdef HAVE_COGL_GL
- /* Temporarily change the wrapping mode on all of the slices to use
- * a transparent border
- * XXX: it's doesn't look like we save/restore this, like the comment
- * implies? */
- _cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_BORDER);
+ {
+ CoglTexture *tex = _cogl_texture_pointer_from_handle (tex_handle);
+ /* Temporarily change the wrapping mode on all of the slices to use
+ * a transparent border
+ * XXX: it's doesn't look like we save/restore this, like
+ * the comment implies? */
+ _cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_BORDER);
+ }
#endif
break;
}
@@ -1254,7 +1240,7 @@ cogl_polygon (CoglTextureVertex *vertices,
/* Prepare GL state */
enable_flags = COGL_ENABLE_VERTEX_ARRAY;
- enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material);
+ enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
if (ctx->enable_backface_culling)
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
diff --git a/common/cogl-util.c b/common/cogl-util.c
index d71b9ffd8..2d86f73f3 100644
--- a/common/cogl-util.c
+++ b/common/cogl-util.c
@@ -103,159 +103,6 @@ cogl_handle_get_type (void)
return our_type;
}
-GType
-cogl_pixel_format_get_type (void)
-{
- static GType gtype = 0;
-
- if (G_UNLIKELY (gtype == 0))
- {
- static const GEnumValue values[] = {
- { COGL_PIXEL_FORMAT_ANY, "COGL_PIXEL_FORMAT_ANY", "any" },
- { COGL_PIXEL_FORMAT_A_8, "COGL_PIXEL_FORMAT_A_8", "a-8" },
- { COGL_PIXEL_FORMAT_RGB_565, "COGL_PIXEL_FORMAT_RGB_565", "rgb-565" },
- { COGL_PIXEL_FORMAT_RGBA_4444, "COGL_PIXEL_FORMAT_RGBA_4444", "rgba-4444" },
- { COGL_PIXEL_FORMAT_RGBA_5551, "COGL_PIXEL_FORMAT_RGBA_5551", "rgba-5551" },
- { COGL_PIXEL_FORMAT_YUV, "COGL_PIXEL_FORMAT_YUV", "yuv" },
- { COGL_PIXEL_FORMAT_G_8, "COGL_PIXEL_FORMAT_G_8", "g-8" },
- { COGL_PIXEL_FORMAT_RGB_888, "COGL_PIXEL_FORMAT_RGB_888", "rgb-888" },
- { COGL_PIXEL_FORMAT_BGR_888, "COGL_PIXEL_FORMAT_BGR_888", "bgr-888" },
- { COGL_PIXEL_FORMAT_RGBA_8888, "COGL_PIXEL_FORMAT_RGBA_8888", "rgba-8888" },
- { COGL_PIXEL_FORMAT_BGRA_8888, "COGL_PIXEL_FORMAT_BGRA_8888", "bgra-8888" },
- { COGL_PIXEL_FORMAT_ARGB_8888, "COGL_PIXEL_FORMAT_ARGB_8888", "argb-8888" },
- { COGL_PIXEL_FORMAT_ABGR_8888, "COGL_PIXEL_FORMAT_ABGR_8888", "abgr-8888" },
- { COGL_PIXEL_FORMAT_RGBA_8888_PRE, "COGL_PIXEL_FORMAT_RGBA_8888_PRE", "rgba-8888-pre" },
- { COGL_PIXEL_FORMAT_BGRA_8888_PRE, "COGL_PIXEL_FORMAT_BGRA_8888_PRE", "bgra-8888-pre" },
- { COGL_PIXEL_FORMAT_ARGB_8888_PRE, "COGL_PIXEL_FORMAT_ARGB_8888_PRE", "argb-8888-pre" },
- { COGL_PIXEL_FORMAT_ABGR_8888_PRE, "COGL_PIXEL_FORMAT_ABGR_8888_PRE", "abgr-8888-pre" },
- { COGL_PIXEL_FORMAT_RGBA_4444_PRE, "COGL_PIXEL_FORMAT_RGBA_4444_PRE", "rgba-4444-pre" },
- { COGL_PIXEL_FORMAT_RGBA_5551_PRE, "COGL_PIXEL_FORMAT_RGBA_5551_PRE", "rgba-5551-pre" },
- { 0, NULL, NULL }
- };
-
- gtype =
- g_enum_register_static (g_intern_static_string ("CoglPixelFormat"),
- values);
- }
-
- return gtype;
-}
-
-GType
-cogl_feature_flags_get_type (void)
-{
- static GType gtype = 0;
-
- if (G_UNLIKELY (gtype == 0))
- {
- static const GFlagsValue values[] = {
- { COGL_FEATURE_TEXTURE_RECTANGLE, "COGL_FEATURE_TEXTURE_RECTANGLE", "texture-rectangle" },
- { COGL_FEATURE_TEXTURE_NPOT, "COGL_FEATURE_TEXTURE_NPOT", "texture-npot" },
- { COGL_FEATURE_TEXTURE_YUV, "COGL_FEATURE_TEXTURE_YUV", "yuv" },
- { COGL_FEATURE_TEXTURE_READ_PIXELS, "COGL_FEATURE_TEXTURE_READ_PIXELS", "read-pixels" },
- { COGL_FEATURE_SHADERS_GLSL, "COGL_FEATURE_SHADERS_GLSL", "shaders-glsl" },
- { COGL_FEATURE_OFFSCREEN, "COGL_FEATURE_OFFSCREEN", "offscreen" },
- { COGL_FEATURE_OFFSCREEN_MULTISAMPLE, "COGL_FEATURE_OFFSCREEN_MULTISAMPLE", "offscreen-multisample" },
- { COGL_FEATURE_OFFSCREEN_BLIT, "COGL_FEATURE_OFFSCREEN_BLIT", "offscreen-blit" },
- { COGL_FEATURE_FOUR_CLIP_PLANES, "COGL_FEATURE_FOUR_CLIP_PLANES", "four-clip-planes" },
- { COGL_FEATURE_STENCIL_BUFFER, "COGL_FEATURE_STENCIL_BUFFER", "stencil-buffer" },
- { 0, NULL, NULL }
- };
-
- gtype =
- g_flags_register_static (g_intern_static_string ("CoglFeatureFlags"),
- values);
- }
-
- return gtype;
-}
-
-GType
-cogl_buffer_target_get_type (void)
-{
- static GType gtype = 0;
-
- if (G_UNLIKELY (gtype == 0))
- {
- static const GFlagsValue values[] = {
- { COGL_WINDOW_BUFFER, "COGL_WINDOW_BUFFER", "window-buffer" },
- { COGL_OFFSCREEN_BUFFER, "COGL_OFFSCREEN_BUFFER", "offscreen-buffer" },
- { 0, NULL, NULL }
- };
-
- gtype =
- g_flags_register_static (g_intern_static_string ("CoglBufferTarget"),
- values);
- }
-
- return gtype;
-}
-
-GType
-cogl_matrix_mode_get_type (void)
-{
- static GType gtype = 0;
-
- if (G_UNLIKELY (gtype == 0))
- {
- static const GEnumValue values[] = {
- { COGL_MATRIX_MODELVIEW, "COGL_MATRIX_MODELVIEW", "modelview" },
- { COGL_MATRIX_PROJECTION, "COGL_MATRIX_PROJECTION", "projection" },
- { COGL_MATRIX_TEXTURE, "COGL_MATRIX_TEXTURE", "texture" },
- { 0, NULL, NULL }
- };
-
- gtype =
- g_enum_register_static (g_intern_static_string ("CoglMatrixMode"),
- values);
- }
-
- return gtype;
-}
-
-GType
-cogl_texture_flags_get_type (void)
-{
- static GType gtype = 0;
-
- if (G_UNLIKELY (gtype == 0))
- {
- static const GFlagsValue values[] = {
- { COGL_TEXTURE_NONE, "COGL_TEXTURE_NONE", "none" },
- { COGL_TEXTURE_AUTO_MIPMAP, "COGL_TEXTURE_AUTO_MIPMAP", "auto-mipmap" },
- { 0, NULL, NULL }
- };
-
- gtype =
- g_flags_register_static (g_intern_static_string ("CoglTextureFlags"),
- values);
- }
-
- return gtype;
-}
-
-GType
-cogl_fog_mode_get_type (void)
-{
- static GType gtype = 0;
-
- if (G_UNLIKELY (gtype == 0))
- {
- static const GEnumValue values[] = {
- { COGL_FOG_MODE_LINEAR, "COGL_FOG_MODE_LINEAR", "linear" },
- { COGL_FOG_MODE_EXPONENTIAL, "COGL_FOG_MODE_EXPONENTIAL", "exponential" },
- { COGL_FOG_MODE_EXPONENTIAL_SQUARED, "COGL_FOG_MODE_EXPONENTIAL_SQUARED", "exponential-squared" },
- { 0, NULL, NULL }
- };
-
- gtype =
- g_enum_register_static (g_intern_static_string ("CoglFogMode"),
- values);
- }
-
- return gtype;
-}
-
/*
* CoglFixed
*/
diff --git a/common/cogl-vertex-buffer-private.h b/common/cogl-vertex-buffer-private.h
index 68a709b54..558765303 100644
--- a/common/cogl-vertex-buffer-private.h
+++ b/common/cogl-vertex-buffer-private.h
@@ -99,9 +99,9 @@ typedef struct _CoglVertexBufferAttrib
union _u
{
const void *pointer;
- gsize vbo_offset;
+ size_t vbo_offset;
} u;
- gsize span_bytes;
+ size_t span_bytes;
guint16 stride;
guint8 n_components;
guint8 texture_unit;
@@ -129,25 +129,41 @@ typedef struct _CoglVertexBufferVBO
{
CoglVertexBufferVBOFlags flags;
- /* Note: this is a pointer to handle fallbacks, and normally holds
- * a GLuint value */
- gpointer vbo_name; /*!< The name of the corresponding buffer object */
- gsize vbo_bytes; /*!< The lengh of the allocated buffer object in bytes */
+ /* Note: this is a pointer to handle fallbacks. It normally holds
+ * a GLuint VBO name, but when the driver doesn't support VBOs then
+ * this simply points to an malloc'd buffer. */
+ void *vbo_name; /*!< The name of the corresponding buffer object */
+ size_t vbo_bytes; /*!< The lengh of the allocated buffer object in bytes */
GList *attributes;
} CoglVertexBufferVBO;
+typedef struct _CoglVertexBufferIndices
+{
+ CoglHandleObject _parent;
+
+ /* Note: this is a pointer to handle fallbacks. It normally holds
+ * a GLuint VBO name, but when the driver doesn't support VBOs then
+ * this simply points to an malloc'd buffer. */
+ void *vbo_name;
+ GLenum type;
+} CoglVertexBufferIndices;
typedef struct _CoglVertexBuffer
{
CoglHandleObject _parent;
- guint n_vertices; /*!< The number of vertices in the buffer */
- GList *submitted_vbos; /* The VBOs currently submitted to the GPU */
+ int n_vertices; /*!< The number of vertices in the buffer */
+ GList *submitted_vbos; /* The VBOs currently submitted to the GPU */
/* Note: new_attributes is normally NULL and only valid while
* modifying a buffer. */
- GList *new_attributes; /*!< attributes pending submission */
+ GList *new_attributes; /*!< attributes pending submission */
+
} CoglVertexBuffer;
+CoglVertexBuffer *_cogl_vertex_buffer_pointer_from_handle (CoglHandle handle);
+CoglVertexBufferIndices *
+ _cogl_vertex_buffer_indices_pointer_from_handle (CoglHandle handle);
+
#endif /* __COGL_VERTEX_BUFFER_H */
diff --git a/common/cogl-vertex-buffer.c b/common/cogl-vertex-buffer.c
index f6fa6ba89..a36bb1cec 100644
--- a/common/cogl-vertex-buffer.c
+++ b/common/cogl-vertex-buffer.c
@@ -136,6 +136,7 @@
#include "cogl-handle.h"
#include "cogl-vertex-buffer-private.h"
#include "cogl-texture-private.h"
+#include "cogl-material-private.h"
#define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \
(VAR = TYPE_SIZE + ((VAR - 1) & ~(TYPE_SIZE - 1)))
@@ -200,8 +201,10 @@
#endif /* HAVE_COGL_GL */
static void _cogl_vertex_buffer_free (CoglVertexBuffer *buffer);
+static void _cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *buffer_indices);
COGL_HANDLE_DEFINE (VertexBuffer, vertex_buffer);
+COGL_HANDLE_DEFINE (VertexBufferIndices, vertex_buffer_indices);
CoglHandle
cogl_vertex_buffer_new (guint n_vertices)
@@ -411,13 +414,13 @@ get_gl_type_size (CoglVertexBufferAttribFlags flags)
}
void
-cogl_vertex_buffer_add (CoglHandle handle,
- const char *attribute_name,
- guint8 n_components,
- GLenum gl_type,
- gboolean normalized,
- guint16 stride,
- const void *pointer)
+cogl_vertex_buffer_add (CoglHandle handle,
+ const char *attribute_name,
+ guint8 n_components,
+ CoglAttributeType type,
+ gboolean normalized,
+ guint16 stride,
+ const void *pointer)
{
CoglVertexBuffer *buffer;
GQuark name_quark = g_quark_from_string (attribute_name);
@@ -485,7 +488,7 @@ cogl_vertex_buffer_add (CoglHandle handle,
attribute->u.pointer = pointer;
attribute->texture_unit = texture_unit;
- flags |= get_attribute_gl_type_flag_from_gl_type (gl_type);
+ flags |= get_attribute_gl_type_flag_from_gl_type (type);
flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED;
/* Note: We currently just assume, if an attribute is *ever* updated
@@ -1638,14 +1641,14 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
}
}
- cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_FALLBACK_MASK,
- fallback_mask,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- disable_mask,
- NULL);
+ _cogl_material_flush_gl_state (ctx->source_material,
+ COGL_MATERIAL_FLUSH_FALLBACK_MASK,
+ fallback_mask,
+ COGL_MATERIAL_FLUSH_DISABLE_MASK,
+ disable_mask,
+ NULL);
- enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material);
+ enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
if (ctx->enable_backface_culling)
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
@@ -1716,23 +1719,21 @@ disable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
}
void
-cogl_vertex_buffer_draw (CoglHandle handle,
- GLenum mode,
- GLint first,
- GLsizei count)
+cogl_vertex_buffer_draw (CoglHandle handle,
+ CoglVerticesMode mode,
+ int first,
+ int count)
{
CoglVertexBuffer *buffer;
if (!cogl_is_vertex_buffer (handle))
return;
- cogl_clip_ensure ();
-
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
- enable_state_for_drawing_buffer (buffer);
-
+ cogl_clip_ensure ();
_cogl_current_matrix_state_flush ();
+ enable_state_for_drawing_buffer (buffer);
/* FIXME: flush cogl cache */
GE (glDrawArrays (mode, first, count));
@@ -1740,35 +1741,127 @@ cogl_vertex_buffer_draw (CoglHandle handle,
disable_state_for_drawing_buffer (buffer);
}
+static int
+get_indices_type_size (GLuint indices_type)
+{
+ if (indices_type == GL_UNSIGNED_BYTE)
+ return sizeof (GLubyte);
+ if (indices_type == GL_UNSIGNED_SHORT)
+ return sizeof (GLushort);
+ else
+ {
+ g_critical ("Unknown indices type %d\n", indices_type);
+ return 0;
+ }
+}
+
+CoglHandle
+cogl_vertex_buffer_indices_new (CoglIndicesType indices_type,
+ const void *indices_array,
+ int indices_len)
+{
+ gboolean fallback =
+ (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
+ size_t indices_bytes;
+ CoglVertexBufferIndices *indices;
+
+ _COGL_GET_CONTEXT (ctx, 0);
+
+ indices = g_slice_alloc (sizeof (CoglVertexBufferIndices));
+
+ if (indices_type == COGL_INDICES_TYPE_UNSIGNED_BYTE)
+ indices->type = GL_UNSIGNED_BYTE;
+ else if (indices_type == COGL_INDICES_TYPE_UNSIGNED_SHORT)
+ indices->type = GL_UNSIGNED_SHORT;
+ else
+ {
+ g_critical ("unknown indices type %d", indices_type);
+ g_slice_free (CoglVertexBufferIndices, indices);
+ return 0;
+ }
+
+ indices_bytes = get_indices_type_size (indices->type) * indices_len;
+ if (fallback)
+ {
+ indices->vbo_name = g_malloc (indices_len);
+ memcpy (indices->vbo_name, indices_array, indices_bytes);
+ }
+ else
+ {
+ GE (glGenBuffers (1, (GLuint *)&indices->vbo_name));
+ GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
+ GPOINTER_TO_UINT (indices->vbo_name)));
+ GE (glBufferData (GL_ELEMENT_ARRAY_BUFFER,
+ indices_bytes,
+ indices_array,
+ GL_STATIC_DRAW));
+ GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
+ }
+
+ return _cogl_vertex_buffer_indices_handle_new (indices);
+}
+
void
-cogl_vertex_buffer_draw_elements (CoglHandle handle,
- GLenum mode,
- GLuint min_index,
- GLuint max_index,
- GLsizei count,
- GLenum indices_type,
- const GLvoid *indices)
+_cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *indices)
+{
+ gboolean fallback =
+ (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ if (fallback)
+ g_free (indices->vbo_name);
+ else
+ GE (glDeleteBuffers (1, (GLuint *)&indices->vbo_name));
+
+ g_slice_free (CoglVertexBufferIndices, indices);
+}
+
+void
+cogl_vertex_buffer_draw_elements (CoglHandle handle,
+ CoglVerticesMode mode,
+ CoglHandle indices_handle,
+ int min_index,
+ int max_index,
+ int indices_offset,
+ int count)
{
CoglVertexBuffer *buffer;
+ gboolean fallback =
+ (cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
+ size_t byte_offset;
+ CoglVertexBufferIndices *indices = NULL;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (!cogl_is_vertex_buffer (handle))
return;
- cogl_clip_ensure ();
-
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
+ if (!cogl_is_vertex_buffer_indices (indices_handle))
+ return;
+
+ indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
+
+ cogl_clip_ensure ();
+ _cogl_current_matrix_state_flush ();
enable_state_for_drawing_buffer (buffer);
- _cogl_current_matrix_state_flush ();
+ byte_offset = indices_offset * get_indices_type_size (indices->type);
+ if (fallback)
+ byte_offset = (size_t)(((char *)indices->vbo_name) + byte_offset);
+ else
+ GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
+ GPOINTER_TO_UINT (indices->vbo_name)));
/* FIXME: flush cogl cache */
GE (glDrawRangeElements (mode, min_index, max_index,
- count, indices_type, indices));
+ count, indices->type, (void *)byte_offset));
disable_state_for_drawing_buffer (buffer);
+
+ GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
}
static void
@@ -1778,8 +1871,92 @@ _cogl_vertex_buffer_free (CoglVertexBuffer *buffer)
for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next)
cogl_vertex_buffer_vbo_free (tmp->data, TRUE);
+ g_list_free (buffer->submitted_vbos);
+
for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next)
cogl_vertex_buffer_attribute_free (tmp->data);
+ g_list_free (buffer->new_attributes);
g_slice_free (CoglVertexBuffer, buffer);
}
+
+CoglHandle
+cogl_vertex_buffer_indices_get_for_quads (guint n_indices)
+{
+ _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
+
+ /* Check if the indices would fit in a byte array */
+ if (n_indices <= 256 / 4 * 6)
+ {
+ /* Generate the byte array if we haven't already */
+ if (ctx->quad_indices_byte == COGL_INVALID_HANDLE)
+ {
+ guint8 *byte_array = g_malloc (256 / 4 * 6 * sizeof (guint8));
+ guint8 *p = byte_array;
+ int i, vert_num = 0;
+
+ for (i = 0; i < 256 / 4; i++)
+ {
+ *(p++) = vert_num + 0;
+ *(p++) = vert_num + 1;
+ *(p++) = vert_num + 2;
+ *(p++) = vert_num + 0;
+ *(p++) = vert_num + 2;
+ *(p++) = vert_num + 3;
+ vert_num += 4;
+ }
+
+ ctx->quad_indices_byte
+ = cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_BYTE,
+ byte_array,
+ 256 / 4 * 6);
+
+ g_free (byte_array);
+ }
+
+ return ctx->quad_indices_byte;
+ }
+ else
+ {
+ if (ctx->quad_indices_short_len < n_indices)
+ {
+ guint16 *short_array;
+ guint16 *p;
+ int i, vert_num = 0;
+
+ if (ctx->quad_indices_short != COGL_INVALID_HANDLE)
+ cogl_handle_unref (ctx->quad_indices_short);
+ /* Pick a power of two >= MAX (512, n_indices) */
+ if (ctx->quad_indices_short_len == 0)
+ ctx->quad_indices_short_len = 512;
+ while (ctx->quad_indices_short_len < n_indices)
+ ctx->quad_indices_short_len *= 2;
+
+ /* Over-allocate to generate a whole number of quads */
+ p = short_array = g_malloc ((ctx->quad_indices_short_len
+ + 5) / 6 * 6
+ * sizeof (guint16));
+
+ /* Fill in the complete quads */
+ for (i = 0; i < ctx->quad_indices_short_len; i += 6)
+ {
+ *(p++) = vert_num + 0;
+ *(p++) = vert_num + 1;
+ *(p++) = vert_num + 2;
+ *(p++) = vert_num + 0;
+ *(p++) = vert_num + 2;
+ *(p++) = vert_num + 3;
+ vert_num += 4;
+ }
+
+ ctx->quad_indices_short
+ = cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT,
+ short_array,
+ ctx->quad_indices_short_len);
+
+ g_free (short_array);
+ }
+
+ return ctx->quad_indices_short;
+ }
+}
diff --git a/common/cogl.c b/common/cogl.c
index 2495d8172..336303917 100644
--- a/common/cogl.c
+++ b/common/cogl.c
@@ -42,6 +42,7 @@ typedef CoglFuncPtr (*GLXGetProcAddressProc) (const guint8 *procName);
#include "cogl-internal.h"
#include "cogl-util.h"
#include "cogl-context.h"
+#include "cogl-material-private.h"
#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES)
#include "cogl-gles2-wrapper.h"
@@ -213,30 +214,39 @@ cogl_get_enable ()
}
void
-cogl_enable_depth_test (gboolean setting)
+cogl_set_depth_test_enabled (gboolean setting)
{
if (setting)
{
glEnable (GL_DEPTH_TEST);
- glEnable (GL_ALPHA_TEST);
glDepthFunc (GL_LEQUAL);
- glAlphaFunc (GL_GREATER, 0.1);
}
else
- {
- glDisable (GL_DEPTH_TEST);
- glDisable (GL_ALPHA_TEST);
- }
+ glDisable (GL_DEPTH_TEST);
+}
+
+gboolean
+cogl_get_depth_test_enabled (void)
+{
+ return glIsEnabled (GL_DEPTH_TEST) == GL_TRUE ? TRUE : FALSE;
}
void
-cogl_enable_backface_culling (gboolean setting)
+cogl_set_backface_culling_enabled (gboolean setting)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
ctx->enable_backface_culling = setting;
}
+gboolean
+cogl_get_backface_culling_enabled (void)
+{
+ _COGL_GET_CONTEXT (ctx, FALSE);
+
+ return ctx->enable_backface_culling;
+}
+
void
cogl_set_source_color (const CoglColor *color)
{
@@ -375,7 +385,7 @@ _cogl_add_stencil_clip (float x_offset,
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- cogl_material_flush_gl_state (ctx->stencil_material, NULL);
+ _cogl_material_flush_gl_state (ctx->stencil_material, NULL);
if (first)
{
@@ -465,12 +475,12 @@ cogl_viewport (guint width,
}
void
-cogl_setup_viewport (guint width,
- guint height,
- float fovy,
- float aspect,
- float z_near,
- float z_far)
+_cogl_setup_viewport (guint width,
+ guint height,
+ float fovy,
+ float aspect,
+ float z_near,
+ float z_far)
{
float z_camera;
CoglMatrix projection_matrix;
@@ -478,7 +488,7 @@ cogl_setup_viewport (guint width,
GE( glViewport (0, 0, width, height) );
/* For Ortho projection.
- * _cogl_current_matrix_ortho (0, width << 16, 0, height << 16, -1 << 16, 1 << 16);
+ * _cogl_current_matrix_ortho (0, width, 0, height, -1, 1);
*/
cogl_perspective (fovy, aspect, z_near, z_far);
@@ -532,7 +542,7 @@ cogl_setup_viewport (guint width,
}
CoglFeatureFlags
-cogl_get_features ()
+cogl_get_features (void)
{
_COGL_GET_CONTEXT (ctx, 0);
@@ -653,9 +663,11 @@ cogl_disable_fog (void)
glDisable (GL_FOG);
}
+#if 0
void
cogl_flush_gl_state (int flags)
{
_cogl_current_matrix_state_flush ();
}
+#endif
diff --git a/doc/reference/cogl/Makefile.am b/doc/reference/cogl/Makefile.am
index 82b96928f..9888caaa3 100644
--- a/doc/reference/cogl/Makefile.am
+++ b/doc/reference/cogl/Makefile.am
@@ -24,7 +24,7 @@ DOC_SOURCE_DIR=../../../clutter/cogl
SCANGOBJ_OPTIONS=--type-init-func="g_type_init()"
# Extra options to supply to gtkdoc-scan.
-# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
+# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=--deprecated-guards="COGL_DISABLE_DEPRECATED"
# Extra options to supply to gtkdoc-mkdb.
@@ -70,12 +70,14 @@ HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
-content_files= version.xml
+content_files = \
+ blend-strings.xml
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
-expand_content_files=
+expand_content_files = \
+ blend-strings.xml
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
@@ -91,4 +93,3 @@ include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
-EXTRA_DIST += version.xml.in
diff --git a/doc/reference/cogl/blend-strings.xml b/doc/reference/cogl/blend-strings.xml
new file mode 100644
index 000000000..9c3c8d3c9
--- /dev/null
+++ b/doc/reference/cogl/blend-strings.xml
@@ -0,0 +1,130 @@
+
+
+]>
+
+
+
+Material Blend Strings
+3
+COGL Library
+
+
+
+Material Blend Strings
+A simple syntax and grammar for describing blending and texture
+combining functions.
+
+
+
+Cogl Blend Strings
+
+Describing GPU blending and texture combining states is rather awkward to do
+in a consise but also readable fashion. Cogl helps by supporting
+string based descriptions using a simple syntax.
+
+
+
+Some examples
+
+Here is an example used for blending:
+
+"RGBA = ADD (SRC_COLOR * (SRC_COLOR[A]), DST_COLOR * (1-SRC_COLOR[A]))"
+
+In OpenGL terms this replaces glBlendFunc[Separate] and
+glBlendEquation[Separate]
+
+Actually in this case it's more verbose than the GL equivalent:
+
+
+glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+
+But unless you are familiar with OpenGL or refer to its API documentation
+you wouldn't know that the default function used by OpenGL is GL_FUNC_ADD
+nor would you know that the above arguments determine what the source color
+and destination color will be multiplied by before being adding.
+
+
+Here is an example used for texture combining:
+
+"RGB = REPLACE (PREVIOUS)"
+"A = MODULATE (PREVIOUS, TEXTURE)"
+
+
+In OpenGL terms this replaces glTexEnv, and the above example is equivalent
+to this OpenGL code:
+
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+
+
+
+
+
+Here's the syntax
+
+
+<statement>:
+ <channel-mask>=<function-name>(<arg-list>)
+
+ You can either use a single statement with an RGBA channel-mask or you can use
+ two statements; one with an A channel-mask and the other with an RGB
+ channel-mask.
+
+<channel-mask>:
+ A or RGB or RGBA
+
+<function-name>:
+ [A-Za-z_]*
+
+<arg-list>:
+ <arg>,<arg>
+ or <arg>
+ or ""
+
+ I.e. functions may take 0 or more arguments
+
+<arg>:
+ <color-source>
+ 1 - <color-source> : Only intended for texture combining
+ <color-source> * ( <factor> ) : Only intended for blending
+ 0 : Only intended for blending
+
+ See the blending or texture combining sections for further notes and examples.
+
+<color-source>:
+ <source-name>[<channel-mask>]
+ <source-name>
+
+ See the blending or texture combining sections for the list of source-names
+ valid in each context.
+
+ If a channel mask is not given then the channel mask of the statement
+ is assumed instead.
+
+<factor>:
+ 0
+ 1
+ <color-source>
+ 1-<color-source>
+ SRC_ALPHA_SATURATE
+
+
+
+
+
+
+
+
+
diff --git a/doc/reference/cogl/cogl-docs.xml b/doc/reference/cogl/cogl-docs.xml.in
similarity index 97%
rename from doc/reference/cogl/cogl-docs.xml
rename to doc/reference/cogl/cogl-docs.xml.in
index ba5d2cf89..7f9c1c26b 100644
--- a/doc/reference/cogl/cogl-docs.xml
+++ b/doc/reference/cogl/cogl-docs.xml.in
@@ -1,7 +1,7 @@
+
]>
@@ -55,6 +55,7 @@
+
diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt
index 3032a6863..872e02d11 100644
--- a/doc/reference/cogl/cogl-sections.txt
+++ b/doc/reference/cogl/cogl-sections.txt
@@ -15,33 +15,35 @@ COGL_UNPREMULT_MASK
CoglPixelFormat
CoglBufferTarget
-cogl_create_context
-cogl_destroy_context
-
CoglFeatureFlags
cogl_get_features
cogl_features_available
cogl_check_extension
cogl_get_proc_address
-cogl_perspective
-cogl_frustum
-cogl_setup_viewport
-cogl_viewport
-cogl_get_modelview_matrix
-cogl_get_projection_matrix
-cogl_get_viewport
-
cogl_push_matrix
cogl_pop_matrix
cogl_scale
cogl_translate
cogl_rotate
+cogl_frustum
+cogl_perspective
+cogl_ortho
+
+cogl_get_modelview_matrix
+cogl_set_modelview_matrix
+cogl_get_projection_matrix
+cogl_set_projection_matrix
+cogl_viewport
+cogl_setup_viewport
+cogl_get_viewport
cogl_clear
cogl_get_bitmasks
-cogl_enable_depth_test
-cogl_enable_backface_culling
+cogl_set_depth_test_enabled
+cogl_get_depth_test_enabled
+cogl_set_backface_culling_enabled
+cogl_get_backface_culling_enabled
CoglFogMode
cogl_set_fog
@@ -130,12 +132,9 @@ cogl_texture_get_height
cogl_texture_get_format
cogl_texture_get_rowstride
cogl_texture_get_max_waste
-cogl_texture_get_min_filter
-cogl_texture_get_mag_filter
cogl_texture_is_sliced
cogl_texture_get_gl_texture
cogl_texture_get_data
-cogl_texture_set_filters
cogl_texture_set_region
@@ -307,7 +306,11 @@ cogl_vertex_buffer_submit
cogl_vertex_buffer_disable
cogl_vertex_buffer_enable
cogl_vertex_buffer_draw
+CoglIndicesType
+cogl_vertex_buffer_add_indices
+cogl_vertex_buffer_delete_indices
cogl_vertex_buffer_draw_elements
+cogl_vertex_buffer_indices_get_for_quads
CoglVertexBufferAttribFlags
COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_MASK
@@ -349,41 +352,35 @@ cogl_material_set_specular
cogl_material_get_specular
cogl_material_set_shininess
cogl_material_get_shininess
-
CoglMaterialAlphaFunc
cogl_material_set_alpha_test_function
CoglMaterialBlendFactor
-cogl_material_set_blend_factors
+cogl_material_set_blend
+cogl_material_set_blend_constant
cogl_material_set_layer
cogl_material_remove_layer
-CoglMaterialLayerCombineFunc
-cogl_material_set_layer_combine_function
-CoglMaterialLayerCombineChannels
-CoglMaterialLayerCombineSrc
-cogl_material_set_layer_combine_arg_src
-CoglMaterialLayerCombineOp
-cogl_material_set_layer_combine_arg_op
+cogl_material_set_layer_combine
+cogl_material_set_layer_combine_constant
cogl_material_set_layer_matrix
+cogl_material_get_layers
+CoglMaterialFilter
+cogl_material_set_layer_filters
+cogl_material_layer_get_type
+cogl_material_layer_get_texture
+cogl_material_layer_get_min_filter
+cogl_material_layer_get_mag_filter
CoglMaterial
CoglMaterialFlags
CoglMaterialLayerPrivFlags
-cogl_material_set_layer_alpha_combine
-cogl_material_set_layer_rgb_combine
cogl-material-internals
Material Internals
-cogl_material_get_cogl_enable_flags
-CoglMaterialFlushOption
-cogl_material_flush_gl_state
CoglMaterialLayer
cogl_material_get_layers
CoglMaterialLayerType
cogl_material_layer_get_type
-CoglMaterialLayerFlags
-cogl_material_layer_get_flags
cogl_material_layer_get_texture
-cogl_material_layer_flush_gl_sampler_state
diff --git a/doc/reference/cogl/version.xml.in b/doc/reference/cogl/version.xml.in
deleted file mode 100644
index 7fc1bf340..000000000
--- a/doc/reference/cogl/version.xml.in
+++ /dev/null
@@ -1 +0,0 @@
-@CLUTTER_VERSION@
\ No newline at end of file
diff --git a/gl/Makefile.am b/gl/Makefile.am
index 367f674f2..1aab5b649 100644
--- a/gl/Makefile.am
+++ b/gl/Makefile.am
@@ -35,11 +35,6 @@ cogl_sources = \
cogl-context.c \
$(NULL)
-coglincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/cogl
-coglinclude_HEADERS = \
- $(cogl_headers) \
- $(top_builddir)/clutter/cogl/cogl.h
-
INCLUDES = \
-I$(top_srcdir)/clutter/cogl \
-I$(top_srcdir)/clutter/cogl/common \
@@ -50,12 +45,12 @@ INCLUDES = \
-DG_LOG_DOMAIN=\"Cogl-GL\" \
-DCLUTTER_COMPILATION
-noinst_LTLIBRARIES = libclutter-cogl.la
+noinst_LTLIBRARIES = libclutter-cogl-gl.la
-libclutter_cogl_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
-libclutter_cogl_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
-libclutter_cogl_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
-libclutter_cogl_la_SOURCES = \
+libclutter_cogl_gl_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
+libclutter_cogl_gl_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
+libclutter_cogl_gl_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
+libclutter_cogl_gl_la_SOURCES = \
$(top_builddir)/clutter/cogl/cogl.h \
$(cogl_headers) \
$(cogl_priv_headers) \
diff --git a/gl/cogl-context.c b/gl/cogl-context.c
index 986da8aa8..201e05db7 100644
--- a/gl/cogl-context.c
+++ b/gl/cogl-context.c
@@ -37,7 +37,7 @@
static CoglContext *_context = NULL;
static gboolean gl_is_indirect = FALSE;
-gboolean
+static gboolean
cogl_create_context ()
{
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
@@ -69,7 +69,6 @@ cogl_create_context ()
_context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
_context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat));
- _context->static_indices = g_array_new (FALSE, FALSE, sizeof (GLushort));
_context->polygon_vertices = g_array_new (FALSE, FALSE,
sizeof (CoglTextureGLVertex));
@@ -136,6 +135,9 @@ cogl_create_context ()
_context->pf_glActiveTexture = NULL;
_context->pf_glClientActiveTexture = NULL;
+ _context->pf_glBlendFuncSeparate = NULL;
+ _context->pf_glBlendEquationSeparate = NULL;
+
/* Initialise the clip stack */
_cogl_clip_stack_state_init ();
@@ -146,8 +148,7 @@ cogl_create_context ()
_context->default_gl_texture_2d_tex =
cogl_texture_new_from_data (1, /* width */
1, /* height */
- -1, /* max waste */
- COGL_TEXTURE_NONE, /* flags */
+ COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
/* internal format */
COGL_PIXEL_FORMAT_RGBA_8888,
@@ -156,8 +157,7 @@ cogl_create_context ()
_context->default_gl_texture_rect_tex =
cogl_texture_new_from_data (1, /* width */
1, /* height */
- -1, /* max waste */
- COGL_TEXTURE_NONE, /* flags */
+ COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
/* internal format */
COGL_PIXEL_FORMAT_RGBA_8888,
@@ -165,16 +165,20 @@ cogl_create_context ()
default_texture_data);
cogl_set_source (_context->default_material);
- cogl_material_flush_gl_state (_context->source_material, NULL);
+ _cogl_material_flush_gl_state (_context->source_material, NULL);
enable_flags =
- cogl_material_get_cogl_enable_flags (_context->source_material);
+ _cogl_material_get_cogl_enable_flags (_context->source_material);
cogl_enable (enable_flags);
+ _context->quad_indices_byte = COGL_INVALID_HANDLE;
+ _context->quad_indices_short = COGL_INVALID_HANDLE;
+ _context->quad_indices_short_len = 0;
+
return TRUE;
}
void
-cogl_destroy_context ()
+_cogl_destroy_context ()
{
if (_context == NULL)
return;
@@ -199,13 +203,16 @@ cogl_destroy_context ()
if (_context->logged_vertices)
g_array_free (_context->logged_vertices, TRUE);
- if (_context->static_indices)
- g_array_free (_context->static_indices, TRUE);
if (_context->polygon_vertices)
g_array_free (_context->polygon_vertices, TRUE);
if (_context->current_layers)
g_array_free (_context->current_layers, TRUE);
+ if (_context->quad_indices_byte)
+ cogl_handle_unref (_context->quad_indices_byte);
+ if (_context->quad_indices_short)
+ cogl_handle_unref (_context->quad_indices_short);
+
g_free (_context);
}
diff --git a/gl/cogl-context.h b/gl/cogl-context.h
index 2660ed812..d845a6c12 100644
--- a/gl/cogl-context.h
+++ b/gl/cogl-context.h
@@ -78,7 +78,6 @@ typedef struct
* can batch things together. */
GArray *journal;
GArray *logged_vertices;
- GArray *static_indices;
GArray *polygon_vertices;
/* Some simple caching, to minimize state changes... */
@@ -102,6 +101,12 @@ typedef struct
floatVec2 path_nodes_max;
CoglHandle stencil_material;
+ /* Pre-generated VBOs containing indices to generate GL_TRIANGLES
+ out of a vertex array of quads */
+ CoglHandle quad_indices_byte;
+ guint quad_indices_short_len;
+ CoglHandle quad_indices_short;
+
/* Relying on glext.h to define these */
COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT;
COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT;
@@ -115,6 +120,7 @@ typedef struct
COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC pf_glDeleteFramebuffersEXT;
COGL_PFNGLBLITFRAMEBUFFEREXTPROC pf_glBlitFramebufferEXT;
COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC pf_glRenderbufferStorageMultisampleEXT;
+ COGL_PFNGLGENERATEMIPMAPEXTPROC pf_glGenerateMipmapEXT;
COGL_PFNGLCREATEPROGRAMOBJECTARBPROC pf_glCreateProgramObjectARB;
COGL_PFNGLCREATESHADEROBJECTARBPROC pf_glCreateShaderObjectARB;
@@ -164,6 +170,11 @@ typedef struct
COGL_PFNGLACTIVETEXTUREPROC pf_glActiveTexture;
COGL_PFNGLCLIENTACTIVETEXTUREPROC pf_glClientActiveTexture;
+
+ COGL_PFNGLBLENDEQUATIONPROC pf_glBlendEquation;
+ COGL_PFNGLBLENDCOLORPROC pf_glBlendColor;
+ COGL_PFNGLBLENDFUNCSEPARATEPROC pf_glBlendFuncSeparate;
+ COGL_PFNGLBLENDEQUATIONSEPARATEPROC pf_glBlendEquationSeparate;
} CoglContext;
CoglContext *
diff --git a/gl/cogl-defines.h.in b/gl/cogl-defines.h.in
index 8e2df9ec3..025b4cad0 100644
--- a/gl/cogl-defines.h.in
+++ b/gl/cogl-defines.h.in
@@ -773,6 +773,10 @@ typedef void
GLsizei width,
GLsizei height);
+typedef void
+ (APIENTRYP COGL_PFNGLGENERATEMIPMAPEXTPROC)
+ (GLenum target);
+
typedef GLhandleARB
(APIENTRYP COGL_PFNGLCREATEPROGRAMOBJECTARBPROC)
(void);
@@ -1020,6 +1024,29 @@ typedef void
(APIENTRYP COGL_PFNGLCLIENTACTIVETEXTUREPROC)
(GLenum texture);
+typedef void
+ (APIENTRYP COGL_PFNGLBLENDFUNCSEPARATEPROC)
+ (GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha);
+
+typedef void
+ (APIENTRYP COGL_PFNGLBLENDEQUATIONSEPARATEPROC)
+ (GLenum modeRGB,
+ GLenum modeAlpha);
+
+typedef void
+ (APIENTRYP COGL_PFNGLBLENDEQUATIONPROC)
+ (GLenum mode);
+
+typedef void
+ (APIENTRYP COGL_PFNGLBLENDCOLORPROC)
+ (GLclampf red,
+ GLclampf green,
+ GLclampf blue,
+ GLclampf alpha);
+
G_END_DECLS
#endif
diff --git a/gl/cogl-primitives.c b/gl/cogl-primitives.c
index f3c11c134..6c106f9ec 100644
--- a/gl/cogl-primitives.c
+++ b/gl/cogl-primitives.c
@@ -29,6 +29,7 @@
#include "cogl-internal.h"
#include "cogl-context.h"
#include "cogl-clip-stack.h"
+#include "cogl-material-private.h"
#include
#include
@@ -78,13 +79,13 @@ _cogl_path_stroke_nodes ()
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material);
+ enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
cogl_enable (enable_flags);
- cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- (guint32)~0, /* disable all texture layers */
- NULL);
+ _cogl_material_flush_gl_state (ctx->source_material,
+ COGL_MATERIAL_FLUSH_DISABLE_MASK,
+ (guint32)~0, /* disable all texture layers */
+ NULL);
_cogl_current_matrix_state_flush ();
while (path_start < ctx->path_nodes->len)
@@ -133,10 +134,10 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* Just setup a simple material that doesn't use texturing... */
- cogl_material_flush_gl_state (ctx->stencil_material, NULL);
+ _cogl_material_flush_gl_state (ctx->stencil_material, NULL);
enable_flags |=
- cogl_material_get_cogl_enable_flags (ctx->source_material);
+ _cogl_material_get_cogl_enable_flags (ctx->source_material);
cogl_enable (enable_flags);
_cogl_path_get_bounds (nodes_min, nodes_max,
diff --git a/gl/cogl-shader.c b/gl/cogl-shader.c
index 944e6736f..de3302e6a 100644
--- a/gl/cogl-shader.c
+++ b/gl/cogl-shader.c
@@ -108,22 +108,23 @@ cogl_shader_compile (CoglHandle handle)
glCompileShaderARB (shader->gl_handle);
}
-void
-cogl_shader_get_info_log (CoglHandle handle,
- size_t size,
- char *buffer)
+gchar *
+cogl_shader_get_info_log (CoglHandle handle)
{
CoglShader *shader;
+ char buffer[512];
int len;
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ _COGL_GET_CONTEXT (ctx, NULL);
if (!cogl_is_shader (handle))
- return;
+ return NULL;
shader = _cogl_shader_pointer_from_handle (handle);
- glGetInfoLogARB (shader->gl_handle, size-1, &len, buffer);
+ glGetInfoLogARB (shader->gl_handle, 511, &len, buffer);
buffer[len]='\0';
+
+ return g_strdup (buffer);
}
CoglShaderType
diff --git a/gl/cogl-texture-private.h b/gl/cogl-texture-private.h
index 7cf6fe951..365a47921 100644
--- a/gl/cogl-texture-private.h
+++ b/gl/cogl-texture-private.h
@@ -30,6 +30,7 @@
typedef struct _CoglTexture CoglTexture;
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
typedef struct _CoglSpanIter CoglSpanIter;
+typedef struct _CoglTexturePixel CoglTexturePixel;
struct _CoglTexSliceSpan
{
@@ -55,6 +56,18 @@ struct _CoglSpanIter
gboolean intersects;
};
+/* This is used to store the first pixel of each slice. This is only
+ used when glGenerateMipmap is not available */
+struct _CoglTexturePixel
+{
+ /* We need to store the format of the pixel because we store the
+ data in the source format which might end up being different for
+ each slice if a subregion is updated with a different format */
+ GLenum gl_format;
+ GLenum gl_type;
+ guint8 data[4];
+};
+
struct _CoglTexture
{
CoglHandleObject _parent;
@@ -68,11 +81,17 @@ struct _CoglTexture
GArray *slice_y_spans;
GArray *slice_gl_handles;
gint max_waste;
- CoglTextureFilter min_filter;
- CoglTextureFilter mag_filter;
+ GLenum min_filter;
+ GLenum mag_filter;
gboolean is_foreign;
GLint wrap_mode;
gboolean auto_mipmap;
+ gboolean mipmaps_dirty;
+
+ /* This holds a copy of the first pixel in each slice. It is only
+ used to force an automatic update of the mipmaps when
+ glGenerateMipmap is not available. */
+ CoglTexturePixel *first_pixels;
};
/* To improve batching of geometry when submitting vertices to OpenGL we
@@ -93,6 +112,14 @@ void
_cogl_texture_set_wrap_mode_parameter (CoglTexture *tex,
GLenum wrap_mode);
+void
+_cogl_texture_set_filters (CoglHandle handle,
+ GLenum min_filter,
+ GLenum mag_filter);
+
+void
+_cogl_texture_ensure_mipmaps (CoglHandle handle);
+
gboolean
_cogl_texture_span_has_waste (CoglTexture *tex,
gint x_span_index,
diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c
index 643b11899..215e14c78 100644
--- a/gl/cogl-texture.c
+++ b/gl/cogl-texture.c
@@ -49,6 +49,7 @@
#define glDrawRangeElements ctx->pf_glDrawRangeElements
#define glActiveTexture ctx->pf_glActiveTexture
#define glClientActiveTexture ctx->pf_glClientActiveTexture
+#define glGenerateMipmap ctx->pf_glGenerateMipmapEXT
#else
@@ -247,11 +248,12 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
/* Iterate horizontal slices */
for (x = 0; x < tex->slice_x_spans->len; ++x)
{
+ gint slice_num = y * tex->slice_x_spans->len + x;
+
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x);
/* Pick the gl texture object handle */
- gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
- y * tex->slice_x_spans->len + x);
+ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num);
/* Setup gl alignment to match rowstride and top-left corner */
prep_for_gl_pixels_upload (tex->bitmap.rowstride,
@@ -259,6 +261,17 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
y_span->start,
bpp);
+ /* Keep a copy of the first pixel if needed */
+ if (tex->first_pixels)
+ {
+ memcpy (tex->first_pixels[slice_num].data,
+ tex->bitmap.data + x_span->start * bpp
+ + y_span->start * tex->bitmap.rowstride,
+ bpp);
+ tex->first_pixels[slice_num].gl_format = tex->gl_format;
+ tex->first_pixels[slice_num].gl_type = tex->gl_type;
+ }
+
/* Upload new image data */
GE( glBindTexture (tex->gl_target, gl_handle) );
@@ -343,6 +356,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
if (waste_buf)
g_free (waste_buf);
+ tex->mipmaps_dirty = TRUE;
+
return TRUE;
}
@@ -494,6 +509,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
_cogl_span_iter_next (&x_iter),
source_x += inter_w )
{
+ gint slice_num;
+
/* Discard slices out of the subregion early */
if (!x_iter.intersects)
{
@@ -516,10 +533,10 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
local_y = (y_iter.intersect_start -
y_iter.pos);
+ slice_num = y_iter.index * tex->slice_x_spans->len + x_iter.index;
+
/* Pick slice GL handle */
- gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
- y_iter.index * tex->slice_x_spans->len +
- x_iter.index);
+ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num);
/* Setup gl alignment to match rowstride and top-left corner */
prep_for_gl_pixels_upload (source_bmp->rowstride,
@@ -527,6 +544,17 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
source_y,
bpp);
+ /* Keep a copy of the first pixel if needed */
+ if (tex->first_pixels && local_x == 0 && local_y == 0)
+ {
+ memcpy (tex->first_pixels[slice_num].data,
+ source_bmp->data + source_x * bpp
+ + source_y * source_bmp->rowstride,
+ bpp);
+ tex->first_pixels[slice_num].gl_format = source_gl_format;
+ tex->first_pixels[slice_num].gl_type = source_gl_type;
+ }
+
/* Upload new image data */
GE( glBindTexture (tex->gl_target, gl_handle) );
@@ -640,14 +668,16 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
if (waste_buf)
g_free (waste_buf);
+ tex->mipmaps_dirty = TRUE;
+
return TRUE;
}
static gint
-_cogl_rect_slices_for_size (gint size_to_fill,
- gint max_span_size,
- gint max_waste,
- GArray *out_spans)
+_cogl_rect_slices_for_size (gint size_to_fill,
+ gint max_span_size,
+ gint max_waste,
+ GArray *out_spans)
{
gint n_spans = 0;
CoglTexSliceSpan span;
@@ -679,10 +709,10 @@ _cogl_rect_slices_for_size (gint size_to_fill,
}
static gint
-_cogl_pot_slices_for_size (gint size_to_fill,
- gint max_span_size,
- gint max_waste,
- GArray *out_spans)
+_cogl_pot_slices_for_size (gint size_to_fill,
+ gint max_span_size,
+ gint max_waste,
+ GArray *out_spans)
{
gint n_spans = 0;
CoglTexSliceSpan span;
@@ -693,7 +723,8 @@ _cogl_pot_slices_for_size (gint size_to_fill,
span.waste = 0;
/* Fix invalid max_waste */
- if (max_waste < 0) max_waste = 0;
+ if (max_waste < 0)
+ max_waste = 0;
while (TRUE)
{
@@ -826,10 +857,10 @@ _cogl_texture_slices_create (CoglTexture *tex)
/* Check if size supported else bail out */
if (!_cogl_texture_size_supported (tex->gl_target,
- tex->gl_format,
- tex->gl_type,
- max_width,
- max_height))
+ tex->gl_format,
+ tex->gl_type,
+ max_width,
+ max_height))
{
return FALSE;
}
@@ -912,6 +943,14 @@ _cogl_texture_slices_create (CoglTexture *tex)
g_array_set_size (tex->slice_gl_handles, n_slices);
+ /* Allocate some space to store a copy of the first pixel of each
+ slice. This is only needed to glGenerateMipmap (which is part of
+ the FBO extension) is not available */
+ if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
+ tex->first_pixels = NULL;
+ else
+ tex->first_pixels = g_new (CoglTexturePixel, n_slices);
+
/* Wrap mode not yet set */
tex->wrap_mode = GL_FALSE;
@@ -940,14 +979,6 @@ _cogl_texture_slices_create (CoglTexture *tex)
/* Setup texture parameters */
GE( glBindTexture (tex->gl_target,
gl_handles[y * n_x_slices + x]) );
- GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
- tex->mag_filter) );
- GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
- tex->min_filter) );
-
- if (tex->auto_mipmap)
- GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP,
- GL_TRUE) );
/* Use a transparent border color so that we can leave the
color buffer alone when using texture co-ordinates
@@ -984,6 +1015,9 @@ _cogl_texture_slices_free (CoglTexture *tex)
g_array_free (tex->slice_gl_handles, TRUE);
}
+
+ if (tex->first_pixels != NULL)
+ g_free (tex->first_pixels);
}
gboolean
@@ -1199,11 +1233,10 @@ _cogl_texture_free (CoglTexture *tex)
}
CoglHandle
-cogl_texture_new_with_size (guint width,
- guint height,
- gint max_waste,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
+cogl_texture_new_with_size (guint width,
+ guint height,
+ CoglTextureFlags flags,
+ CoglPixelFormat internal_format)
{
CoglTexture *tex;
gint bpp;
@@ -1221,7 +1254,8 @@ cogl_texture_new_with_size (guint width,
tex = (CoglTexture*) g_malloc (sizeof (CoglTexture));
tex->is_foreign = FALSE;
- tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
+ tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
+ tex->mipmaps_dirty = TRUE;
tex->bitmap.width = width;
tex->bitmap.height = height;
@@ -1234,9 +1268,14 @@ cogl_texture_new_with_size (guint width,
tex->slice_y_spans = NULL;
tex->slice_gl_handles = NULL;
- tex->max_waste = max_waste;
- tex->min_filter = COGL_TEXTURE_FILTER_NEAREST;
- tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST;
+ if (flags & COGL_TEXTURE_NO_SLICING)
+ tex->max_waste = -1;
+ else
+ tex->max_waste = COGL_TEXTURE_MAX_WASTE;
+
+ /* Unknown filter */
+ tex->min_filter = GL_FALSE;
+ tex->mag_filter = GL_FALSE;
/* Find closest GL format match */
tex->bitmap.format =
@@ -1258,7 +1297,6 @@ cogl_texture_new_with_size (guint width,
CoglHandle
cogl_texture_new_from_data (guint width,
guint height,
- gint max_waste,
CoglTextureFlags flags,
CoglPixelFormat format,
CoglPixelFormat internal_format,
@@ -1282,7 +1320,8 @@ cogl_texture_new_from_data (guint width,
tex = (CoglTexture*) g_malloc (sizeof (CoglTexture));
tex->is_foreign = FALSE;
- tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
+ tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
+ tex->mipmaps_dirty = TRUE;
tex->bitmap.width = width;
tex->bitmap.height = height;
@@ -1295,9 +1334,14 @@ cogl_texture_new_from_data (guint width,
tex->slice_y_spans = NULL;
tex->slice_gl_handles = NULL;
- tex->max_waste = max_waste;
- tex->min_filter = COGL_TEXTURE_FILTER_NEAREST;
- tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST;
+ if (flags & COGL_TEXTURE_NO_SLICING)
+ tex->max_waste = -1;
+ else
+ tex->max_waste = COGL_TEXTURE_MAX_WASTE;
+
+ /* Unknown filter */
+ tex->min_filter = GL_FALSE;
+ tex->mag_filter = GL_FALSE;
/* FIXME: If upload fails we should set some kind of
* error flag but still return texture handle (this
@@ -1328,10 +1372,9 @@ cogl_texture_new_from_data (guint width,
}
CoglHandle
-cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
- gint max_waste,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
+cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
+ CoglTextureFlags flags,
+ CoglPixelFormat internal_format)
{
CoglTexture *tex;
CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
@@ -1342,7 +1385,8 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture));
tex->is_foreign = FALSE;
- tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
+ tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
+ tex->mipmaps_dirty = TRUE;
tex->bitmap = *bmp;
tex->bitmap_owner = FALSE;
@@ -1351,9 +1395,14 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
tex->slice_y_spans = NULL;
tex->slice_gl_handles = NULL;
- tex->max_waste = max_waste;
- tex->min_filter = COGL_TEXTURE_FILTER_NEAREST;
- tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST;
+ if (flags & COGL_TEXTURE_NO_SLICING)
+ tex->max_waste = -1;
+ else
+ tex->max_waste = COGL_TEXTURE_MAX_WASTE;
+
+ /* Unknown filter */
+ tex->min_filter = GL_FALSE;
+ tex->mag_filter = GL_FALSE;
/* FIXME: If upload fails we should set some kind of
* error flag but still return texture handle if the
@@ -1388,13 +1437,12 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
CoglHandle
cogl_texture_new_from_file (const gchar *filename,
- gint max_waste,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
GError **error)
{
- CoglHandle bmp;
- CoglHandle handle;
+ CoglHandle bmp;
+ CoglHandle handle;
g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
@@ -1402,10 +1450,7 @@ cogl_texture_new_from_file (const gchar *filename,
if (bmp == COGL_INVALID_HANDLE)
return COGL_INVALID_HANDLE;
- handle = cogl_texture_new_from_bitmap (bmp,
- max_waste,
- flags,
- internal_format);
+ handle = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
cogl_handle_unref (bmp);
return handle;
@@ -1433,8 +1478,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
GLint gl_int_format = 0;
GLint gl_width = 0;
GLint gl_height = 0;
- GLint gl_min_filter;
- GLint gl_mag_filter;
GLint gl_gen_mipmap;
guint bpp;
CoglTexture *tex;
@@ -1482,14 +1525,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
GL_TEXTURE_HEIGHT,
&gl_height) );
- GE( glGetTexParameteriv (gl_target,
- GL_TEXTURE_MIN_FILTER,
- &gl_min_filter) );
-
- GE( glGetTexParameteriv (gl_target,
- GL_TEXTURE_MAG_FILTER,
- &gl_mag_filter) );
-
GE( glGetTexParameteriv (gl_target,
GL_GENERATE_MIPMAP,
&gl_gen_mipmap) );
@@ -1508,18 +1543,16 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
return COGL_INVALID_HANDLE;
/* Try and match to a cogl format */
- if (!_cogl_pixel_format_from_gl_internal (gl_int_format,
- &format))
- {
- return COGL_INVALID_HANDLE;
- }
+ if (!_cogl_pixel_format_from_gl_internal (gl_int_format, &format))
+ return COGL_INVALID_HANDLE;
/* Create new texture */
- tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture));
+ tex = (CoglTexture *) g_malloc (sizeof (CoglTexture));
/* Setup bitmap info */
tex->is_foreign = TRUE;
tex->auto_mipmap = (gl_gen_mipmap == GL_TRUE) ? TRUE : FALSE;
+ tex->mipmaps_dirty = TRUE;
bpp = _cogl_get_format_bpp (format);
tex->bitmap.format = format;
@@ -1533,8 +1566,9 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
tex->gl_format = gl_int_format;
tex->gl_type = GL_UNSIGNED_BYTE;
- tex->min_filter = gl_min_filter;
- tex->mag_filter = gl_mag_filter;
+ /* Unknown filter */
+ tex->min_filter = GL_FALSE;
+ tex->mag_filter = GL_FALSE;
tex->max_waste = 0;
/* Wrap mode not yet set */
@@ -1680,36 +1714,10 @@ cogl_texture_get_gl_texture (CoglHandle handle,
return TRUE;
}
-CoglTextureFilter
-cogl_texture_get_min_filter (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return 0;
-
- tex = _cogl_texture_pointer_from_handle (handle);
-
- return tex->min_filter;
-}
-
-CoglTextureFilter
-cogl_texture_get_mag_filter (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return 0;
-
- tex = _cogl_texture_pointer_from_handle (handle);
-
- return tex->mag_filter;
-}
-
void
-cogl_texture_set_filters (CoglHandle handle,
- CoglTextureFilter min_filter,
- CoglTextureFilter mag_filter)
+_cogl_texture_set_filters (CoglHandle handle,
+ GLenum min_filter,
+ GLenum mag_filter)
{
CoglTexture *tex;
GLuint gl_handle;
@@ -1720,14 +1728,18 @@ cogl_texture_set_filters (CoglHandle handle,
tex = _cogl_texture_pointer_from_handle (handle);
- /* Store new values */
- tex->min_filter = min_filter;
- tex->mag_filter = mag_filter;
-
/* Make sure slices were created */
if (tex->slice_gl_handles == NULL)
return;
+ if (min_filter == tex->min_filter
+ && mag_filter == tex->mag_filter)
+ return;
+
+ /* Store new values */
+ tex->min_filter = min_filter;
+ tex->mag_filter = mag_filter;
+
/* Apply new filters to every slice */
for (i=0; islice_gl_handles->len; ++i)
{
@@ -1740,6 +1752,52 @@ cogl_texture_set_filters (CoglHandle handle,
}
}
+void
+_cogl_texture_ensure_mipmaps (CoglHandle handle)
+{
+ CoglTexture *tex;
+ int i;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ if (!cogl_is_texture (handle))
+ return;
+
+ tex = _cogl_texture_pointer_from_handle (handle);
+
+ /* Only update if the mipmaps are dirty */
+ if (!tex->auto_mipmap || !tex->mipmaps_dirty)
+ return;
+
+ /* Make sure slices were created */
+ if (tex->slice_gl_handles == NULL)
+ return;
+
+ /* Regenerate the mipmaps on every slice */
+ for (i = 0; i < tex->slice_gl_handles->len; i++)
+ {
+ GLuint gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i);
+ GE( glBindTexture (tex->gl_target, gl_handle) );
+
+ /* glGenerateMipmap is defined in the FBO extension */
+ if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
+ GE( glGenerateMipmap (tex->gl_target) );
+ else
+ {
+ CoglTexturePixel *pixel = tex->first_pixels + i;
+ /* Temporarily enable automatic mipmap generation and
+ re-upload the first pixel to cause a regeneration */
+ GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_TRUE) );
+ GE( glTexSubImage2D (tex->gl_target, 0, 0, 0, 1, 1,
+ pixel->gl_format, pixel->gl_type,
+ pixel->data) );
+ GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_FALSE) );
+ }
+ }
+
+ tex->mipmaps_dirty = FALSE;
+}
+
gboolean
cogl_texture_set_region (CoglHandle handle,
gint src_x,
diff --git a/gl/cogl.c b/gl/cogl.c
index b2c5417e7..748c082ac 100644
--- a/gl/cogl.c
+++ b/gl/cogl.c
@@ -399,6 +399,10 @@ _cogl_features_init (void)
(COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC)
cogl_get_proc_address ("glDeleteFramebuffersEXT");
+ ctx->pf_glGenerateMipmapEXT =
+ (COGL_PFNGLGENERATEMIPMAPEXTPROC)
+ cogl_get_proc_address ("glGenerateMipmapEXT");
+
if (ctx->pf_glGenRenderbuffersEXT &&
ctx->pf_glBindRenderbufferEXT &&
ctx->pf_glRenderbufferStorageEXT &&
@@ -407,7 +411,8 @@ _cogl_features_init (void)
ctx->pf_glFramebufferTexture2DEXT &&
ctx->pf_glFramebufferRenderbufferEXT &&
ctx->pf_glCheckFramebufferStatusEXT &&
- ctx->pf_glDeleteFramebuffersEXT)
+ ctx->pf_glDeleteFramebuffersEXT &&
+ ctx->pf_glGenerateMipmapEXT)
flags |= COGL_FEATURE_OFFSCREEN;
}
@@ -486,6 +491,23 @@ _cogl_features_init (void)
(COGL_PFNGLCLIENTACTIVETEXTUREPROC)
cogl_get_proc_address ("glClientActiveTexture");
+ ctx->pf_glBlendEquation =
+ (COGL_PFNGLBLENDEQUATIONPROC)
+ cogl_get_proc_address ("glBlendEquation");
+ ctx->pf_glBlendColor =
+ (COGL_PFNGLBLENDCOLORPROC)
+ cogl_get_proc_address ("glBlendColor");
+
+ /* Available in 1.4 */
+ ctx->pf_glBlendFuncSeparate =
+ (COGL_PFNGLBLENDFUNCSEPARATEPROC)
+ cogl_get_proc_address ("glBlendFuncSeparate");
+
+ /* Available in 2.0 */
+ ctx->pf_glBlendEquationSeparate =
+ (COGL_PFNGLBLENDEQUATIONSEPARATEPROC)
+ cogl_get_proc_address ("glBlendEquationSeparate");
+
/* Cache features */
ctx->feature_flags = flags;
ctx->features_cached = TRUE;
diff --git a/gles/Makefile.am b/gles/Makefile.am
index 3f84b4b2f..3ce5365a7 100644
--- a/gles/Makefile.am
+++ b/gles/Makefile.am
@@ -27,12 +27,12 @@ INCLUDES = \
-DG_LOG_DOMAIN=\"Cogl-GLES\" \
-DCLUTTER_COMPILATION
-noinst_LTLIBRARIES = libclutter-cogl.la
+noinst_LTLIBRARIES = libclutter-cogl-gles.la
-libclutter_cogl_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
-libclutter_cogl_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
-libclutter_cogl_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
-libclutter_cogl_la_SOURCES = \
+libclutter_cogl_gles_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
+libclutter_cogl_gles_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
+libclutter_cogl_gles_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
+libclutter_cogl_gles_la_SOURCES = \
$(top_builddir)/clutter/cogl/cogl.h \
$(top_builddir)/clutter/cogl/cogl-defines-gles.h \
$(top_builddir)/clutter/cogl/cogl-color.h \
@@ -60,7 +60,7 @@ libclutter_cogl_la_SOURCES = \
cogl-shader.c
if USE_GLES2_WRAPPER
-libclutter_cogl_la_SOURCES += \
+libclutter_cogl_gles_la_SOURCES += \
cogl-gles2-wrapper.c \
cogl-fixed-vertex-shader.h \
cogl-fixed-vertex-shader.c \
diff --git a/gles/cogl-context.c b/gles/cogl-context.c
index d70d59d35..293ac4689 100644
--- a/gles/cogl-context.c
+++ b/gles/cogl-context.c
@@ -39,7 +39,7 @@
static CoglContext *_context = NULL;
static gboolean gl_is_indirect = FALSE;
-gboolean
+static gboolean
cogl_create_context ()
{
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
@@ -72,7 +72,6 @@ cogl_create_context ()
_context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
_context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat));
- _context->static_indices = g_array_new (FALSE, FALSE, sizeof (GLushort));
_context->polygon_vertices = g_array_new (FALSE, FALSE,
sizeof (CoglTextureGLVertex));
@@ -107,8 +106,7 @@ cogl_create_context ()
_context->default_gl_texture_2d_tex =
cogl_texture_new_from_data (1, /* width */
1, /* height */
- -1, /* max waste */
- COGL_TEXTURE_NONE, /* flags */
+ COGL_TEXTURE_NO_SLICING, /* flags */
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
/* internal format */
COGL_PIXEL_FORMAT_RGBA_8888,
@@ -117,8 +115,7 @@ cogl_create_context ()
_context->default_gl_texture_rect_tex =
cogl_texture_new_from_data (1, /* width */
1, /* height */
- -1, /* max waste */
- COGL_TEXTURE_NONE, /* flags */
+ COGL_TEXTURE_NO_SLICING, /* flags */
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
/* internal format */
COGL_PIXEL_FORMAT_RGBA_8888,
@@ -126,16 +123,20 @@ cogl_create_context ()
default_texture_data);
cogl_set_source (_context->default_material);
- cogl_material_flush_gl_state (_context->source_material, NULL);
+ _cogl_material_flush_gl_state (_context->source_material, NULL);
enable_flags =
- cogl_material_get_cogl_enable_flags (_context->source_material);
+ _cogl_material_get_cogl_enable_flags (_context->source_material);
cogl_enable (enable_flags);
+ _context->quad_indices_byte = COGL_INVALID_HANDLE;
+ _context->quad_indices_short = COGL_INVALID_HANDLE;
+ _context->quad_indices_short_len = 0;
+
return TRUE;
}
void
-cogl_destroy_context ()
+_cogl_destroy_context ()
{
if (_context == NULL)
return;
@@ -160,13 +161,16 @@ cogl_destroy_context ()
if (_context->logged_vertices)
g_array_free (_context->logged_vertices, TRUE);
- if (_context->static_indices)
- g_array_free (_context->static_indices, TRUE);
if (_context->polygon_vertices)
g_array_free (_context->polygon_vertices, TRUE);
if (_context->current_layers)
g_array_free (_context->current_layers, TRUE);
+ if (_context->quad_indices_byte)
+ cogl_handle_unref (_context->quad_indices_byte);
+ if (_context->quad_indices_short)
+ cogl_handle_unref (_context->quad_indices_short);
+
g_free (_context);
}
diff --git a/gles/cogl-context.h b/gles/cogl-context.h
index 3542e038d..2e39f2bc0 100644
--- a/gles/cogl-context.h
+++ b/gles/cogl-context.h
@@ -80,7 +80,6 @@ typedef struct
* can batch things together. */
GArray *journal;
GArray *logged_vertices;
- GArray *static_indices;
GArray *polygon_vertices;
/* Some simple caching, to minimize state changes... */
@@ -104,6 +103,12 @@ typedef struct
floatVec2 path_nodes_max;
CoglHandle stencil_material;
+ /* Pre-generated VBOs containing indices to generate GL_TRIANGLES
+ out of a vertex array of quads */
+ CoglHandle quad_indices_byte;
+ guint quad_indices_short_len;
+ CoglHandle quad_indices_short;
+
#ifdef HAVE_COGL_GLES2
CoglGles2Wrapper gles2;
@@ -111,7 +116,6 @@ typedef struct
supported */
GLint viewport_store[4];
#endif
-
} CoglContext;
CoglContext *
diff --git a/gles/cogl-gles2-wrapper.c b/gles/cogl-gles2-wrapper.c
index 523676dd2..979ade598 100644
--- a/gles/cogl-gles2-wrapper.c
+++ b/gles/cogl-gles2-wrapper.c
@@ -89,13 +89,13 @@ cogl_gles2_wrapper_create_shader (GLenum type, const char *source)
if (!status)
{
- char log[1024];
+ char shader_log[1024];
GLint len;
- glGetShaderInfoLog (shader, sizeof (log) - 1, &len, log);
- log[len] = '\0';
+ glGetShaderInfoLog (shader, sizeof (shader_log) - 1, &len, shader_log);
+ shader_log[len] = '\0';
- g_critical ("%s", log);
+ g_critical ("%s", shader_log);
glDeleteShader (shader);
@@ -538,9 +538,9 @@ cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings)
CoglShader *shader
= _cogl_shader_pointer_from_handle ((CoglHandle) node->data);
- if (shader->type == CGL_VERTEX_SHADER)
+ if (shader->type == COGL_SHADER_TYPE_VERTEX)
custom_vertex_shader = TRUE;
- else if (shader->type == CGL_FRAGMENT_SHADER)
+ else if (shader->type == COGL_SHADER_TYPE_FRAGMENT)
custom_fragment_shader = TRUE;
}
}
@@ -581,13 +581,13 @@ cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings)
if (!status)
{
- char log[1024];
+ char shader_log[1024];
GLint len;
- glGetProgramInfoLog (program->program, sizeof (log) - 1, &len, log);
- log[len] = '\0';
+ glGetProgramInfoLog (program->program, sizeof (shader_log) - 1, &len, shader_log);
+ shader_log[len] = '\0';
- g_critical ("%s", log);
+ g_critical ("%s", shader_log);
glDeleteProgram (program->program);
g_slice_free (CoglGles2WrapperProgram, program);
@@ -1300,13 +1300,20 @@ cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture,
}
void
-cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLfloat param)
+cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLint param)
{
/* This function is only used to set the texture mode once to
GL_MODULATE. The shader is hard-coded to modulate the texture so
nothing needs to be done here. */
}
+void
+cogl_wrap_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params)
+{
+ /* FIXME: Currently needed to support texture combining using
+ * COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT */
+}
+
void
cogl_wrap_glClientActiveTexture (GLenum texture)
{
diff --git a/gles/cogl-gles2-wrapper.h b/gles/cogl-gles2-wrapper.h
index bd7f6d978..51bee2d5c 100644
--- a/gles/cogl-gles2-wrapper.h
+++ b/gles/cogl-gles2-wrapper.h
@@ -259,6 +259,7 @@ struct _CoglGles2WrapperShader
#define GL_TEXTURE_ENV 0x2300
#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_ENV_COLOR 0x2201
#define GL_MODULATE 0x2100
#define GL_EXP 0x8000
@@ -327,7 +328,8 @@ void cogl_wrap_glColorPointer (GLint size, GLenum type, GLsizei stride,
void cogl_wrap_glNormalPointer (GLenum type, GLsizei stride,
const GLvoid *pointer);
-void cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLfloat param);
+void cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLint param);
+void cogl_wrap_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params);
void cogl_wrap_glClientActiveTexture (GLenum texture);
void cogl_wrap_glActiveTexture (GLenum texture);
@@ -384,6 +386,7 @@ void _cogl_gles2_clear_cache_for_program (CoglHandle program);
#define glColorPointer cogl_wrap_glColorPointer
#define glNormalPointer cogl_wrap_glNormalPointer
#define glTexEnvi cogl_wrap_glTexEnvi
+#define glTexEnvfv cogl_wrap_glTexEnvfv
#define glActiveTexture cogl_wrap_glActiveTexture
#define glClientActiveTexture cogl_wrap_glClientActiveTexture
#define glEnableClientState cogl_wrap_glEnableClientState
diff --git a/gles/cogl-primitives.c b/gles/cogl-primitives.c
index 1e03e1ea2..d8dee0ba6 100644
--- a/gles/cogl-primitives.c
+++ b/gles/cogl-primitives.c
@@ -29,6 +29,7 @@
#include "cogl-internal.h"
#include "cogl-context.h"
#include "cogl-clip-stack.h"
+#include "cogl-material-private.h"
#include
#include
@@ -78,13 +79,13 @@ _cogl_path_stroke_nodes ()
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
- enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material);
+ enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
cogl_enable (enable_flags);
- cogl_material_flush_gl_state (ctx->source_material,
- COGL_MATERIAL_FLUSH_DISABLE_MASK,
- (guint32)~0, /* disable all texture layers */
- NULL);
+ _cogl_material_flush_gl_state (ctx->source_material,
+ COGL_MATERIAL_FLUSH_DISABLE_MASK,
+ (guint32)~0, /* disable all texture layers */
+ NULL);
_cogl_current_matrix_state_flush ();
while (path_start < ctx->path_nodes->len)
@@ -139,10 +140,10 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* Just setup a simple material that doesn't use texturing... */
- cogl_material_flush_gl_state (ctx->stencil_material, NULL);
+ _cogl_material_flush_gl_state (ctx->stencil_material, NULL);
enable_flags |=
- cogl_material_get_cogl_enable_flags (ctx->source_material);
+ _cogl_material_get_cogl_enable_flags (ctx->source_material);
cogl_enable (enable_flags);
_cogl_path_get_bounds (nodes_min, nodes_max,
@@ -361,30 +362,30 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
while (iter)
{
GSList *next = iter->next;
- GLfloat x0, x1;
- GLfloat y0, y1;
+ GLfloat x_0, x_1;
+ GLfloat y_0, y_1;
if (!next)
break;
- x0 = GPOINTER_TO_INT (iter->data);
- x1 = GPOINTER_TO_INT (next->data);
- y0 = bounds_y + i;
- y1 = bounds_y + i + 1.0625f;
+ x_0 = GPOINTER_TO_INT (iter->data);
+ x_1 = GPOINTER_TO_INT (next->data);
+ y_0 = bounds_y + i;
+ y_1 = bounds_y + i + 1.0625f;
/* render scanlines 1.0625 high to avoid gaps when
transformed */
- coords[span_no * 12 + 0] = x0;
- coords[span_no * 12 + 1] = y0;
- coords[span_no * 12 + 2] = x1;
- coords[span_no * 12 + 3] = y0;
- coords[span_no * 12 + 4] = x1;
- coords[span_no * 12 + 5] = y1;
- coords[span_no * 12 + 6] = x0;
- coords[span_no * 12 + 7] = y0;
- coords[span_no * 12 + 8] = x0;
- coords[span_no * 12 + 9] = y1;
- coords[span_no * 12 + 10] = x1;
- coords[span_no * 12 + 11] = y1;
+ coords[span_no * 12 + 0] = x_0;
+ coords[span_no * 12 + 1] = y_0;
+ coords[span_no * 12 + 2] = x_1;
+ coords[span_no * 12 + 3] = y_0;
+ coords[span_no * 12 + 4] = x_1;
+ coords[span_no * 12 + 5] = y_1;
+ coords[span_no * 12 + 6] = x_0;
+ coords[span_no * 12 + 7] = y_0;
+ coords[span_no * 12 + 8] = x_0;
+ coords[span_no * 12 + 9] = y_1;
+ coords[span_no * 12 + 10] = x_1;
+ coords[span_no * 12 + 11] = y_1;
span_no ++;
iter = next->next;
}
diff --git a/gles/cogl-shader.c b/gles/cogl-shader.c
index ff5f0c58a..23109be34 100644
--- a/gles/cogl-shader.c
+++ b/gles/cogl-shader.c
@@ -99,22 +99,23 @@ cogl_shader_compile (CoglHandle handle)
glCompileShader (shader->gl_handle);
}
-void
-cogl_shader_get_info_log (CoglHandle handle,
- size_t size,
- char *buffer)
+gchar *
+cogl_shader_get_info_log (CoglHandle handle)
{
CoglShader *shader;
+ char buffer[512];
int len = 0;
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+ _COGL_GET_CONTEXT (ctx, NULL);
if (!cogl_is_shader (handle))
- return;
+ return NULL;
shader = _cogl_shader_pointer_from_handle (handle);
- glGetShaderInfoLog (shader->gl_handle, size - 1, &len, buffer);
+ glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
buffer[len] = '\0';
+
+ return g_strdup (buffer);
}
CoglShaderType
@@ -199,11 +200,10 @@ cogl_shader_compile (CoglHandle shader_handle)
{
}
-void
-cogl_shader_get_info_log (CoglHandle handle,
- size_t size,
- char *buffer)
+gchar *
+cogl_shader_get_info_log (CoglHandle handle)
{
+ return NULL;
}
CoglShaderType
diff --git a/gles/cogl-texture-private.h b/gles/cogl-texture-private.h
index 7cf6fe951..365a47921 100644
--- a/gles/cogl-texture-private.h
+++ b/gles/cogl-texture-private.h
@@ -30,6 +30,7 @@
typedef struct _CoglTexture CoglTexture;
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
typedef struct _CoglSpanIter CoglSpanIter;
+typedef struct _CoglTexturePixel CoglTexturePixel;
struct _CoglTexSliceSpan
{
@@ -55,6 +56,18 @@ struct _CoglSpanIter
gboolean intersects;
};
+/* This is used to store the first pixel of each slice. This is only
+ used when glGenerateMipmap is not available */
+struct _CoglTexturePixel
+{
+ /* We need to store the format of the pixel because we store the
+ data in the source format which might end up being different for
+ each slice if a subregion is updated with a different format */
+ GLenum gl_format;
+ GLenum gl_type;
+ guint8 data[4];
+};
+
struct _CoglTexture
{
CoglHandleObject _parent;
@@ -68,11 +81,17 @@ struct _CoglTexture
GArray *slice_y_spans;
GArray *slice_gl_handles;
gint max_waste;
- CoglTextureFilter min_filter;
- CoglTextureFilter mag_filter;
+ GLenum min_filter;
+ GLenum mag_filter;
gboolean is_foreign;
GLint wrap_mode;
gboolean auto_mipmap;
+ gboolean mipmaps_dirty;
+
+ /* This holds a copy of the first pixel in each slice. It is only
+ used to force an automatic update of the mipmaps when
+ glGenerateMipmap is not available. */
+ CoglTexturePixel *first_pixels;
};
/* To improve batching of geometry when submitting vertices to OpenGL we
@@ -93,6 +112,14 @@ void
_cogl_texture_set_wrap_mode_parameter (CoglTexture *tex,
GLenum wrap_mode);
+void
+_cogl_texture_set_filters (CoglHandle handle,
+ GLenum min_filter,
+ GLenum mag_filter);
+
+void
+_cogl_texture_ensure_mipmaps (CoglHandle handle);
+
gboolean
_cogl_texture_span_has_waste (CoglTexture *tex,
gint x_span_index,
diff --git a/gles/cogl-texture.c b/gles/cogl-texture.c
index 1564faf2a..1929184c0 100644
--- a/gles/cogl-texture.c
+++ b/gles/cogl-texture.c
@@ -225,11 +225,12 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
/* Iterate horizontal slices */
for (x = 0; x < tex->slice_x_spans->len; ++x)
{
+ gint slice_num = y * tex->slice_x_spans->len + x;
+
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x);
/* Pick the gl texture object handle */
- gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
- y * tex->slice_x_spans->len + x);
+ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num);
/* FIXME: might optimize by not copying to intermediate slice
bitmap when source rowstride = bpp * width and the texture
@@ -258,6 +259,16 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
slice_bmp.width,
slice_bmp.height);
+ /* Keep a copy of the first pixel if needed */
+ if (tex->first_pixels)
+ {
+ memcpy (tex->first_pixels[slice_num].data,
+ slice_bmp.data,
+ bpp);
+ tex->first_pixels[slice_num].gl_format = tex->gl_format;
+ tex->first_pixels[slice_num].gl_type = tex->gl_type;
+ }
+
/* Upload new image data */
GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle,
tex->gl_intformat) );
@@ -338,9 +349,6 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
waste_buf) );
}
- if (tex->auto_mipmap)
- cogl_wrap_glGenerateMipmap (tex->gl_target);
-
/* Free temp bitmap */
g_free (slice_bmp.data);
}
@@ -349,6 +357,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
if (waste_buf)
g_free (waste_buf);
+ tex->mipmaps_dirty = TRUE;
+
return TRUE;
}
@@ -442,6 +452,7 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
gint bpp;
GLint viewport[4];
CoglBitmap alpha_bmp;
+ CoglHandle prev_source;
_COGL_GET_CONTEXT (ctx, FALSE);
@@ -477,31 +488,21 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
if (ctx->texture_download_material == COGL_INVALID_HANDLE)
{
ctx->texture_download_material = cogl_material_new ();
- cogl_material_set_layer_combine_function (
- ctx->texture_download_material,
- 0, /* layer */
- COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
- COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE);
- cogl_material_set_layer_combine_arg_src (
- ctx->texture_download_material,
- 0, /* layer */
- 0, /* arg */
- COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
- COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE);
- cogl_material_set_blend_factors (ctx->texture_download_material,
- COGL_MATERIAL_BLEND_FACTOR_ONE,
- COGL_MATERIAL_BLEND_FACTOR_ZERO);
+ cogl_material_set_blend (ctx->texture_download_material,
+ "RGBA = ADD (SRC_COLOR, 0)",
+ NULL);
}
+ prev_source = cogl_handle_ref (ctx->source_material);
+ cogl_set_source (ctx->texture_download_material);
+
cogl_material_set_layer (ctx->texture_download_material, 0, tex);
- cogl_material_set_layer_combine_arg_op (
- ctx->texture_download_material,
- 0, /* layer */
- 0, /* arg */
- COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
- COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR);
- cogl_material_flush_gl_state (ctx->texture_download_material, NULL);
+ cogl_material_set_layer_combine (ctx->texture_download_material,
+ 0, /* layer */
+ "RGBA = REPLACE (TEXTURE)",
+ NULL);
+
_cogl_texture_draw_and_read (tex, target_bmp, viewport);
/* Check whether texture has alpha and framebuffer not */
@@ -534,13 +535,11 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
alpha_bmp.height);
/* Draw alpha values into RGB channels */
- cogl_material_set_layer_combine_arg_op (
- ctx->texture_download_material,
- 0, /* layer */
- 0, /* arg */
- COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
- COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA);
- cogl_material_flush_gl_state (ctx->texture_download_material, NULL);
+ cogl_material_set_layer_combine (ctx->texture_download_material,
+ 0, /* layer */
+ "RGBA = REPLACE (TEXTURE[A])",
+ NULL);
+
_cogl_texture_draw_and_read (tex, &alpha_bmp, viewport);
/* Copy temp R to target A */
@@ -568,6 +567,10 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
_cogl_current_matrix_pop ();
+ /* restore the original material */
+ cogl_set_source (prev_source);
+ cogl_handle_unref (prev_source);
+
return TRUE;
}
@@ -631,6 +634,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
_cogl_span_iter_next (&x_iter),
source_x += inter_w )
{
+ gint slice_num;
+
/* Discard slices out of the subregion early */
if (!x_iter.intersects)
{
@@ -653,10 +658,10 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
local_y = (y_iter.intersect_start -
y_iter.pos);
+ slice_num = y_iter.index * tex->slice_x_spans->len + x_iter.index;
+
/* Pick slice GL handle */
- gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
- y_iter.index * tex->slice_x_spans->len +
- x_iter.index);
+ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num);
/* FIXME: might optimize by not copying to intermediate slice
bitmap when source rowstride = bpp * width and the texture
@@ -685,6 +690,15 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
slice_bmp.width,
slice_bmp.height);
+ /* Keep a copy of the first pixel if needed */
+ if (tex->first_pixels && local_x == 0 && local_y == 0)
+ {
+ memcpy (tex->first_pixels[slice_num].data,
+ slice_bmp.data, bpp);
+ tex->first_pixels[slice_num].gl_format = source_gl_format;
+ tex->first_pixels[slice_num].gl_type = source_gl_type;
+ }
+
/* Upload new image data */
GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle,
tex->gl_intformat) );
@@ -794,9 +808,6 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
waste_buf) );
}
- if (tex->auto_mipmap)
- cogl_wrap_glGenerateMipmap (tex->gl_target);
-
/* Free temp bitmap */
g_free (slice_bmp.data);
}
@@ -805,6 +816,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
if (waste_buf)
g_free (waste_buf);
+ tex->mipmaps_dirty = TRUE;
+
return TRUE;
}
@@ -858,7 +871,8 @@ _cogl_pot_slices_for_size (gint size_to_fill,
span.waste = 0;
/* Fix invalid max_waste */
- if (max_waste < 0) max_waste = 0;
+ if (max_waste < 0)
+ max_waste = 0;
while (TRUE)
{
@@ -866,7 +880,9 @@ _cogl_pot_slices_for_size (gint size_to_fill,
if (size_to_fill > span.size)
{
/* Not yet - add a span of this size */
- if (out_spans) g_array_append_val (out_spans, span);
+ if (out_spans)
+ g_array_append_val (out_spans, span);
+
span.start += span.size;
size_to_fill -= span.size;
n_spans++;
@@ -875,7 +891,9 @@ _cogl_pot_slices_for_size (gint size_to_fill,
{
/* Yes and waste is small enough */
span.waste = span.size - size_to_fill;
- if (out_spans) g_array_append_val (out_spans, span);
+ if (out_spans)
+ g_array_append_val (out_spans, span);
+
return ++n_spans;
}
else
@@ -971,10 +989,10 @@ _cogl_texture_slices_create (CoglTexture *tex)
/* Check if size supported else bail out */
if (!_cogl_texture_size_supported (tex->gl_target,
- tex->gl_format,
- tex->gl_type,
- max_width,
- max_height))
+ tex->gl_format,
+ tex->gl_type,
+ max_width,
+ max_height))
{
return FALSE;
}
@@ -1057,6 +1075,14 @@ _cogl_texture_slices_create (CoglTexture *tex)
g_array_set_size (tex->slice_gl_handles, n_slices);
+ /* Allocate some space to store a copy of the first pixel of each
+ slice. This is only needed to glGenerateMipmap (which is part of
+ the FBO extension) is not available */
+ if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
+ tex->first_pixels = NULL;
+ else
+ tex->first_pixels = g_new (CoglTexturePixel, n_slices);
+
/* Wrap mode not yet set */
tex->wrap_mode = GL_FALSE;
@@ -1087,20 +1113,11 @@ _cogl_texture_slices_create (CoglTexture *tex)
GE( cogl_gles2_wrapper_bind_texture (tex->gl_target,
gl_handles[y * n_x_slices + x],
tex->gl_intformat) );
- GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
- tex->mag_filter) );
- GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
- tex->min_filter) );
-
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S,
tex->wrap_mode) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T,
tex->wrap_mode) );
- if (tex->auto_mipmap)
- GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP,
- GL_TRUE) );
-
/* Pass NULL data to init size and internal format */
GE( glTexImage2D (tex->gl_target, 0, tex->gl_intformat,
x_span->size, y_span->size, 0,
@@ -1130,6 +1147,9 @@ _cogl_texture_slices_free (CoglTexture *tex)
g_array_free (tex->slice_gl_handles, TRUE);
}
+
+ if (tex->first_pixels != NULL)
+ g_free (tex->first_pixels);
}
gboolean
@@ -1288,11 +1308,10 @@ _cogl_texture_free (CoglTexture *tex)
}
CoglHandle
-cogl_texture_new_with_size (guint width,
- guint height,
- gint max_waste,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
+cogl_texture_new_with_size (guint width,
+ guint height,
+ CoglTextureFlags flags,
+ CoglPixelFormat internal_format)
{
CoglTexture *tex;
gint bpp;
@@ -1310,7 +1329,8 @@ cogl_texture_new_with_size (guint width,
tex = (CoglTexture*) g_malloc (sizeof (CoglTexture));
tex->is_foreign = FALSE;
- tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
+ tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
+ tex->mipmaps_dirty = TRUE;
tex->bitmap.width = width;
tex->bitmap.height = height;
@@ -1323,9 +1343,14 @@ cogl_texture_new_with_size (guint width,
tex->slice_y_spans = NULL;
tex->slice_gl_handles = NULL;
- tex->max_waste = max_waste;
- tex->min_filter = CGL_NEAREST;
- tex->mag_filter = CGL_NEAREST;
+ if (flags & COGL_TEXTURE_NO_SLICING)
+ tex->max_waste = -1;
+ else
+ tex->max_waste = COGL_TEXTURE_MAX_WASTE;
+
+ /* Unknown filter */
+ tex->min_filter = GL_FALSE;
+ tex->mag_filter = GL_FALSE;
/* Find closest GL format match */
tex->bitmap.format =
@@ -1347,7 +1372,6 @@ cogl_texture_new_with_size (guint width,
CoglHandle
cogl_texture_new_from_data (guint width,
guint height,
- gint max_waste,
CoglTextureFlags flags,
CoglPixelFormat format,
CoglPixelFormat internal_format,
@@ -1371,7 +1395,8 @@ cogl_texture_new_from_data (guint width,
tex = (CoglTexture*) g_malloc (sizeof (CoglTexture));
tex->is_foreign = FALSE;
- tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
+ tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
+ tex->mipmaps_dirty = TRUE;
tex->bitmap.width = width;
tex->bitmap.height = height;
@@ -1384,9 +1409,14 @@ cogl_texture_new_from_data (guint width,
tex->slice_y_spans = NULL;
tex->slice_gl_handles = NULL;
- tex->max_waste = max_waste;
- tex->min_filter = CGL_NEAREST;
- tex->mag_filter = CGL_NEAREST;
+ if (flags & COGL_TEXTURE_NO_SLICING)
+ tex->max_waste = -1;
+ else
+ tex->max_waste = COGL_TEXTURE_MAX_WASTE;
+
+ /* Unknown filter */
+ tex->min_filter = GL_FALSE;
+ tex->mag_filter = GL_FALSE;
/* FIXME: If upload fails we should set some kind of
* error flag but still return texture handle (this
@@ -1417,10 +1447,9 @@ cogl_texture_new_from_data (guint width,
}
CoglHandle
-cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
- gint max_waste,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
+cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
+ CoglTextureFlags flags,
+ CoglPixelFormat internal_format)
{
CoglTexture *tex;
CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
@@ -1429,7 +1458,8 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture));
tex->is_foreign = FALSE;
- tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
+ tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
+ tex->mipmaps_dirty = TRUE;
tex->bitmap = *bmp;
tex->bitmap_owner = TRUE;
@@ -1439,9 +1469,14 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
tex->slice_y_spans = NULL;
tex->slice_gl_handles = NULL;
- tex->max_waste = max_waste;
- tex->min_filter = CGL_NEAREST;
- tex->mag_filter = CGL_NEAREST;
+ if (flags & COGL_TEXTURE_NO_SLICING)
+ tex->max_waste = -1;
+ else
+ tex->max_waste = COGL_TEXTURE_MAX_WASTE;
+
+ /* Unknown filter */
+ tex->min_filter = GL_FALSE;
+ tex->mag_filter = GL_FALSE;
/* FIXME: If upload fails we should set some kind of
* error flag but still return texture handle if the
@@ -1476,7 +1511,6 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
CoglHandle
cogl_texture_new_from_file (const gchar *filename,
- gint max_waste,
CoglTextureFlags flags,
CoglPixelFormat internal_format,
GError **error)
@@ -1490,10 +1524,7 @@ cogl_texture_new_from_file (const gchar *filename,
if (bmp == COGL_INVALID_HANDLE)
return COGL_INVALID_HANDLE;
- handle = cogl_texture_new_from_bitmap (bmp,
- max_waste,
- flags,
- internal_format);
+ handle = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
cogl_handle_unref (bmp);
return handle;
@@ -1521,8 +1552,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
GLint gl_int_format = 0;
GLint gl_width = 0;
GLint gl_height = 0;
- GLint gl_min_filter;
- GLint gl_mag_filter;
GLint gl_gen_mipmap;
guint bpp;
CoglTexture *tex;
@@ -1569,14 +1598,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
gl_height = height + y_pot_waste;
#endif
- GE( glGetTexParameteriv (gl_target,
- GL_TEXTURE_MIN_FILTER,
- &gl_min_filter) );
-
- GE( glGetTexParameteriv (gl_target,
- GL_TEXTURE_MAG_FILTER,
- &gl_mag_filter) );
-
GE( glGetTexParameteriv (gl_target,
GL_GENERATE_MIPMAP,
&gl_gen_mipmap) );
@@ -1607,6 +1628,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
/* Setup bitmap info */
tex->is_foreign = TRUE;
tex->auto_mipmap = (gl_gen_mipmap == GL_TRUE) ? TRUE : FALSE;
+ tex->mipmaps_dirty = TRUE;
bpp = _cogl_get_format_bpp (format);
tex->bitmap.format = format;
@@ -1620,8 +1642,9 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
tex->gl_format = gl_int_format;
tex->gl_type = GL_UNSIGNED_BYTE;
- tex->min_filter = gl_min_filter;
- tex->mag_filter = gl_mag_filter;
+ /* Unknown filter */
+ tex->min_filter = GL_FALSE;
+ tex->mag_filter = GL_FALSE;
tex->max_waste = 0;
/* Wrap mode not yet set */
@@ -1767,36 +1790,10 @@ cogl_texture_get_gl_texture (CoglHandle handle,
return TRUE;
}
-CoglTextureFilter
-cogl_texture_get_min_filter (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return 0;
-
- tex = _cogl_texture_pointer_from_handle (handle);
-
- return tex->min_filter;
-}
-
-CoglTextureFilter
-cogl_texture_get_mag_filter (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return 0;
-
- tex = _cogl_texture_pointer_from_handle (handle);
-
- return tex->mag_filter;
-}
-
void
-cogl_texture_set_filters (CoglHandle handle,
- CoglTextureFilter min_filter,
- CoglTextureFilter mag_filter)
+_cogl_texture_set_filters (CoglHandle handle,
+ GLenum min_filter,
+ GLenum mag_filter)
{
CoglTexture *tex;
GLuint gl_handle;
@@ -1807,14 +1804,18 @@ cogl_texture_set_filters (CoglHandle handle,
tex = _cogl_texture_pointer_from_handle (handle);
- /* Store new values */
- tex->min_filter = min_filter;
- tex->mag_filter = mag_filter;
-
/* Make sure slices were created */
if (tex->slice_gl_handles == NULL)
return;
+ if (min_filter == tex->min_filter
+ && mag_filter == tex->mag_filter)
+ return;
+
+ /* Store new values */
+ tex->min_filter = min_filter;
+ tex->mag_filter = mag_filter;
+
/* Apply new filters to every slice */
for (i=0; islice_gl_handles->len; ++i)
{
@@ -1827,6 +1828,52 @@ cogl_texture_set_filters (CoglHandle handle,
}
}
+void
+_cogl_texture_ensure_mipmaps (CoglHandle handle)
+{
+ CoglTexture *tex;
+ int i;
+
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ if (!cogl_is_texture (handle))
+ return;
+
+ tex = _cogl_texture_pointer_from_handle (handle);
+
+ /* Only update if the mipmaps are dirty */
+ if (!tex->auto_mipmap || !tex->mipmaps_dirty)
+ return;
+
+ /* Make sure slices were created */
+ if (tex->slice_gl_handles == NULL)
+ return;
+
+ /* Regenerate the mipmaps on every slice */
+ for (i = 0; i < tex->slice_gl_handles->len; i++)
+ {
+ GLuint gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i);
+ GE( glBindTexture (tex->gl_target, gl_handle) );
+
+ /* glGenerateMipmap is defined in the FBO extension */
+ if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
+ GE( cogl_wrap_glGenerateMipmap (tex->gl_target) );
+ else
+ {
+ CoglTexturePixel *pixel = tex->first_pixels + i;
+ /* Temporarily enable automatic mipmap generation and
+ re-upload the first pixel to cause a regeneration */
+ GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_TRUE) );
+ GE( glTexSubImage2D (tex->gl_target, 0, 0, 0, 1, 1,
+ pixel->gl_format, pixel->gl_type,
+ pixel->data) );
+ GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_FALSE) );
+ }
+ }
+
+ tex->mipmaps_dirty = FALSE;
+}
+
gboolean
cogl_texture_set_region (CoglHandle handle,
gint src_x,