Merge branch 'cogl-material'

Conflicts:

	clutter/cogl/gl/cogl-texture.c
	clutter/cogl/gles/cogl-primitives.c

* cogl-material:
 clutter-{clone-,}texture weren't updating their material opacity.
 Updates GLES1 support for CoglMaterial
 Normalizes gl vs gles code in preperation for synching material changes
 Removes cogl_blend_func and cogl_alpha_func
 Fully integrates CoglMaterial throughout the rest of Cogl
 [cogl-material] Restore the GL_TEXTURE_ENV_MODE after material_rectangle
 [cogl-material] Make the user_tex_coords parameter of _rectangle const
 [test-cogl-material] Remove return value from material_rectangle_paint
 Add cogl-material.h and cogl-matrix.h to libclutterinclude_HEADERS
 [cogl-material] improvements for cogl_material_rectangle
 [cogl-material] Adds a cogl_material_set_color function
 [cogl-material] Some improvements for how we sync CoglMaterial state with OpenGL
 [cogl-material] Converts clutter-texture/clutter-clone-texture to the material API
 [doc] Hooks up cogl-material reference documentation
 Updates previous GLES multi-texturing code to use CoglMaterial
 Adds a CoglMaterial abstraction, which includes support for multi-texturing
 [doc] Hooks up cogl-matrix reference documentation
 Adds CoglMatrix utility code
 [tests] Adds an interactive unit test for multi-texturing
 [multi-texturing] This adds a new cogl_multi_texture API for GL,GLES1 + GLES2
This commit is contained in:
Robert Bragg 2009-01-27 15:19:34 +00:00
commit 323eaf3fb3
37 changed files with 6155 additions and 1950 deletions

837
cogl-material.h Normal file
View File

@ -0,0 +1,837 @@
#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <cogl/cogl.h> can be included directly."
#endif
#ifndef __COGL_MATERIAL_H__
#define __COGL_MATERIAL_H__
G_BEGIN_DECLS
#include <cogl/cogl-types.h>
#include <cogl/cogl-matrix.h>
/**
* SECTION:cogl-material
* @short_description: Fuctions for creating and manipulating materials
*
* COGL allows creating and manipulating materials used to fill in
* geometry. Materials may simply be lighting attributes (such as an
* ambient and diffuse colour) or might represent one or more textures
* blended together.
*/
/**
* cogl_material_new:
*
* Allocates and initializes a blank white material
*
* Returns: a handle to the new material
*/
CoglHandle cogl_material_new (void);
/**
* cogl_material_ref:
* @handle: a @CoglHandle.
*
* Increment the reference count for a cogl material.
*
* Returns: the @handle.
*
* Since 1.0
*/
CoglHandle cogl_material_ref (CoglHandle handle);
/**
* cogl_material_unref:
* @handle: a @CoglHandle.
*
* Decrement the reference count for a cogl material.
*
* Since 1.0
*/
void cogl_material_unref (CoglHandle handle);
/**
* cogl_material_set_color:
* @material: A CoglMaterial object
* @color: The components of the color
*
* This is the basic color of the material, used when no lighting is enabled.
*
* The default value is (1.0, 1.0, 1.0, 1.0)
*
* Since 1.0
*/
void cogl_material_set_color (CoglHandle material, const CoglColor *color);
/**
* cogl_material_set_color:
* @material: A CoglMaterial object
* @red: The red component
* @green: The green component
* @blue: The blue component
* @alpha: The alpha component
*
* This is the basic color of the material, used when no lighting is enabled.
*
* The default value is (1.0, 1.0, 1.0, 1.0)
*
* Since 1.0
*/
void cogl_material_set_color4ub (CoglHandle handle,
guint8 red,
guint8 green,
guint8 blue,
guint8 alpha);
/**
* cogl_material_get_color:
* @material: A CoglMaterial object
* @color: The location to store the color
*
* This retrieves the current material color.
*
* Since 1.0
*/
void cogl_material_get_color (CoglHandle handle, CoglColor *color);
/**
* cogl_material_set_ambient:
* @material: A CoglMaterial object
* @ambient: The components of the desired ambient color
*
* Exposing the standard OpenGL lighting model; this function sets
* the material's ambient color. The ambient color affects the overall
* color of the object. Since the diffuse color will be intense when
* the light hits the surface directly, the ambient will most aparent
* where the light hits at a slant.
*
* The default value is (0.2, 0.2, 0.2, 1.0)
*
* Since 1.0
*/
void cogl_material_set_ambient (CoglHandle material,
const CoglColor *ambient);
/**
* cogl_material_get_ambient:
* @material: A CoglMaterial object
* @ambient: The location to store the ambient color
*
* This retrieves the materials current ambient color.
*
* Since 1.0
*/
void cogl_material_get_ambient (CoglHandle handle, CoglColor *ambient);
/**
* cogl_material_set_diffuse:
* @material: A CoglMaterial object
* @diffuse: The components of the desired diffuse color
*
* Exposing the standard OpenGL lighting model; this function sets
* the material's diffuse color. The diffuse color is most intense
* where the light hits the surface directly; perpendicular to the
* surface.
*
* The default value is (0.8, 0.8, 0.8, 1.0)
*
* Since 1.0
*/
void cogl_material_set_diffuse (CoglHandle material,
const CoglColor *diffuse);
/**
* cogl_material_get_diffuse:
* @material: A CoglMaterial object
* @diffuse: The location to store the diffuse color
*
* This retrieves the materials current diffuse color.
*
* Since 1.0
*/
void cogl_material_get_diffuse (CoglHandle handle, CoglColor *diffuse);
/**
* cogl_material_set_ambient_and_diffuse:
* @material: A CoglMaterial object
* @color: The components of the desired ambient and diffuse colors
*
* This is a convenience for setting the diffuse and ambient color
* of the material at the same time.
*
* The default ambient color is (0.2, 0.2, 0.2, 1.0)
* The default diffuse color is (0.8, 0.8, 0.8, 1.0)
*
* Since 1.0
*/
void cogl_material_set_ambient_and_diffuse (CoglHandle material,
const CoglColor *color);
/**
* cogl_material_set_specular:
* @material: A CoglMaterial object
* @specular: The components of the desired specular color
*
* Exposing the standard OpenGL lighting model; this function sets
* the material's specular color. The intensity of the specular color
* depends on the viewport position, and is brightest along the lines
* of reflection.
*
* The default value is (0.0, 0.0, 0.0, 1.0)
*
* Since 1.0
*/
void cogl_material_set_specular (CoglHandle material,
const CoglColor *specular);
/**
* cogl_material_get_specular:
* @material: A CoglMaterial object
* @specular: The location to store the specular color
*
* This retrieves the materials current specular color.
*
* Since 1.0
*/
void cogl_material_get_specular (CoglHandle handle, CoglColor *specular);
/**
* cogl_material_set_shininess:
* @material: A CoglMaterial object
* shininess: The desired shininess; range: [0.0, 1.0]
*
* This function sets the materials shininess which determines how
* specular highlights are calculated. A higher shininess will produce
* smaller brigher highlights.
*
* The default value is 0.0
*
* Since 1.0
*/
void cogl_material_set_shininess (CoglHandle material,
float shininess);
/**
* cogl_material_get_shininess:
* @material: A CoglMaterial object
*
* This retrieves the materials current emission color.
*
* Return value: The materials current shininess value
*
* Since 1.0
*/
float cogl_material_get_shininess (CoglHandle handle);
/**
* cogl_material_set_emission:
* @material: A CoglMaterial object
* @emission: The components of the desired emissive color
*
* Exposing the standard OpenGL lighting model; this function sets
* the material's emissive color. It will look like the surface is
* a light source emitting this color.
*
* The default value is (0.0, 0.0, 0.0, 1.0)
*
* Since 1.0
*/
void cogl_material_set_emission (CoglHandle material,
const CoglColor *emission);
/**
* cogl_material_get_emission:
* @material: A CoglMaterial object
* @emission: The location to store the emission color
*
* This retrieves the materials current emission color.
*
* Since 1.0
*/
void cogl_material_get_emission (CoglHandle handle, CoglColor *emission);
/**
* CoglMaterialAlphaFunc:
* @COGL_MATERIAL_ALPHA_FUNC_NEVER: Never let the fragment through.
* @COGL_MATERIAL_ALPHA_FUNC_LESS: Let the fragment through if the incoming
* alpha value is less than the reference alpha
* value.
* @COGL_MATERIAL_ALPHA_FUNC_EQUAL: Let the fragment through if the incoming
* alpha value equals the reference alpha
* value.
* @COGL_MATERIAL_ALPHA_FUNC_LEQUAL: Let the fragment through if the incoming
* alpha value is less than or equal to the
* reference alpha value.
* @COGL_MATERIAL_ALPHA_FUNC_GREATER: Let the fragment through if the incoming
* alpha value is greater than the reference
* alpha value.
* @COGL_MATERIAL_ALPHA_FUNC_NOTEQUAL: Let the fragment through if the incoming
* alpha value does not equal the reference
* alpha value.
* @COGL_MATERIAL_ALPHA_FUNC_GEQUAL: Let the fragment through if the incoming
* alpha value is greater than or equal to the
* reference alpha value.
* @COGL_MATERIAL_ALPHA_FUNC_ALWAYS: Always let the fragment through.
*
* Alpha testing happens before blending primitives with the framebuffer and
* gives an opportunity to discard fragments based on a comparison with the
* incoming alpha value and a reference alpha value. The #CoglMaterialAlphaFunc
* determines how the comparison is done.
*/
typedef enum _CoglMaterialAlphaFunc
{
COGL_MATERIAL_ALPHA_FUNC_NEVER = GL_NEVER,
COGL_MATERIAL_ALPHA_FUNC_LESS = GL_LESS,
COGL_MATERIAL_ALPHA_FUNC_EQUAL = GL_EQUAL,
COGL_MATERIAL_ALPHA_FUNC_LEQUAL = GL_LEQUAL,
COGL_MATERIAL_ALPHA_FUNC_GREATER = GL_GREATER,
COGL_MATERIAL_ALPHA_FUNC_NOTEQUAL = GL_NOTEQUAL,
COGL_MATERIAL_ALPHA_FUNC_GEQUAL = GL_GEQUAL,
COGL_MATERIAL_ALPHA_FUNC_ALWAYS = GL_ALWAYS
} CoglMaterialAlphaFunc;
/**
* cogl_material_set_alpha_test_function:
* @material: A CoglMaterial object
* @alpha_func: A @CoglMaterialAlphaFunc constant
* @alpha_reference: A reference point that the chosen alpha function uses
* to compare incoming fragments to.
*
* Before a primitive is blended with the framebuffer, it goes through an
* alpha test stage which lets you discard fragments based on the current
* alpha value. This function lets you change the function used to evaluate
* the alpha channel, and thus determine which fragments are discarded
* and which continue on to the blending stage.
*
* The default is COGL_MATERIAL_ALPHA_FUNC_ALWAYS
*
* Since 1.0
*/
void cogl_material_set_alpha_test_function (CoglHandle material,
CoglMaterialAlphaFunc alpha_func,
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)
*
* Blending occurs after the alpha test function, and combines fragments with
* the framebuffer.
* <para>
* 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:
* </para>
* <programlisting>
* R = Rs*Sr + Rd*Dr
* G = Gs*Sg + Gd*Dg
* B = Bs*Sb + Bd*Db
* A = As*Sa + Ad*Da
* </programlisting>
*
* All factors have a range [0, 1]
*
* The factors are selected with the following constants:
*/
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;
/**
* cogl_material_set_blend_factors:
* @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.
*
* This function lets you control how primitives using this material will get
* blended with the contents of your framebuffer. The blended RGBA components
* are calculated like this:
*
* (RsSr+RdDr, GsSg+GdDg, BsSb+BsSb, AsSa+AdDa)
*
* Where (Rs,Gs,Bs,As) represents your source - material- color,
* (Rd,Gd,Bd,Ad) represents your destination - framebuffer - color,
* (Sr,Sg,Sb,Sa) represents your source blend factor and
* (Dr,Dg,Db,Da) represents you destination blend factor.
*
* All factors lie in the range [0,1] and incoming color components are also
* normalized to the range [0,1]
*
* Since 1.0
*/
void cogl_material_set_blend_factors (CoglHandle material,
CoglMaterialBlendFactor src_factor,
CoglMaterialBlendFactor dst_factor);
/**
* cogl_material_set_layer:
* @material: A CoglMaterial object
*
* In addition to the standard OpenGL lighting model a Cogl material may have
* one or more layers comprised of textures that can be blended together in
* order, with a number of different texture combine modes. This function
* defines a new texture layer.
*
* The index values of multiple layers do not have to be consecutive; it is
* only their relative order that is important.
*
* XXX: In the future, we may define other types of material layers, such
* as purely GLSL based layers.
*
* Since 1.0
*/
void cogl_material_set_layer (CoglHandle material,
gint layer_index,
CoglHandle texture);
/**
* cogl_material_add_texture:
* @material: A CoglMaterial object
* @layer_index: Specifies the layer you want to remove
*
* This function removes a layer from your 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)) +
*
* 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:
*
* <programlisting>
* (Rs*Rp, Gs*Gp, Bs*Bp, As*Ap)
* </programlisting>
*
* 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 = GL_REPLACE,
COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE = GL_MODULATE,
COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD = GL_ADD,
COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED = GL_ADD_SIGNED,
COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE = GL_INTERPOLATE,
COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT = GL_SUBTRACT,
COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB = GL_DOT3_RGB,
COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA = GL_DOT3_RGBA
} CoglMaterialLayerCombineFunc;
/**
* 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:
* <orderedlist>
* <listitem>
* Choose a function.
* </listitem>
* <listitem>
* Specify the source color for each argument of the chosen function. (Note
* the functions don't all take the same number of arguments)
* </listitem>
* <listitem>
* Specify an operator for each argument that can modify the corresponding
* source color before the function is applied.
* </listitem>
* </orderedlist>
*
* 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:
* <programlisting>
* //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);
* </programlisting>
*/
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.
*/
typedef enum _CoglMaterialLayerCombineSrc
{
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE = GL_TEXTURE,
/* Can we find a nicer way... */
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE0 = GL_TEXTURE0,
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE1 = GL_TEXTURE1,
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE2 = GL_TEXTURE2,
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE3 = GL_TEXTURE3,
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE4 = GL_TEXTURE4,
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE5 = GL_TEXTURE5,
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE6 = GL_TEXTURE6,
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE7 = GL_TEXTURE7,
/* .. who would ever need more than 8 texture layers.. :-) */
COGL_MATERIAL_LAYER_COMBINE_SRC_CONSTANT = GL_CONSTANT,
COGL_MATERIAL_LAYER_COMBINE_SRC_PRIMARY_COLOR = GL_PRIMARY_COLOR,
COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS = GL_PREVIOUS
} CoglMaterialLayerCombineSrc;
/**
* cogl_material_set_layer_combine_arg_src:
* @material: A CoglMaterial object
* @layer_index:
* @argument:
* @channels:
* @src:
*
*/
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:
*
*/
void cogl_material_set_layer_combine_arg_op (CoglHandle material,
gint layer_index,
gint argument,
CoglMaterialLayerCombineChannels channels,
CoglMaterialLayerCombineOp op);
/* TODO: */
#if 0
I think it would be be really neat to support a simple string description
of the fixed function texture combine modes exposed above. I think we can
consider this stuff to be set in stone from the POV that more advanced
texture combine functions are catered for with GLSL, so it seems reasonable
to find a concise string representation that can represent all the above
modes in a *much* more readable/useable fashion. I think somthing like
this would be quite nice:
"MODULATE(TEXTURE[RGB], PREVIOUS[A])"
"ADD(TEXTURE[A],PREVIOUS[RGB])"
"INTERPOLATE(TEXTURE[1-A], PREVIOUS[RGB])"
void cogl_material_set_layer_rgb_combine (CoglHandle material
gint layer_index,
const char *combine_description);
void cogl_material_set_layer_alpha_combine (CoglHandle material
gint layer_index,
const char *combine_description);
#endif
/**
* cogl_material_set_layer_matrix:
* @material: A CoglMaterial object
*
* This function lets you set a matrix that can be used to e.g. translate
* and rotate a single layer of a material used to fill your geometry.
*/
void cogl_material_set_layer_matrix (CoglHandle material,
gint layer_index,
CoglMatrix *matrix);
/**
* cogl_material_get_cogl_enable_flags:
* @material: A CoglMaterial object
*
* This determines what flags need to be passed to cogl_enable before
* this material can be used. Normally you shouldn't need to use this
* function directly since Cogl will do this internally, but if you are
* developing custom primitives directly with OpenGL you may want to use
* this.
*
* Note: This API is hopfully just a stop-gap solution. Ideally
* cogl_enable will be replaced.
*/
/* TODO: find a nicer solution! */
gulong
cogl_material_get_cogl_enable_flags (CoglHandle handle);
/**
* cogl_material_get_layers:
* @material: A CoglMaterial object
*
* This function lets you access a materials internal list of layers
* for iteration.
*
* Note: Normally you shouldn't need to use this function directly since
* Cogl will do this internally, but if you are developing custom primitives
* directly with OpenGL, you will need to iterate the layers that you want
* to texture with.
*
* Note: This function may return more layers than OpenGL can use at once
* so it's your responsability limit yourself to
* CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS.
*
* Note: It's a bit out of the ordinary to return a const GList *, but it
* was considered sensible to try and avoid list manipulation for every
* primitive emitted in a scene, every frame.
*/
const GList *cogl_material_get_layers (CoglHandle material_handle);
/**
* CoglMaterialLayerType:
* @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a CoglTexture
*/
typedef enum _CoglMaterialLayerType
{
COGL_MATERIAL_LAYER_TYPE_TEXTURE
} CoglMaterialLayerType;
/**
* cogl_material_layer_get_type:
* @material: A CoglMaterial object
*
* Currently there is only one type of layer defined:
* COGL_MATERIAL_LAYER_TYPE_TEXTURE, but considering we may add purely GLSL
* based layers in the future, you should write code that checks the type
* first.
*
* Note: Normally you shouldn't need to use this function directly since
* Cogl will do this internally, but if you are developing custom primitives
* directly with OpenGL, you will need to iterate the layers that you want
* to texture with, and thus should be checking the layer types.
*/
CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle);
/**
* cogl_material_layer_get_texture:
* @layer_handle: A CoglMaterial layer object
*
* This lets you extract a CoglTexture handle for a specific layer. Normally
* you shouldn't need to use this function directly since Cogl will do this
* internally, but if you are developing custom primitives directly with
* OpenGL you may need this.
*
* Note: In the future, we may support purely GLSL based layers which will
* likley return COGL_INVALID_HANDLE if you try to get the texture.
* Considering this, you should always call cogl_material_layer_get_type
* first, to check it is of type COGL_MATERIAL_LAYER_TYPE_TEXTURE.
*/
CoglHandle cogl_material_layer_get_texture (CoglHandle layer_handle);
/**
* 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 CoglMaterial layer object
*
* 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.
*
* Normally you shouldn't need to use this function directly, but if you
* are developing a custom primitive using raw OpenGL that works with
* CoglMaterials, then you may want to use this function.
*
* Since 1.0
*/
void cogl_material_flush_gl_state (CoglHandle material,
...) G_GNUC_NULL_TERMINATED;
/**
* cogl_set_source:
* @material: A CoglMaterial object
*
* This function sets the source material that will be used to fill
* subsequent geometry emitted via the cogl API.
*
* Note: in the future we may add the ability to set a front facing
* material, and a back facing material, in which case this function
* will set both to the same.
*
* Since 1.0
*/
/* XXX: This doesn't really belong to the cogl-material API, it should
* move to cogl.h */
void cogl_set_source (CoglHandle material);
/**
* cogl_set_source_texture:
* @texture_handle: The Cogl texture you want as your source
*
* This is a convenience function for creating a material with the first
* layer set to #texture_handle and setting that material as the source with
* cogl_set_source.
*
* Since 1.0
*/
void cogl_set_source_texture (CoglHandle texture_handle);
G_END_DECLS
#endif /* __COGL_MATERIAL_H__ */

146
cogl-matrix.h Normal file
View File

