[Cogl] [PATCH] Test case for atlas textures beeing freed during atlas migration
Neil Roberts
neil at linux.intel.com
Mon May 19 04:52:08 PDT 2014
We currently have a problem where Cogl will crash if atlas migration
causes the atlas to be freed. This can happen if the only reference to
the atlas is by a texture that is only referenced by the last flushed
pipeline. That pipeline will lose its reference during migration
because a new pipeline will be flushed to migrate the textures. This
test case replicates that situation.
https://bugzilla.gnome.org/show_bug.cgi?id=719551
Reviewed-by: Neil Roberts <neil at linux.intel.com>
---
tests/conform/Makefile.am | 1 +
tests/conform/test-atlas-free-while-migrate.c | 96 +++++++++++++++++++++++++++
tests/conform/test-conform-main.c | 1 +
3 files changed, 98 insertions(+)
create mode 100644 tests/conform/test-atlas-free-while-migrate.c
diff --git a/tests/conform/Makefile.am b/tests/conform/Makefile.am
index edfe940..a2d71c7 100644
--- a/tests/conform/Makefile.am
+++ b/tests/conform/Makefile.am
@@ -25,6 +25,7 @@ unported_test_sources = \
test_sources = \
test-atlas-migration.c \
+ test-atlas-free-while-migrate.c \
test-blend-strings.c \
test-blend.c \
test-depth-test.c \
diff --git a/tests/conform/test-atlas-free-while-migrate.c b/tests/conform/test-atlas-free-while-migrate.c
new file mode 100644
index 0000000..483f7f4
--- /dev/null
+++ b/tests/conform/test-atlas-free-while-migrate.c
@@ -0,0 +1,96 @@
+#include <cogl/cogl.h>
+
+#include "test-utils.h"
+
+/* This test is intended to replicate the following bug:
+ *
+ * https://bugzilla.gnome.org/show_bug.cgi?id=728064
+ *
+ * The problem in that bug is that a texture can be freed while the
+ * atlas is being migrated if the only reference to it was by the last
+ * flushed pipeline. This pipeline will lose a reference when a new
+ * pipeline is used to blit the textures. If that texture was the only
+ * one in an atlas then the atlas will also get freed before Cogl gets
+ * a chance to take a reference on it for the new texture
+ */
+
+static CoglTexture *
+create_texture (int size)
+{
+ CoglAtlasTexture *texture;
+ uint8_t *data;
+
+ data = g_malloc (size * size * 4);
+
+ texture = cogl_atlas_texture_new_from_data (test_ctx,
+ size, /* width */
+ size, /* height */
+ /* format */
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE,
+ /* rowstride */
+ size * 4,
+ data,
+ NULL);
+
+ g_free (data);
+
+ return texture;
+}
+
+static void
+texture_destroy_cb (void *user_data)
+{
+ CoglBool *texture_destroyed = user_data;
+
+ *texture_destroyed = TRUE;
+}
+
+void
+test_atlas_free_while_migrate (void)
+{
+ CoglTexture *tex;
+ CoglPipeline *pipeline;
+ static CoglUserDataKey texture_key;
+ CoglBool texture_destroyed = FALSE;
+
+ pipeline = cogl_pipeline_new (test_ctx);
+
+ tex = create_texture (500);
+
+ cogl_object_set_user_data (tex,
+ &texture_key,
+ &texture_destroyed,
+ texture_destroy_cb);
+
+ cogl_pipeline_set_layer_texture (pipeline, 0 /* layer */, tex);
+
+ cogl_object_unref (tex);
+
+ cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 10, 10);
+
+ cogl_object_unref (pipeline);
+
+ /* The texture shouldn't have been destroyed yet because Cogl will
+ * still be keeping a reference to it as the last texture used.
+ * Technically it is free to destroy the texture here if it wants to
+ * but if it does then this test case is useless so we need to
+ * change it anyway if that code changes */
+ g_assert (!texture_destroyed);
+
+ /* The only reference to the pipeline should now be due to it being
+ * the last flushed pipeline. This will also keep the texture alive
+ * until the middle of the atlas migration. We'll now try to create
+ * a new texture which will cause CoglAtlas to try and move the
+ * existing texture to a larger texture but this will cause the
+ * texture to be unref'd in the process.
+ */
+
+ tex = create_texture (32);
+ cogl_texture_allocate (tex, NULL);
+
+ /* The texture should now have been destroyed in the process of
+ * atlas migration */
+ g_assert (texture_destroyed);
+
+ cogl_object_unref (tex);
+}
diff --git a/tests/conform/test-conform-main.c b/tests/conform/test-conform-main.c
index c119d79..d1ce4aa 100644
--- a/tests/conform/test-conform-main.c
+++ b/tests/conform/test-conform-main.c
@@ -83,6 +83,7 @@ main (int argc, char **argv)
* the maximum texture level. */
ADD_TEST (test_texture_mipmap_get_set, TEST_REQUIREMENT_GL, 0);
ADD_TEST (test_atlas_migration, 0, 0);
+ ADD_TEST (test_atlas_free_while_migrate, 0, 0);
ADD_TEST (test_read_texture_formats, 0, 0);
ADD_TEST (test_write_texture_formats, 0, 0);
ADD_TEST (test_alpha_textures, 0, 0);
--
1.9.0
More information about the Cogl
mailing list