mirror of
https://github.com/brl/mutter.git
synced 2024-12-27 13:22:15 +00:00
[multi-texturing] This adds a new cogl_multi_texture API for GL,GLES1 + GLES2
Multitexturing allows blending multiple layers of texture data when texturing some geometry. A common use is for pre-baked light maps which can give nice lighting effects relativly cheaply. Another is for dot-3 bump mapping, and another is applying alpha channel masks. The dot-3 bump mapping would be really nice one day, but currently cogl doesn't support lighting so that's not dealt with in this patch. notable limitations: - It can only texture rectangles a.t.m - and like cogl_texture_rectangle there is no support for rotated texturing. - Sliced textures are not supported. I think I've figured out how to handle layers with different slice sizes at least for rectangular geometry, but I'm not sure how complex it becomes once rotations are possible and texturing arbitrary cogl_polygons. - Except for this new API, cogl still doesn't know about more than one texture unit, and so has no way of caching any enables related to other units. So that things don't break it's currently necessary to disable anything to do with additional units as soon as we are done with them which isn't ideal. - No clutter API yet.
This commit is contained in:
parent
b4438143e5
commit
509928cc76
@ -385,6 +385,68 @@ void cogl_texture_polygon (CoglHandle handle,
|
||||
CoglTextureVertex *vertices,
|
||||
gboolean use_color);
|
||||
|
||||
/**
|
||||
* cogl_muti_texture_new:
|
||||
*
|
||||
* Creates a multi layered texture object. When first created it has
|
||||
* zero layers. You must use cogl_multi_texture_layer_set_texture to
|
||||
* define new layers.
|
||||
*/
|
||||
CoglHandle cogl_multi_texture_new (void);
|
||||
|
||||
/**
|
||||
* cogl_multi_texture_layer_set_texture:
|
||||
* @multi_texture_handle: a @CoglHandle
|
||||
* @layer: The index of the layer you want a handle for.
|
||||
*
|
||||
* A layer is implicitly created once you set a texture for a certain
|
||||
* layer_index. The texture layers are blended together starting with
|
||||
* the lowest index so the order is significant. It doesn't matter what
|
||||
* order you create the layers in and you may use sparsely generated index
|
||||
* values, it is only the relative index order that matters.
|
||||
*/
|
||||
void cogl_multi_texture_layer_set_texture (CoglHandle multi_texture_handle,
|
||||
guint layer_index,
|
||||
CoglHandle texture_handle);
|
||||
|
||||
/**
|
||||
* cogl_multi_texture_layer_remove:
|
||||
* @multi_texture_handle: a @CoglHandle
|
||||
* @index: The index of the layer you want to remove.
|
||||
*
|
||||
* Removes a single texture layer.
|
||||
*/
|
||||
void cogl_multi_texture_layer_remove (CoglHandle multi_texture_handle,
|
||||
guint layer_index);
|
||||
|
||||
/**
|
||||
* cogl_multi_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.
|
||||
* @texcoords: A multidimensional array containing sets of 4 texture
|
||||
* coordinates - one set for each texture layer that has been created.
|
||||
*
|
||||
* Draw a rectangle combining multiple texture layers together
|
||||
* where each layer can use different texture data and different texture
|
||||
* coordinates.
|
||||
*
|
||||
* The texture coordinates are supplied as a contiguous array of
|
||||
* CoglFixed items containing groups of [tx1, ty1, tx2, ty2] values
|
||||
* that are interpreted in the same way as the corresponding arguments
|
||||
* to cogl_texture_rectangle. The first group of coordinates are for the
|
||||
* first layer (with the smallest layer_index) you _must_ supply as many
|
||||
* groups of texture coordinates as you have layers.
|
||||
*/
|
||||
void cogl_multi_texture_rectangle (CoglHandle handle,
|
||||
CoglFixed x1,
|
||||
CoglFixed y1,
|
||||
CoglFixed x2,
|
||||
CoglFixed y2,
|
||||
CoglFixed *tex_coords);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COGL_TEXTURE_H__ */
|
||||
|
@ -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) \
|
||||
{ \
|
||||
|
@ -58,6 +58,9 @@ cogl_create_context ()
|
||||
_context->texture_handles = NULL;
|
||||
_context->texture_vertices_size = 0;
|
||||
_context->texture_vertices = NULL;
|
||||
|
||||
_context->multi_texture_handles = NULL;
|
||||
_context->multi_texture_layer_handles = NULL;
|
||||
|
||||
_context->fbo_handles = NULL;
|
||||
_context->draw_buffer = COGL_WINDOW_BUFFER;
|
||||
|
@ -66,6 +66,12 @@ typedef struct
|
||||
CoglTextureGLVertex *texture_vertices;
|
||||
gulong texture_vertices_size;
|
||||
|
||||
/* Multi Textures */
|
||||
GArray *multi_texture_handles;
|
||||
|
||||
/* Multi Texture Layers */
|
||||
GArray *multi_texture_layer_handles;
|
||||
|
||||
/* Framebuffer objects */
|
||||
GArray *fbo_handles;
|
||||
CoglBufferTarget draw_buffer;
|
||||
|
@ -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
|
||||
|
@ -28,9 +28,11 @@
|
||||
|
||||
#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;
|
||||
typedef struct _CoglMultiTexture CoglMultiTexture;
|
||||
typedef struct _CoglMultiTextureLayer CoglMultiTextureLayer;
|
||||
|
||||
struct _CoglTexSliceSpan
|
||||
{
|
||||
@ -59,6 +61,25 @@ struct _CoglTexture
|
||||
gboolean auto_mipmap;
|
||||
};
|
||||
|
||||
struct _CoglMultiTextureLayer
|
||||
{
|
||||
guint ref_count;
|
||||
|
||||
guint index; /*!< lowest index is blended first then others
|
||||
on top */
|
||||
CoglTexture *tex; /*!< The texture for this layer, or NULL
|
||||
for an empty layer */
|
||||
|
||||
/* TODO: Add more control over the texture environment for each texture
|
||||
* unit. For example we should support dot3 normal mapping. */
|
||||
};
|
||||
|
||||
struct _CoglMultiTexture
|
||||
{
|
||||
guint ref_count;
|
||||
GList *layers;
|
||||
};
|
||||
|
||||
CoglTexture*
|
||||
_cogl_texture_pointer_from_handle (CoglHandle handle);
|
||||
|
||||
|
@ -49,6 +49,16 @@
|
||||
printf("err: 0x%x\n", err); \
|
||||
} */
|
||||
|
||||
static void _cogl_texture_free (CoglTexture *tex);
|
||||
static void _cogl_multi_texture_free (CoglMultiTexture *multi_texture);
|
||||
static void _cogl_multi_texture_layer_free (CoglMultiTextureLayer *layer);
|
||||
|
||||
COGL_HANDLE_DEFINE (Texture, texture, texture_handles);
|
||||
COGL_HANDLE_DEFINE (MultiTexture, multi_texture, multi_texture_handles);
|
||||
COGL_HANDLE_DEFINE (MultiTextureLayer,
|
||||
multi_texture_layer,
|
||||
multi_texture_layer_handles);
|
||||
|
||||
struct _CoglSpanIter
|
||||
{
|
||||
gint index;
|
||||
@ -66,11 +76,6 @@ struct _CoglSpanIter
|
||||
gboolean intersects;
|
||||
};
|
||||
|
||||
static void _cogl_texture_free (CoglTexture *tex);
|
||||
|
||||
COGL_HANDLE_DEFINE (Texture, texture, texture_handles);
|
||||
|
||||
|
||||
static void
|
||||
_cogl_texture_bitmap_free (CoglTexture *tex)
|
||||
{
|
||||
@ -2405,3 +2410,263 @@ cogl_texture_polygon (CoglHandle handle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_multi_texture_new (void)
|
||||
{
|
||||
CoglMultiTexture *multi_tex = g_new0 (CoglMultiTexture, 1);
|
||||
return _cogl_multi_texture_handle_new (multi_tex);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_multi_texture_free (CoglMultiTexture *multi_tex)
|
||||
{
|
||||
g_list_foreach (multi_tex->layers,
|
||||
(GFunc)cogl_multi_texture_layer_unref, NULL);
|
||||
g_free (multi_tex);
|
||||
}
|
||||
|
||||
static CoglMultiTextureLayer *
|
||||
_cogl_multi_texture_get_layer (CoglMultiTexture *multi_tex, guint index)
|
||||
{
|
||||
CoglMultiTextureLayer *layer;
|
||||
GList *tmp;
|
||||
|
||||
for (tmp = multi_tex->layers; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
layer = tmp->data;
|
||||
if (layer->index == index)
|
||||
return layer;
|
||||
|
||||
/* The layers are always sorted, so we know this layer doesn't exists */
|
||||
if (layer->index > index)
|
||||
break;
|
||||
}
|
||||
/* NB: if we now insert a new layer before tmp, that will maintain order.
|
||||
*/
|
||||
|
||||
layer = g_new (CoglMultiTextureLayer, 1);
|
||||
|
||||
layer->ref_count = 1;
|
||||
layer->index = index;
|
||||
/* Note: comment after for() loop above */
|
||||
multi_tex->layers = g_list_insert_before (multi_tex->layers, tmp, layer);
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_multi_texture_layer_set_texture (CoglHandle multi_texture_handle,
|
||||
guint layer_index,
|
||||
CoglHandle tex_handle)
|
||||
{
|
||||
CoglMultiTexture *multi_tex;
|
||||
CoglMultiTextureLayer *layer;
|
||||
CoglTexture *tex;
|
||||
|
||||
if (!cogl_is_multi_texture (multi_texture_handle)
|
||||
|| !cogl_is_texture (tex_handle))
|
||||
return;
|
||||
|
||||
multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
|
||||
layer = _cogl_multi_texture_get_layer (multi_tex, layer_index);
|
||||
tex = _cogl_texture_pointer_from_handle (tex_handle);
|
||||
|
||||
cogl_texture_ref (tex_handle);
|
||||
|
||||
layer->tex = tex;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_multi_texture_layer_free (CoglMultiTextureLayer *layer)
|
||||
{
|
||||
cogl_texture_unref (layer->tex);
|
||||
g_free (layer);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_multi_texture_layer_remove (CoglHandle multi_texture_handle,
|
||||
guint layer_index)
|
||||
{
|
||||
CoglMultiTexture *multi_tex;
|
||||
CoglMultiTextureLayer *layer;
|
||||
GList *tmp;
|
||||
|
||||
/* Check if valid multi texture */
|
||||
if (!cogl_is_multi_texture (multi_texture_handle))
|
||||
return;
|
||||
|
||||
multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
|
||||
for (tmp = multi_tex->layers; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
layer = tmp->data;
|
||||
if (layer->index == layer_index)
|
||||
{
|
||||
CoglHandle handle =
|
||||
_cogl_multi_texture_layer_handle_from_pointer (layer);
|
||||
cogl_multi_texture_layer_unref (handle);
|
||||
multi_tex->layers = g_list_remove (multi_tex->layers, layer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cogl_multi_texture_rectangle (CoglHandle multi_texture_handle,
|
||||
CoglFixed x1,
|
||||
CoglFixed y1,
|
||||
CoglFixed x2,
|
||||
CoglFixed y2,
|
||||
CoglFixed *user_tex_coords)
|
||||
{
|
||||
CoglMultiTexture *multi_tex;
|
||||
GLfloat quad_coords[8];
|
||||
GList *tmp;
|
||||
GList *valid_layers = NULL;
|
||||
int count;
|
||||
GLfloat *tex_coords_buff;
|
||||
gulong enable_flags = 0;
|
||||
/* FIXME - currently cogl deals with enabling texturing
|
||||
* via enable flags, but that can't scale to n texture
|
||||
* units. Currently we have to be carefull how we leave the
|
||||
* environment so we don't break things. See the cleanup
|
||||
* notes at the end of this function */
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Check if valid multi texture */
|
||||
if (!cogl_is_multi_texture (multi_texture_handle))
|
||||
return;
|
||||
|
||||
multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
|
||||
|
||||
#define CFX_F COGL_FIXED_TO_FLOAT
|
||||
quad_coords[0] = CFX_F (x1);
|
||||
quad_coords[1] = CFX_F (y1);
|
||||
quad_coords[2] = CFX_F (x2);
|
||||
quad_coords[3] = CFX_F (y1);
|
||||
quad_coords[4] = CFX_F (x1);
|
||||
quad_coords[5] = CFX_F (y2);
|
||||
quad_coords[6] = CFX_F (x2);
|
||||
quad_coords[7] = CFX_F (y2);
|
||||
#undef CFX_F
|
||||
|
||||
enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
|
||||
GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords));
|
||||
|
||||
for (count = 0, tmp = multi_tex->layers;
|
||||
tmp != NULL;
|
||||
count++, tmp = tmp->next)
|
||||
{
|
||||
CoglMultiTextureLayer *layer = tmp->data;
|
||||
|
||||
/* Skip empty layers */
|
||||
if (!layer->tex)
|
||||
{
|
||||
count--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* FIXME - currently we don't support sliced textures */
|
||||
if (layer->tex->slice_gl_handles == NULL
|
||||
|| layer->tex->slice_gl_handles->len < 1)
|
||||
continue;
|
||||
|
||||
if (count >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
|
||||
{
|
||||
static gboolean shown_warning = FALSE;
|
||||
|
||||
if (!shown_warning)
|
||||
{
|
||||
g_warning ("Your driver does not support enough texture layers"
|
||||
"to correctly handle this multi texturing");
|
||||
shown_warning = TRUE;
|
||||
}
|
||||
/* NB: We make a best effort attempt to display as many layers as
|
||||
* possible. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (layer->tex->bitmap.format & COGL_A_BIT)
|
||||
enable_flags |= COGL_ENABLE_BLEND;
|
||||
|
||||
valid_layers = g_list_prepend (valid_layers, layer);
|
||||
}
|
||||
valid_layers = g_list_reverse (valid_layers);
|
||||
|
||||
/* Enable blending if the geometry has an associated alpha color,
|
||||
* or - see above - we also check each layer texture and if any has
|
||||
* an alpha channel also enable blending. */
|
||||
if (ctx->color_alpha < 255)
|
||||
enable_flags |= COGL_ENABLE_BLEND;
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
/* NB: It could be that no valid texture layers were found, but
|
||||
* we will still submit a non-textured rectangle in that case. */
|
||||
if (count)
|
||||
tex_coords_buff = alloca (sizeof(GLfloat) * 8 * count);
|
||||
|
||||
/* NB: valid_layers is in order, sorted by index */
|
||||
for (count = 0, tmp = valid_layers;
|
||||
tmp != NULL;
|
||||
count++, tmp = tmp->next)
|
||||
{
|
||||
CoglMultiTextureLayer *layer = tmp->data;
|
||||
CoglFixed *in_tex_coords = &user_tex_coords[count * 4];
|
||||
GLfloat *out_tex_coords = &tex_coords_buff[count * 8];
|
||||
GLenum gl_tex_handle;
|
||||
|
||||
#define CFX_F COGL_FIXED_TO_FLOAT
|
||||
/* IN LAYOUT: [ tx1:0, ty1:1, tx2:2, ty2:3 ] */
|
||||
out_tex_coords[0] = CFX_F (in_tex_coords[0]); /* tx1 */
|
||||
out_tex_coords[1] = CFX_F (in_tex_coords[1]); /* ty1 */
|
||||
out_tex_coords[2] = CFX_F (in_tex_coords[2]); /* tx2 */
|
||||
out_tex_coords[3] = CFX_F (in_tex_coords[1]); /* ty1 */
|
||||
out_tex_coords[4] = CFX_F (in_tex_coords[0]); /* tx1 */
|
||||
out_tex_coords[5] = CFX_F (in_tex_coords[3]); /* ty2 */
|
||||
out_tex_coords[6] = CFX_F (in_tex_coords[2]); /* tx2 */
|
||||
out_tex_coords[7] = CFX_F (in_tex_coords[3]); /* ty2 */
|
||||
#undef CFX_F
|
||||
|
||||
/* TODO - support sliced textures */
|
||||
gl_tex_handle = g_array_index (layer->tex->slice_gl_handles, GLuint, 0);
|
||||
|
||||
GE (glActiveTexture (GL_TEXTURE0 + count));
|
||||
GE (glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
|
||||
GE (glBindTexture (GL_TEXTURE_2D, gl_tex_handle));
|
||||
/* GE (glEnable (GL_TEXTURE_2D)); */
|
||||
|
||||
GE (glClientActiveTexture (GL_TEXTURE0 + count));
|
||||
GE (glTexCoordPointer (2, GL_FLOAT, 0, out_tex_coords));
|
||||
/* GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY)); */
|
||||
|
||||
/* FIXME - cogl only knows about one texture unit a.t.m
|
||||
* (Also see cleanup note below) */
|
||||
if (count == 0)
|
||||
{
|
||||
enable_flags |= COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_TEXCOORD_ARRAY;
|
||||
cogl_enable (enable_flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
GE (glEnable (GL_TEXTURE_2D));
|
||||
GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY));
|
||||
}
|
||||
}
|
||||
|
||||
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
/* FIXME - cogl doesn't currently have a way of caching the
|
||||
* enable states for more than one texture unit so for now,
|
||||
* we just disable anything relating to additional units once
|
||||
* we are done with them. */
|
||||
while (--count > 0)
|
||||
{
|
||||
GE (glActiveTexture (GL_TEXTURE0 + count));
|
||||
GE (glClientActiveTexture (GL_TEXTURE0 + count));
|
||||
|
||||
GE (glDisable (GL_TEXTURE_2D));
|
||||
GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,9 @@ cogl_create_context ()
|
||||
_context->texture_handles = NULL;
|
||||
_context->texture_vertices_size = 0;
|
||||
_context->texture_vertices = NULL;
|
||||
|
||||
_context->multi_texture_handles = NULL;
|
||||
_context->multi_texture_layer_handles = NULL;
|
||||
|
||||
_context->fbo_handles = NULL;
|
||||
_context->program_handles = NULL;
|
||||
_context->shader_handles = NULL;
|
||||
|
@ -68,6 +68,12 @@ typedef struct
|
||||
CoglTextureGLVertex *texture_vertices;
|
||||
gulong texture_vertices_size;
|
||||
|
||||
/* Multi Textures */
|
||||
GArray *multi_texture_handles;
|
||||
|
||||
/* Multi Texture Layers */
|
||||
GArray *multi_texture_layer_handles;
|
||||
|
||||
/* Framebuffer objects */
|
||||
GArray *fbo_handles;
|
||||
CoglBufferTarget draw_buffer;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 ***/
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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_glFogx (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;
|
||||
}
|
||||
}
|
||||
@ -551,11 +676,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 */
|
||||
@ -565,6 +698,7 @@ cogl_wrap_glPushMatrix ()
|
||||
void
|
||||
cogl_wrap_glPopMatrix ()
|
||||
{
|
||||
CoglGles2WrapperTextureUnit *texture_unit;
|
||||
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
|
||||
|
||||
/* Decrement the stack pointer */
|
||||
@ -582,7 +716,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;
|
||||
}
|
||||
@ -602,6 +739,8 @@ cogl_wrap_glMatrixMode (GLenum mode)
|
||||
static float *
|
||||
cogl_gles2_get_matrix_stack_top (CoglGles2Wrapper *wrapper)
|
||||
{
|
||||
CoglGles2WrapperTextureUnit *texture_unit;
|
||||
|
||||
switch (wrapper->matrix_mode)
|
||||
{
|
||||
default:
|
||||
@ -612,7 +751,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -743,7 +887,7 @@ cogl_wrap_glRotatex (GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
|
||||
float anglef = COGL_FIXED_TO_FLOAT (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;
|
||||
@ -800,8 +944,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
|
||||
@ -935,7 +1093,7 @@ cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count)
|
||||
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,
|
||||
@ -944,11 +1102,28 @@ cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count)
|
||||
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)
|
||||
@ -965,9 +1140,22 @@ cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count)
|
||||
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;
|
||||
}
|
||||
@ -995,10 +1183,70 @@ cogl_wrap_glDrawArrays (GLenum mode, GLint first, GLsizei count)
|
||||
&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;
|
||||
}
|
||||
}
|
||||
glDrawArrays (mode, first, count);
|
||||
}
|
||||
|
||||
@ -1013,7 +1261,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
|
||||
@ -1024,6 +1275,79 @@ cogl_wrap_glTexEnvx (GLenum target, GLenum pname, GLfixed 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)
|
||||
{
|
||||
@ -1032,7 +1356,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:
|
||||
@ -1056,7 +1381,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:
|
||||
@ -1075,13 +1401,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);
|
||||
@ -1095,13 +1434,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);
|
||||
@ -1162,6 +1514,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;
|
||||
@ -1208,7 +1564,7 @@ cogl_wrap_glFogx (GLenum pname, GLfixed 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,
|
||||
COGL_FIXED_TO_FLOAT (param));
|
||||
|
@ -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];
|
||||
@ -234,6 +295,9 @@ void cogl_wrap_glNormalPointer (GLenum type, GLsizei stride,
|
||||
|
||||
void cogl_wrap_glTexEnvx (GLenum target, GLenum pname, GLfixed 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);
|
||||
|
||||
@ -259,12 +323,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 */
|
||||
@ -291,6 +349,7 @@ void _cogl_gles2_clear_cache_for_program (CoglHandle program);
|
||||
#define cogl_wrap_glColorPointer glColorPointer
|
||||
#define cogl_wrap_glNormalPointer glNormalPointer
|
||||
#define cogl_wrap_glTexEnvx glTexEnvx
|
||||
#define cogl_wrap_glActiveTexture glActiveTexture
|
||||
#define cogl_wrap_glEnableClientState glEnableClientState
|
||||
#define cogl_wrap_glDisableClientState glDisableClientState
|
||||
#define cogl_wrap_glAlphaFunc glAlphaFunc
|
||||
|
@ -31,6 +31,8 @@
|
||||
typedef struct _CoglTexture CoglTexture;
|
||||
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
|
||||
typedef struct _CoglSpanIter CoglSpanIter;
|
||||
typedef struct _CoglMultiTexture CoglMultiTexture;
|
||||
typedef struct _CoglMultiTextureLayer CoglMultiTextureLayer;
|
||||
|
||||
struct _CoglTexSliceSpan
|
||||
{
|
||||
@ -59,7 +61,26 @@ struct _CoglTexture
|
||||
gboolean auto_mipmap;
|
||||
};
|
||||
|
||||
struct _CoglMultiTextureLayer
|
||||
{
|
||||
guint ref_count;
|
||||
guint index; /*!< lowest index is blended first then others
|
||||
on top */
|
||||
CoglTexture *tex; /*!< The texture for this layer, or NULL
|
||||
for an empty layer */
|
||||
|
||||
/* TODO: Add more control over the texture environment for each texture
|
||||
* unit. For example we should support dot3 normal mapping. */
|
||||
};
|
||||
|
||||
struct _CoglMultiTexture
|
||||
{
|
||||
guint ref_count;
|
||||
GList *layers;
|
||||
};
|
||||
|
||||
CoglTexture*
|
||||
_cogl_texture_pointer_from_handle (CoglHandle handle);
|
||||
|
||||
#endif /* __COGL_TEXTURE_H */
|
||||
|
||||
|
@ -40,11 +40,20 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if HAVE_COGL_GLES2
|
||||
#define glVertexPointer cogl_wrap_glVertexPointer
|
||||
#define glTexCoordPointer cogl_wrap_glTexCoordPointer
|
||||
#define glColorPointer cogl_wrap_glColorPointer
|
||||
#define glDrawArrays cogl_wrap_glDrawArrays
|
||||
#define glTexParameteri cogl_wrap_glTexParameteri
|
||||
#define glClientActiveTexture cogl_wrap_glClientActiveTexture
|
||||
#define glActiveTexture cogl_wrap_glActiveTexture
|
||||
#define glEnable cogl_wrap_glEnable
|
||||
#define glEnableClientState cogl_wrap_glEnableClientState
|
||||
#define glDisable cogl_wrap_glDisable
|
||||
#define glDisableClientState cogl_wrap_glDisableClientState
|
||||
#define glTexEnvx cogl_wrap_glTexEnvx
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define COGL_DEBUG 1
|
||||
@ -75,14 +84,14 @@ struct _CoglSpanIter
|
||||
};
|
||||
|
||||
static void _cogl_texture_free (CoglTexture *tex);
|
||||
static void _cogl_multi_texture_free (CoglMultiTexture *multi_texture);
|
||||
static void _cogl_multi_texture_layer_free (CoglMultiTextureLayer *layer);
|
||||
|
||||
COGL_HANDLE_DEFINE (Texture, texture, texture_handles);
|
||||
|
||||
CoglHandle
|
||||
_cogl_texture_handle_from_pointer (CoglTexture *tex)
|
||||
{
|
||||
return (CoglHandle) tex;
|
||||
}
|
||||
COGL_HANDLE_DEFINE (MultiTexture, multi_texture, multi_texture_handles);
|
||||
COGL_HANDLE_DEFINE (MultiTextureLayer,
|
||||
multi_texture_layer,
|
||||
multi_texture_layer_handles);
|
||||
|
||||
static void
|
||||
_cogl_texture_bitmap_free (CoglTexture *tex)
|
||||
@ -2493,3 +2502,263 @@ cogl_texture_polygon (CoglHandle handle,
|
||||
if (use_color && n_vertices > 0)
|
||||
cogl_set_source_color (&vertices[n_vertices - 1].color);
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_multi_texture_new (void)
|
||||
{
|
||||
CoglMultiTexture *multi_tex = g_new0 (CoglMultiTexture, 1);
|
||||
return _cogl_multi_texture_handle_new (multi_tex);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_multi_texture_free (CoglMultiTexture *multi_tex)
|
||||
{
|
||||
g_list_foreach (multi_tex->layers,
|
||||
(GFunc)cogl_multi_texture_layer_unref, NULL);
|
||||
g_free (multi_tex);
|
||||
}
|
||||
|
||||
static CoglMultiTextureLayer *
|
||||
_cogl_multi_texture_get_layer (CoglMultiTexture *multi_tex, guint index)
|
||||
{
|
||||
CoglMultiTextureLayer *layer;
|
||||
GList *tmp;
|
||||
|
||||
for (tmp = multi_tex->layers; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
layer = tmp->data;
|
||||
if (layer->index == index)
|
||||
return layer;
|
||||
|
||||
/* The layers are always sorted, so we know this layer doesn't exists */
|
||||
if (layer->index > index)
|
||||
break;
|
||||
}
|
||||
/* NB: if we now insert a new layer before tmp, that will maintain order.
|
||||
*/
|
||||
|
||||
layer = g_new (CoglMultiTextureLayer, 1);
|
||||
|
||||
layer->ref_count = 1;
|
||||
layer->index = index;
|
||||
/* Note: comment after for() loop above */
|
||||
multi_tex->layers = g_list_insert_before (multi_tex->layers, tmp, layer);
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_multi_texture_layer_set_texture (CoglHandle multi_texture_handle,
|
||||
guint layer_index,
|
||||
CoglHandle tex_handle)
|
||||
{
|
||||
CoglMultiTexture *multi_tex;
|
||||
CoglMultiTextureLayer *layer;
|
||||
CoglTexture *tex;
|
||||
|
||||
if (!cogl_is_multi_texture (multi_texture_handle)
|
||||
|| !cogl_is_texture (tex_handle))
|
||||
return;
|
||||
|
||||
multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
|
||||
layer = _cogl_multi_texture_get_layer (multi_tex, layer_index);
|
||||
tex = _cogl_texture_pointer_from_handle (tex_handle);
|
||||
|
||||
cogl_texture_ref (tex_handle);
|
||||
|
||||
layer->tex = tex;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_multi_texture_layer_free (CoglMultiTextureLayer *layer)
|
||||
{
|
||||
cogl_texture_unref (layer->tex);
|
||||
g_free (layer);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_multi_texture_layer_remove (CoglHandle multi_texture_handle,
|
||||
guint layer_index)
|
||||
{
|
||||
CoglMultiTexture *multi_tex;
|
||||
CoglMultiTextureLayer *layer;
|
||||
GList *tmp;
|
||||
|
||||
/* Check if valid multi texture */
|
||||
if (!cogl_is_multi_texture (multi_texture_handle))
|
||||
return;
|
||||
|
||||
multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
|
||||
for (tmp = multi_tex->layers; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
layer = tmp->data;
|
||||
if (layer->index == layer_index)
|
||||
{
|
||||
CoglHandle handle =
|
||||
_cogl_multi_texture_layer_handle_from_pointer (layer);
|
||||
cogl_multi_texture_layer_unref (handle);
|
||||
multi_tex->layers = g_list_remove (multi_tex->layers, layer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cogl_multi_texture_rectangle (CoglHandle multi_texture_handle,
|
||||
CoglFixed x1,
|
||||
CoglFixed y1,
|
||||
CoglFixed x2,
|
||||
CoglFixed y2,
|
||||
CoglFixed *user_tex_coords)
|
||||
{
|
||||
CoglMultiTexture *multi_tex;
|
||||
GLfixed quad_coords[8];
|
||||
GList *tmp;
|
||||
GList *valid_layers = NULL;
|
||||
int count;
|
||||
GLfloat *tex_coords_buff;
|
||||
gulong enable_flags = 0;
|
||||
/* FIXME - currently cogl deals with enabling texturing
|
||||
* via enable flags, but that can't scale to n texture
|
||||
* units. Currently we have to be carefull how we leave the
|
||||
* environment so we don't break things. See the cleanup
|
||||
* notes at the end of this function */
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Check if valid multi texture */
|
||||
if (!cogl_is_multi_texture (multi_texture_handle))
|
||||
return;
|
||||
|
||||
multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
|
||||
|
||||
#define CFX_F COGL_FIXED_TO_FLOAT
|
||||
quad_coords[0] = CFX_F (x1);
|
||||
quad_coords[1] = CFX_F (y1);
|
||||
quad_coords[2] = CFX_F (x2);
|
||||
quad_coords[3] = CFX_F (y1);
|
||||
quad_coords[4] = CFX_F (x1);
|
||||
quad_coords[5] = CFX_F (y2);
|
||||
quad_coords[6] = CFX_F (x2);
|
||||
quad_coords[7] = CFX_F (y2);
|
||||
#undef CFX_F
|
||||
|
||||
enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
|
||||
GE( glVertexPointer (2, GL_FIXED, 0, quad_coords) );
|
||||
|
||||
for (count = 0, tmp = multi_tex->layers;
|
||||
tmp != NULL;
|
||||
count++, tmp = tmp->next)
|
||||
{
|
||||
CoglMultiTextureLayer *layer = tmp->data;
|
||||
|
||||
/* Skip empty layers */
|
||||
if (!layer->tex)
|
||||
{
|
||||
count--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* FIXME - currently we don't support sliced textures */
|
||||
if (layer->tex->slice_gl_handles == NULL
|
||||
|| layer->tex->slice_gl_handles->len < 1)
|
||||
continue;
|
||||
|
||||
if (count >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
|
||||
{
|
||||
static gboolean shown_warning = FALSE;
|
||||
|
||||
if (!shown_warning)
|
||||
{
|
||||
g_warning ("Your driver does not support enough texture layers"
|
||||
"to correctly handle this multi texturing");
|
||||
shown_warning = TRUE;
|
||||
}
|
||||
/* NB: We make a best effort attempt to display as many layers as
|
||||
* possible. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (layer->tex->bitmap.format & COGL_A_BIT)
|
||||
enable_flags |= COGL_ENABLE_BLEND;
|
||||
|
||||
valid_layers = g_list_prepend (valid_layers, layer);
|
||||
}
|
||||
valid_layers = g_list_reverse (valid_layers);
|
||||
|
||||
/* Enable blending if the geometry has an associated alpha color,
|
||||
* or - see above - we also check each layer texture and if any has
|
||||
* an alpha channel also enable blending. */
|
||||
if (ctx->color_alpha < 255)
|
||||
enable_flags |= COGL_ENABLE_BLEND;
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
/* NB: It could be that no valid texture layers were found, but
|
||||
* we will still submit a non-textured rectangle in that case. */
|
||||
if (count)
|
||||
tex_coords_buff = alloca (sizeof(GLfloat) * 8 * count);
|
||||
|
||||
/* NB: valid_layers is in order, sorted by index */
|
||||
for (count = 0, tmp = valid_layers;
|
||||
tmp != NULL;
|
||||
count++, tmp = tmp->next)
|
||||
{
|
||||
CoglMultiTextureLayer *layer = tmp->data;
|
||||
CoglFixed *in_tex_coords = &user_tex_coords[count * 4];
|
||||
GLfloat *out_tex_coords = &tex_coords_buff[count * 8];
|
||||
GLenum gl_tex_handle;
|
||||
|
||||
#define CFX_F COGL_FIXED_TO_FLOAT
|
||||
/* IN LAYOUT: [ tx1:0, ty1:1, tx2:2, ty2:3 ] */
|
||||
out_tex_coords[0] = CFX_F (in_tex_coords[0]); /* tx1 */
|
||||
out_tex_coords[1] = CFX_F (in_tex_coords[1]); /* ty1 */
|
||||
out_tex_coords[2] = CFX_F (in_tex_coords[2]); /* tx2 */
|
||||
out_tex_coords[3] = CFX_F (in_tex_coords[1]); /* ty1 */
|
||||
out_tex_coords[4] = CFX_F (in_tex_coords[0]); /* tx1 */
|
||||
out_tex_coords[5] = CFX_F (in_tex_coords[3]); /* ty2 */
|
||||
out_tex_coords[6] = CFX_F (in_tex_coords[2]); /* tx2 */
|
||||
out_tex_coords[7] = CFX_F (in_tex_coords[3]); /* ty2 */
|
||||
#undef CFX_F
|
||||
|
||||
/* TODO - support sliced textures */
|
||||
gl_tex_handle = g_array_index (layer->tex->slice_gl_handles, GLuint, 0);
|
||||
|
||||
GE (glActiveTexture (GL_TEXTURE0 + count));
|
||||
GE (glTexEnvx (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE));
|
||||
GE( cogl_gles2_wrapper_bind_texture (layer->tex->gl_target,
|
||||
gl_tex_handle,
|
||||
layer->tex->gl_intformat));
|
||||
|
||||
GE (glClientActiveTexture (GL_TEXTURE0 + count));
|
||||
GE (glTexCoordPointer (2, GL_FLOAT, 0, out_tex_coords));
|
||||
|
||||
/* FIXME - cogl only knows about one texture unit a.t.m
|
||||
* (Also see cleanup note below) */
|
||||
if (count == 0)
|
||||
{
|
||||
enable_flags |= COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_TEXCOORD_ARRAY;
|
||||
cogl_enable (enable_flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
GE (glEnable (GL_TEXTURE_2D));
|
||||
GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY));
|
||||
}
|
||||
}
|
||||
|
||||
GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
|
||||
|
||||
/* FIXME - cogl doesn't currently have a way of caching the
|
||||
* enable states for more than one texture unit so for now,
|
||||
* we just disable anything relating to additional units once
|
||||
* we are done with them. */
|
||||
while (--count > 0)
|
||||
{
|
||||
GE (glActiveTexture (GL_TEXTURE0 + count));
|
||||
GE (glClientActiveTexture (GL_TEXTURE0 + count));
|
||||
|
||||
GE (cogl_wrap_glDisable (GL_TEXTURE_2D));
|
||||
GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user