@ -0,0 +1,146 @@
#ifndef __COGL_MATRIX_H
#define __COGL_MATRIX_H
#include <glib.h>
G_BEGIN_DECLS
/**
* SECTION:cogl-matrix
* @short_description: Fuctions for initializing and manipulating 4x4
* matrices.
*
* Matrices are used in Cogl to describe affine model-view transforms and
* texture transforms, and projective transforms. This exposes a utility API
* that can be used for direct manipulation of these matrices.
*/
/**
* CoglMatrix:
*
* A CoglMatrix holds a 4x4 transform matrix. This is a single precision,
* column-major matrix which means it is compatible with what OpenGL expects.
*
* A CoglMatix can represent transforms such as, rotations, scaling,
* translation, sheering, and linear projections. You can combine these
* transforms by multiplying multiple matrices in the order you want them
* applied.
*
* The transformation of a vertex (x, y, z, w) by a CoglMatrix is given by:
* <programlisting>
* x_new = xx * x + xy * y + xz * z + xw * w
* y_new = yx * x + yy * y + yz * z + yw * w
* z_new = zx * x + zy * y + zz * z + zw * w
* w_new = wx * x + wy * y + wz * z + ww * w
* </programlisting>
* Where w is normally 1
*/
typedef struct _CoglMatrix {
/* column 0 */
float xx;
float yx;
float zx;
float wx;
/* column 1 */
float xy;
float yy;
float zy;
float wy;
/* column 2 */
float xz;
float yz;
float zz;
float wz;
/* column 3 */
float xw;
float yw;
float zw;
float ww;
/*< private >*/
/* Note: we may want to extend this later with private flags
* and a cache of the inverse transform matrix. */
} CoglMatrix;
/**
* cogl_matrix_init_identity:
* @matrix: A 4x4 transformation matrix
*
* Resets matrix to the identity matrix:
* <programlisting>
* .xx=1; .xy=0; .xz=0; .xw=0;
* .yx=0; .yy=1; .yz=0; .yw=0;
* .zx=0; .zy=0; .zz=1; .zw=0;
* .wx=0; .wy=0; .wz=0; .ww=1;
* </programlisting>
*/
void cogl_matrix_init_identity (CoglMatrix *matrix);
/**
* cogl_matrix_multiply:
* @result: The address of a 4x4 matrix to store the result in
* @a: A 4x4 transformation matrix
* @b: A 4x4 transformation matrix
*
* This function multiples the two supplied matricies together and stores
* the result in #result
*/
void cogl_matrix_multiply (CoglMatrix *result,
const CoglMatrix *a,
const CoglMatrix *b);
/**
* cogl_matrix_rotate:
* @matrix: A 4x4 transformation matrix
* @angle: The angle you want to rotate in degrees
* @x: X component of your rotation vector
* @y: Y component of your rotation vector
* @z: Z component of your rotation vector
*
* This function multiples your matrix with a rotation matrix that applies
* a rotation of #angle degrees around the specified 3D vector.
*/
void cogl_matrix_rotate (CoglMatrix *matrix,
float angle,
float x,
float y,
float z);
/* cogl_matrix_translate:
* @matrix: A 4x4 transformation matrix
* @x: The X translation you want to apply
* @y: The Y translation you want to apply
* @z: The Z translation you want to apply
*
* This function multiples your matrix with a transform matrix that translates
* along the X, Y and Z axis.
*/
void cogl_matrix_translate (CoglMatrix *matrix,
float x,
float y,
float z);
/**
* cogl_matrix_scale:
* @matrix: A 4x4 transformation matrix
* @sx: The X scale factor
* @sy: The Y scale factor
* @sz: The Z scale factor
*
* This function multiples your matrix with a transform matrix that scales
* along the X, Y and Z axis.
*/
void cogl_matrix_scale (CoglMatrix *matrix,
float sx,
float sy,
float sz);
G_END_DECLS
#endif /* __COGL_MATRIX_H */

View File

@ -57,8 +57,7 @@ G_BEGIN_DECLS
* @width: Width of the rectangle
* @height: Height of the rectangle
*
* Fills a rectangle at the given coordinates with the current
* drawing color in a highly optimizied fashion.
* Fills a rectangle at the given coordinates with the current source material
**/
void cogl_rectangle (float x,
float y,

View File

@ -359,68 +359,15 @@ CoglHandle cogl_texture_ref (CoglHandle handle);
*/
void cogl_texture_unref (CoglHandle handle);
/**
* cogl_texture_rectangle:
* @handle: a @CoglHandle.
* @x1: x coordinate upper left on screen.
* @y1: y coordinate upper left on screen.
* @x2: x coordinate lower right on screen.
* @y2: y coordinate lower right on screen.
* @tx1: x part of texture coordinate to use for upper left pixel
* @ty1: y part of texture coordinate to use for upper left pixel
* @tx2: x part of texture coordinate to use for lower right pixel
* @ty2: y part of texture coordinate to use for left pixel
*
* Draw a rectangle from a texture to the display, to draw the entire
* texture pass in @tx1=0.0 @ty1=0.0 @tx2=1.0 @ty2=1.0.
*/
void cogl_texture_rectangle (CoglHandle handle,
float x1,
float y1,
float x2,
float y2,
float tx1,
float ty1,
float tx2,
float ty2);
/**
* cogl_texture_polygon:
* @handle: A CoglHandle for a texture
* @n_vertices: The length of the vertices array
* @vertices: An array of #CoglTextureVertex structs
* @use_color: %TRUE if the color member of #CoglTextureVertex should be used
*
* Draws a polygon from a texture with the given model and texture
* coordinates. This can be used to draw arbitrary shapes textured
* with a COGL texture. If @use_color is %TRUE then the current COGL
* color will be changed for each vertex using the value specified in
* the color member of #CoglTextureVertex. This can be used for
* example to make the texture fade out by setting the alpha value of
* the color.
*
* All of the texture coordinates must be in the range [0,1] and
* repeating the texture is not supported.
*
* Because of the way this function is implemented it will currently
* only work if either the texture is not sliced or the backend is not
* OpenGL ES and the minifying and magnifying functions are both set
* to CGL_NEAREST.
*/
void cogl_texture_polygon (CoglHandle handle,
guint n_vertices,
CoglTextureVertex *vertices,
gboolean use_color);
/**
* cogl_bitmap_new_from_file:
* @filename: the file to load.
* @error: a #GError or %NULL.
*
* Load an image file from disk. This function can be safely called from
* Load an image file from disk. This function can be safely called from
* within a thread.
*
* Returns: A #CoglBitmap to the new loaded image data, or %NULL if loading
* Returns: A #CoglBitmap to the new loaded image data, or %NULL if loading
* the image failed.
*
* Since: 1.0
@ -452,27 +399,110 @@ gboolean cogl_bitmap_get_size_from_file (const gchar *filename,
void cogl_bitmap_free (CoglBitmap *bmp);
/**
* cogl_texture_multiple_rectangles:
* @handle: a @CoglHandle.
* cogl_rectangle_with_texture_coords:
* @x1: x coordinate upper left on screen.
* @y1: y coordinate upper left on screen.
* @x2: x coordinate lower right on screen.
* @y2: y coordinate lower right on screen.
* @tx1: x part of texture coordinate to use for upper left pixel
* @ty1: y part of texture coordinate to use for upper left pixel
* @tx2: x part of texture coordinate to use for lower right pixel
* @ty2: y part of texture coordinate to use for left pixel
*
* Draw a rectangle using the current material and supply texture coordinates
* to be used for the first texture layer of the material. To draw the entire
* texture pass in @tx1=0.0 @ty1=0.0 @tx2=1.0 @ty2=1.0.
*
* Since 1.0
*/
void cogl_rectangle_with_texture_coords (float x1,
float y1,
float x2,
float y2,
float tx1,
float ty1,
float tx2,
float ty2);
/**
* cogl_rectangle_with_multitexture_coords:
* @x1: x coordinate upper left on screen.
* @y1: y coordinate upper left on screen.
* @x2: x coordinate lower right on screen.
* @y2: y coordinate lower right on screen.
* @tex_coords: An array containing groups of 4 float values:
* [tx1, ty1, tx2, ty2] that are interpreted as two texture coordinates; one
* for the upper left texel, and one for the lower right texel. Each value
* should be between 0.0 and 1.0, where the coordinate (0.0, 0.0) represents
* the top left of the texture, and (1.0, 1.0) the bottom right.
* @tex_coords_len: The length of the tex_coords array. (e.g. for one layer
* and one group of texture coordinates, this would be 4)
*
* This function draws a rectangle using the current source material to
* texture or fill with. As a material may contain multiple texture layers
* this interface lets you supply texture coordinates for each layer of the
* material.
*
* The first pair of coordinates are for the first layer (with the smallest
* layer index) and if you supply less texture coordinates than there are
* layers in the current source material then default texture coordinates
* (0.0, 0.0, 1.0, 1.0) are generated.
*
* Since 1.0
*/
void cogl_rectangle_with_multitexture_coords (float x1,
float y1,
float x2,
float y2,
const float *tex_coords,
gint tex_coords_len);
/**
* cogl_rectangles_with_texture_coords:
* @verts: an array of vertices
* @n_rects: number of rectangles to draw
*
* Draws a series of rectangles in the same way that
* cogl_texture_rectangle() does. In some situations it can give a
* cogl_rectangle_with_texture_coords() does. In some situations it can give a
* significant performance boost to use this function rather than
* calling cogl_texture_rectangle() separately for each rectangle.
* calling cogl_rectangle_with_texture_coords() separately for each rectangle.
*
* @verts should point to an array of #float<!-- -->s with
* @n_rects * 8 elements. Each group of 8 values corresponds to the
* parameters x1, y1, x2, y2, tx1, ty1, tx2 and ty2 and have the same
* meaning as in cogl_texture_rectangle().
* meaning as in cogl_rectangle_with_texture_coords().
*
* Since: 0.8.6
*/
void cogl_texture_multiple_rectangles
(CoglHandle handle,
const float *verts,
guint n_rects);
void cogl_rectangles_with_texture_coords (const float *verts,
guint n_rects);
/**
* cogl_polygon:
* @vertices: An array of #CoglTextureVertex structs
* @n_vertices: The length of the vertices array
* @use_color: %TRUE if the color member of #CoglTextureVertex should be used
*
* Draws a convex polygon using the current source material to fill / texture
* with according to the texture coordinates passed.
*
* If @use_color is %TRUE then the color will be changed for each vertex using
* the value specified in the color member of #CoglTextureVertex. This can be
* used for example to make the texture fade out by setting the alpha value of
* the color.
*
* All of the texture coordinates must be in the range [0,1] and repeating the
* texture is not supported.
*
* Because of the way this function is implemented it will currently only work
* if either the texture is not sliced or the backend is not OpenGL ES and the
* minifying and magnifying functions are both set to CGL_NEAREST.
*
* Since 1.0
*/
void cogl_polygon (CoglTextureVertex *vertices,
guint n_vertices,
gboolean use_color);
G_END_DECLS

View File

@ -32,10 +32,13 @@
#include <cogl/cogl-defines-@CLUTTER_COGL@.h>
#include <cogl/cogl-vertex-buffer.h>
#include <cogl/cogl-matrix.h>
#include <cogl/cogl-vertex-buffer.h>
#include <cogl/cogl-fixed.h>
#include <cogl/cogl-color.h>
#include <cogl/cogl-offscreen.h>
#include <cogl/cogl-material.h>
#include <cogl/cogl-path.h>
#include <cogl/cogl-shader.h>
#include <cogl/cogl-texture.h>
@ -402,19 +405,6 @@ void cogl_enable_depth_test (gboolean setting);
*/
void cogl_enable_backface_culling (gboolean setting);
/**
* cogl_alpha_func:
* @func: the comparison function to use, one of CGL_NEVER, CGL_LESS,
* CGL_EQUAL, CGL_LEQUAL, CGL_GREATER, CGL_NOTEQUAL, CGL_GEQUAL and GL_ALWAYS.
* @ref: reference value.
*
* Changes the alpha test to use the specified function specified in @func,
* comparing with the value in @ref. The default function is CGL_ALWAYS the
* initial reference value is 1.0.
*/
void cogl_alpha_func (COGLenum func,
float ref);
/**
* cogl_fog_set:
* @fog_color: The color of the fog

View File

@ -31,5 +31,7 @@ libclutter_cogl_common_la_SOURCES = \
cogl-clip-stack.c \
cogl-fixed.c \
cogl-color.c \
cogl-vertex-buffer-private.h \
cogl-vertex-buffer.c
cogl-vertex-buffer-private.h \
cogl-vertex-buffer.c \
cogl-matrix.c \
cogl-material.c

View File

@ -57,6 +57,12 @@
#define COGL_HANDLE_DEFINE(TypeName, type_name, handle_array) \
\
static CoglHandle * \
_cogl_##type_name##_handle_from_pointer (Cogl##TypeName *obj) \
{ \
return (CoglHandle)obj; \
} \
\
static gint \
_cogl_##type_name##_handle_find (CoglHandle handle) \
{ \

View File

@ -0,0 +1,99 @@
#ifndef __COGL_MATERIAL_PRIVATE_H
#define __COGL_MATERIAL_PRIVATE_H
#include "cogl-material.h"
#include "cogl-matrix.h"
#include <glib.h>
typedef struct _CoglMaterial CoglMaterial;
typedef struct _CoglMaterialLayer CoglMaterialLayer;
/* XXX: I don't think gtk-doc supports having private enums so these aren't
* bundled in with CoglMaterialLayerFlags */
typedef enum _CoglMaterialLayerPrivFlags
{
/* Ref: CoglMaterialLayerFlags
COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX = 1L<<0
*/
COGL_MATERIAL_LAYER_FLAG_DIRTY = 1L<<1,
COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE = 1L<<2
} CoglMaterialLayerPrivFlags;
/* For tracking the state of a layer that's been flushed to OpenGL */
typedef struct _CoglLayerInfo
{
CoglHandle handle;
gulong flags;
GLenum gl_target;
GLuint gl_texture;
gboolean fallback;
gboolean disabled;
gboolean layer0_overridden;
} CoglLayerInfo;
struct _CoglMaterialLayer
{
guint ref_count;
guint index; /*!< lowest index is blended first then others
on top */
gulong flags;
CoglHandle texture; /*!< The texture for this layer, or COGL_INVALID_HANDLE
for an empty layer */
/* Determines how the color of individual texture fragments
* are calculated. */
CoglMaterialLayerCombineFunc texture_combine_rgb_func;
CoglMaterialLayerCombineSrc texture_combine_rgb_src[3];
CoglMaterialLayerCombineOp texture_combine_rgb_op[3];
CoglMaterialLayerCombineFunc texture_combine_alpha_func;
CoglMaterialLayerCombineSrc texture_combine_alpha_src[3];
CoglMaterialLayerCombineOp texture_combine_alpha_op[3];
/* TODO: Support purely GLSL based material layers */
CoglMatrix matrix;
};
typedef enum _CoglMaterialFlags
{
COGL_MATERIAL_FLAG_ENABLE_BLEND = 1L<<0,
COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING = 1L<<1,
COGL_MATERIAL_FLAG_DIRTY = 1L<<2,
COGL_MATERIAL_FLAG_LAYERS_DIRTY = 1L<<3,
COGL_MATERIAL_FLAG_DEFAULT_COLOR = 1L<<4,
COGL_MATERIAL_FLAG_DEFAULT_GL_MATERIAL = 1L<<5,
COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC = 1L<<6,
COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC = 1L<<7
} CoglMaterialFlags;
struct _CoglMaterial
{
guint ref_count;
gulong flags;
/* If no lighting is enabled; this is the basic material color */
GLfloat unlit[4];
/* Standard OpenGL lighting model attributes */
GLfloat ambient[4];
GLfloat diffuse[4];
GLfloat specular[4];
GLfloat emission[4];
GLfloat shininess;
/* Determines what fragments are discarded based on their alpha */
CoglMaterialAlphaFunc alpha_func;
GLfloat alpha_func_reference;
/* Determines how this material is blended with other primitives */
CoglMaterialBlendFactor blend_src_factor;
CoglMaterialBlendFactor blend_dst_factor;
GList *layers;
};
#endif /* __COGL_MATERIAL_PRIVATE_H */

1152
common/cogl-material.c Normal file

File diff suppressed because it is too large Load Diff

138
common/cogl-matrix.c Normal file
View File

@ -0,0 +1,138 @@
#include <cogl-matrix.h>
#include <glib.h>
#include <math.h>
void
cogl_matrix_init_identity (CoglMatrix *matrix)
{
matrix->xx = 1; matrix->xy = 0; matrix->xz = 0; matrix->xw = 0;
matrix->yx = 0; matrix->yy = 1; matrix->yz = 0; matrix->yw = 0;
matrix->zx = 0; matrix->zy = 0; matrix->zz = 1; matrix->zw = 0;
matrix->wx = 0; matrix->wy = 0; matrix->wz = 0; matrix->ww = 1;
}
void
cogl_matrix_multiply (CoglMatrix *result,
const CoglMatrix *a,
const CoglMatrix *b)
{
CoglMatrix r;
/* row 0 */
r.xx = a->xx * b->xx + a->xy * b->yx + a->xz * b->zx + a->xw * b->wx;
r.xy = a->xx * b->xy + a->xy * b->yy + a->xz * b->zy + a->xw * b->wy;
r.xz = a->xx * b->xz + a->xy * b->yz + a->xz * b->zz + a->xw * b->wz;
r.xw = a->xx * b->xw + a->xy * b->yw + a->xz * b->zw + a->xw * b->ww;
/* row 1 */
r.yx = a->yx * b->xx + a->yy * b->yx + a->yz * b->zx + a->yw * b->wx;
r.yy = a->yx * b->xy + a->yy * b->yy + a->yz * b->zy + a->yw * b->wy;
r.yz = a->yx * b->xz + a->yy * b->yz + a->yz * b->zz + a->yw * b->wz;
r.yw = a->yx * b->xw + a->yy * b->yw + a->yz * b->zw + a->yw * b->ww;
/* row 2 */
r.zx = a->zx * b->xx + a->zy * b->yx + a->zz * b->zx + a->zw * b->wx;
r.zy = a->zx * b->xy + a->zy * b->yy + a->zz * b->zy + a->zw * b->wy;
r.zz = a->zx * b->xz + a->zy * b->yz + a->zz * b->zz + a->zw * b->wz;
r.zw = a->zx * b->xw + a->zy * b->yw + a->zz * b->zw + a->zw * b->ww;
/* row 3 */
r.wx = a->wx * b->xx + a->wy * b->yx + a->wz * b->zx + a->ww * b->wx;
r.wy = a->wx * b->xy + a->wy * b->yy + a->wz * b->zy + a->ww * b->wy;
r.wz = a->wx * b->xz + a->wy * b->yz + a->wz * b->zz + a->ww * b->wz;
r.ww = a->wx * b->xw + a->wy * b->yw + a->wz * b->zw + a->ww * b->ww;
/* The idea was that having this unrolled; it might be easier for the
* compiler to vectorize, but that's probably not true. Mesa does it
* using a single for (i=0; i<4; i++) approach, may that's better...
*/
*result = r;
}
/**
* cogl_3dmatrix_rotate:
* matrix: A 3D Affine transformation matrix
* angle: The angle in degrees you want to rotate by
* x: The X component of your rotation vector
* y: The Y component of your rotation vector
* z: The Z component of your rotation vector
*
* The matrix is multiplied with a rotation matrix representing a rotation
* of angle degress around the vector (x,y,z)
*/
void
cogl_matrix_rotate (CoglMatrix *matrix,
float angle,
float x,
float y,
float z)
{
CoglMatrix rotation;
CoglMatrix result;
angle *= G_PI / 180.0f;
float c = cosf (angle);
float s = sinf (angle);
rotation.xx = x * x * (1.0f - c) + c;
rotation.yx = y * x * (1.0f - c) + z * s;
rotation.zx = x * z * (1.0f - c) - y * s;
rotation.wx = 0.0f;
rotation.xy = x * y * (1.0f - c) - z * s;
rotation.yy = y * y * (1.0f - c) + c;
rotation.zy = y * z * (1.0f - c) + x * s;
rotation.wy = 0.0f;
rotation.xz = x * z * (1.0f - c) + y * s;
rotation.yz = y * z * (1.0f - c) - x * s;
rotation.zz = z * z * (1.0f - c) + c;
rotation.wz = 0.0f;
rotation.xw = 0.0f;
rotation.yw = 0.0f;
rotation.zw = 0.0f;
rotation.ww = 1.0f;
cogl_matrix_multiply (&result, matrix, &rotation);
*matrix = result;
}
void
cogl_matrix_translate (CoglMatrix *matrix,
float x,
float y,
float z)
{
matrix->xw = matrix->xx * x + matrix->xy * y + matrix->xz * z + matrix->xw;
matrix->yw = matrix->yx * x + matrix->yy * y + matrix->yz * z + matrix->yw;
matrix->zw = matrix->zx * x + matrix->zy * y + matrix->zz * z + matrix->zw;
matrix->ww = matrix->wx * x + matrix->wy * y + matrix->wz * z + matrix->ww;
}
void
cogl_matrix_scale (CoglMatrix *matrix,
float sx,
float sy,
float sz)
{
matrix->xx *= sx; matrix->xy *= sy; matrix->xz *= sz;
matrix->yx *= sx; matrix->yy *= sy; matrix->yz *= sz;
matrix->zx *= sx; matrix->zy *= sy; matrix->zz *= sz;
matrix->wx *= sx; matrix->wy *= sy; matrix->wz *= sz;
}
#if 0
gboolean
cogl_matrix_invert (CoglMatrix *matrix)
{
/* TODO */
/* Note: It might be nice to also use the flag based tricks that mesa does
* to alow it to track the type of transformations a matrix represents
* so it can use various assumptions to optimise the inversion.
*/
}
#endif

View File

@ -43,19 +43,18 @@ void _cogl_path_add_node (gboolean new_sub_path,
float y);
void _cogl_path_fill_nodes ();
void _cogl_path_stroke_nodes ();
void _cogl_rectangle (float x,
float y,
float width,
float height);
void
cogl_rectangle (float x,
float y,
float width,
float height)
{
cogl_clip_ensure ();
_cogl_rectangle (x, y, width, height);
cogl_rectangle_with_multitexture_coords (x, y,
x+width,
y+height,
NULL,
0);
}
void

View File

@ -134,6 +134,7 @@
#include "cogl-context.h"
#include "cogl-handle.h"
#include "cogl-vertex-buffer-private.h"
#include "cogl-texture-private.h"
#define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \
(VAR = TYPE_SIZE + ((VAR - 1) & ~(TYPE_SIZE - 1)))
@ -1416,12 +1417,15 @@ get_gl_type_from_attribute_flags (CoglVertexBufferAttribFlags flags)
static void
enable_state_for_drawing_attributes_buffer (CoglVertexBuffer *buffer)
{
GList *tmp;
GLenum gl_type;
GLuint generic_index = 0;
gulong enable_flags = COGL_ENABLE_BLEND;
/* FIXME: I don't think it's appropriate to force enable
* GL_BLEND here. */
GList *tmp;
GLenum gl_type;
GLuint generic_index = 0;
gulong enable_flags = 0;
guint max_texcoord_attrib_unit = 0;
const GList *layers;
guint32 fallback_mask = 0;
guint32 disable_mask = ~0;
int i;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -1460,17 +1464,16 @@ enable_state_for_drawing_attributes_buffer (CoglVertexBuffer *buffer)
(const GLvoid *)attribute->u.vbo_offset));
break;
case COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY:
/* FIXME: set the active texture unit */
/* NB: Cogl currently manages unit 0 */
enable_flags |= (COGL_ENABLE_TEXCOORD_ARRAY
| COGL_ENABLE_TEXTURE_2D);
/* FIXME: I don't think it's appropriate to force enable
* GL_TEXTURE_2D here. */
/* GE (glEnableClientState (GL_VERTEX_ARRAY)); */
GE (glClientActiveTexture (GL_TEXTURE0 +
attribute->texture_unit));
GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY));
GE (glTexCoordPointer (attribute->n_components,
gl_type,
attribute->stride,
(const GLvoid *)attribute->u.vbo_offset));
if (attribute->texture_unit > max_texcoord_attrib_unit)
max_texcoord_attrib_unit = attribute->texture_unit;
disable_mask &= ~(1 << attribute->texture_unit);
break;
case COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY:
enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
@ -1505,8 +1508,51 @@ enable_state_for_drawing_attributes_buffer (CoglVertexBuffer *buffer)
}
}
cogl_enable (enable_flags);
layers = cogl_material_get_layers (ctx->source_material);
for (tmp = (GList *)layers, i = 0;
tmp != NULL && i <= max_texcoord_attrib_unit;
tmp = tmp->next, i++)
{
CoglHandle layer = (CoglHandle)tmp->data;
CoglHandle tex_handle = cogl_material_layer_get_texture (layer);
CoglTexture *texture =
_cogl_texture_pointer_from_handle (tex_handle);
if (cogl_texture_is_sliced (tex_handle)
|| _cogl_texture_span_has_waste (texture, 0, 0))
{
g_warning ("Disabling layer %d of the current source material, "
"because texturing with the vertex buffer API is not "
"currently supported using sliced textures, or textures "
"with waste\n", i);
/* XXX: maybe we can add a mechanism for users to forcibly use
* textures with waste where it would be their responsability to use
* texture coords in the range [0,1] such that sampling outside isn't
* required. We can then use a texture matrix (or a modification of
* the users own matrix) to map 1 to the edge of the texture data.
*
* Potentially, given the same guarantee as above we could also
* support a single sliced layer too. We would have to redraw the
* vertices once for each layer, each time with a fiddled texture
* matrix.
*/
fallback_mask |= (1 << i);
}
else if (!(disable_mask & (1 << i)))
fallback_mask |= (1 << i);
}
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);
cogl_enable (enable_flags);
}
static void
@ -1550,9 +1596,9 @@ disable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
GE (glDisableClientState (GL_NORMAL_ARRAY));
break;
case COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY:
/* FIXME: set the active texture unit */
/* NB: Cogl currently manages unit 0 */
/* GE (glDisableClientState (GL_VERTEX_ARRAY)); */
GE (glClientActiveTexture (GL_TEXTURE0 +
attribute->texture_unit));
GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY));
break;
case COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY:
/* GE (glDisableClientState (GL_VERTEX_ARRAY)); */

