[cogl/cogl-1.14] Add test to verify replacing a layer doesn't leak the pipeline parent



commit f9456574ef18cd58bccdd7ac69ac76f1267c84b5
Author: Neil Roberts <neil linux intel com>
Date:   Sat Mar 9 19:43:46 2013 +0000

    Add test to verify replacing a layer doesn't leak the pipeline parent
    
    The current recommendation for pipelines is that once they have been
    used for painting then they should be considered immutable. If you
    want to modify a pipeline you should instead make a copy and unref the
    original pipeline. Internally we try to check whether the modified
    copy replaces all of the properties of the parent and prune a
    redundant ancestor hierarchy. Pruning the hierarchy is particularly
    important if the pipelines contain textures because otherwise the
    textures may be leaked when the parent pipeline keeps a reference to
    it.
    
    This test verifies that usage pattern by creating a chain of pipeline
    copies each with their own replacement texture. Some user data is then
    set on the textures with a callback so that we can verify that once
    the original pipelines are destroyed then the textures are also
    destroyed.
    
    The test is currently failing because Cogl doesn't correctly prune
    ancestory for layer state authority.
    
    Reviewed-by: Robert Bragg <robert linux intel com>
    
    (cherry picked from commit 3fbec92acb90008492eb125025f92b42d6e07930)

 tests/conform/Makefile.am                 |    1 +
 tests/conform/test-conform-main.c         |    2 +
 tests/conform/test-copy-replace-texture.c |  121 +++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+), 0 deletions(-)
---
diff --git a/tests/conform/Makefile.am b/tests/conform/Makefile.am
index cb1f25e..69a460d 100644
--- a/tests/conform/Makefile.am
+++ b/tests/conform/Makefile.am
@@ -64,6 +64,7 @@ test_sources = \
        test-texture-get-set-data.c \
        test-framebuffer-get-bits.c \
        test-primitive-and-journal.c \
+       test-copy-replace-texture.c \
        $(NULL)
 
 test_conformance_SOURCES = $(common_sources) $(test_sources)
diff --git a/tests/conform/test-conform-main.c b/tests/conform/test-conform-main.c
index 8cae25e..4110c82 100644
--- a/tests/conform/test-conform-main.c
+++ b/tests/conform/test-conform-main.c
@@ -118,6 +118,8 @@ main (int argc, char **argv)
 
   ADD_TEST (test_primitive_and_journal, 0, 0);
 
+  ADD_TEST (test_copy_replace_texture, 0, TEST_KNOWN_FAILURE);
+
   UNPORTED_TEST (test_viewport);
 
   ADD_TEST (test_gles2_context, TEST_REQUIREMENT_GLES2_CONTEXT, 0);
diff --git a/tests/conform/test-copy-replace-texture.c b/tests/conform/test-copy-replace-texture.c
new file mode 100644
index 0000000..7d5ab48
--- /dev/null
+++ b/tests/conform/test-copy-replace-texture.c
@@ -0,0 +1,121 @@
+#include <cogl/cogl.h>
+#include <string.h>
+
+#include "test-utils.h"
+
+/* Keep track of the number of textures that we've created and are
+ * still alive */
+static int alive_texture_mask = 0;
+
+#define N_LAYERS 3
+#define N_PIPELINES 4
+
+#define PIPELINE_LAYER_MASK(pipeline_num)                       \
+  (((1 << N_LAYERS) - 1) << (N_LAYERS * (pipeline_num) + 1))
+#define LAST_PIPELINE_MASK PIPELINE_LAYER_MASK (N_PIPELINES - 1)
+#define FIRST_PIPELINE_MASK PIPELINE_LAYER_MASK (0)
+
+static void
+free_texture_cb (void *user_data)
+{
+  int texture_num = GPOINTER_TO_INT (user_data);
+
+  alive_texture_mask &= ~(1 << texture_num);
+}
+
+static CoglTexture *
+create_texture (void)
+{
+  static const guint8 data[] =
+    { 0xff, 0xff, 0xff, 0xff };
+  static CoglUserDataKey texture_data_key;
+  CoglTexture2D *tex_2d;
+  static int texture_num = 1;
+
+  alive_texture_mask |= (1 << texture_num);
+
+  tex_2d = cogl_texture_2d_new_from_data (test_ctx,
+                                          1, 1, /* width / height */
+                                          COGL_PIXEL_FORMAT_RGBA_8888_PRE,
+                                          COGL_PIXEL_FORMAT_ANY,
+                                          4, /* rowstride */
+                                          data,
+                                          NULL);
+
+  /* Set some user data on the texture so we can track when it has
+   * been destroyed */
+  cogl_object_set_user_data (COGL_OBJECT (tex_2d),
+                             &texture_data_key,
+                             GINT_TO_POINTER (texture_num),
+                             free_texture_cb);
+
+  texture_num++;
+
+  return COGL_TEXTURE (tex_2d);
+}
+
+void
+test_copy_replace_texture (void)
+{
+  CoglPipeline *pipelines[N_PIPELINES];
+  int pipeline_num;
+
+  /* Create a set of pipeline copies each with three of their own
+   * replacement textures */
+  for (pipeline_num = 0; pipeline_num < N_PIPELINES; pipeline_num++)
+    {
+      int layer_num;
+
+      if (pipeline_num == 0)
+        pipelines[pipeline_num] = cogl_pipeline_new (test_ctx);
+      else
+        pipelines[pipeline_num] =
+          cogl_pipeline_copy (pipelines[pipeline_num - 1]);
+
+      for (layer_num = 0; layer_num < N_LAYERS; layer_num++)
+        {
+          CoglTexture *tex = create_texture ();
+          cogl_pipeline_set_layer_texture (pipelines[pipeline_num],
+                                           layer_num,
+                                           tex);
+          cogl_object_unref (tex);
+        }
+    }
+
+  /* Unref everything but the last pipeline */
+  for (pipeline_num = 0; pipeline_num < N_PIPELINES - 1; pipeline_num++)
+    cogl_object_unref (pipelines[pipeline_num]);
+
+  if (alive_texture_mask && cogl_test_verbose ())
+    {
+      int i;
+
+      g_print ("Alive textures:");
+
+      for (i = 0; i < N_PIPELINES * N_LAYERS; i++)
+        if ((alive_texture_mask & (1 << (i + 1))))
+          g_print (" %i", i);
+
+      g_print ("\n");
+    }
+
+  /* Ideally there should only be the textures from the last pipeline
+   * left alive. We also let Cogl keep the textures from the first
+   * texture alive because currently the child of the third layer in
+   * the first pipeline will retain its authority on the unit index
+   * state so that it can set it to 2. If there are more textures then
+   * it means the pipeline isn't correctly pruning redundant
+   * ancestors */
+  g_assert_cmpint (alive_texture_mask & ~FIRST_PIPELINE_MASK,
+                   ==,
+                   LAST_PIPELINE_MASK);
+
+  /* Clean up the last pipeline */
+  cogl_object_unref (pipelines[N_PIPELINES - 1]);
+
+  /* That should get rid of the last of the textures */
+  g_assert_cmpint (alive_texture_mask, ==, 0);
+
+  if (cogl_test_verbose ())
+    g_print ("OK\n");
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]