[cogl-material] improvements for cogl_material_rectangle
authorRobert Bragg <robert@linux.intel.com>
Tue, 23 Dec 2008 23:50:02 +0000 (23:50 +0000)
committerRobert Bragg <robert@linux.intel.com>
Wed, 24 Dec 2008 01:35:33 +0000 (01:35 +0000)
The API has been changed to take an explicit length for the number of
texture coordinates passed, and it's now documented that if there are
more layers to the current material than the number of texture coords
passed, then default coordinates will be generated for the other
layers.

cogl_material_rectangle should now handle the case where a single
sliced texture is supplied as a material layer by falling back to
cogl_texture_rectangle. We are nearly at the point that
cogl_texture_rectangle could be deprecated. A few issues remain
though, such as not considering waste in cogl_material_rectangle.

clutter/clutter-clone-texture.c
clutter/clutter-texture.c
clutter/cogl/cogl-texture.h
clutter/cogl/common/cogl-material-private.h
clutter/cogl/gl/cogl-texture.c
tests/interactive/test-cogl-material.c

index ba509ad..c84b048 100644 (file)
@@ -229,6 +229,7 @@ clutter_clone_texture_paint (ClutterActor *self)
   cogl_material_rectangle (0, 0,
                            COGL_FIXED_FROM_INT (x_2 - x_1),
                           COGL_FIXED_FROM_INT (y_2 - y_1),
+                           0,
                            tex_coords);
 #else
   /* Parent paint translated us into position */