View File

@ -55,7 +55,9 @@
<xi:include href="xml/cogl.xml"/>
<xi:include href="xml/cogl-primitives.xml"/>
<xi:include href="xml/cogl-util.xml"/>
<xi:include href="xml/cogl-matrix.xml"/>
<xi:include href="xml/cogl-texture.xml"/>
<xi:include href="xml/cogl-material.xml"/>
<xi:include href="xml/cogl-shaders.xml"/>
<xi:include href="xml/cogl-offscreen.xml"/>
<xi:include href="xml/cogl-fixed.xml"/>

View File

@ -310,3 +310,52 @@ cogl_vertex_buffer_draw
cogl_vertex_buffer_draw_range_elements
</SECTION>
<SECTION>
<FILE>cogl-matrix</FILE>
<TITLE>Matrices</TITLE>
CoglMatrix
cogl_matrix_init_identity
cogl_matrix_multiply
cogl_matrix_rotate
cogl_matrix_translate
cogl_matrix_scale
</SECTION>
<SECTION>
<FILE>cogl-material</FILE>
<TITLE>Materials</TITLE>
cogl_material_new
cogl_material_ref
cogl_material_unref
cogl_material_set_diffuse
cogl_material_set_ambient
cogl_material_set_ambient_and_diffuse
cogl_material_set_specular
cogl_material_set_shininess
cogl_material_set_emission
cogl_set_source
CoglMaterialAlphaFunc
cogl_material_set_alpha_test_function
CoglMaterialBlendFactor
cogl_material_set_blend_factors
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_matrix
cogl_material_get_cogl_enable_flags
cogl_material_flush_gl_material_state
cogl_material_flush_gl_alpha_func
cogl_material_flush_gl_blend_func
cogl_material_get_layers
CoglMaterialLayerType
cogl_material_layer_get_type
cogl_material_layer_get_texture
cogl_material_layer_flush_gl_sampler_state
</SECTION>

View File

@ -10,7 +10,9 @@ libclutterinclude_HEADERS = \
$(top_builddir)/clutter/cogl/cogl-shader.h \
$(top_builddir)/clutter/cogl/cogl-texture.h \
$(top_builddir)/clutter/cogl/cogl-types.h \
$(top_builddir)/clutter/cogl/cogl-vertex-buffer.h
$(top_builddir)/clutter/cogl/cogl-vertex-buffer.h \
$(top_builddir)/clutter/cogl/cogl-material.h \
$(top_builddir)/clutter/cogl/cogl-matrix.h
INCLUDES = \
-I$(top_srcdir) \

View File

@ -31,6 +31,8 @@
#include "cogl-internal.h"
#include "cogl-util.h"
#include "cogl-context.h"
#include "cogl-texture-private.h"
#include "cogl-material-private.h"
#include <string.h>
@ -39,6 +41,9 @@ static CoglContext *_context = NULL;
gboolean
cogl_create_context ()
{
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
gulong enable_flags = 0;
if (_context != NULL)
return FALSE;
@ -52,27 +57,40 @@ cogl_create_context ()
_context->enable_flags = 0;
_context->color_alpha = 255;
_context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
_context->last_path = 0;
_context->material_handles = NULL;
_context->material_layer_handles = NULL;
_context->default_material = cogl_material_new ();
_context->source_material = NULL;
_context->texture_handles = NULL;
_context->texture_vertices = g_array_new (FALSE, FALSE,
_context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE;
_context->default_gl_texture_rect_tex = COGL_INVALID_HANDLE;
_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));
_context->texture_indices = g_array_new (FALSE, FALSE,
sizeof (GLushort));
_context->current_material = NULL;
_context->current_material_flags = 0;
_context->current_layers = g_array_new (FALSE, FALSE,
sizeof (CoglLayerInfo));
_context->n_texcoord_arrays_enabled = 0;
_context->fbo_handles = NULL;
_context->draw_buffer = COGL_WINDOW_BUFFER;
_context->blend_src_factor = CGL_SRC_ALPHA;
_context->blend_dst_factor = CGL_ONE_MINUS_SRC_ALPHA;
_context->shader_handles = NULL;
_context->program_handles = NULL;
_context->vertex_buffer_handles = NULL;
_context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
_context->last_path = 0;
_context->stencil_material = cogl_material_new ();
_context->pf_glGenRenderbuffersEXT = NULL;
_context->pf_glBindRenderbufferEXT = NULL;
_context->pf_glRenderbufferStorageEXT = NULL;
@ -118,15 +136,37 @@ cogl_create_context ()
_context->pf_glDrawRangeElements = NULL;
/* Init OpenGL state */
GE( glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) );
GE( glColorMask (TRUE, TRUE, TRUE, FALSE) );
GE( glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) );
cogl_enable (0);
/* Initialise the clip stack */
_cogl_clip_stack_state_init ();
/* Create default textures used for fall backs */
_context->default_gl_texture_2d_tex =
cogl_texture_new_from_data (1, /* width */
1, /* height */
-1, /* max waste */
FALSE, /* auto mipmap */
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
/* internal format */
COGL_PIXEL_FORMAT_RGBA_8888,
0, /* auto calc row stride */
&default_texture_data);
_context->default_gl_texture_rect_tex =
cogl_texture_new_from_data (1, /* width */
1, /* height */
-1, /* max waste */
FALSE, /* auto mipmap */
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
/* internal format */
COGL_PIXEL_FORMAT_RGBA_8888,
0, /* auto calc row stride */
&default_texture_data);
cogl_set_source (_context->default_material);
cogl_material_flush_gl_state (_context->source_material, NULL);
enable_flags =
cogl_material_get_cogl_enable_flags (_context->source_material);
cogl_enable (enable_flags);
return TRUE;
}
@ -150,10 +190,25 @@ cogl_destroy_context ()
if (_context->program_handles)
g_array_free (_context->program_handles, TRUE);
if (_context->texture_vertices)
g_array_free (_context->texture_vertices, TRUE);
if (_context->texture_indices)
g_array_free (_context->texture_indices, TRUE);
if (_context->default_gl_texture_2d_tex)
cogl_texture_unref (_context->default_gl_texture_2d_tex);
if (_context->default_gl_texture_rect_tex)
cogl_texture_unref (_context->default_gl_texture_rect_tex);
if (_context->default_material)
cogl_material_unref (_context->default_material);
if (_context->journal)
g_array_free (_context->journal, TRUE);
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);
g_free (_context);
}

View File

@ -45,32 +45,37 @@ typedef struct
/* Enable cache */
gulong enable_flags;
guint8 color_alpha;
COGLenum blend_src_factor;
COGLenum blend_dst_factor;
gboolean enable_backface_culling;
/* Primitives */
floatVec2 path_start;
floatVec2 path_pen;
GArray *path_nodes;
guint last_path;
floatVec2 path_nodes_min;
floatVec2 path_nodes_max;
/* Cache of inverse projection matrix */
GLfloat inverse_projection[16];
/* Textures */
GArray *texture_handles;
GArray *texture_vertices;
GArray *texture_indices;
/* The gl texture number that the above vertices apply to. This to
detect when a different slice is encountered so that the vertices
can be flushed */
GLuint texture_current;
GLenum texture_target;
GLenum texture_wrap_mode;
GArray *texture_handles;
CoglHandle default_gl_texture_2d_tex;
CoglHandle default_gl_texture_rect_tex;
/* Materials */
GArray *material_handles;
GArray *material_layer_handles;
CoglHandle default_material;
CoglHandle source_material;
/* Batching geometry... */
/* We journal the texture rectangles we want to submit to OpenGL so
* we have an oppertunity to optimise the final order so that we
* can batch things together. */
GArray *journal;
GArray *logged_vertices;
GArray *static_indices;
GArray *polygon_vertices;
/* Some simple caching, to minimize state changes... */
CoglHandle current_material;
gulong current_material_flags;
GArray *current_layers;
guint n_texcoord_arrays_enabled;
/* Framebuffer objects */
GArray *fbo_handles;
@ -88,6 +93,15 @@ typedef struct
/* Vertex buffers */
GArray *vertex_buffer_handles;
/* Primitives */
floatVec2 path_start;
floatVec2 path_pen;
GArray *path_nodes;
guint last_path;
floatVec2 path_nodes_min;
floatVec2 path_nodes_max;
CoglHandle stencil_material;
/* Relying on glext.h to define these */
COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT;
COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT;

View File

@ -309,6 +309,7 @@ typedef GLuint COGLuint;
#define CGL_MAX_TEXTURE_STACK_DEPTH GL_MAX_TEXTURE_STACK_DEPTH
#define CGL_MAX_VIEWPORT_DIMS GL_MAX_VIEWPORT_DIMS
#define CGL_MAX_CLIENT_ATTRIB_STACK_DEPTH GL_MAX_CLIENT_ATTRIB_STACK_DEPTH
#define CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS GL_MAX_TEXTURE_UNITS
#define CGL_ATTRIB_STACK_DEPTH GL_ATTRIB_STACK_DEPTH
#define CGL_CLIENT_ATTRIB_STACK_DEPTH GL_CLIENT_ATTRIB_STACK_DEPTH
#define CGL_COLOR_CLEAR_VALUE GL_COLOR_CLEAR_VALUE

View File

@ -51,13 +51,10 @@ const char *_cogl_error_string(GLenum errorCode);
#endif /* COGL_DEBUG */
#define COGL_ENABLE_BLEND (1<<1)
#define COGL_ENABLE_TEXTURE_2D (1<<2)
#define COGL_ENABLE_ALPHA_TEST (1<<3)
#define COGL_ENABLE_TEXTURE_RECT (1<<4)
#define COGL_ENABLE_VERTEX_ARRAY (1<<5)
#define COGL_ENABLE_TEXCOORD_ARRAY (1<<6)
#define COGL_ENABLE_COLOR_ARRAY (1<<7)
#define COGL_ENABLE_BACKFACE_CULLING (1<<8)
#define COGL_ENABLE_ALPHA_TEST (1<<2)
#define COGL_ENABLE_VERTEX_ARRAY (1<<3)
#define COGL_ENABLE_COLOR_ARRAY (1<<4)
#define COGL_ENABLE_BACKFACE_CULLING (1<<5)
gint
_cogl_get_format_bpp (CoglPixelFormat format);

View File

@ -38,31 +38,17 @@
#define _COGL_MAX_BEZ_RECURSE_DEPTH 16
void
_cogl_rectangle (float x,
float y,
float width,
float height)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (ctx->color_alpha < 255
? COGL_ENABLE_BLEND : 0);
GE( glRectf (x, y, x + width, y + height) );
}
void
_cogl_path_add_node (gboolean new_sub_path,
float x,
float y)
{
CoglPathNode new_node;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
new_node.x = (x);
new_node.y = (y);
new_node.x = x;
new_node.y = y;
new_node.path_size = 0;
if (new_sub_path || ctx->path_nodes->len == 0)
@ -89,13 +75,18 @@ _cogl_path_add_node (gboolean new_sub_path,
void
_cogl_path_stroke_nodes ()
{
guint path_start = 0;
guint path_start = 0;
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (COGL_ENABLE_VERTEX_ARRAY
| (ctx->color_alpha < 255
? COGL_ENABLE_BLEND : 0));
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);
while (path_start < ctx->path_nodes->len)
{
@ -106,7 +97,7 @@ _cogl_path_stroke_nodes ()
(guchar *) path
+ G_STRUCT_OFFSET (CoglPathNode, x)) );
GE( glDrawArrays (GL_LINE_STRIP, 0, path->path_size) );
path_start += path->path_size;
}
}
@ -132,12 +123,22 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
CoglPathNode *path,
gboolean merge)
{
guint path_start = 0;
guint sub_path_num = 0;
float bounds_x;
float bounds_y;
float bounds_w;
float bounds_h;
guint path_start = 0;
guint sub_path_num = 0;
float bounds_x;
float bounds_y;
float bounds_w;
float bounds_h;
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
_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);
enable_flags |=
cogl_material_get_cogl_enable_flags (ctx->source_material);
cogl_enable (enable_flags);
_cogl_path_get_bounds (nodes_min, nodes_max,
&bounds_x, &bounds_y, &bounds_w, &bounds_h);
@ -159,11 +160,9 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
GE( glColorMask (FALSE, FALSE, FALSE, FALSE) );
GE( glDepthMask (FALSE) );
while (path_start < path_size)
{
cogl_enable (COGL_ENABLE_VERTEX_ARRAY);
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
(guchar *) path
+ G_STRUCT_OFFSET (CoglPathNode, x)) );
@ -201,17 +200,17 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
GE( glMatrixMode (GL_PROJECTION) );
GE( glPushMatrix () );
GE( glLoadIdentity () );
GE( glRecti (-1, 1, 1, -1) );
GE( glRecti (-1, 1, 1, -1) );
cogl_rectangle (-1.0, -1.0, 2, 2);
cogl_rectangle (-1.0, -1.0, 2, 2);
GE( glPopMatrix () );
GE( glMatrixMode (GL_MODELVIEW) );
GE( glPopMatrix () );
}
GE( glStencilMask (~(GLuint) 0) );
GE( glDepthMask (TRUE) );
GE( glColorMask (TRUE, TRUE, TRUE, TRUE) );
GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) );
GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
}
@ -226,6 +225,9 @@ _cogl_path_fill_nodes ()
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
_cogl_path_get_bounds (ctx->path_nodes_min, ctx->path_nodes_max,
&bounds_x, &bounds_y, &bounds_w, &bounds_h);
_cogl_add_path_to_stencil_buffer (ctx->path_nodes_min,
ctx->path_nodes_max,
ctx->path_nodes->len,
@ -233,9 +235,6 @@ _cogl_path_fill_nodes ()
CoglPathNode, 0),
ctx->clip.stencil_used);
_cogl_path_get_bounds (ctx->path_nodes_min, ctx->path_nodes_max,
&bounds_x, &bounds_y, &bounds_w, &bounds_h);
cogl_rectangle (bounds_x, bounds_y, bounds_w, bounds_h);
/* The stencil buffer now contains garbage so the clip area needs to

View File

@ -28,9 +28,9 @@
#include "cogl-bitmap.h"
typedef struct _CoglTexture CoglTexture;
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
typedef struct _CoglSpanIter CoglSpanIter;
typedef struct _CoglTexture CoglTexture;
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
typedef struct _CoglSpanIter CoglSpanIter;
struct _CoglTexSliceSpan
{
@ -59,7 +59,23 @@ struct _CoglTexture
gboolean auto_mipmap;
};
/* To improve batching of geometry when submitting vertices to OpenGL we
* log the texture rectangles we want to draw to a journal, so when we
* later flush the journal we aim to batch data, and gl draw calls. */
typedef struct _CoglJournalEntry
{
CoglHandle material;
gint n_layers;
guint32 fallback_mask;
GLuint layer0_override_texture;
} CoglJournalEntry;
CoglTexture*
_cogl_texture_pointer_from_handle (CoglHandle handle);
gboolean
_cogl_texture_span_has_waste (CoglTexture *tex,
gint x_span_index,
gint y_span_index);
#endif /* __COGL_TEXTURE_H */

File diff suppressed because it is too large Load Diff

294
gl/cogl.c
View File

