[Cogl] [PATCH] journal: layer no determines tex coord attrib names

Robert Bragg robert at sixbynine.org
Mon Sep 10 07:06:45 PDT 2012


From: Robert Bragg <robert at linux.intel.com>

The documentation for cogl_framebuffer_draw_multitextured_rectangle
states that texture coordinates are explicitly mapped to pipeline layers
so we can't simply assume that a pipeline with 3 layers should use
attributes cogl_tex_coord0_in, cogl_tex_coord1_in and
cogl_tex_coord2_in.

This changes the journal flushing code to use pipeline layer numbers
to determine the name of texture coordinate attributes.

We now also break batches by using a deeper comparison of layers so
such that two pipelines with the same number of layers can now cause a
batch break if they use different layer numbers.

This adds an internal _cogl_pipeline_layer_numbers_equal() function that
takes two pipelines and returns TRUE if they have the same number of
layers and all the layer numbers are the same too, otherwise it returns
FALSE.

Where we used to break batches based on changes to the number of layers
we now break according to the status of
_cogl_pipeline_layer_numbers_equal
---
 cogl/cogl-journal.c          |  119 +++++++++++++++++++++++++----------------
 cogl/cogl-pipeline-private.h |    4 ++
 cogl/cogl-pipeline.c         |   29 ++++++++++
 3 files changed, 105 insertions(+), 47 deletions(-)

diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c
index 52cab98..a467c33 100644
--- a/cogl/cogl-journal.c
+++ b/cogl/cogl-journal.c
@@ -464,6 +464,67 @@ compare_entry_pipelines (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
     return FALSE;
 }
 
+typedef struct _CreateAttributeState
+{
+  int current;
+  CoglJournalFlushState *flush_state;
+} CreateAttributeState;
+
+static CoglBool
+create_attribute_cb (CoglPipeline *pipeline,
+                     int layer_number,
+                     void *user_data)
+{
+  CreateAttributeState *state = user_data;
+  CoglJournalFlushState *flush_state = state->flush_state;
+  CoglAttribute **attribute_entry =
+    &g_array_index (flush_state->attributes,
+                    CoglAttribute *,
+                    state->current + 2);
+  const char *names[] = {
+      "cogl_tex_coord0_in",
+      "cogl_tex_coord1_in",
+      "cogl_tex_coord2_in",
+      "cogl_tex_coord3_in",
+      "cogl_tex_coord4_in",
+      "cogl_tex_coord5_in",
+      "cogl_tex_coord6_in",
+      "cogl_tex_coord7_in"
+  };
+  char *name;
+
+  /* XXX NB:
+   * Our journal's vertex data is arranged as follows:
+   * 4 vertices per quad:
+   *    2 or 3 floats per position (3 when doing software transforms)
+   *    4 RGBA bytes,
+   *    2 floats per tex coord * n_layers
+   * (though n_layers may be padded; see definition of
+   *  GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS for details)
+   */
+  name = layer_number < 8 ? (char *)names[layer_number] :
+    g_strdup_printf ("cogl_tex_coord%d_in", layer_number);
+
+  /* XXX: it may be worth having some form of static initializer for
+   * attributes... */
+  *attribute_entry =
+    cogl_attribute_new (flush_state->attribute_buffer,
+                        name,
+                        flush_state->stride,
+                        flush_state->array_offset +
+                        (POS_STRIDE + COLOR_STRIDE) * 4 +
+                        TEX_STRIDE * 4 * state->current,
+                        2,
+                        COGL_ATTRIBUTE_TYPE_FLOAT);
+
+  if (layer_number >= 8)
+    g_free (name);
+
+  state->current++;
+
+  return TRUE;
+}
+
 /* Since the stride may not reflect the number of texture layers in use
  * (due to padding) we deal with texture coordinate offsets separately
  * from vertex and color offsets... */
