mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +00:00
Updates previous GLES multi-texturing code to use CoglMaterial
test-cogl-material now runs on GLES 1 using the PVR GLES1 SDK (though since only 2 texture units are supported the third rotating light map doesn't show) Note: It currently doesn't build for GLES 2.0
This commit is contained in:
parent
61b8cc1874
commit
1a8a9c4bc8
@ -47,12 +47,14 @@ typedef enum _CoglMaterialBlendFactor
|
||||
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,
|
||||
#if 0
|
||||
COGL_MATERIAL_BLEND_FACTOR_CONSTANT_COLOR = GL_CONSTANT_COLOR,
|
||||
COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR =
|
||||
GL_ONE_MINUS_CONSTANT_COLOR,
|
||||
COGL_MATERIAL_BLEND_FACTOR_CONSTANT_ALPHA = GL_CONSTANT_ALPHA,
|
||||
COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA =
|
||||
GL_ONE_MINUS_CONSTANT_ALPHA
|
||||
#endif
|
||||
} CoglMaterialBlendFactor;
|
||||
|
||||
typedef enum _CoglMaterialLayerType
|
||||
|
@ -61,8 +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->material_handles = NULL;
|
||||
_context->material_layer_handles = NULL;
|
||||
_context->source_material = COGL_INVALID_HANDLE;
|
||||
|
||||
_context->fbo_handles = NULL;
|
||||
_context->program_handles = NULL;
|
||||
|
@ -68,11 +68,10 @@ typedef struct
|
||||
CoglTextureGLVertex *texture_vertices;
|
||||
gulong texture_vertices_size;
|
||||
|
||||
/* Multi Textures */
|
||||
GArray *multi_texture_handles;
|
||||
|
||||
/* Multi Texture Layers */
|
||||
GArray *multi_texture_layer_handles;
|
||||
/* Materials */
|
||||
GArray *material_handles;
|
||||
GArray *material_layer_handles;
|
||||
CoglHandle source_material;
|
||||
|
||||
/* Framebuffer objects */
|
||||
GArray *fbo_handles;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "cogl-util.h"
|
||||
#include "cogl-bitmap.h"
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-material.h"
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-handle.h"
|
||||
|
||||
@ -52,7 +53,6 @@
|
||||
#define glEnableClientState cogl_wrap_glEnableClientState
|
||||
#define glDisable cogl_wrap_glDisable
|
||||
#define glDisableClientState cogl_wrap_glDisableClientState
|
||||
#define glTexEnvx cogl_wrap_glTexEnvx
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -84,14 +84,8 @@ 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);
|
||||
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)
|
||||
@ -2503,210 +2497,81 @@ cogl_texture_polygon (CoglHandle handle,
|
||||
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)
|
||||
cogl_material_rectangle (CoglFixed x1,
|
||||
CoglFixed y1,
|
||||
CoglFixed x2,
|
||||
CoglFixed y2,
|
||||
CoglFixed *user_tex_coords)
|
||||
{
|
||||
CoglMultiTexture *multi_tex;
|
||||
CoglMultiTextureLayer *layer;
|
||||
CoglTexture *tex;
|
||||
CoglHandle material;
|
||||
const GList *layers;
|
||||
int n_layers;
|
||||
const GList *tmp;
|
||||
CoglHandle *valid_layers = NULL;
|
||||
int n_valid_layers = 0;
|
||||
gboolean handle_slicing = FALSE;
|
||||
int i;
|
||||
GLfloat *tex_coords_buff;
|
||||
GLfloat quad_coords[8];
|
||||
gulong enable_flags = 0;
|
||||
GLfloat values[4];
|
||||
|
||||
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
|
||||
/* 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;
|
||||
material = ctx->source_material;
|
||||
|
||||
multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
|
||||
layers = cogl_material_get_layers (material);
|
||||
n_layers = g_list_length ((GList *)layers);
|
||||
valid_layers = alloca (sizeof (CoglHandle) * n_layers);
|
||||
|
||||
#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)
|
||||
for (tmp = layers; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
CoglMultiTextureLayer *layer = tmp->data;
|
||||
CoglHandle layer = tmp->data;
|
||||
CoglHandle texture = cogl_material_layer_get_texture (layer);
|
||||
|
||||
/* 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)
|
||||
if (cogl_material_layer_get_type (layer)
|
||||
!= COGL_MATERIAL_LAYER_TYPE_TEXTURE)
|
||||
continue;
|
||||
|
||||
if (count >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
|
||||
/* FIXME: support sliced textures. For now if the first layer is
|
||||
* sliced then all other layers are ignored, or if the first layer
|
||||
* is not sliced, we ignore sliced textures in other layers. */
|
||||
if (cogl_texture_is_sliced (texture))
|
||||
{
|
||||
static gboolean shown_warning = FALSE;
|
||||
|
||||
if (!shown_warning)
|
||||
if (n_valid_layers == 0)
|
||||
{
|
||||
g_warning ("Your driver does not support enough texture layers"
|
||||
"to correctly handle this multi texturing");
|
||||
shown_warning = TRUE;
|
||||
valid_layers[n_valid_layers++] = layer;
|
||||
handle_slicing = TRUE;
|
||||
break;
|
||||
}
|
||||
/* NB: We make a best effort attempt to display as many layers as
|
||||
* possible. */
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
valid_layers[n_valid_layers++] = tmp->data;
|
||||
|
||||
if (layer->tex->bitmap.format & COGL_A_BIT)
|
||||
enable_flags |= COGL_ENABLE_BLEND;
|
||||
|
||||
valid_layers = g_list_prepend (valid_layers, layer);
|
||||
if (n_valid_layers >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
|
||||
break;
|
||||
}
|
||||
valid_layers = g_list_reverse (valid_layers);
|
||||
|
||||
/* Enable blending if the geometry has an associated alpha color,
|
||||
* or - see above - we also check each layer texture and if any has
|
||||
* an alpha channel also enable blending. */
|
||||
if (ctx->color_alpha < 255)
|
||||
enable_flags |= COGL_ENABLE_BLEND;
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
/* NB: It could be that no valid texture layers were found, but
|
||||
* we will still submit a non-textured rectangle in that case. */
|
||||
if (count)
|
||||
tex_coords_buff = alloca (sizeof(GLfloat) * 8 * count);
|
||||
if (n_valid_layers)
|
||||
tex_coords_buff = alloca (sizeof(GLfloat) * 8 * n_valid_layers);
|
||||
|
||||
/* NB: valid_layers is in order, sorted by index */
|
||||
for (count = 0, tmp = valid_layers;
|
||||
tmp != NULL;
|
||||
count++, tmp = tmp->next)
|
||||
for (i = 0; i < n_valid_layers; i++)
|
||||
{
|
||||
CoglMultiTextureLayer *layer = tmp->data;
|
||||
CoglFixed *in_tex_coords = &user_tex_coords[count * 4];
|
||||
GLfloat *out_tex_coords = &tex_coords_buff[count * 8];
|
||||
GLenum gl_tex_handle;
|
||||
CoglHandle layer = valid_layers[i];
|
||||
CoglHandle texture_handle = cogl_material_layer_get_texture (layer);
|
||||
CoglTexture *texture = _cogl_texture_pointer_from_handle (texture_handle);
|
||||
CoglFixed *in_tex_coords = &user_tex_coords[i * 4];
|
||||
GLfloat *out_tex_coords = &tex_coords_buff[i * 8];
|
||||
GLuint gl_tex_handle;
|
||||
GLenum gl_target;
|
||||
|
||||
#define CFX_F COGL_FIXED_TO_FLOAT
|
||||
/* IN LAYOUT: [ tx1:0, ty1:1, tx2:2, ty2:3 ] */
|
||||
@ -2721,24 +2586,23 @@ cogl_multi_texture_rectangle (CoglHandle multi_texture_handle,
|
||||
#undef CFX_F
|
||||
|
||||
/* TODO - support sliced textures */
|
||||
gl_tex_handle = g_array_index (layer->tex->slice_gl_handles, GLuint, 0);
|
||||
cogl_texture_get_gl_texture (texture, &gl_tex_handle, &gl_target);
|
||||
|
||||
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,
|
||||
GE (glActiveTexture (GL_TEXTURE0 + i));
|
||||
cogl_material_layer_flush_gl_sampler_state (layer);
|
||||
GE( cogl_gles2_wrapper_bind_texture (gl_target,
|
||||
gl_tex_handle,
|
||||
layer->tex->gl_intformat));
|
||||
texure->gl_intformat));
|
||||
/* GE (glEnable (GL_TEXTURE_2D)); */
|
||||
|
||||
GE (glClientActiveTexture (GL_TEXTURE0 + count));
|
||||
GE (glClientActiveTexture (GL_TEXTURE0 + i));
|
||||
GE (glTexCoordPointer (2, GL_FLOAT, 0, out_tex_coords));
|
||||
/* GE (glEnableClientState (GL_TEXTURE_COORD_ARRAY)); */
|
||||
|
||||
/* FIXME - cogl only knows about one texture unit a.t.m
|
||||
* (Also see cleanup note below) */
|
||||
if (count == 0)
|
||||
{
|
||||
enable_flags |= COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_TEXCOORD_ARRAY;
|
||||
cogl_enable (enable_flags);
|
||||
}
|
||||
if (i == 0)
|
||||
enable_flags |= COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_TEXCOORD_ARRAY;
|
||||
else
|
||||
{
|
||||
GE (glEnable (GL_TEXTURE_2D));
|
||||
@ -2746,19 +2610,61 @@ cogl_multi_texture_rectangle (CoglHandle multi_texture_handle,
|
||||
}
|
||||
}
|
||||
|
||||
GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
|
||||
#define CFX_F COGL_FIXED_TO_FLOAT
|
||||
quad_coords[0] = CFX_F (x1);
|
||||
quad_coords[1] = CFX_F (y1);
|
||||
quad_coords[2] = CFX_F (x2);
|
||||
quad_coords[3] = CFX_F (y1);
|
||||
quad_coords[4] = CFX_F (x1);
|
||||
quad_coords[5] = CFX_F (y2);
|
||||
quad_coords[6] = CFX_F (x2);
|
||||
quad_coords[7] = CFX_F (y2);
|
||||
#undef CFX_F
|
||||
|
||||
enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
|
||||
GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords));
|
||||
|
||||
/* Setup the remaining GL state according to this material... */
|
||||
cogl_material_flush_gl_material_state (material);
|
||||
cogl_material_flush_gl_alpha_func (material);
|
||||
cogl_material_flush_gl_blend_func (material);
|
||||
/* FIXME: This api is a bit yukky, ideally it will be removed if we
|
||||
* re-work the cogl_enable mechanism */
|
||||
enable_flags |= cogl_material_get_cogl_enable_flags (material);
|
||||
|
||||
/* FIXME - cogl only knows about one texture unit so assumes that unit 0
|
||||
* is always active...*/
|
||||
GE (glActiveTexture (GL_TEXTURE0));
|
||||
GE (glClientActiveTexture (GL_TEXTURE0));
|
||||
cogl_enable (enable_flags);
|
||||
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
/* FIXME - cogl doesn't currently have a way of caching the
|
||||
* enable states for more than one texture unit so for now,
|
||||
* we just disable anything relating to additional units once
|
||||
* we are done with them. */
|
||||
while (--count > 0)
|
||||
for (i = 1; i < n_valid_layers; i++)
|
||||
{
|
||||
GE (glActiveTexture (GL_TEXTURE0 + count));
|
||||
GE (glClientActiveTexture (GL_TEXTURE0 + count));
|
||||
GE (glActiveTexture (GL_TEXTURE0 + i));
|
||||
GE (glClientActiveTexture (GL_TEXTURE0 + i));
|
||||
|
||||
GE (cogl_wrap_glDisable (GL_TEXTURE_2D));
|
||||
GE (glDisable (GL_TEXTURE_2D));
|
||||
GE (glDisableClientState (GL_TEXTURE_COORD_ARRAY));
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME - CoglMaterials aren't yet used pervasively throughout
|
||||
* the cogl API, so we currently need to cleanup material state
|
||||
* that will confuse other parts of the API.
|
||||
* Other places to tweak, include the primitives API and lite
|
||||
* GL wrappers like cogl_rectangle */
|
||||
values[0] = 0.2; values[1] = 0.2; values[2] = 0.2; values[3] = 1.0;
|
||||
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, values));
|
||||
values[0] = 0.8; values[1] = 0.8; values[2] = 0.8; values[3] = 1.0;
|
||||
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, values));
|
||||
values[0] = 0; values[1] = 0; values[2] = 0; values[3] = 1.0;
|
||||
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, values));
|
||||
values[0] = 0; values[1] = 0; values[2] = 0; values[3] = 1.0;
|
||||
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, values));
|
||||
values[0] = 0;
|
||||
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, values));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user