@ -171,6 +171,10 @@ cogl_check_extension (const gchar *name, const gchar *ext)
void
cogl_paint_init (const CoglColor *color)
{
#if COGL_DEBUG
fprintf(stderr, "\n ============== Paint Start ================ \n");
#endif
GE( glClearColor (cogl_color_get_red_float (color),
cogl_color_get_green_float (color),
cogl_color_get_blue_float (color),
@ -180,16 +184,16 @@ cogl_paint_init (const CoglColor *color)
glDisable (GL_LIGHTING);
glDisable (GL_FOG);
/*
/*
* Disable the depth test for now as has some strange side effects,
* mainly on x/y axis rotation with multiple layers at same depth
* (eg rotating text on a bg has very strange effect). Seems no clean
* 100% effective way to fix without other odd issues.. So for now
* mainly on x/y axis rotation with multiple layers at same depth
* (eg rotating text on a bg has very strange effect). Seems no clean
* 100% effective way to fix without other odd issues.. So for now
* move to application to handle and add cogl_enable_depth_test()
* as for custom actors (i.e groups) to enable if need be.
*
* glEnable (GL_DEPTH_TEST);
* glEnable (GL_ALPHA_TEST)
* glEnable (GL_DEPTH_TEST);
* glEnable (GL_ALPHA_TEST)
* glDepthFunc (GL_LEQUAL);
* glAlphaFunc (GL_GREATER, 0.1);
*/
@ -199,33 +203,31 @@ cogl_paint_init (const CoglColor *color)
void
cogl_push_matrix (void)
{
glPushMatrix();
GE( glPushMatrix() );
}
void
cogl_pop_matrix (void)
{
glPopMatrix();
GE( glPopMatrix() );
}
void
cogl_scale (float x, float y)
{
glScalef ((float)(x),
(float)(y),
1.0);
GE( glScalef (x, y, 1.0) );
}
void
cogl_translate (float x, float y, float z)
{
glTranslatef (x, y, z);
GE( glTranslatef (x, y, z) );
}
void
cogl_rotate (float angle, float x, float y, float z)
{
glRotatef (angle, x, y, z);
GE( glRotatef (angle, x, y, z) );
}
static inline gboolean
@ -251,7 +253,7 @@ cogl_toggle_flag (CoglContext *ctx,
GE( glDisable (gl_flag) );
ctx->enable_flags &= ~flag;
}
return FALSE;
}
@ -278,7 +280,7 @@ cogl_toggle_client_flag (CoglContext *ctx,
GE( glDisableClientState (gl_flag) );
ctx->enable_flags &= ~flag;
}
return FALSE;
}
@ -289,33 +291,19 @@ cogl_enable (gulong flags)
* hope of lessening number GL traffic.
*/
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_toggle_flag (ctx, flags,
COGL_ENABLE_BLEND,
GL_BLEND);
cogl_toggle_flag (ctx, flags,
COGL_ENABLE_TEXTURE_2D,
GL_TEXTURE_2D);
cogl_toggle_flag (ctx, flags,
COGL_ENABLE_BACKFACE_CULLING,
GL_CULL_FACE);
#ifdef GL_TEXTURE_RECTANGLE_ARB
cogl_toggle_flag (ctx, flags,
COGL_ENABLE_TEXTURE_RECT,
GL_TEXTURE_RECTANGLE_ARB);
#endif
cogl_toggle_client_flag (ctx, flags,
COGL_ENABLE_VERTEX_ARRAY,
GL_VERTEX_ARRAY);
cogl_toggle_client_flag (ctx, flags,
COGL_ENABLE_TEXCOORD_ARRAY,
GL_TEXTURE_COORD_ARRAY);
cogl_toggle_client_flag (ctx, flags,
COGL_ENABLE_COLOR_ARRAY,
GL_COLOR_ARRAY);
@ -325,25 +313,8 @@ gulong
cogl_get_enable ()
{
_COGL_GET_CONTEXT (ctx, 0);
return ctx->enable_flags;
}
void
cogl_blend_func (COGLenum src_factor, COGLenum dst_factor)
{
/* This function caches the blending setup in the
* hope of lessening GL traffic.
*/
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (ctx->blend_src_factor != src_factor ||
ctx->blend_dst_factor != dst_factor)
{
glBlendFunc (src_factor, dst_factor);
ctx->blend_src_factor = src_factor;
ctx->blend_dst_factor = dst_factor;
}
return ctx->enable_flags;
}
void
@ -351,14 +322,14 @@ cogl_enable_depth_test (gboolean setting)
{
if (setting)
{
glEnable (GL_DEPTH_TEST);
glEnable (GL_DEPTH_TEST);
glEnable (GL_ALPHA_TEST);
glDepthFunc (GL_LEQUAL);
glAlphaFunc (GL_GREATER, 0.1);
}
else
{
glDisable (GL_DEPTH_TEST);
glDisable (GL_DEPTH_TEST);
glDisable (GL_ALPHA_TEST);
}
}
@ -375,21 +346,19 @@ void
cogl_set_source_color (const CoglColor *color)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
glColor4ub (cogl_color_get_red_byte (color),
cogl_color_get_green_byte (color),
cogl_color_get_blue_byte (color),
cogl_color_get_alpha_byte (color));
/* Store alpha for proper blending enables */
ctx->color_alpha = cogl_color_get_alpha_byte (color);
/* In case cogl_set_source_texture was previously used... */
cogl_material_remove_layer (ctx->default_material, 0);
cogl_material_set_color (ctx->default_material, color);
cogl_set_source (ctx->default_material);
}
static void
apply_matrix (const GLfloat *matrix, GLfloat *vertex)
apply_matrix (const float *matrix, float *vertex)
{
int x, y;
GLfloat vertex_out[4] = { 0 };
float vertex_out[4] = { 0 };
for (y = 0; y < 4; y++)
for (x = 0; x < 4; x++)
@ -399,7 +368,9 @@ apply_matrix (const GLfloat *matrix, GLfloat *vertex)
}
static void
project_vertex (GLfloat *modelview, GLfloat *project, GLfloat *vertex)
project_vertex (float *modelview,
float *project,
float *vertex)
{
int i;
@ -414,8 +385,8 @@ project_vertex (GLfloat *modelview, GLfloat *project, GLfloat *vertex)
static void
set_clip_plane (GLint plane_num,
const GLfloat *vertex_a,
const GLfloat *vertex_b)
const float *vertex_a,
const float *vertex_b)
{
GLdouble plane[4];
GLfloat angle;
@ -423,15 +394,15 @@ set_clip_plane (GLint plane_num,
/* Calculate the angle between the axes and the line crossing the
two points */
angle = atan2f ((vertex_b[1] - vertex_a[1]),
(vertex_b[0] - vertex_a[0])) * 180.0f / G_PI;
angle = atan2f (vertex_b[1] - vertex_a[1],
vertex_b[0] - vertex_a[0]) * (180.0/G_PI);
GE( glPushMatrix () );
/* Load the identity matrix and multiply by the reverse of the
projection matrix so we can specify the plane in screen
coordinates */
GE( glLoadIdentity () );
GE( glMultMatrixf (ctx->inverse_projection) );
GE( glMultMatrixf ((GLfloat *) ctx->inverse_projection) );
/* Rotate about point a */
GE( glTranslatef (vertex_a[0], vertex_a[1], vertex_a[2]) );
/* Rotate the plane by the calculated angle so that it will connect
@ -439,9 +410,9 @@ set_clip_plane (GLint plane_num,
GE( glRotatef (angle, 0.0f, 0.0f, 1.0f) );
GE( glTranslatef (-vertex_a[0], -vertex_a[1], -vertex_a[2]) );
plane[0] = 0.0f;
plane[1] = -1.0f;
plane[2] = 0.0f;
plane[0] = 0;
plane[1] = -1.0;
plane[2] = 0;
plane[3] = vertex_a[1];
GE( glClipPlane (plane_num, plane) );
@ -456,18 +427,11 @@ _cogl_set_clip_planes (float x_offset,
{
GLfloat modelview[16], projection[16];
GLfloat vertex_tl[4] = { (x_offset),
(y_offset),
0.0f, 1.0f };
GLfloat vertex_tr[4] = { (x_offset + width),
(y_offset),
0.0f, 1.0f };
GLfloat vertex_bl[4] = { (x_offset),
(y_offset + height),
0.0f, 1.0f };
GLfloat vertex_br[4] = { (x_offset + width),
(y_offset + height),
0.0f, 1.0f };
float vertex_tl[4] = { x_offset, y_offset, 0, 1.0 };
float vertex_tr[4] = { x_offset + width, y_offset, 0, 1.0 };
float vertex_bl[4] = { x_offset, y_offset + height, 0, 1.0 };
float vertex_br[4] = { x_offset + width, y_offset + height,
0, 1.0 };
GE( glGetFloatv (GL_MODELVIEW_MATRIX, modelview) );
GE( glGetFloatv (GL_PROJECTION_MATRIX, projection) );
@ -485,7 +449,7 @@ _cogl_set_clip_planes (float x_offset,
if ((vertex_tl[0] < vertex_tr[0] ? 1 : 0)
!= (vertex_bl[1] < vertex_tl[1] ? 1 : 0))
{
GLfloat temp[4];
float temp[4];
memcpy (temp, vertex_tl, sizeof (temp));
memcpy (vertex_tl, vertex_tr, sizeof (temp));
memcpy (vertex_tr, temp, sizeof (temp));
@ -512,7 +476,7 @@ _cogl_add_stencil_clip (float x_offset,
if (first)
{
GE( glEnable (GL_STENCIL_TEST) );
/* Initially disallow everything */
GE( glClearStencil (0) );
GE( glClear (GL_STENCIL_BUFFER_BIT) );
@ -545,7 +509,7 @@ _cogl_add_stencil_clip (float x_offset,
GE( glMatrixMode (GL_PROJECTION) );
GE( glPushMatrix () );
GE( glLoadIdentity () );
GE( glRecti (-1, 1, 1, -1) );
GE( glRectf (-1, 1, 1, -1) );
GE( glPopMatrix () );
GE( glMatrixMode (GL_MODELVIEW) );
GE( glPopMatrix () );
@ -559,14 +523,8 @@ _cogl_add_stencil_clip (float x_offset,
void
_cogl_set_matrix (const float *matrix)
{
float float_matrix[16];
int i;
for (i = 0; i < 16; i++)
float_matrix[i] = (matrix[i]);
GE( glLoadIdentity () );
GE( glMultMatrixf (float_matrix) );
GE( glMultMatrixf (matrix) );
}
void
@ -593,13 +551,6 @@ _cogl_disable_clip_planes (void)
GE( glDisable (GL_CLIP_PLANE0) );
}
void
cogl_alpha_func (COGLenum func,
float ref)
{
GE( glAlphaFunc (func, (ref)) );
}
void
cogl_perspective (float fovy,
float aspect,
@ -637,26 +588,27 @@ cogl_perspective (float fovy,
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.0F;
M(0,0) = x;
M(1,1) = y;
M(2,2) = c;
M(2,3) = d;
M(3,2) = -1.0;
GE( glMultMatrixf (m) );
GE( glMatrixMode (GL_MODELVIEW) );
/* Calculate and store the inverse of the matrix */
memset (ctx->inverse_projection, 0, sizeof (GLfloat) * 16);
memset (ctx->inverse_projection, 0, sizeof (float) * 16);
#define m ctx->inverse_projection
M(0, 0) = 1.0f / (x);
M(1, 1) = 1.0f / (y);
M(2, 3) = -1.0f;
M(3, 2) = 1.0f / (d);
M(3, 3) = (c) / (d);
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
}
@ -668,7 +620,7 @@ cogl_frustum (float left,
float z_near,
float z_far)
{
GLfloat c, d;
float c, d;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -685,24 +637,18 @@ cogl_frustum (float left,
GE( glMatrixMode (GL_MODELVIEW) );
/* Calculate and store the inverse of the matrix */
memset (ctx->inverse_projection, 0, sizeof (GLfloat) * 16);
memset (ctx->inverse_projection, 0, sizeof (float) * 16);
c = - (z_far + z_near)
/ (z_far - z_near);
d = - (2 * (z_far * z_near))
/ (z_far - z_near);
c = - (z_far + z_near) / (z_far - z_near);
d = - (2 * (z_far * z_near)) / (z_far - z_near);
#define M(row,col) ctx->inverse_projection[col*4+row]
M(0,0) = (right - left)
/ (2 * z_near);
M(0,3) = (right + left)
/ (2 * z_near);
M(1,1) = (top - bottom)
/ (2 * z_near);
M(1,3) = (top + bottom)
/ (2 * z_near);
M(2,3) = -1.0f;
M(3,2) = 1.0f / d;
M(0,0) = (right - left) / (2 * z_near);
M(0,3) = (right + left) / (2 * z_near);
M(1,1) = (top - bottom) / (2 * z_near);
M(1,3) = (top + bottom) / (2 * z_near);
M(2,3) = -1.0;
M(3,2) = 1.0 / d;
M(3,3) = c / d;
#undef M
}
@ -715,18 +661,22 @@ cogl_viewport (guint width,
}
void
cogl_setup_viewport (guint width,
guint height,
cogl_setup_viewport (guint width,
guint height,
float fovy,
float aspect,
float z_near,
float z_far)
{
GLfloat z_camera;
GLfloat projection_matrix[16];
float z_camera;
float projection_matrix[16];
GE( glViewport (0, 0, width, height) );
/* For Ortho projection.
* glOrthof (0, width << 16, 0, height << 16, -1 << 16, 1 << 16);
*/
cogl_perspective (fovy, aspect, z_near, z_far);
/*
@ -774,9 +724,7 @@ cogl_setup_viewport (guint width,
GE( glLoadIdentity () );
GE( glTranslatef (-0.5f, -0.5f, -z_camera) );
GE( glScalef ( 1.0f / width,
-1.0f / height,
1.0f / width) );
GE( glScalef (1.0f / width, -1.0f / height, 1.0f / width) );
GE( glTranslatef (0.0f, -1.0 * height, 0.0f) );
}
@ -815,7 +763,7 @@ _cogl_features_init ()
GLint num_stencil_bits = 0;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
flags = COGL_FEATURE_TEXTURE_READ_PIXELS;
gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);
@ -827,7 +775,7 @@ _cogl_features_init ()
#endif
flags |= COGL_FEATURE_TEXTURE_NPOT;
}
#ifdef GL_YCBCR_MESA
if (cogl_check_extension ("GL_MESA_ycbcr_texture", gl_extensions))
{
@ -842,47 +790,47 @@ _cogl_features_init ()
ctx->pf_glCreateProgramObjectARB =
(COGL_PFNGLCREATEPROGRAMOBJECTARBPROC)
cogl_get_proc_address ("glCreateProgramObjectARB");
ctx->pf_glCreateShaderObjectARB =
(COGL_PFNGLCREATESHADEROBJECTARBPROC)
cogl_get_proc_address ("glCreateShaderObjectARB");
ctx->pf_glShaderSourceARB =
(COGL_PFNGLSHADERSOURCEARBPROC)
cogl_get_proc_address ("glShaderSourceARB");
ctx->pf_glCompileShaderARB =
(COGL_PFNGLCOMPILESHADERARBPROC)
cogl_get_proc_address ("glCompileShaderARB");
ctx->pf_glAttachObjectARB =
(COGL_PFNGLATTACHOBJECTARBPROC)
cogl_get_proc_address ("glAttachObjectARB");
ctx->pf_glLinkProgramARB =
(COGL_PFNGLLINKPROGRAMARBPROC)
cogl_get_proc_address ("glLinkProgramARB");
ctx->pf_glUseProgramObjectARB =
(COGL_PFNGLUSEPROGRAMOBJECTARBPROC)
cogl_get_proc_address ("glUseProgramObjectARB");
ctx->pf_glGetUniformLocationARB =
(COGL_PFNGLGETUNIFORMLOCATIONARBPROC)
cogl_get_proc_address ("glGetUniformLocationARB");
ctx->pf_glDeleteObjectARB =
(COGL_PFNGLDELETEOBJECTARBPROC)
cogl_get_proc_address ("glDeleteObjectARB");
ctx->pf_glGetInfoLogARB =
(COGL_PFNGLGETINFOLOGARBPROC)
cogl_get_proc_address ("glGetInfoLogARB");
ctx->pf_glGetObjectParameterivARB =
(COGL_PFNGLGETOBJECTPARAMETERIVARBPROC)
cogl_get_proc_address ("glGetObjectParameterivARB");
ctx->pf_glUniform1fARB =
(COGL_PFNGLUNIFORM1FARBPROC)
cogl_get_proc_address ("glUniform1fARB");
@ -898,7 +846,7 @@ _cogl_features_init ()
ctx->pf_glDisableVertexAttribArrayARB =
(COGL_PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)
cogl_get_proc_address ("glDisableVertexAttribArrayARB");
ctx->pf_glUniform2fARB =
(COGL_PFNGLUNIFORM2FARBPROC)
cogl_get_proc_address ("glUniform2fARB");
@ -962,7 +910,7 @@ _cogl_features_init ()
ctx->pf_glUniformMatrix2fvARB =
(COGL_PFNGLUNIFORMMATRIX2FVARBPROC)
cogl_get_proc_address ("glUniformMatrix2fvARB");
ctx->pf_glUniformMatrix3fvARB =
(COGL_PFNGLUNIFORMMATRIX3FVARBPROC)
cogl_get_proc_address ("glUniformMatrix3fvARB");
@ -1006,50 +954,50 @@ _cogl_features_init ()
ctx->pf_glDisableVertexAttribArrayARB)
flags |= COGL_FEATURE_SHADERS_GLSL;
}
if (cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions) ||
cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions))
{
{
ctx->pf_glGenRenderbuffersEXT =
(COGL_PFNGLGENRENDERBUFFERSEXTPROC)
cogl_get_proc_address ("glGenRenderbuffersEXT");
ctx->pf_glDeleteRenderbuffersEXT =
(COGL_PFNGLDELETERENDERBUFFERSEXTPROC)
cogl_get_proc_address ("glDeleteRenderbuffersEXT");
ctx->pf_glBindRenderbufferEXT =
(COGL_PFNGLBINDRENDERBUFFEREXTPROC)
cogl_get_proc_address ("glBindRenderbufferEXT");
ctx->pf_glRenderbufferStorageEXT =
(COGL_PFNGLRENDERBUFFERSTORAGEEXTPROC)
cogl_get_proc_address ("glRenderbufferStorageEXT");
ctx->pf_glGenFramebuffersEXT =
(COGL_PFNGLGENFRAMEBUFFERSEXTPROC)
cogl_get_proc_address ("glGenFramebuffersEXT");
ctx->pf_glBindFramebufferEXT =
(COGL_PFNGLBINDFRAMEBUFFEREXTPROC)
cogl_get_proc_address ("glBindFramebufferEXT");
ctx->pf_glFramebufferTexture2DEXT =
(COGL_PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
cogl_get_proc_address ("glFramebufferTexture2DEXT");
ctx->pf_glFramebufferRenderbufferEXT =
(COGL_PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
cogl_get_proc_address ("glFramebufferRenderbufferEXT");
ctx->pf_glCheckFramebufferStatusEXT =
(COGL_PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
cogl_get_proc_address ("glCheckFramebufferStatusEXT");
ctx->pf_glDeleteFramebuffersEXT =
(COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC)
cogl_get_proc_address ("glDeleteFramebuffersEXT");
if (ctx->pf_glGenRenderbuffersEXT &&
ctx->pf_glBindRenderbufferEXT &&
ctx->pf_glRenderbufferStorageEXT &&
@ -1061,23 +1009,23 @@ _cogl_features_init ()
ctx->pf_glDeleteFramebuffersEXT)
flags |= COGL_FEATURE_OFFSCREEN;
}
if (cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
{
ctx->pf_glBlitFramebufferEXT =
(COGL_PFNGLBLITFRAMEBUFFEREXTPROC)
cogl_get_proc_address ("glBlitFramebufferEXT");
if (ctx->pf_glBlitFramebufferEXT)
flags |= COGL_FEATURE_OFFSCREEN_BLIT;
}
if (cogl_check_extension ("GL_EXT_framebuffer_multisample", gl_extensions))
{
ctx->pf_glRenderbufferStorageMultisampleEXT =
(COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)
cogl_get_proc_address ("glRenderbufferStorageMultisampleEXT");
if (ctx->pf_glRenderbufferStorageMultisampleEXT)
flags |= COGL_FEATURE_OFFSCREEN_MULTISAMPLE;
}
@ -1140,10 +1088,10 @@ CoglFeatureFlags
cogl_get_features ()
{
_COGL_GET_CONTEXT (ctx, 0);
if (!ctx->features_cached)
_cogl_features_init ();
return ctx->feature_flags;
}
@ -1151,10 +1099,10 @@ gboolean
cogl_features_available (CoglFeatureFlags features)
{
_COGL_GET_CONTEXT (ctx, 0);
if (!ctx->features_cached)
_cogl_features_init ();
return (ctx->feature_flags & features) == features;
}
@ -1205,8 +1153,8 @@ cogl_get_bitmasks (gint *red, gint *green, gint *blue, gint *alpha)
void
cogl_fog_set (const CoglColor *fog_color,
float density,
float start,
float stop)
float z_near,
float z_far)
{
GLfloat fogColor[4];
@ -1222,8 +1170,8 @@ cogl_fog_set (const CoglColor *fog_color,
glFogi (GL_FOG_MODE, GL_LINEAR);
glHint (GL_FOG_HINT, GL_NICEST);
glFogf (GL_FOG_DENSITY, (density));
glFogf (GL_FOG_START, (start));
glFogf (GL_FOG_END, (stop));
glFogf (GL_FOG_DENSITY, (GLfloat) density);
glFogf (GL_FOG_START, (GLfloat) z_near);
glFogf (GL_FOG_END, (GLfloat) z_far);
}

View File

@ -10,7 +10,9 @@ libclutterinclude_HEADERS = \
$(top_builddir)/clutter/cogl/cogl-shader.h \
$(top_builddir)/clutter/cogl/cogl-texture.h \
$(top_builddir)/clutter/cogl/cogl-types.h \
$(top_builddir)/clutter/cogl/cogl-vertex-buffer.h
$(top_builddir)/clutter/cogl/cogl-vertex-buffer.h \
$(top_builddir)/clutter/cogl/cogl-material.h \
$(top_builddir)/clutter/cogl/cogl-matrix.h
INCLUDES = \
-I$(top_srcdir) \

View File

@ -28,65 +28,108 @@
#endif
#include "cogl.h"
#include <string.h>
#include "cogl-internal.h"
#include "cogl-util.h"
#include "cogl-context.h"
#include "cogl-texture-private.h"
#include "cogl-material-private.h"
#include "cogl-gles2-wrapper.h"
#include <string.h>
static CoglContext *_context = NULL;
gboolean
cogl_create_context ()
{
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
gulong enable_flags = 0;
if (_context != NULL)
return FALSE;
/* Allocate context memory */
_context = (CoglContext*) g_malloc (sizeof (CoglContext));
/* Init default values */
_context->feature_flags = 0;
_context->features_cached = FALSE;
_context->enable_flags = 0;
_context->color_alpha = 255;
_context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
_context->last_path = 0;
_context->material_handles = NULL;
_context->material_layer_handles = NULL;
_context->default_material = cogl_material_new ();
_context->source_material = NULL;
_context->texture_handles = NULL;
_context->texture_vertices = g_array_new (FALSE, FALSE,
_context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE;
_context->default_gl_texture_rect_tex = COGL_INVALID_HANDLE;
_context->texture_download_material = COGL_INVALID_HANDLE;
_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));
_context->texture_indices = g_array_new (FALSE, FALSE,
sizeof (GLushort));
_context->current_material = NULL;
_context->current_material_flags = 0;
_context->current_layers = g_array_new (FALSE, FALSE,
sizeof (CoglLayerInfo));
_context->n_texcoord_arrays_enabled = 0;
_context->fbo_handles = NULL;
_context->program_handles = NULL;
_context->shader_handles = NULL;
_context->draw_buffer = COGL_WINDOW_BUFFER;
_context->shader_handles = NULL;
_context->program_handles = NULL;
_context->vertex_buffer_handles = NULL;
_context->blend_src_factor = CGL_SRC_ALPHA;
_context->blend_dst_factor = CGL_ONE_MINUS_SRC_ALPHA;
_context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
_context->last_path = 0;
_context->stencil_material = cogl_material_new ();
/* Init the GLES2 wrapper */
#ifdef HAVE_COGL_GLES2
cogl_gles2_wrapper_init (&_context->gles2);
#endif
/* Init OpenGL state */
GE( cogl_wrap_glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) );
GE( glColorMask (TRUE, TRUE, TRUE, FALSE) );
GE( glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) );
cogl_enable (0);
/* Initialise the clip stack */
_cogl_clip_stack_state_init ();
/* Create default textures used for fall backs */
_context->default_gl_texture_2d_tex =
cogl_texture_new_from_data (1, /* width */
1, /* height */
-1, /* max waste */
FALSE, /* auto mipmap */
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
/* internal format */
COGL_PIXEL_FORMAT_RGBA_8888,
0, /* auto calc row stride */
&default_texture_data);
_context->default_gl_texture_rect_tex =
cogl_texture_new_from_data (1, /* width */
1, /* height */
-1, /* max waste */
FALSE, /* auto mipmap */
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
/* internal format */
COGL_PIXEL_FORMAT_RGBA_8888,
0, /* auto calc row stride */
&default_texture_data);
cogl_set_source (_context->default_material);
cogl_material_flush_gl_state (_context->source_material, NULL);
enable_flags =
cogl_material_get_cogl_enable_flags (_context->source_material);
cogl_enable (enable_flags);
return TRUE;
}
@ -101,15 +144,6 @@ cogl_destroy_context ()
if (_context->path_nodes)
g_array_free (_context->path_nodes, TRUE);
#ifdef HAVE_COGL_GLES2
cogl_gles2_wrapper_deinit (&_context->gles2);
#endif
if (_context->texture_vertices)
g_array_free (_context->texture_vertices, TRUE);
if (_context->texture_indices)
g_array_free (_context->texture_indices, TRUE);
if (_context->texture_handles)
g_array_free (_context->texture_handles, TRUE);
if (_context->fbo_handles)
@ -118,16 +152,36 @@ cogl_destroy_context ()
g_array_free (_context->shader_handles, TRUE);
if (_context->program_handles)
g_array_free (_context->program_handles, TRUE);
if (_context->default_gl_texture_2d_tex)
cogl_texture_unref (_context->default_gl_texture_2d_tex);
if (_context->default_gl_texture_rect_tex)
cogl_texture_unref (_context->default_gl_texture_rect_tex);
if (_context->default_material)
cogl_material_unref (_context->default_material);
if (_context->journal)
g_array_free (_context->journal, TRUE);
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);
g_free (_context);
}
CoglContext *
_cogl_context_get_default ()
{
/* Create if doesn't exists yet */
/* Create if doesn't exist yet */
if (_context == NULL)
cogl_create_context ();
return _context;
}

View File

@ -41,52 +41,69 @@ typedef struct
typedef struct
{
/* Features cache */
CoglFeatureFlags feature_flags;
gboolean features_cached;
/* Enable cache */
gulong enable_flags;
guint8 color_alpha;
COGLenum blend_src_factor;
COGLenum blend_dst_factor;
CoglFeatureFlags feature_flags;
gboolean features_cached;
/* Enable cache */
gulong enable_flags;
guint8 color_alpha;
gboolean enable_backface_culling;
gboolean enable_backface_culling;
/* Primitives */
floatVec2 path_start;
floatVec2 path_pen;
GArray *path_nodes;
guint last_path;
floatVec2 path_nodes_min;
floatVec2 path_nodes_max;
/* Cache of inverse projection matrix */
float inverse_projection[16];
/* Materials */
GArray *material_handles;
GArray *material_layer_handles;
CoglHandle default_material;
CoglHandle source_material;
/* Textures */
GArray *texture_handles;
GArray *texture_vertices;
GArray *texture_indices;
/* The gl texture number that the above vertices apply to. This to
detect when a different slice is encountered so that the vertices
can be flushed */
GLuint texture_current;
GLenum texture_target;
GLenum texture_format;
GArray *texture_handles;
CoglHandle default_gl_texture_2d_tex;
CoglHandle default_gl_texture_rect_tex;
CoglHandle texture_download_material;
/* Batching geometry... */
/* We journal the texture rectangles we want to submit to OpenGL so
* we have an oppertunity to optimise the final order so that we
* can batch things together. */
GArray *journal;
GArray *logged_vertices;
GArray *static_indices;
GArray *polygon_vertices;
/* Some simple caching, to minimize state changes... */
CoglHandle current_material;
gulong current_material_flags;
GArray *current_layers;
guint n_texcoord_arrays_enabled;
/* Framebuffer objects */
GArray *fbo_handles;
CoglBufferTarget draw_buffer;
GArray *fbo_handles;
CoglBufferTarget draw_buffer;
/* Shaders */
GArray *program_handles;
GArray *shader_handles;
GArray *shader_handles;
/* Vertex buffers */
GArray *vertex_buffer_handles;
/* Programs */
GArray *program_handles;
/* Clip stack */
CoglClipStackState clip;
CoglClipStackState clip;
/* Vertex buffers */
GArray *vertex_buffer_handles;
/* Primitives */
floatVec2 path_start;
floatVec2 path_pen;
GArray *path_nodes;
guint last_path;
floatVec2 path_nodes_min;
floatVec2 path_nodes_max;
CoglHandle stencil_material;
#ifdef HAVE_COGL_GLES2
CoglGles2Wrapper gles2;
@ -95,7 +112,7 @@ typedef struct
supported */
GLint viewport_store[4];
#endif
} CoglContext;
CoglContext *
@ -106,6 +123,6 @@ _cogl_context_get_default ();
CoglContext *ctxvar = _cogl_context_get_default (); \
if (ctxvar == NULL) return retval;
#define NO_RETVAL
#define NO_RETVAL
#endif /* __COGL_CONTEXT_H */

View File

@ -162,7 +162,11 @@ G_BEGIN_DECLS
#define CGL_STENCIL_PASS_DEPTH_PASS GL_STENCIL_PASS_DEPTH_PASS
#define CGL_STENCIL_REF GL_STENCIL_REF
#define CGL_STENCIL_WRITEMASK GL_STENCIL_WRITEMASK
#ifdef HAVE_COGL_GLES2
#define CGL_MATRIX_MODE 0x0BA0 /* bad style but works for now */
#else
#define CGL_MATRIX_MODE GL_MATRIX_MODE
#endif
#define CGL_VIEWPORT GL_VIEWPORT
#define CGL_MODELVIEW_STACK_DEPTH GL_MODELVIEW_STACK_DEPTH
#define CGL_PROJECTION_STACK_DEPTH GL_PROJECTION_STACK_DEPTH
@ -190,7 +194,11 @@ G_BEGIN_DECLS
#define CGL_MAX_VIEWPORT_DIMS GL_MAX_VIEWPORT_DIMS
#define CGL_MAX_ELEMENTS_VERTICES GL_MAX_ELEMENTS_VERTICES
#define CGL_MAX_ELEMENTS_INDICES GL_MAX_ELEMENTS_INDICES
#define CGL_MAX_TEXTURE_UNITS GL_MAX_TEXTURE_UNITS
#ifdef HAVE_COGL_GLES2
#define CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
#else
#define CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS GL_MAX_TEXTURE_UNITS
#endif
#define CGL_SUBPIXEL_BITS GL_SUBPIXEL_BITS
#define CGL_RED_BITS GL_RED_BITS
#define CGL_GREEN_BITS GL_GREEN_BITS
@ -315,7 +323,7 @@ G_BEGIN_DECLS
/* PixelType */
/* GL_UNSIGNED_BYTE */
#define CGL_UNSIGNED_SHORT_4_4_4_4 GL_UNSIGNED_SHORT_4_4_4_4
#define CGL_UNSIGNED_SHORT_4_4_4_4 GL_UNSIGNED_SHORT_4_4_4_4
#define CGL_UNSIGNED_SHORT_5_5_5_1 GL_UNSIGNED_SHORT_5_5_5_1
#define CGL_UNSIGNED_SHORT_5_6_5 CGL_UNSIGNED_SHORT_5_6_5

View File

@ -206,29 +206,29 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
from a non-screen buffer */
GE( glGetIntegerv (GL_VIEWPORT, ctx->viewport_store) );
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
GE( cogl_wrap_glPushMatrix () );
GE( cogl_wrap_glLoadIdentity () );
GE( glMatrixMode (GL_PROJECTION) );
GE( glPushMatrix () );
GE( glLoadIdentity () );
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
GE( cogl_wrap_glPushMatrix () );
GE( cogl_wrap_glLoadIdentity () );
GE( glMatrixMode (GL_MODELVIEW) );
GE( glPushMatrix () );
GE( glLoadIdentity () );
}
else
{
/* Override viewport and matrix setup if redirecting
from another offscreen buffer */
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
GE( cogl_wrap_glLoadIdentity () );
GE( glMatrixMode (GL_PROJECTION) );
GE( glLoadIdentity () );
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
GE( cogl_wrap_glLoadIdentity () );
GE( glMatrixMode (GL_MODELVIEW) );
GE( glLoadIdentity () );
}
/* Setup new viewport and matrices */
GE( glViewport (0, 0, fbo->width, fbo->height) );
GE( cogl_wrap_glTranslatef (-1.0, -1.0, 0) );
GE( cogl_wrap_glScalef (((float)(2) /
GE( glTranslatef (-1.0, -1.0, 0) );
GE( glScalef (((float)(2) /
(float)(fbo->width)),
((float)(2) /
(float)(fbo->height)),
@ -265,11 +265,11 @@ cogl_draw_buffer (CoglBufferTarget target, CoglHandle offscreen)
GE( glViewport (ctx->viewport_store[0], ctx->viewport_store[1],
ctx->viewport_store[2], ctx->viewport_store[3]) );
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
GE( cogl_wrap_glPopMatrix () );
GE( glMatrixMode (GL_PROJECTION) );
GE( glPopMatrix () );
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
GE( cogl_wrap_glPopMatrix () );
GE( glMatrixMode (GL_MODELVIEW) );
GE( glPopMatrix () );
}
/* Bind window framebuffer object */

View File

@ -1,16 +1,20 @@
/*** cogl_fixed_fragment_shader_start ***/
/*** cogl_fixed_fragment_shader_variables_start ***/
/* There is no default precision for floats in fragment shaders in
GLES 2 so we need to define one */
precision mediump float;
precision highp float;
/*** cogl_fixed_fragment_shader_inputs ***/
/* Inputs from the vertex shader */
varying vec4 frag_color;
varying vec2 tex_coord;
varying float fog_amount;
/*** cogl_fixed_fragment_shader_texturing_options ***/
/* Texturing options */
uniform sampler2D texture_unit;
/*** cogl_fixed_fragment_shader_fogging_options ***/
/* Fogging options */
uniform vec4 fog_color;
@ -18,28 +22,13 @@ uniform vec4 fog_color;
/* Alpha test options */
uniform float alpha_test_ref;
/*** cogl_fixed_fragment_shader_main_declare ***/
void
main (void)
{
/*** cogl_fixed_fragment_shader_texture_alpha_only ***/
/*** cogl_fixed_fragment_shader_main_start ***/
/* If the texture only has an alpha channel (eg, with the textures
from the pango renderer) then the RGB components will be
black. We want to use the RGB from the current color in that
case */
gl_FragColor = frag_color;
gl_FragColor.a *= texture2D (texture_unit, tex_coord).a;
/*** cogl_fixed_fragment_shader_texture ***/
/* This pointless extra variable is needed to work around an
apparent bug in the PowerVR drivers. Without it the alpha
blending seems to stop working */
vec4 frag_color_copy = frag_color;
gl_FragColor = frag_color_copy * texture2D (texture_unit, tex_coord);
/*** cogl_fixed_fragment_shader_solid_color ***/
gl_FragColor = frag_color;
/*** cogl_fixed_fragment_shader_fog ***/

View File

@ -1,34 +1,41 @@
/*** cogl_fixed_vertex_shader_start ***/
/*** cogl_fixed_vertex_shader_per_vertex_attribs ***/
/* Per vertex attributes */
attribute vec4 vertex_attrib;
attribute vec4 tex_coord_attrib;
attribute vec4 color_attrib;
/*** cogl_fixed_vertex_shader_transform_matrices ***/
/* Transformation matrices */
uniform mat4 modelview_matrix;
uniform mat4 mvp_matrix; /* combined modelview and projection matrix */
uniform mat4 texture_matrix;
/*** cogl_fixed_vertex_shader_output_variables ***/
/* Outputs to the fragment shader */
varying vec4 frag_color;
varying vec2 tex_coord;
varying float fog_amount;
/*** cogl_fixed_vertex_shader_fogging_options ***/
/* Fogging options */
uniform float fog_density;
uniform float fog_start;
uniform float fog_end;
/*** cogl_fixed_vertex_shader_main_start ***/
void
main (void)
{
vec4 transformed_tex_coord;
/* Calculate the transformed position */
gl_Position = mvp_matrix * vertex_attrib;
/* Calculate the transformed texture coordinate */
vec4 transformed_tex_coord = texture_matrix * tex_coord_attrib;
tex_coord = transformed_tex_coord.st / transformed_tex_coord.q;
/*** cogl_fixed_vertex_shader_frag_color_start ***/
/* Pass the interpolated vertex color on to the fragment shader */
frag_color = color_attrib;

View File

@ -38,6 +38,7 @@
#include "cogl-context.h"
#include "cogl-shader-private.h"
#include "cogl-program.h"
#include "cogl-internal.h"
#define _COGL_GET_GLES2_WRAPPER(wvar, retval) \
CoglGles2Wrapper *wvar; \
@ -66,9 +67,9 @@
while (0)
#define COGL_GLES2_WRAPPER_VERTEX_ATTRIB 0
#define COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB 1
#define COGL_GLES2_WRAPPER_COLOR_ATTRIB 2
#define COGL_GLES2_WRAPPER_NORMAL_ATTRIB 3
#define COGL_GLES2_WRAPPER_COLOR_ATTRIB 1
#define COGL_GLES2_WRAPPER_NORMAL_ATTRIB 2
static GLuint
cogl_gles2_wrapper_create_shader (GLenum type, const char *source)
@ -109,13 +110,19 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
memset (wrapper, 0, sizeof (CoglGles2Wrapper));
/* Initialize the stacks */
cogl_wrap_glMatrixMode (GL_TEXTURE);
cogl_wrap_glLoadIdentity ();
cogl_wrap_glMatrixMode (GL_PROJECTION);
cogl_wrap_glLoadIdentity ();
cogl_wrap_glMatrixMode (GL_MODELVIEW);
cogl_wrap_glLoadIdentity ();
wrapper->texture_units =
g_array_new (FALSE, FALSE, sizeof (CoglGles2WrapperTextureUnit *));
/* The gl*ActiveTexture wrappers will initialise the texture
* stack for the texture unit when it's first activated */
cogl_wrap_glActiveTexture (GL_TEXTURE0);
cogl_wrap_glClientActiveTexture (GL_TEXTURE0);
/* Initialize the fogging options */
cogl_wrap_glDisable (GL_FOG);
cogl_wrap_glFogf (GL_FOG_MODE, GL_LINEAR);
@ -137,11 +144,14 @@ cogl_gles2_settings_equal (const CoglGles2WrapperSettings *a,
{
if (fragment_tests)
{
if (a->texture_2d_enabled != b->texture_2d_enabled)
return FALSE;
if (a->texture_2d_enabled && a->alpha_only != b->alpha_only)
return FALSE;
int i;
for (i = 0; i < a->n_texture_units; i++)
{
if (a->texture_units[i].enabled != b->texture_units[i].enabled)
return FALSE;
if (a->texture_units[i].alpha_only != b->texture_units[i].alpha_only)
return FALSE;
}
if (a->alpha_test_enabled != b->alpha_test_enabled)
return FALSE;
@ -165,6 +175,7 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
GLuint shader_obj;
CoglGles2WrapperShader *shader;
GSList *node;
int i;
_COGL_GET_GLES2_WRAPPER (w, NULL);
@ -177,7 +188,47 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
return (CoglGles2WrapperShader *) node->data;
/* Otherwise create a new shader */
shader_source = g_string_new (cogl_fixed_vertex_shader_start);
shader_source = g_string_new (cogl_fixed_vertex_shader_per_vertex_attribs);
for (i = 0; i < settings->n_texture_units; i++)
{
if (!settings->texture_units[i].enabled)
continue;
g_string_append_printf (shader_source,
"attribute vec4 multi_tex_coord_attrib%d;\n",
i);
}
g_string_append (shader_source, cogl_fixed_vertex_shader_transform_matrices);
g_string_append_printf (shader_source,
"uniform mat4 texture_matrix[%d];\n",
settings->n_texture_units);
g_string_append (shader_source, cogl_fixed_vertex_shader_output_variables);
g_string_append_printf (shader_source,
"varying vec2 tex_coord[%d];",
settings->n_texture_units);
g_string_append (shader_source, cogl_fixed_vertex_shader_fogging_options);
g_string_append (shader_source, cogl_fixed_vertex_shader_main_start);
for (i = 0; i < settings->n_texture_units; i++)
{
if (!settings->texture_units[i].enabled)
continue;
g_string_append_printf (shader_source,
"transformed_tex_coord = "
"texture_matrix[%d] "
" * multi_tex_coord_attrib%d;\n",
i, i);
g_string_append_printf (shader_source,
"tex_coord[%d] = transformed_tex_coord.st "
" / transformed_tex_coord.q;\n",
i);
}
g_string_append (shader_source, cogl_fixed_vertex_shader_frag_color_start);
if (settings->fog_enabled)
{
@ -207,10 +258,10 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
shader_source->str);
g_string_free (shader_source, TRUE);
if (shader_obj == 0)
return NULL;
shader = g_slice_new (CoglGles2WrapperShader);
shader->shader = shader_obj;
shader->settings = *settings;
@ -228,6 +279,7 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
GLuint shader_obj;
CoglGles2WrapperShader *shader;
GSList *node;
int i;
_COGL_GET_GLES2_WRAPPER (w, NULL);
@ -240,18 +292,61 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
return (CoglGles2WrapperShader *) node->data;
/* Otherwise create a new shader */
shader_source = g_string_new (cogl_fixed_fragment_shader_start);
if (settings->texture_2d_enabled)
shader_source = g_string_new (cogl_fixed_fragment_shader_variables_start);
g_string_append (shader_source, cogl_fixed_fragment_shader_inputs);
g_string_append_printf (shader_source,
"varying vec2 tex_coord[%d];\n",
settings->n_texture_units);
g_string_append (shader_source, cogl_fixed_fragment_shader_texturing_options);
g_string_append_printf (shader_source,
"uniform sampler2D texture_unit[%d];\n",
settings->n_texture_units);
g_string_append (shader_source, cogl_fixed_fragment_shader_fogging_options);
g_string_append (shader_source, cogl_fixed_fragment_shader_main_declare);
g_string_append (shader_source, cogl_fixed_fragment_shader_main_start);
/* This pointless extra variable is needed to work around an
apparent bug in the PowerVR drivers. Without it the alpha
blending seems to stop working */
/* g_string_append (shader_source, "gl_FragColor = frag_color;\n");
*/
g_string_append (shader_source,
"vec4 frag_color_copy = frag_color;\n");
g_string_append (shader_source, "gl_FragColor = frag_color;\n");
for (i = 0; i < settings->n_texture_units; i++)
{
if (settings->alpha_only)
g_string_append (shader_source,
cogl_fixed_fragment_shader_texture_alpha_only);
if (settings->texture_units[i].alpha_only)
{
/* If the texture only has an alpha channel (eg, with the textures
from the pango renderer) then the RGB components will be
black. We want to use the RGB from the current color in that
case */
g_string_append_printf (
shader_source,
"gl_FragColor.a *= "
"texture2D (texture_unit[%d], tex_coord[%d]).a;\n",
i, i);
}
else
g_string_append (shader_source,
cogl_fixed_fragment_shader_texture);
{
g_string_append_printf (
shader_source,
"gl_FragColor *= "
"texture2D (texture_unit[%d], tex_coord[%d]);\n",
i, i);
}
}
else
g_string_append (shader_source, cogl_fixed_fragment_shader_solid_color);
/* FIXME */
g_string_append (shader_source, "gl_FragColor.r = 1.0;\n");
g_string_append (shader_source, "gl_FragColor.g = 1.0;\n");
if (i == 0)
g_string_append (shader_source, "gl_FragColor = frag_color;\n");
if (settings->fog_enabled)
g_string_append (shader_source, cogl_fixed_fragment_shader_fog);
@ -294,10 +389,10 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
shader_source->str);
g_string_free (shader_source, TRUE);
if (shader_obj == 0)
return NULL;
shader = g_slice_new (CoglGles2WrapperShader);
shader->shader = shader_obj;
shader->settings = *settings;
@ -308,6 +403,69 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
return shader;
}
static void
cogl_gles2_wrapper_get_locations (GLuint program,
CoglGles2WrapperSettings *settings,
CoglGles2WrapperUniforms *uniforms,
CoglGles2WrapperAttributes *attribs)
{
int i;
uniforms->mvp_matrix_uniform
= glGetUniformLocation (program, "mvp_matrix");
uniforms->modelview_matrix_uniform
= glGetUniformLocation (program, "modelview_matrix");
uniforms->texture_matrix_uniforms =
g_array_new (FALSE, FALSE, sizeof (GLint));
uniforms->texture_sampler_uniforms =
g_array_new (FALSE, FALSE, sizeof (GLint));
attribs->multi_texture_coords =
g_array_new (FALSE, FALSE, sizeof (GLint));
for (i = 0; i < settings->n_texture_units; i++)
{
char *matrix_var_name = g_strdup_printf ("texture_matrix[%d]", i);
char *sampler_var_name = g_strdup_printf ("texture_unit[%d]", i);
char *tex_coord_var_name =
g_strdup_printf ("multi_tex_coord_attrib%d", i);
GLint location;
location = glGetUniformLocation (program, matrix_var_name);
g_array_append_val (uniforms->texture_matrix_uniforms, location);
location = glGetUniformLocation (program, sampler_var_name);
g_array_append_val (uniforms->texture_sampler_uniforms, location);
location = glGetAttribLocation (program, tex_coord_var_name);
g_array_append_val (attribs->multi_texture_coords, location);
g_free (tex_coord_var_name);
g_free (sampler_var_name);
g_free (matrix_var_name);
}
uniforms->fog_density_uniform
= glGetUniformLocation (program, "fog_density");
uniforms->fog_start_uniform
= glGetUniformLocation (program, "fog_start");
uniforms->fog_end_uniform
= glGetUniformLocation (program, "fog_end");
uniforms->fog_color_uniform
= glGetUniformLocation (program, "fog_color");
uniforms->alpha_test_ref_uniform
= glGetUniformLocation (program, "alpha_test_ref");
}
static void
cogl_gles2_wrapper_bind_attributes (GLuint program)
{
glBindAttribLocation (program, COGL_GLES2_WRAPPER_VERTEX_ATTRIB,
"vertex_attrib");
glBindAttribLocation (program, COGL_GLES2_WRAPPER_COLOR_ATTRIB,
"color_attrib");
glBindAttribLocation (program, COGL_GLES2_WRAPPER_NORMAL_ATTRIB,
"normal_attrib");
}
static CoglGles2WrapperProgram *
cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings)
{
@ -403,61 +561,22 @@ cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings)
}
program->settings = *settings;
cogl_gles2_wrapper_get_uniforms (program->program, &program->uniforms);
cogl_gles2_wrapper_get_locations (program->program,
&program->settings,
&program->uniforms,
&program->attributes);
/* We haven't tried to get a location for any of the custom uniforms
yet */
for (i = 0; i < COGL_GLES2_NUM_CUSTOM_UNIFORMS; i++)
program->custom_uniforms[i] = COGL_GLES2_UNBOUND_CUSTOM_UNIFORM;
w->compiled_programs = g_slist_append (w->compiled_programs, program);
return program;
}
void
cogl_gles2_wrapper_bind_attributes (GLuint program)
{
glBindAttribLocation (program, COGL_GLES2_WRAPPER_VERTEX_ATTRIB,
"vertex_attrib");
glBindAttribLocation (program, COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB,
"tex_coord_attrib");
glBindAttribLocation (program, COGL_GLES2_WRAPPER_COLOR_ATTRIB,
"color_attrib");
glBindAttribLocation (program, COGL_GLES2_WRAPPER_NORMAL_ATTRIB,
"normal_attrib");
}
void
cogl_gles2_wrapper_get_uniforms (GLuint program,
CoglGles2WrapperUniforms *uniforms)
{
uniforms->mvp_matrix_uniform
= glGetUniformLocation (program, "mvp_matrix");
uniforms->modelview_matrix_uniform
= glGetUniformLocation (program, "modelview_matrix");
uniforms->texture_matrix_uniform
= glGetUniformLocation (program, "texture_matrix");
uniforms->bound_texture_uniform
= glGetUniformLocation (program, "texture_unit");
uniforms->fog_density_uniform
= glGetUniformLocation (program, "fog_density");
uniforms->fog_start_uniform
= glGetUniformLocation (program, "fog_start");
uniforms->fog_end_uniform
= glGetUniformLocation (program, "fog_end");
uniforms->fog_color_uniform
= glGetUniformLocation (program, "fog_color");
uniforms->alpha_test_ref_uniform
= glGetUniformLocation (program, "alpha_test_ref");
uniforms->texture_unit_uniform
= glGetUniformLocation (program, "texture_unit");
}
void
cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper)
{
@ -493,9 +612,11 @@ cogl_gles2_wrapper_deinit (CoglGles2Wrapper *wrapper)
g_free (wrapper->custom_uniforms[i].v.array);
}
void
static void
cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper, GLenum matrix_num)
{
CoglGles2WrapperTextureUnit *texture_unit;
switch (matrix_num)
{
default:
@ -509,7 +630,11 @@ cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper, GLenum matrix_num)
break;
case GL_TEXTURE:
wrapper->dirty_uniforms |= COGL_GLES2_DIRTY_TEXTURE_MATRIX;
wrapper->dirty_uniforms |= COGL_GLES2_DIRTY_TEXTURE_MATRICES;
texture_unit = g_array_index (wrapper->texture_units,
CoglGles2WrapperTextureUnit *,
wrapper->active_texture_unit);
texture_unit->dirty_matrix = 1;
break;
}
}
@ -542,11 +667,19 @@ cogl_wrap_glPushMatrix ()
break;
case GL_TEXTURE:
src = w->texture_stack + w->texture_stack_pos * 16;
w->texture_stack_pos = (w->texture_stack_pos + 1)
& (COGL_GLES2_TEXTURE_STACK_SIZE - 1);
dst = w->texture_stack + w->texture_stack_pos * 16;
break;
{
CoglGles2WrapperTextureUnit *texture_unit;
texture_unit = g_array_index (w->texture_units,
CoglGles2WrapperTextureUnit *,
w->active_texture_unit);
src = texture_unit->texture_stack
+ texture_unit->texture_stack_pos * 16;
texture_unit->texture_stack_pos = (texture_unit->texture_stack_pos + 1)
& (COGL_GLES2_TEXTURE_STACK_SIZE - 1);
dst = texture_unit->texture_stack
+ texture_unit->texture_stack_pos * 16;
break;
}
}
/* Copy the old matrix to the new position */
@ -556,6 +689,7 @@ cogl_wrap_glPushMatrix ()
void
cogl_wrap_glPopMatrix ()
{
CoglGles2WrapperTextureUnit *texture_unit;
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
/* Decrement the stack pointer */
@ -573,7 +707,10 @@ cogl_wrap_glPopMatrix ()
break;
case GL_TEXTURE:
w->texture_stack_pos = (w->texture_stack_pos - 1)
texture_unit = g_array_index (w->texture_units,
CoglGles2WrapperTextureUnit *,
w->active_texture_unit);
texture_unit->texture_stack_pos = (texture_unit->texture_stack_pos - 1)
& (COGL_GLES2_TEXTURE_STACK_SIZE - 1);
break;
}
@ -593,6 +730,8 @@ cogl_wrap_glMatrixMode (GLenum mode)
static float *
cogl_gles2_get_matrix_stack_top (CoglGles2Wrapper *wrapper)
{
CoglGles2WrapperTextureUnit *texture_unit;
switch (wrapper->matrix_mode)
{
default:
@ -603,7 +742,12 @@ cogl_gles2_get_matrix_stack_top (CoglGles2Wrapper *wrapper)
return wrapper->projection_stack + wrapper->projection_stack_pos * 16;
case GL_TEXTURE:
return wrapper->texture_stack + wrapper->texture_stack_pos * 16;
texture_unit = g_array_index (wrapper->texture_units,
CoglGles2WrapperTextureUnit *,
wrapper->active_texture_unit);
return texture_unit->texture_stack
+ texture_unit->texture_stack_pos * 16;
}
}
@ -734,7 +878,7 @@ cogl_wrap_glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
float anglef = (angle) * G_PI / 180.0f;
float c = cosf (anglef);
float s = sinf (anglef);
matrix[0] = xf * xf * (1.0f - c) + c;
matrix[1] = yf * xf * (1.0f - c) + zf * s;
matrix[2] = xf * zf * (1.0f - c) - yf * s;
@ -791,8 +935,22 @@ void
cogl_wrap_glTexCoordPointer (GLint size, GLenum type, GLsizei stride,
const GLvoid *pointer)
{
glVertexAttribPointer (COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB, size, type,
GL_FALSE, stride, pointer);
int active_unit;
CoglGles2WrapperTextureUnit *texture_unit;
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
active_unit = w->active_client_texture_unit;
texture_unit = g_array_index (w->texture_units,
CoglGles2WrapperTextureUnit *,
active_unit);
texture_unit->texture_coords_size = size;
texture_unit->texture_coords_type = type;
texture_unit->texture_coords_stride = stride;
texture_unit->texture_coords_pointer = pointer;
w->dirty_attribute_pointers
|= COGL_GLES2_DIRTY_TEX_COORD_VERTEX_ATTRIB;
}
void
@ -926,7 +1084,7 @@ cogl_wrap_prepare_for_draw (void)
cogl_gles2_wrapper_mult_matrix (mvp_matrix,
w->projection_stack
+ w->projection_stack_pos * 16,
modelview_matrix);
modelview_matrix);
if (program->uniforms.mvp_matrix_uniform != -1)
glUniformMatrix4fv (program->uniforms.mvp_matrix_uniform, 1,
@ -935,11 +1093,28 @@ cogl_wrap_prepare_for_draw (void)
glUniformMatrix4fv (program->uniforms.modelview_matrix_uniform, 1,
GL_FALSE, modelview_matrix);
}
if ((w->dirty_uniforms & COGL_GLES2_DIRTY_TEXTURE_MATRIX)
&& program->uniforms.texture_matrix_uniform != -1)
glUniformMatrix4fv (program->uniforms.texture_matrix_uniform, 1,
GL_FALSE,
w->texture_stack + w->texture_stack_pos * 16);
if ((w->dirty_uniforms & COGL_GLES2_DIRTY_TEXTURE_MATRICES))
{
int i;
/* TODO - we should probably have a per unit dirty flag too */
for (i = 0; i < program->uniforms.texture_matrix_uniforms->len; i++)
{
CoglGles2WrapperTextureUnit *texture_unit;
GLint uniform =
g_array_index (program->uniforms.texture_matrix_uniforms,
GLint, i);
texture_unit = g_array_index (w->texture_units,
CoglGles2WrapperTextureUnit *,
i);
if (uniform != -1)
glUniformMatrix4fv (uniform, 1, GL_FALSE,
texture_unit->texture_stack
+ texture_unit->texture_stack_pos * 16);
}
}
if ((w->dirty_uniforms & COGL_GLES2_DIRTY_FOG_DENSITY)
&& program->uniforms.fog_density_uniform != -1)
@ -956,9 +1131,22 @@ cogl_wrap_prepare_for_draw (void)
glUniform1f (program->uniforms.alpha_test_ref_uniform,
w->alpha_test_ref);
if ((w->dirty_uniforms & COGL_GLES2_DIRTY_TEXTURE_UNIT)
&& program->uniforms.texture_unit_uniform != -1)
glUniform1i (program->uniforms.texture_unit_uniform, 0);
if ((w->dirty_uniforms & COGL_GLES2_DIRTY_TEXTURE_UNITS))
{
int i;
/* TODO - we should probably have a per unit dirty flag too */
for (i = 0; i < program->uniforms.texture_sampler_uniforms->len; i++)
{
GLint uniform =
g_array_index (program->uniforms.texture_sampler_uniforms,
GLint, i);
if (uniform != -1)
glUniform1i (uniform, i);
}
}
w->dirty_uniforms = 0;
}
@ -986,10 +1174,70 @@ cogl_wrap_prepare_for_draw (void)
&w->custom_uniforms[i]);
}
}
w->dirty_custom_uniforms = 0;
}
if (w->dirty_attribute_pointers
& COGL_GLES2_DIRTY_TEX_COORD_VERTEX_ATTRIB)
{
int i;
/* TODO - coverage test */
for (i = 0; i < w->settings.n_texture_units; i++)
{
GLint tex_coord_var_index;
CoglGles2WrapperTextureUnit *texture_unit;
if (!w->settings.texture_units[i].enabled)
continue;
texture_unit = g_array_index (w->texture_units,
CoglGles2WrapperTextureUnit *,
w->active_texture_unit);
if (!texture_unit->texture_coords_enabled)
continue;
/* TODO - we should probably have a per unit dirty flag too */
/* TODO - coverage test */
tex_coord_var_index =
g_array_index (program->attributes.multi_texture_coords,
GLint, i);
glVertexAttribPointer (tex_coord_var_index,
texture_unit->texture_coords_size,
texture_unit->texture_coords_type,
GL_FALSE,
texture_unit->texture_coords_stride,
texture_unit->texture_coords_pointer);
}
}
if (w->dirty_vertex_attrib_enables)
{
int i;
/* TODO - coverage test */
/* TODO - we should probably have a per unit dirty flag too */
for (i = 0; i < w->texture_units->len; i++)
{
CoglGles2WrapperTextureUnit *texture_unit =
g_array_index (w->texture_units,
CoglGles2WrapperTextureUnit *,
w->active_texture_unit);
if (texture_unit->texture_coords_enabled)
glEnableVertexAttribArray (
g_array_index (program->attributes.multi_texture_coords,
GLint, i));
else
glDisableVertexAttribArray (
g_array_index (program->attributes.multi_texture_coords,
GLint, i));
w->dirty_vertex_attrib_enables = 0;
}
}
}
void
@ -1020,7 +1268,10 @@ cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture,
/* We need to keep track of whether the texture is alpha-only
because the emulation of GL_MODULATE needs to work differently in
that case */
_COGL_GLES2_CHANGE_SETTING (w, alpha_only, internal_format == GL_ALPHA);
_COGL_GLES2_CHANGE_SETTING (
w, texture_units[w->active_texture_unit].alpha_only,
internal_format == GL_ALPHA);
}
void
@ -1031,6 +1282,79 @@ cogl_wrap_glTexEnvf (GLenum target, GLenum pname, GLfloat param)
nothing needs to be done here. */
}
static void
realize_texture_units (CoglGles2Wrapper *w, int texture_unit_index)
{
/* We save the active texture unit since we may need to temporarily
* change this to initialise each new texture unit and we want to
* restore the active unit afterwards */
int initial_active_unit = w->active_texture_unit;
if (texture_unit_index >= w->settings.n_texture_units)
{
int n_new_texture_units =
texture_unit_index + 1 - w->settings.n_texture_units;
GLint prev_mode;
int i;
w->settings.texture_units =
g_realloc (w->settings.texture_units,
texture_unit_index + 1
* sizeof (CoglGles2WrapperTextureUnitSettings));
/* We will need to set the matrix mode to GL_TEXTURE to
* initialise any new texture units, so we save the current
* mode for restoring afterwards */
GE( cogl_wrap_glGetIntegerv (CGL_MATRIX_MODE, &prev_mode));
for (i = 0; i < n_new_texture_units; i++)
{
CoglGles2WrapperTextureUnit *new_unit;
CoglGles2WrapperTextureUnitSettings *new_unit_settings;
new_unit = g_new0 (CoglGles2WrapperTextureUnit, 1);
g_array_append_val (w->texture_units, new_unit);
w->active_texture_unit = i;
GE( cogl_wrap_glMatrixMode (GL_TEXTURE));
GE( cogl_wrap_glLoadIdentity ());
new_unit_settings =
&w->settings.texture_units[w->settings.n_texture_units + i];
new_unit_settings->enabled = FALSE;
new_unit_settings->alpha_only = FALSE;
}
GE( cogl_wrap_glMatrixMode ((GLenum)prev_mode));
w->settings.n_texture_units = w->texture_units->len;
}
w->active_texture_unit = initial_active_unit;
}
void
cogl_wrap_glClientActiveTexture (GLenum texture)
{
int texture_unit_index = texture - GL_TEXTURE0;
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
w->active_client_texture_unit = texture_unit_index;
realize_texture_units (w, texture_unit_index);
}
void
cogl_wrap_glActiveTexture (GLenum texture)
{
int texture_unit_index = texture - GL_TEXTURE0;
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
w->active_texture_unit = texture_unit_index;
realize_texture_units (w, texture_unit_index);
}
void
cogl_wrap_glEnable (GLenum cap)
{
@ -1039,7 +1363,8 @@ cogl_wrap_glEnable (GLenum cap)
switch (cap)
{
case GL_TEXTURE_2D:
_COGL_GLES2_CHANGE_SETTING (w, texture_2d_enabled, TRUE);
_COGL_GLES2_CHANGE_SETTING (
w, texture_units[w->active_texture_unit].enabled, TRUE);
break;
case GL_FOG:
@ -1063,7 +1388,8 @@ cogl_wrap_glDisable (GLenum cap)
switch (cap)
{
case GL_TEXTURE_2D:
_COGL_GLES2_CHANGE_SETTING (w, texture_2d_enabled, FALSE);
_COGL_GLES2_CHANGE_SETTING (
w, texture_units[w->active_texture_unit].enabled, FALSE);
break;
case GL_FOG:
@ -1082,13 +1408,26 @@ cogl_wrap_glDisable (GLenum cap)
void
cogl_wrap_glEnableClientState (GLenum array)
{
CoglGles2WrapperTextureUnit *texture_unit;
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
switch (array)
{
case GL_VERTEX_ARRAY:
glEnableVertexAttribArray (COGL_GLES2_WRAPPER_VERTEX_ATTRIB);
break;
case GL_TEXTURE_COORD_ARRAY:
glEnableVertexAttribArray (COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB);
/* TODO - review if this should be in w->settings? */
texture_unit = g_array_index (w->texture_units,
CoglGles2WrapperTextureUnit *,
w->active_texture_unit);
if (texture_unit->texture_coords_enabled != 1)
{
texture_unit->texture_coords_enabled = 1;
w->dirty_vertex_attrib_enables
|= COGL_GLES2_DIRTY_TEX_COORD_ATTRIB_ENABLES;
}
break;
case GL_COLOR_ARRAY:
glEnableVertexAttribArray (COGL_GLES2_WRAPPER_COLOR_ATTRIB);
@ -1102,13 +1441,26 @@ cogl_wrap_glEnableClientState (GLenum array)
void
cogl_wrap_glDisableClientState (GLenum array)
{
CoglGles2WrapperTextureUnit *texture_unit;
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
switch (array)
{
case GL_VERTEX_ARRAY:
glDisableVertexAttribArray (COGL_GLES2_WRAPPER_VERTEX_ATTRIB);
break;
case GL_TEXTURE_COORD_ARRAY:
glDisableVertexAttribArray (COGL_GLES2_WRAPPER_TEX_COORD_ATTRIB);
texture_unit = g_array_index (w->texture_units,
CoglGles2WrapperTextureUnit *,
w->active_texture_unit);
/* TODO - review if this should be in w->settings? */
if (texture_unit->texture_coords_enabled != 0)
{
texture_unit->texture_coords_enabled = 0;
w->dirty_vertex_attrib_enables
|= COGL_GLES2_DIRTY_TEX_COORD_ATTRIB_ENABLES;
}
break;
case GL_COLOR_ARRAY:
glDisableVertexAttribArray (COGL_GLES2_WRAPPER_COLOR_ATTRIB);
@ -1156,6 +1508,10 @@ cogl_wrap_glGetIntegerv (GLenum pname, GLint *params)
*params = 0;
break;
case CGL_MATRIX_MODE:
*params = w->matrix_mode;
break;
default:
glGetIntegerv (pname, params);
break;
@ -1195,7 +1551,7 @@ cogl_wrap_glFogf (GLenum pname, GLfloat param)
case GL_FOG_MODE:
_COGL_GLES2_CHANGE_SETTING (w, fog_mode, param);
break;
case GL_FOG_DENSITY:
_COGL_GLES2_CHANGE_UNIFORM (w, FOG_DENSITY, fog_density,
(param));

View File

@ -32,11 +32,17 @@ G_BEGIN_DECLS
#ifdef HAVE_COGL_GLES2
typedef struct _CoglGles2Wrapper CoglGles2Wrapper;
typedef struct _CoglGles2WrapperUniforms CoglGles2WrapperUniforms;
typedef struct _CoglGles2WrapperSettings CoglGles2WrapperSettings;
typedef struct _CoglGles2WrapperProgram CoglGles2WrapperProgram;
typedef struct _CoglGles2WrapperShader CoglGles2WrapperShader;
typedef struct _CoglGles2Wrapper CoglGles2Wrapper;
typedef struct _CoglGles2WrapperTextureUnit
CoglGles2WrapperTextureUnit;
typedef struct _CoglGles2WrapperAttributes CoglGles2WrapperAttributes;
typedef struct _CoglGles2WrapperUniforms CoglGles2WrapperUniforms;
typedef struct _CoglGles2WrapperTextureUnitSettings
CoglGles2WrapperTextureUnitSettings;
typedef struct _CoglGles2WrapperSettings CoglGles2WrapperSettings;
typedef struct _CoglGles2WrapperProgram CoglGles2WrapperProgram;
typedef struct _CoglGles2WrapperShader CoglGles2WrapperShader;
#define COGL_GLES2_NUM_CUSTOM_UNIFORMS 16
#define COGL_GLES2_UNBOUND_CUSTOM_UNIFORM -2
@ -46,78 +52,129 @@ typedef struct _CoglGles2WrapperShader CoglGles2WrapperShader;
#define COGL_GLES2_PROJECTION_STACK_SIZE 2
#define COGL_GLES2_TEXTURE_STACK_SIZE 2
/* Dirty flags for shader uniforms */
enum
{
COGL_GLES2_DIRTY_MVP_MATRIX = 1 << 0,
COGL_GLES2_DIRTY_MODELVIEW_MATRIX = 1 << 1,
COGL_GLES2_DIRTY_TEXTURE_MATRIX = 1 << 2,
COGL_GLES2_DIRTY_TEXTURE_MATRICES = 1 << 2,
COGL_GLES2_DIRTY_FOG_DENSITY = 1 << 3,
COGL_GLES2_DIRTY_FOG_START = 1 << 4,
COGL_GLES2_DIRTY_FOG_END = 1 << 5,
COGL_GLES2_DIRTY_FOG_COLOR = 1 << 6,
COGL_GLES2_DIRTY_ALPHA_TEST_REF = 1 << 7,
COGL_GLES2_DIRTY_TEXTURE_UNIT = 1 << 8,
COGL_GLES2_DIRTY_TEXTURE_UNITS = 1 << 8,
COGL_GLES2_DIRTY_ALL = (1 << 9) - 1
};
/* Dirty flags for shader vertex attribute pointers */
enum
{
COGL_GLES2_DIRTY_TEX_COORD_VERTEX_ATTRIB = 1 << 0
};
/* Dirty flags for shader vertex attributes enabled status */
enum
{
COGL_GLES2_DIRTY_TEX_COORD_ATTRIB_ENABLES = 1 << 0
};
struct _CoglGles2WrapperAttributes
{
GArray *multi_texture_coords;
};
struct _CoglGles2WrapperUniforms
{
GLint mvp_matrix_uniform;
GLint modelview_matrix_uniform;
GLint texture_matrix_uniform;
GLint bound_texture_uniform;
GLint mvp_matrix_uniform;
GLint modelview_matrix_uniform;
GArray *texture_matrix_uniforms;
GLint fog_density_uniform;
GLint fog_start_uniform;
GLint fog_end_uniform;
GLint fog_color_uniform;
GArray *texture_sampler_uniforms;
GLint alpha_test_ref_uniform;
GLint fog_density_uniform;
GLint fog_start_uniform;
GLint fog_end_uniform;
GLint fog_color_uniform;
GLint alpha_test_ref_uniform;
GLint texture_unit_uniform;
};
struct _CoglGles2WrapperTextureUnitSettings
{
guint enabled:1;
guint alpha_only:1;
/* TODO: blending state */
};
/* NB: We get a copy of this for each fragment/vertex
* program varient we generate so we try to keep it
* fairly lean */
struct _CoglGles2WrapperSettings
{
gboolean texture_2d_enabled;
gboolean alpha_only;
CoglGles2WrapperTextureUnitSettings *texture_units;
guint n_texture_units;
gboolean alpha_test_enabled;
GLint alpha_test_func;
gboolean fog_enabled;
GLint fog_mode;
/* The current in-use user program */
CoglHandle user_program;
guint alpha_test_enabled:1;
guint fog_enabled:1;
};
struct _CoglGles2WrapperTextureUnit
{
GLfloat texture_stack[COGL_GLES2_TEXTURE_STACK_SIZE * 16];
GLuint texture_stack_pos;
GLenum texture_coords_type;
GLint texture_coords_size;
GLsizei texture_coords_stride;
const void *texture_coords_pointer;
guint texture_coords_enabled:1;
guint dirty_matrix:1; /*!< shader uniform needs updating */
};
struct _CoglGles2Wrapper
{
GLuint matrix_mode;
GLfloat modelview_stack[COGL_GLES2_MODELVIEW_STACK_SIZE * 16];
GLuint modelview_stack_pos;
GLfloat projection_stack[COGL_GLES2_PROJECTION_STACK_SIZE * 16];
GLuint projection_stack_pos;
GLfloat texture_stack[COGL_GLES2_TEXTURE_STACK_SIZE * 16];
GLuint texture_stack_pos;
GLuint matrix_mode;
GLfloat modelview_stack[COGL_GLES2_MODELVIEW_STACK_SIZE * 16];
GLuint modelview_stack_pos;
GLfloat projection_stack[COGL_GLES2_PROJECTION_STACK_SIZE * 16];
GLuint projection_stack_pos;
GArray *texture_units;
guint active_texture_unit;
guint active_client_texture_unit;
/* The combined modelview and projection matrix is only updated at
the last minute in glDrawArrays to avoid recalculating it for
every change to the modelview matrix */
GLboolean mvp_uptodate;
GLboolean mvp_uptodate;
/* The currently bound program */
CoglGles2WrapperProgram *current_program;
/* The current settings */
/* The current settings. Effectively these represent anything that
* will require a modified fixed function shader */
CoglGles2WrapperSettings settings;
/* Whether the settings have changed since the last draw */
gboolean settings_dirty;
/* Uniforms that have changed since the last draw */
int dirty_uniforms, dirty_custom_uniforms;
/* Attribute pointers that have changed since the last draw */
int dirty_attribute_pointers;
/* Vertex attribute pointer enables that have changed since the last draw */
int dirty_vertex_attrib_enables;
/* List of all compiled program combinations */
GSList *compiled_programs;
@ -143,6 +200,10 @@ struct _CoglGles2WrapperProgram
/* The settings that were used to generate this combination */
CoglGles2WrapperSettings settings;
/* The attributes for this program that are not bound up-front
* with constant indices */
CoglGles2WrapperAttributes attributes;
/* The uniforms for this program */
CoglGles2WrapperUniforms uniforms;
GLint custom_uniforms[COGL_GLES2_NUM_CUSTOM_UNIFORMS];
@ -232,6 +293,9 @@ void cogl_wrap_glNormalPointer (GLenum type, GLsizei stride,
void cogl_wrap_glTexEnvf (GLenum target, GLenum pname, GLfloat param);
void cogl_wrap_glClientActiveTexture (GLenum texture);
void cogl_wrap_glActiveTexture (GLenum texture);
void cogl_wrap_glEnableClientState (GLenum array);
void cogl_wrap_glDisableClientState (GLenum array);
@ -258,12 +322,6 @@ void cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture,
/* This function is only available on GLES 2 */
#define cogl_wrap_glGenerateMipmap glGenerateMipmap
void cogl_gles2_wrapper_bind_attributes (GLuint program);
void cogl_gles2_wrapper_get_uniforms (GLuint program,
CoglGles2WrapperUniforms *uniforms);
void cogl_gles2_wrapper_update_matrix (CoglGles2Wrapper *wrapper,
GLenum matrix_num);
void _cogl_gles2_clear_cache_for_program (CoglHandle program);
#else /* HAVE_COGL_GLES2 */
@ -290,6 +348,7 @@ void _cogl_gles2_clear_cache_for_program (CoglHandle program);
#define cogl_wrap_glColorPointer glColorPointer
#define cogl_wrap_glNormalPointer glNormalPointer
#define cogl_wrap_glTexEnvf glTexEnvf
#define cogl_wrap_glActiveTexture glActiveTexture
#define cogl_wrap_glEnableClientState glEnableClientState
#define cogl_wrap_glDisableClientState glDisableClientState
#define cogl_wrap_glAlphaFunc glAlphaFunc
@ -310,6 +369,11 @@ void _cogl_gles2_clear_cache_for_program (CoglHandle program);
glGenerateMipmap doesn't need to do anything */
#define cogl_wrap_glGenerateMipmap(x) ((void) 0)
/* 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 /* HAVE_COGL_GLES2 */
G_END_DECLS

View File

@ -75,13 +75,10 @@ const char *_cogl_error_string(GLenum errorCode);
#endif /* COGL_DEBUG */
#define COGL_ENABLE_BLEND (1<<1)
#define COGL_ENABLE_TEXTURE_2D (1<<2)
#define COGL_ENABLE_ALPHA_TEST (1<<3)
#define COGL_ENABLE_TEXTURE_RECT (1<<4)
#define COGL_ENABLE_VERTEX_ARRAY (1<<5)
#define COGL_ENABLE_TEXCOORD_ARRAY (1<<6)
#define COGL_ENABLE_COLOR_ARRAY (1<<7)
#define COGL_ENABLE_BACKFACE_CULLING (1<<8)
#define COGL_ENABLE_ALPHA_TEST (1<<2)
#define COGL_ENABLE_VERTEX_ARRAY (1<<3)
#define COGL_ENABLE_COLOR_ARRAY (1<<4)
#define COGL_ENABLE_BACKFACE_CULLING (1<<5)
gint
_cogl_get_format_bpp (CoglPixelFormat format);

View File

@ -38,30 +38,9 @@
#define _COGL_MAX_BEZ_RECURSE_DEPTH 16
void
_cogl_rectangle (float x,
float y,
float width,
float height)
{
GLfloat rect_verts[8] = {
(GLfloat) x, (GLfloat) y,
(GLfloat) (x + width), (GLfloat) y,
(GLfloat) x, (GLfloat) (y + height),
(GLfloat) (x + width), (GLfloat) (y + height)
};
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (COGL_ENABLE_VERTEX_ARRAY
| (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0));
GE ( cogl_wrap_glVertexPointer (2, GL_FLOAT, 0, rect_verts ) );
GE ( cogl_wrap_glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
}
void
_cogl_path_add_node (gboolean new_sub_path,
float x,
float x,
float y)
{
CoglPathNode new_node;
@ -96,23 +75,28 @@ _cogl_path_add_node (gboolean new_sub_path,
void
_cogl_path_stroke_nodes ()
{
guint path_start = 0;
guint path_start = 0;
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (COGL_ENABLE_VERTEX_ARRAY
| (ctx->color_alpha < 255
? COGL_ENABLE_BLEND : 0));
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);
while (path_start < ctx->path_nodes->len)
{
CoglPathNode *path = &g_array_index (ctx->path_nodes, CoglPathNode,
path_start);
GE( cogl_wrap_glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
(guchar *) path
+ G_STRUCT_OFFSET (CoglPathNode, x)) );
GE( cogl_wrap_glDrawArrays (GL_LINE_STRIP, 0, path->path_size) );
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
(guchar *) path
+ G_STRUCT_OFFSET (CoglPathNode, x)) );
GE( glDrawArrays (GL_LINE_STRIP, 0, path->path_size) );
path_start += path->path_size;
}
@ -145,12 +129,22 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
CoglPathNode *path,
gboolean merge)
{
guint path_start = 0;
guint sub_path_num = 0;
float bounds_x;
float bounds_y;
float bounds_w;
float bounds_h;
guint path_start = 0;
guint sub_path_num = 0;
float bounds_x;
float bounds_y;
float bounds_w;
float bounds_h;
gulong enable_flags = COGL_ENABLE_VERTEX_ARRAY;
_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);
enable_flags |=
cogl_material_get_cogl_enable_flags (ctx->source_material);
cogl_enable (enable_flags);
_cogl_path_get_bounds (nodes_min, nodes_max,
&bounds_x, &bounds_y, &bounds_w, &bounds_h);
@ -167,7 +161,7 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
GE( glStencilFunc (GL_LEQUAL, 0x1, 0x3) );
}
GE( cogl_wrap_glEnable (GL_STENCIL_TEST) );
GE( glEnable (GL_STENCIL_TEST) );
GE( glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT) );
GE( glColorMask (FALSE, FALSE, FALSE, FALSE) );
@ -175,12 +169,10 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
while (path_start < path_size)
{
cogl_enable (COGL_ENABLE_VERTEX_ARRAY);
GE( cogl_wrap_glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
(guchar *) path
+ G_STRUCT_OFFSET (CoglPathNode, x)) );
GE( cogl_wrap_glDrawArrays (GL_TRIANGLE_FAN, 0, path->path_size) );
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
(guchar *) path
+ G_STRUCT_OFFSET (CoglPathNode, x)) );
GE( glDrawArrays (GL_TRIANGLE_FAN, 0, path->path_size) );
if (sub_path_num > 0)
{
@ -209,16 +201,16 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) );
/* Decrement all of the bits twice so that only pixels where the
value is 3 will remain */
GE( cogl_wrap_glPushMatrix () );
GE( cogl_wrap_glLoadIdentity () );
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
GE( cogl_wrap_glPushMatrix () );
GE( cogl_wrap_glLoadIdentity () );
GE( glPushMatrix () );
GE( glLoadIdentity () );
GE( glMatrixMode (GL_PROJECTION) );
GE( glPushMatrix () );
GE( glLoadIdentity () );
cogl_rectangle (-1.0, -1.0, 2, 2);
cogl_rectangle (-1.0, -1.0, 2, 2);
GE( cogl_wrap_glPopMatrix () );
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
GE( cogl_wrap_glPopMatrix () );
GE( glPopMatrix () );
GE( glMatrixMode (GL_MODELVIEW) );
GE( glPopMatrix () );
}
GE( glStencilMask (~(GLuint) 0) );
@ -255,7 +247,7 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* clear scanline intersection lists */
for (i=0; i < bounds_h; i++)
for (i=0; i < bounds_h; i++)
scanlines[i]=NULL;
first_x = prev_x = (path->x);
@ -392,8 +384,8 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
/* render triangles */
cogl_enable (COGL_ENABLE_VERTEX_ARRAY
| (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0));
GE ( cogl_wrap_glVertexPointer (2, GL_FLOAT, 0, coords ) );
GE ( cogl_wrap_glDrawArrays (GL_TRIANGLES, 0, spans * 2 * 3));
GE ( glVertexPointer (2, GL_FLOAT, 0, coords ) );
GE ( glDrawArrays (GL_TRIANGLES, 0, spans * 2 * 3));
g_free (coords);
}
}
@ -444,4 +436,3 @@ _cogl_path_fill_nodes ()
}
}
}