@@ -474,7 +535,8 @@ _cogl_journal_flush_texcoord_vbo_offsets_and_entries (
                                           void             *data)
 {
   CoglJournalFlushState *state = data;
-  int                    i;
+  CreateAttributeState create_attrib_state;
+  int i;
   COGL_STATIC_TIMER (time_flush_texcoord_pipeline_entries,
                      "flush: vbo+texcoords+pipeline+entries", /* parent */
                      "flush: texcoords+pipeline+entries",
@@ -493,49 +555,12 @@ _cogl_journal_flush_texcoord_vbo_offsets_and_entries (
 
   g_array_set_size (state->attributes, batch_start->n_layers + 2);
 
-  for (i = 0; i < batch_start->n_layers; i++)
-    {
-      CoglAttribute **attribute_entry =
-        &g_array_index (state->attributes, CoglAttribute *, i + 2);
-      const char *names[] = {
-          "cogl_tex_coord0_in",
-          "cogl_tex_coord1_in",
-          "cogl_tex_coord2_in",
-          "cogl_tex_coord3_in",
-          "cogl_tex_coord4_in",
-          "cogl_tex_coord5_in",
-          "cogl_tex_coord6_in",
-          "cogl_tex_coord7_in"
-      };
-      char *name;
-
-      /* XXX NB:
-       * Our journal's vertex data is arranged as follows:
-       * 4 vertices per quad:
-       *    2 or 3 floats per position (3 when doing software transforms)
-       *    4 RGBA bytes,
-       *    2 floats per tex coord * n_layers
-       * (though n_layers may be padded; see definition of
-       *  GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS for details)
-       */
-      name = i < 8 ? (char *)names[i] :
-        g_strdup_printf ("cogl_tex_coord%d_in", i);
-
-      /* XXX: it may be worth having some form of static initializer for
-       * attributes... */
-      *attribute_entry =
-        cogl_attribute_new (state->attribute_buffer,
-                            name,
-                            state->stride,
-                            state->array_offset +
-                            (POS_STRIDE + COLOR_STRIDE) * 4 +
-                            TEX_STRIDE * 4 * i,
-                            2,
-                            COGL_ATTRIBUTE_TYPE_FLOAT);
-
-      if (i >= 8)
-        g_free (name);
-    }
+  create_attrib_state.current = 0;
+  create_attrib_state.flush_state = state;
+
+  cogl_pipeline_foreach_layer (batch_start->pipeline,
+                               create_attribute_cb,
+                               &create_attrib_state);
 
   batch_and_call (batch_start,
                   batch_len,
@@ -546,9 +571,9 @@ _cogl_journal_flush_texcoord_vbo_offsets_and_entries (
 }
 
 static CoglBool
-compare_entry_n_layers (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
+compare_entry_layer_numbers (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
 {
-  if (entry0->n_layers == entry1->n_layers)
+  if (_cogl_pipeline_layer_numbers_equal (entry0->pipeline, entry1->pipeline))
     return TRUE;
   else
     return FALSE;
@@ -645,7 +670,7 @@ _cogl_journal_flush_vbo_offsets_and_entries (CoglJournalEntry *batch_start,
 
   batch_and_call (batch_start,
                   batch_len,
-                  compare_entry_n_layers,
+                  compare_entry_layer_numbers,
                   _cogl_journal_flush_texcoord_vbo_offsets_and_entries,
                   data);
 
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index 3c2f0a5..31d896f 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -925,6 +925,10 @@ _cogl_pipeline_foreach_layer_internal (CoglPipeline *pipeline,
                                        void *user_data);
 
 CoglBool
+_cogl_pipeline_layer_numbers_equal (CoglPipeline *pipeline0,
+                                    CoglPipeline *pipeline1);
+
+CoglBool
 _cogl_pipeline_need_texture_combine_separate
                                     (CoglPipelineLayer *combine_authority);
 
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index 3f7f941..46ef805 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -574,6 +574,35 @@ _cogl_pipeline_foreach_layer_internal (CoglPipeline *pipeline,
     }
 }
 
+CoglBool
+_cogl_pipeline_layer_numbers_equal (CoglPipeline *pipeline0,
+                                    CoglPipeline *pipeline1)
+{
+  CoglPipeline *authority0 =
+    _cogl_pipeline_get_authority (pipeline0, COGL_PIPELINE_STATE_LAYERS);
+  CoglPipeline *authority1 =
+    _cogl_pipeline_get_authority (pipeline1, COGL_PIPELINE_STATE_LAYERS);
+  int n_layers = authority0->n_layers;
+  int i;
+
+  if (authority1->n_layers != n_layers)
+    return FALSE;
+
+  _cogl_pipeline_update_layers_cache (authority0);
+  _cogl_pipeline_update_layers_cache (authority1);
+
+  for (i = 0; i < n_layers; i++)
+    {
+      CoglPipelineLayer *layer0 = authority0->layers_cache[i];
+      CoglPipelineLayer *layer1 = authority1->layers_cache[i];
+
+      if (layer0->index != layer1->index)
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
 typedef struct
 {
   int i;
-- 
1.7.7.6



More information about the Cogl mailing list