Updates previous GLES multi-texturing code to use CoglMaterial
authorRobert Bragg <robert@linux.intel.com>
Thu, 18 Dec 2008 19:12:09 +0000 (19:12 +0000)
committerRobert Bragg <robert@linux.intel.com>
Mon, 22 Dec 2008 16:35:52 +0000 (16:35 +0000)
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

clutter/cogl/cogl-material.h
clutter/cogl/gles/cogl-context.c
clutter/cogl/gles/cogl-context.h
clutter/cogl/gles/cogl-texture.c

index 9a6f0eb..973a9d7 100644 (file)
@@ -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
index 7b08576..c6ac088 100644 (file)
@@ -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;
index 91fac2e..cc1abdd 100644 (file)
@@ -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;
index ba1979e..a745e3b 100644 (file)
@@ -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)
-{
-  CoglMultiTexture     *multi_tex;
-  CoglMultiTextureLayer *layer;
-  CoglTexture          *tex;
-
-  if (!cogl_is_multi_texture (multi_texture_handle)
-      || !cogl_is_texture (tex_handle))
-    return;
-
-  multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
-  layer = _cogl_multi_texture_get_layer (multi_tex, layer_index);
-  tex = _cogl_texture_pointer_from_handle (tex_handle);
-
-  cogl_texture_ref (tex_handle);
-
-  layer->tex = tex;
-}
-
-static void
-_cogl_multi_texture_layer_free (CoglMultiTextureLayer *layer)
-{
-  cogl_texture_unref (layer->tex);
-  g_free (layer);
-}
-
-void
-cogl_multi_texture_layer_remove (CoglHandle multi_texture_handle,
-                                guint layer_index)
-{
-  CoglMultiTexture     *multi_tex;
-  CoglMultiTextureLayer *layer;
-  GList                        *tmp;
-
-  /* Check if valid multi texture */
-  if (!cogl_is_multi_texture (multi_texture_handle))
-    return;
-
-  multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
-  for (tmp = multi_tex->layers; tmp != NULL; tmp = tmp->next)
-    {
-      layer = tmp->data;
-      if (layer->index == layer_index)
-       {
-         CoglHandle handle =
-           _cogl_multi_texture_layer_handle_from_pointer (layer);
-         cogl_multi_texture_layer_unref (handle);
-         multi_tex->layers = g_list_remove (multi_tex->layers, layer);
-         return;
-       }
-    }
-}
-
 void