index 94541ff..52a671b 100644 (file)
@@ -617,6 +617,7 @@ clutter_texture_paint (ClutterActor *self)
   cogl_material_rectangle (0, 0,
                            COGL_FIXED_FROM_INT (x_2 - x_1),
                           COGL_FIXED_FROM_INT (y_2 - y_1),
+                           4,
                            tex_coords);
 #else
   cogl_texture_rectangle (priv->texture, 0, 0,
index 475de2a..3314076 100644 (file)
@@ -386,66 +386,35 @@ void            cogl_texture_polygon          (CoglHandle          handle,
                                                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
+ * cogl_material_rectangle:
  * @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
+ * @tex_coords_len: The length of the tex_coords array. (e.g. for one layer
+ *                  and one group of texture coordinates, this would be 4)
+ * @tex_coords: An array containing groups of 4 CoglFixed values:
+ *   [tx1, ty1, tx2, ty2] that are interpreted as two texture coordinates; one
+ *   for the upper left texel, and one for the lower right texel. Each value
+ *   should be between 0.0 and 1.0, where the coordinate (0.0, 0.0) represents
+ *   the top left of the texture, and (1.0, 1.0) the bottom right.
+ *
+ * This function draws a rectangle using the current source material to
+ * texture or fill with. Since a material may contain multiple texture
+ * layers the interface lets you supply corresponding sets of 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.
+ * The first pair of coordinates are for the first layer (with the smallest
+ * layer index) and if you supply less texture coordinates than there are
+ * layers in the current source material then default texture coordinates
+ * [0.0, 0.0, 1.0, 1.0] are generated.
  */
-void  cogl_multi_texture_rectangle  (CoglHandle        handle,
-                                    CoglFixed  x1,
-                                    CoglFixed  y1,
-                                    CoglFixed  x2,
-                                    CoglFixed  y2,
-                                    CoglFixed *tex_coords);
+void cogl_material_rectangle (CoglFixed   x1,
+                              CoglFixed   y1,
+                              CoglFixed   x2,
+                              CoglFixed   y2,
+                              gint        tex_coords_len,
+                              CoglFixed  *tex_coords);
 
 G_END_DECLS
 
index d64d848..935e0ae 100644 (file)
@@ -22,8 +22,8 @@ struct _CoglMaterialLayer
   gulong       flags;
   CoglHandle   texture;        /*!< The texture for this layer, or COGL_INVALID_HANDLE
                             for an empty layer */
-  
-  /* Determines how the color of individual texture fragments 
+
+  /* Determines how the color of individual texture fragments
    * are calculated. */
   CoglMaterialLayerCombineFunc texture_combine_rgb_func;
   CoglMaterialLayerCombineSrc texture_combine_rgb_src[3];
@@ -32,7 +32,7 @@ struct _CoglMaterialLayer
   CoglMaterialLayerCombineFunc texture_combine_alpha_func;
   CoglMaterialLayerCombineSrc texture_combine_alpha_src[3];
   CoglMaterialLayerCombineOp texture_combine_alpha_op[3];
-  
+
   /* TODO: Support purely GLSL based material layers */
 
   CoglMatrix matrix;
@@ -41,7 +41,8 @@ struct _CoglMaterialLayer
 typedef enum _CoglMaterialFlags
 {
   COGL_MATERIAL_FLAG_ENABLE_BLEND          = 1L<<0,
-  COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING  = 1L<<1
+  COGL_MATERIAL_FLAG_SHOWN_SAMPLER_WARNING  = 1L<<1,
+  COGL_MATERIAL_FLAG_DIRTY                 = 1L<<2
 } CoglMaterialFlags;
 
 struct _CoglMaterial
@@ -50,13 +51,16 @@ struct _CoglMaterial
 
   gulong    flags;
 
+  /* If no lighting is enabled; this is the basic material color */
+  GLfloat   unlit[4];
+
   /* Standard OpenGL lighting model attributes */
   GLfloat   ambient[4];
   GLfloat   diffuse[4];
   GLfloat   specular[4];
   GLfloat   emission[4];
   GLfloat   shininess;
-  
+
   /* Determines what fragments are discarded based on their alpha */
   CoglMaterialAlphaFunc alpha_func;
   GLfloat              alpha_func_reference;
index ab84c95..357fc28 100644 (file)
@@ -2411,6 +2411,7 @@ cogl_material_rectangle (CoglFixed   x1,
                         CoglFixed   y1,
                         CoglFixed   x2,
                         CoglFixed   y2,
+                         gint        user_tex_coords_len,
                         CoglFixed  *user_tex_coords)
 {
   CoglHandle    material;
@@ -2424,7 +2425,6 @@ cogl_material_rectangle (CoglFixed   x1,
   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
@@ -2443,7 +2443,7 @@ cogl_material_rectangle (CoglFixed   x1,
     {
       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;
@@ -2466,7 +2466,18 @@ cogl_material_rectangle (CoglFixed   x1,
       if (n_valid_layers >= CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
        break;
     }
-  
+
+  /* We at least support slicing as much as cogl_texture_rectangle... */
+  if (n_valid_layers == 1 && handle_slicing)
+    {
+      CoglHandle texture = cogl_material_layer_get_texture (valid_layers[0]);
+      cogl_texture_rectangle (texture,
+                              x1, y1, x2, y2,
+                              user_tex_coords[0], user_tex_coords[1],
+                              user_tex_coords[2], user_tex_coords[3]);
+      return;
+    }
+
   /* NB: It could be that no valid texture layers were found, but
    * we will still submit a non-textured rectangle in that case. */
   if (n_valid_layers)
@@ -2476,34 +2487,61 @@ cogl_material_rectangle (CoglFixed   x1,
     {
       CoglHandle layer = valid_layers[i];
       CoglHandle texture = cogl_material_layer_get_texture (layer);
-      CoglFixed *in_tex_coords = &user_tex_coords[i * 4];
+      CoglFixed *in_tex_coords;
       GLfloat *out_tex_coords = &tex_coords_buff[i * 8];
       GLuint 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 */
+      if (i < (user_tex_coords_len / 4))
+        {
+          in_tex_coords = &user_tex_coords[i * 4];
+          /* FIXME: don't include waste in the texture coordinates */
+          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 */
+        }
+      else
+        {
+          out_tex_coords[0] = 0.0; /* tx1 */
+          out_tex_coords[1] = 0.0; /* ty1 */
+          out_tex_coords[2] = 1.0; /* tx2 */
+          out_tex_coords[3] = 0.0; /* ty1 */
+          out_tex_coords[4] = 0.0; /* tx1 */
+          out_tex_coords[5] = 1.0; /* ty2 */
+          out_tex_coords[6] = 1.0; /* tx2 */
+          out_tex_coords[7] = 1.0; /* ty2 */
+        }
 #undef CFX_F
 
       /* TODO - support sliced textures */
       cogl_texture_get_gl_texture (texture, &gl_tex_handle, NULL);
-      //gl_tex_handle = g_array_index (layer->tex->slice_gl_handles, GLuint, 0);
 
       GE (glActiveTexture (GL_TEXTURE0 + i));
       cogl_material_layer_flush_gl_sampler_state (layer);
-      GE (glBindTexture (GL_TEXTURE_2D, gl_tex_handle));
-      /* GE (glEnable (GL_TEXTURE_2D)); */
+        {
+          /* FIXME - we should avoid redundant calls to glBindTexture.
+           * Profiling test-actors, I've seen ~ 10% of the time spent in
+           * _mesa_UpdateTexEnvProgram, which the following simple test can
+           * show is as a result of these redundant glBindTexture calls.
+           */
+#if 0
+          static int debug = 0;
+          if (!debug)
+            GE (glBindTexture (GL_TEXTURE_2D, gl_tex_handle));
+          debug = 1;
+#else
+          GE (glBindTexture (GL_TEXTURE_2D, gl_tex_handle));
+#endif
+        }
 
       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) */
@@ -2538,9 +2576,12 @@ cogl_material_rectangle (CoglFixed   x1,
   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));
+   * is always active... */
+  if (n_valid_layers > 1)
+    {
+      GE (glActiveTexture (GL_TEXTURE0));
+      GE (glClientActiveTexture (GL_TEXTURE0));
+    }
   cogl_enable (enable_flags);
   glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
 
@@ -2551,12 +2592,25 @@ cogl_material_rectangle (CoglFixed   x1,
   for (i = 1; i < n_valid_layers; i++)
     {
       GE (glActiveTexture (GL_TEXTURE0 + i));
+      GE (glDisable (GL_TEXTURE_2D));
+    }
+
+  /* XXX: a bit over precautious. For one we don't support lighting yet
+   * so there's no real need to reset the material properties. */
+#if 0
+  /* 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. */
+  for (i = 1; i < n_valid_layers; i++)
+    {
+      GE (glActiveTexture (GL_TEXTURE0 + i));
       GE (glClientActiveTexture (GL_TEXTURE0 + i));
 
       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.
@@ -2572,5 +2626,6 @@ cogl_material_rectangle (CoglFixed   x1,
   GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, values));
   values[0] = 0;
   GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, values));
+#endif
 }
 
index e340824..00084b5 100644 (file)
@@ -49,6 +49,7 @@ material_rectangle_paint (ClutterActor *actor, gpointer data)
                           CLUTTER_INT_TO_FIXED(0),
                           CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT),
                           CLUTTER_INT_TO_FIXED(TIMELINE_FRAME_COUNT),
+                           12,
                           state->tex_coords);
 }