View File

@ -28,9 +28,9 @@
#include "cogl-bitmap.h"
typedef struct _CoglTexture CoglTexture;
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
typedef struct _CoglSpanIter CoglSpanIter;
typedef struct _CoglTexture CoglTexture;
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
typedef struct _CoglSpanIter CoglSpanIter;
struct _CoglTexSliceSpan
{
@ -59,7 +59,23 @@ struct _CoglTexture
gboolean auto_mipmap;
};
/* To improve batching of geometry when submitting vertices to OpenGL we
* log the texture rectangles we want to draw to a journal, so when we
* later flush the journal we aim to batch data, and gl draw calls. */
typedef struct _CoglJournalEntry
{
CoglHandle material;
gint n_layers;
guint32 fallback_mask;
GLuint layer0_override_texture;
} CoglJournalEntry;
CoglTexture*
_cogl_texture_pointer_from_handle (CoglHandle handle);
gboolean
_cogl_texture_span_has_waste (CoglTexture *tex,
gint x_span_index,
gint y_span_index);
#endif /* __COGL_TEXTURE_H */

File diff suppressed because it is too large Load Diff

View File

@ -73,14 +73,13 @@ _cogl_error_string(GLenum errorCode)
}
#endif
CoglFuncPtr
cogl_get_proc_address (const gchar* name)
{
return NULL;
}
gboolean
gboolean
cogl_check_extension (const gchar *name, const gchar *ext)
{
return FALSE;
@ -93,45 +92,59 @@ cogl_paint_init (const CoglColor *color)
fprintf(stderr, "\n ============== Paint Start ================ \n");
#endif
glClearColor (cogl_color_get_red (color),
cogl_color_get_green (color),
cogl_color_get_blue (color),
0);
GE( glClearColor (cogl_color_get_red_float (color),
cogl_color_get_green_float (color),
cogl_color_get_blue_float (color),
0.0) );
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
cogl_wrap_glDisable (GL_LIGHTING);
cogl_wrap_glDisable (GL_FOG);
glDisable (GL_LIGHTING);
glDisable (GL_FOG);
/*
* Disable the depth test for now as has some strange side effects,
* mainly on x/y axis rotation with multiple layers at same depth
* (eg rotating text on a bg has very strange effect). Seems no clean
* 100% effective way to fix without other odd issues.. So for now
* move to application to handle and add cogl_enable_depth_test()
* as for custom actors (i.e groups) to enable if need be.
*
* glEnable (GL_DEPTH_TEST);
* glEnable (GL_ALPHA_TEST)
* glDepthFunc (GL_LEQUAL);
* glAlphaFunc (GL_GREATER, 0.1);
*/
}
/* FIXME: inline most of these */
void
cogl_push_matrix (void)
{
GE( cogl_wrap_glPushMatrix() );
GE( glPushMatrix() );
}
void
cogl_pop_matrix (void)
{
GE( cogl_wrap_glPopMatrix() );
GE( glPopMatrix() );
}
void
cogl_scale (float x, float y)
{
GE( cogl_wrap_glScalef (x, y, 1.0) );
GE( glScalef (x, y, 1.0) );
}
void
cogl_translate (float x, float y, float z)
{
GE( cogl_wrap_glTranslatef (x, y, z) );
GE( glTranslatef (x, y, z) );
}
void
cogl_rotate (float angle, float x, float y, float z)
{
GE( cogl_wrap_glRotatef (angle, x, y, z) );
GE( glRotatef (angle, x, y, z) );
}
static inline gboolean
@ -147,17 +160,17 @@ cogl_toggle_flag (CoglContext *ctx,
{
if (!(ctx->enable_flags & flag))
{
GE( cogl_wrap_glEnable (gl_flag) );
GE( glEnable (gl_flag) );
ctx->enable_flags |= flag;
return TRUE;
}
}
else if (ctx->enable_flags & flag)
{
GE( cogl_wrap_glDisable (gl_flag) );
GE( glDisable (gl_flag) );
ctx->enable_flags &= ~flag;
}
return FALSE;
}
@ -174,17 +187,17 @@ cogl_toggle_client_flag (CoglContext *ctx,
{
if (!(ctx->enable_flags & flag))
{
GE( cogl_wrap_glEnableClientState (gl_flag) );
GE( glEnableClientState (gl_flag) );
ctx->enable_flags |= flag;
return TRUE;
}
}
else if (ctx->enable_flags & flag)
{
GE( cogl_wrap_glDisableClientState (gl_flag) );
GE( glDisableClientState (gl_flag) );
ctx->enable_flags &= ~flag;
}
return FALSE;
}
@ -195,14 +208,10 @@ cogl_enable (gulong flags)
* hope of lessening number GL traffic.
*/
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_toggle_flag (ctx, flags,
COGL_ENABLE_BLEND,
GL_BLEND);
cogl_toggle_flag (ctx, flags,
COGL_ENABLE_TEXTURE_2D,
GL_TEXTURE_2D);
cogl_toggle_flag (ctx, flags,
COGL_ENABLE_BACKFACE_CULLING,
@ -211,10 +220,6 @@ cogl_enable (gulong flags)
cogl_toggle_client_flag (ctx, flags,
COGL_ENABLE_VERTEX_ARRAY,
GL_VERTEX_ARRAY);
cogl_toggle_client_flag (ctx, flags,
COGL_ENABLE_TEXCOORD_ARRAY,
GL_TEXTURE_COORD_ARRAY);
cogl_toggle_client_flag (ctx, flags,
COGL_ENABLE_COLOR_ARRAY,
@ -225,25 +230,8 @@ gulong
cogl_get_enable ()
{
_COGL_GET_CONTEXT (ctx, 0);
return ctx->enable_flags;
}
void
cogl_blend_func (COGLenum src_factor, COGLenum dst_factor)
{
/* This function caches the blending setup in the
* hope of lessening GL traffic.
*/
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (ctx->blend_src_factor != src_factor ||
ctx->blend_dst_factor != dst_factor)
{
glBlendFunc (src_factor, dst_factor);
ctx->blend_src_factor = src_factor;
ctx->blend_dst_factor = dst_factor;
}
return ctx->enable_flags;
}
void
@ -251,15 +239,15 @@ cogl_enable_depth_test (gboolean setting)
{
if (setting)
{
cogl_wrap_glEnable (GL_DEPTH_TEST);
cogl_wrap_glEnable (GL_ALPHA_TEST);
glEnable (GL_DEPTH_TEST);
glEnable (GL_ALPHA_TEST);
glDepthFunc (GL_LEQUAL);
cogl_wrap_glAlphaFunc (GL_GREATER, 0.1);
glAlphaFunc (GL_GREATER, 0.1);
}
else
{
cogl_wrap_glDisable (GL_DEPTH_TEST);
cogl_wrap_glDisable (GL_ALPHA_TEST);
glDisable (GL_DEPTH_TEST);
glDisable (GL_ALPHA_TEST);
}
}
@ -275,35 +263,12 @@ void
cogl_set_source_color (const CoglColor *color)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
#if 0 /*HAVE_GLES_COLOR4UB*/
/* NOTE: seems SDK_OGLES-1.1_LINUX_PCEMULATION_2.02.22.0756 has this call
* but is broken - see #857. Therefor disabling.
*/
/* In case cogl_set_source_texture was previously used... */
cogl_material_remove_layer (ctx->default_material, 0);
/*
* GLES 1.1 does actually have this function, it's in the header file but
* missing in the reference manual (and SDK):
*
* http://www.khronos.org/egl/headers/1_1/gl.h
*/
GE( glColor4ub (color->red,
color->green,
color->blue,
color->alpha) );
#else
/* conversion can cause issues with picking on some gles implementations */
GE( cogl_wrap_glColor4f (cogl_color_get_red (color),
cogl_color_get_green (color),
cogl_color_get_blue (color),
cogl_color_get_alpha (color)) );
#endif
/* Store alpha for proper blending enables */
ctx->color_alpha = cogl_color_get_alpha_byte (color);
cogl_material_set_color (ctx->default_material, color);
cogl_set_source (ctx->default_material);
}
static void
@ -314,7 +279,7 @@ apply_matrix (const float *matrix, float *vertex)
for (y = 0; y < 4; y++)
for (x = 0; x < 4; x++)
vertex_out[y] += (vertex[x] * matrix[y + x * 4]);
vertex_out[y] += vertex[x] * matrix[y + x * 4];
memcpy (vertex, vertex_out, sizeof (vertex_out));
}
@ -332,7 +297,7 @@ project_vertex (float *modelview,
apply_matrix (project, vertex);
/* Convert from homogenized coordinates */
for (i = 0; i < 4; i++)
vertex[i] = (vertex[i] / vertex[3]);
vertex[i] /= vertex[3];
}
static void
@ -349,26 +314,26 @@ set_clip_plane (GLint plane_num,
angle = atan2f (vertex_b[1] - vertex_a[1],
vertex_b[0] - vertex_a[0]) * (180.0/G_PI);
GE( cogl_wrap_glPushMatrix () );
GE( glPushMatrix () );
/* Load the identity matrix and multiply by the reverse of the
projection matrix so we can specify the plane in screen
coordinates */
GE( cogl_wrap_glLoadIdentity () );
GE( cogl_wrap_glMultMatrixf ((GLfloat *) ctx->inverse_projection) );
GE( glLoadIdentity () );
GE( glMultMatrixf ((GLfloat *) ctx->inverse_projection) );
/* Rotate about point a */
GE( cogl_wrap_glTranslatef (vertex_a[0], vertex_a[1], vertex_a[2]) );
GE( glTranslatef (vertex_a[0], vertex_a[1], vertex_a[2]) );
/* Rotate the plane by the calculated angle so that it will connect
the two points */
GE( cogl_wrap_glRotatef (angle, 0.0f, 0.0f, 1.0f) );
GE( cogl_wrap_glTranslatef (-vertex_a[0], -vertex_a[1], -vertex_a[2]) );
GE( glRotatef (angle, 0.0f, 0.0f, 1.0f) );
GE( glTranslatef (-vertex_a[0], -vertex_a[1], -vertex_a[2]) );
plane[0] = 0;
plane[1] = -1.0;
plane[2] = 0;
plane[3] = vertex_a[1];
GE( cogl_wrap_glClipPlanef (plane_num, plane) );
GE( glClipPlanef (plane_num, plane) );
GE( cogl_wrap_glPopMatrix () );
GE( glPopMatrix () );
}
void
@ -383,21 +348,21 @@ _cogl_set_clip_planes (float x_offset,
float vertex_tr[4] = { x_offset + width, y_offset, 0, 1.0 };
float vertex_bl[4] = { x_offset, y_offset + height, 0, 1.0 };
float vertex_br[4] = { x_offset + width, y_offset + height,
0, 1.0 };
0, 1.0 };
GE( cogl_wrap_glGetFloatv (GL_MODELVIEW_MATRIX, modelview) );
GE( cogl_wrap_glGetFloatv (GL_PROJECTION_MATRIX, projection) );
GE( glGetFloatv (GL_MODELVIEW_MATRIX, modelview) );
GE( glGetFloatv (GL_PROJECTION_MATRIX, projection) );
project_vertex (modelview, projection, vertex_tl);
project_vertex (modelview, projection, vertex_tr);
project_vertex (modelview, projection, vertex_bl);
project_vertex (modelview, projection, vertex_br);
/* If the order of the top and bottom lines is different from
the order of the left and right lines then the clip rect must
have been transformed so that the back is visible. We
therefore need to swap one pair of vertices otherwise all of
the planes will be the wrong way around */
/* If the order of the top and bottom lines is different from the
order of the left and right lines then the clip rect must have
been transformed so that the back is visible. We therefore need
to swap one pair of vertices otherwise all of the planes will be
the wrong way around */
if ((vertex_tl[0] < vertex_tr[0] ? 1 : 0)
!= (vertex_bl[1] < vertex_tl[1] ? 1 : 0))
{
@ -425,10 +390,12 @@ _cogl_add_stencil_clip (float x_offset,
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_material_flush_gl_state (ctx->stencil_material);
if (first)
{
GE( cogl_wrap_glEnable (GL_STENCIL_TEST) );
GE( glEnable (GL_STENCIL_TEST) );
/* Initially disallow everything */
GE( glClearStencil (0) );
GE( glClear (GL_STENCIL_BUFFER_BIT) );
@ -451,15 +418,15 @@ _cogl_add_stencil_clip (float x_offset,
only pixels where both the original stencil buffer and the
rectangle are set will be valid */
GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) );
GE( cogl_wrap_glPushMatrix () );
GE( cogl_wrap_glLoadIdentity () );
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
GE( cogl_wrap_glPushMatrix () );
GE( cogl_wrap_glLoadIdentity () );
GE( glPushMatrix () );
GE( glLoadIdentity () );
GE( glMatrixMode (GL_PROJECTION) );
GE( glPushMatrix () );
GE( glLoadIdentity () );
cogl_rectangle (-1.0, -1.0, 2, 2);
GE( cogl_wrap_glPopMatrix () );
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
GE( cogl_wrap_glPopMatrix () );
GE( glPopMatrix () );
GE( glMatrixMode (GL_MODELVIEW) );
GE( glPopMatrix () );
}
/* Restore the stencil mode */
@ -470,44 +437,34 @@ _cogl_add_stencil_clip (float x_offset,
void
_cogl_set_matrix (const float *matrix)
{
GE( cogl_wrap_glLoadIdentity () );
GE( cogl_wrap_glMultMatrixf (matrix) );
GE( glLoadIdentity () );
GE( glMultMatrixf (matrix) );
}
void
_cogl_disable_stencil_buffer (void)
{
GE( cogl_wrap_glDisable (GL_STENCIL_TEST) );
GE( glDisable (GL_STENCIL_TEST) );
}
void
_cogl_enable_clip_planes (void)
{
GE( cogl_wrap_glEnable (GL_CLIP_PLANE0) );
GE( cogl_wrap_glEnable (GL_CLIP_PLANE1) );
GE( cogl_wrap_glEnable (GL_CLIP_PLANE2) );
GE( cogl_wrap_glEnable (GL_CLIP_PLANE3) );
GE( glEnable (GL_CLIP_PLANE0) );
GE( glEnable (GL_CLIP_PLANE1) );
GE( glEnable (GL_CLIP_PLANE2) );
GE( glEnable (GL_CLIP_PLANE3) );
}
void
_cogl_disable_clip_planes (void)
{
GE( cogl_wrap_glDisable (GL_CLIP_PLANE3) );
GE( cogl_wrap_glDisable (GL_CLIP_PLANE2) );
GE( cogl_wrap_glDisable (GL_CLIP_PLANE1) );
GE( cogl_wrap_glDisable (GL_CLIP_PLANE0) );
GE( glDisable (GL_CLIP_PLANE3) );
GE( glDisable (GL_CLIP_PLANE2) );
GE( glDisable (GL_CLIP_PLANE1) );
GE( glDisable (GL_CLIP_PLANE0) );
}
void
cogl_alpha_func (COGLenum func,
float ref)
{
GE( cogl_wrap_glAlphaFunc (func, (ref)) );
}
/*
* Fixed point implementation of the perspective function
*/
void
cogl_perspective (float fovy,
float aspect,
@ -519,21 +476,21 @@ cogl_perspective (float fovy,
float fovy_rad_half = (fovy * G_PI) / 360;
GLfloat m[16];
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
memset (&m[0], 0, sizeof (m));
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
GE( cogl_wrap_glLoadIdentity () );
GE( glMatrixMode (GL_PROJECTION) );
GE( glLoadIdentity () );
/*
/*
* 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 can are loosing significant
* 2) When working with small numbers, we are loosing significant
* precision
*/
ymax = (zNear * (sinf (fovy_rad_half) / cosf (fovy_rad_half)));
@ -551,9 +508,9 @@ cogl_perspective (float fovy,
M(2,3) = d;
M(3,2) = -1.0;
GE( cogl_wrap_glMultMatrixf (m) );
GE( glMultMatrixf (m) );
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
GE( glMatrixMode (GL_MODELVIEW) );
/* Calculate and store the inverse of the matrix */
memset (ctx->inverse_projection, 0, sizeof (float) * 16);
@ -581,30 +538,33 @@ cogl_frustum (float left,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
GE( cogl_wrap_glMatrixMode (GL_PROJECTION) );
GE( cogl_wrap_glLoadIdentity () );
GE( glMatrixMode (GL_PROJECTION) );
GE( glLoadIdentity () );
GE( cogl_wrap_glFrustumf (left, right,
bottom, top,
z_near, z_far) );
GE( glFrustumf (left,
right,
bottom,
top,
z_near,
z_far) );
GE( cogl_wrap_glMatrixMode (GL_MODELVIEW) );
GE( glMatrixMode (GL_MODELVIEW) );
/* Calculate and store the inverse of the matrix */
memset (ctx->inverse_projection, 0, sizeof (float) * 16);
c = -(z_far + z_near / z_far - z_near);
d = -(2 * (z_far * z_near) / z_far - z_near);
c = - (z_far + z_near) / (z_far - z_near);
d = - (2 * (z_far * z_near)) / (z_far - z_near);
#define M(row,col) ctx->inverse_projection[col*4+row]
M(0,0) = (right - left / 2 * z_near);
M(0,3) = (right + left / 2 * z_near);
M(1,1) = (top - bottom / 2 * z_near);
M(1,3) = (top + bottom / 2 * z_near);
M(0,0) = (right - left) / (2 * z_near);
M(0,3) = (right + left) / (2 * z_near);
M(1,1) = (top - bottom) / (2 * z_near);
M(1,3) = (top + bottom) / (2 * z_near);
M(2,3) = -1.0;
M(3,2) = (1.0 / d);
M(3,3) = (c / d);
#undef M
M(3,2) = 1.0 / d;
M(3,3) = c / d;
#undef M
}
void
@ -615,26 +575,24 @@ cogl_viewport (guint width,
}
void
cogl_setup_viewport (guint w,
guint h,
cogl_setup_viewport (guint width,
guint height,
float fovy,
float aspect,
float z_near,
float z_far)
{
gint width = (gint) w;
gint height = (gint) h;
float z_camera;
float projection_matrix[16];
GE( glViewport (0, 0, width, height) );
/* For Ortho projection.
* cogl_wrap_glOrthof (0, width << 16, 0, height << 16, -1 << 16, 1 << 16);
* glOrthof (0, width << 16, 0, height << 16, -1 << 16, 1 << 16);
*/
cogl_perspective (fovy, aspect, z_near, z_far);
/*
* camera distance from screen
*
@ -644,15 +602,13 @@ cogl_setup_viewport (guint w,
cogl_get_projection_matrix (projection_matrix);
z_camera = 0.5 * projection_matrix[0];
GE( cogl_wrap_glLoadIdentity () );
GE( glLoadIdentity () );
GE( cogl_wrap_glTranslatef (-0.5f, -0.5f, -z_camera) );
GE( glTranslatef (-0.5f, -0.5f, -z_camera) );
GE( cogl_wrap_glScalef ( 1.0 / width,
-1.0 / height,
1.0 / width) );
GE( glScalef (1.0f / width, -1.0f / height, 1.0f / width) );
GE( cogl_wrap_glTranslatef (0, -1.0 * height, 0) );
GE( glTranslatef (0.0f, -1.0 * height, 0.0f) );
}
static void
@ -664,12 +620,12 @@ _cogl_features_init ()
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
GE( cogl_wrap_glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
GE( glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
/* We need at least three stencil bits to combine clips */
if (num_stencil_bits > 2)
flags |= COGL_FEATURE_STENCIL_BUFFER;
GE( cogl_wrap_glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
GE( glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
if (max_clip_planes >= 4)
flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
@ -677,6 +633,7 @@ _cogl_features_init ()
flags |= COGL_FEATURE_SHADERS_GLSL | COGL_FEATURE_OFFSCREEN;
#endif
/* Cache features */
ctx->feature_flags = flags;
ctx->features_cached = TRUE;
}
@ -685,10 +642,10 @@ CoglFeatureFlags
cogl_get_features ()
{
_COGL_GET_CONTEXT (ctx, 0);
if (!ctx->features_cached)
_cogl_features_init ();
return ctx->feature_flags;
}
@ -696,23 +653,23 @@ gboolean
cogl_features_available (CoglFeatureFlags features)
{
_COGL_GET_CONTEXT (ctx, 0);
if (!ctx->features_cached)
_cogl_features_init ();
return (ctx->feature_flags & features) == features;
}
void
cogl_get_modelview_matrix (float m[16])
{
cogl_wrap_glGetFloatv (GL_MODELVIEW_MATRIX, m);
glGetFloatv (GL_MODELVIEW_MATRIX, m);
}
void
cogl_get_projection_matrix (float m[16])
{
cogl_wrap_glGetFloatv (GL_PROJECTION_MATRIX, m);
glGetFloatv (GL_PROJECTION_MATRIX, m);
}
void
@ -721,7 +678,7 @@ cogl_get_viewport (float v[4])
GLint viewport[4];
int i;
cogl_wrap_glGetIntegerv (GL_VIEWPORT, viewport);
glGetIntegerv (GL_VIEWPORT, viewport);
for (i = 0; i < 4; i++)
v[i] = (float)(viewport[i]);
@ -730,14 +687,27 @@ cogl_get_viewport (float v[4])
void
cogl_get_bitmasks (gint *red, gint *green, gint *blue, gint *alpha)
{
GLint value;
if (red)
GE( cogl_wrap_glGetIntegerv(GL_RED_BITS, red) );
{
GE( glGetIntegerv(GL_RED_BITS, &value) );
*red = value;
}
if (green)
GE( cogl_wrap_glGetIntegerv(GL_GREEN_BITS, green) );
{
GE( glGetIntegerv(GL_GREEN_BITS, &value) );
*green = value;
}
if (blue)
GE( cogl_wrap_glGetIntegerv(GL_BLUE_BITS, blue) );
{
GE( glGetIntegerv(GL_BLUE_BITS, &value) );
*blue = value;
}
if (alpha)
GE( cogl_wrap_glGetIntegerv(GL_ALPHA_BITS, alpha ) );
{
GE( glGetIntegerv(GL_ALPHA_BITS, &value ) );
*alpha = value;
}
}
void
@ -748,19 +718,20 @@ cogl_fog_set (const CoglColor *fog_color,
{
GLfloat fogColor[4];
fogColor[0] = cogl_color_get_red (fog_color);
fogColor[1] = cogl_color_get_green (fog_color);
fogColor[2] = cogl_color_get_blue (fog_color);
fogColor[3] = cogl_color_get_alpha (fog_color);
fogColor[0] = cogl_color_get_red_float (fog_color);
fogColor[1] = cogl_color_get_green_float (fog_color);
fogColor[2] = cogl_color_get_blue_float (fog_color);
fogColor[3] = cogl_color_get_alpha_float (fog_color);
cogl_wrap_glEnable (GL_FOG);
glEnable (GL_FOG);
cogl_wrap_glFogfv (GL_FOG_COLOR, fogColor);
glFogfv (GL_FOG_COLOR, fogColor);
cogl_wrap_glFogf (GL_FOG_MODE, GL_LINEAR);
glFogf (GL_FOG_MODE, GL_LINEAR);
glHint (GL_FOG_HINT, GL_NICEST);
cogl_wrap_glFogf (GL_FOG_DENSITY, (GLfloat) density);
cogl_wrap_glFogf (GL_FOG_START, (GLfloat) z_near);
cogl_wrap_glFogf (GL_FOG_END, (GLfloat) z_far);
glFogf (GL_FOG_DENSITY, (GLfloat) density);
glFogf (GL_FOG_START, (GLfloat) z_near);
glFogf (GL_FOG_END, (GLfloat) z_far);
}