-cogl_multi_texture_rectangle (CoglHandle     multi_texture_handle,
-                             CoglFixed   x1,
-                             CoglFixed   y1,
-                             CoglFixed   x2,
-                             CoglFixed   y2,
-                             CoglFixed  *user_tex_coords)
+cogl_material_rectangle (CoglFixed   x1,
+                        CoglFixed   y1,
+                        CoglFixed   x2,
+                        CoglFixed   y2,
+                        CoglFixed  *user_tex_coords)
 {
-  CoglMultiTexture  *multi_tex;
-  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
+  CoglHandle    material;
+  const GList  *layers;
+  int           n_layers;
+  const GList  *tmp;
+  CoglHandle   *valid_layers = NULL;
+  int           n_valid_layers = 0;
+  gboolean      handle_slicing = FALSE;
+  int           i;
+  GLfloat      *tex_coords_buff;
+  GLfloat       quad_coords[8];
+  gulong        enable_flags = 0;
+  GLfloat       values[4];
+
+  /* FIXME - currently cogl deals with enabling texturing via enable flags,
+   * but that can't scale to n texture units. Currently we have to be carefull
+   * how we leave the environment so we don't break things. See the cleanup
    * notes at the end of this function */
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
-  /* Check if valid multi texture */
-  if (!cogl_is_multi_texture (multi_texture_handle))
-    return;
-
-  multi_tex = _cogl_multi_texture_pointer_from_handle (multi_texture_handle);
-
-#define CFX_F COGL_FIXED_TO_FLOAT
-  quad_coords[0] = CFX_F (x1);
-  quad_coords[1] = CFX_F (y1);
-  quad_coords[2] = CFX_F (x2);
-  quad_coords[3] = CFX_F (y1);
-  quad_coords[4] = CFX_F (x1);
-  quad_coords[5] = CFX_F (y2);
-  quad_coords[6] = CFX_F (x2);
-  quad_coords[7] = CFX_F (y2);
-#undef CFX_F
+  material = ctx->source_material;
 
-  enable_flags  |= COGL_ENABLE_VERTEX_ARRAY;
-  GE( glVertexPointer (2, GL_FIXED, 0, quad_coords) );
+  layers = cogl_material_get_layers (material);
+  n_layers = g_list_length ((GList *)layers);
+  valid_layers = alloca (sizeof (CoglHandle) * n_layers);
 
-  for (count = 0, tmp = multi_tex->layers;
-       tmp != NULL;
-       count++, tmp = tmp->next)
+  for (tmp = layers; tmp != NULL; tmp = tmp->next)
     {
-      CoglMultiTextureLayer *layer = tmp->data;
-
-      /* Skip empty layers */
-      if (!layer->tex)
-       {
-         count--;
-         continue;
-       }
-
-      /* FIXME - currently we don't support sliced textures */
-      if (layer->tex->slice_gl_handles == NULL
-         || layer->tex->slice_gl_handles->len < 1)
+      CoglHandle layer = tmp->data;
+      CoglHandle texture = cogl_material_layer_get_texture (layer);
+      
+      if (cogl_material_layer_get_type (layer)
+         != COGL_MATERIAL_LAYER_TYPE_TEXTURE)
        continue;
 
-      if (count >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
+      /* FIXME: support sliced textures. For now if the first layer is
+       * sliced then all other layers are ignored, or if the first layer
+       * is not sliced, we ignore sliced textures in other layers. */
+      if (cogl_texture_is_sliced (texture))
        {
-         static gboolean shown_warning = FALSE;
-
-         if (!shown_warning)
+         if (n_valid_layers == 0)
            {
-             g_warning ("Your driver does not support enough texture layers"
-                        "to correctly handle this multi texturing");
-             shown_warning = TRUE;
+             valid_layers[n_valid_layers++] = layer;
+             handle_slicing = TRUE;
+             break;
            }
-         /* NB: We make a best effort attempt to display as many layers as
-          * possible. */
-         break;
+         continue;
        }
+      valid_layers[n_valid_layers++] = tmp->data;
 
-      if (layer->tex->bitmap.format & COGL_A_BIT)
-       enable_flags |= COGL_ENABLE_BLEND;
-
-      valid_layers = g_list_prepend (valid_layers, layer);
+      if (n_valid_layers >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
+       break;
     }
-  valid_layers = g_list_reverse (valid_layers);
-
-  /* Enable blending if the geometry has an associated alpha color,
-   * or - see above - we also check each layer texture and if any has
-   * an alpha channel also enable blending. */
-  if (ctx->color_alpha < 255)
-    enable_flags |= COGL_ENABLE_BLEND;
-  cogl_enable (enable_flags);
-
+  
   /* NB: It could be that no valid texture layers were found, but
    * we will still submit a non-textured rectangle in that case. */
-  if (count)
-    tex_coords_buff = alloca (sizeof(GLfloat) * 8 * count);
+  if (n_valid_layers)
+    tex_coords_buff = alloca (sizeof(GLfloat) * 8 * n_valid_layers);
 
-  /* NB: valid_layers is in order, sorted by index */
-  for (count = 0, tmp = valid_layers;
-       tmp != NULL;
-       count++, tmp = tmp->next)
+  for (i = 0; i < n_valid_layers; i++)
     {
-      CoglMultiTextureLayer *layer = tmp->data;
-      CoglFixed *in_tex_coords = &user_tex_coords[count * 4];
-      GLfloat *out_tex_coords = &tex_coords_buff[count * 8];
-      GLenum gl_tex_handle;
+      CoglHandle layer = valid_layers[i];
+      CoglHandle texture_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));
 }
-