diff --git a/tests/conform/Makefile.am b/tests/conform/Makefile.am index cb1f25ea3..69a460d2b 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 8cae25eff..4110c8219 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 000000000..7d5ab489c --- /dev/null +++ b/tests/conform/test-copy-replace-texture.c @@ -0,0 +1,121 @@ +#include +#include + +#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"); +}