From cefc0e381bfebfdf766b8331e82da474e848013b Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 1 Jul 2010 22:05:51 +0100 Subject: [PATCH] Add a conformance test for 3D textures This creates a 3D texture with different colors on all of the images and renders it using a VBO to verify that the texture coordinates can select all of the images. --- tests/conform/.gitignore | 1 + tests/conform/Makefile.am | 1 + tests/conform/test-cogl-texture-3d.c | 230 +++++++++++++++++++++++++++ tests/conform/test-conform-main.c | 1 + 4 files changed, 233 insertions(+) create mode 100644 tests/conform/test-cogl-texture-3d.c diff --git a/tests/conform/.gitignore b/tests/conform/.gitignore index 8cda30394..2c603e26b 100644 --- a/tests/conform/.gitignore +++ b/tests/conform/.gitignore @@ -114,6 +114,7 @@ /test-cogl-depth-test /test-cogl-pixel-array /test-cogl-texture-get-set-data +/test-cogl-texture-3d /wrappers /*-report.xml /*-report.html diff --git a/tests/conform/Makefile.am b/tests/conform/Makefile.am index 5a40308fd..1c23444cd 100644 --- a/tests/conform/Makefile.am +++ b/tests/conform/Makefile.am @@ -27,6 +27,7 @@ test_conformance_SOURCES = \ test-cogl-multitexture.c \ test-cogl-texture-mipmaps.c \ test-cogl-texture-rectangle.c \ + test-cogl-texture-3d.c \ test-cogl-texture-pixmap-x11.c \ test-cogl-texture-get-set-data.c \ test-cogl-wrap-modes.c \ diff --git a/tests/conform/test-cogl-texture-3d.c b/tests/conform/test-cogl-texture-3d.c new file mode 100644 index 000000000..82b34ba08 --- /dev/null +++ b/tests/conform/test-cogl-texture-3d.c @@ -0,0 +1,230 @@ +#include +#include + +#include "test-conform-common.h" + +static const ClutterColor stage_color = { 0x0, 0xff, 0x0, 0xff }; + +#define TEX_WIDTH 4 +#define TEX_HEIGHT 8 +#define TEX_DEPTH 16 +/* Leave four bytes of padding between each row */ +#define TEX_ROWSTRIDE (TEX_WIDTH * 4 + 4) +/* Leave four rows of padding between each image */ +#define TEX_IMAGE_STRIDE ((TEX_HEIGHT + 4) * TEX_ROWSTRIDE) + +static CoglHandle +create_texture_3d (void) +{ + int x, y, z; + guint8 *data = g_malloc (TEX_IMAGE_STRIDE * TEX_DEPTH); + guint8 *p = data; + CoglHandle tex; + GError *error = NULL; + + for (z = 0; z < TEX_DEPTH; z++) + { + for (y = 0; y < TEX_HEIGHT; y++) + { + for (x = 0; x < TEX_WIDTH; x++) + { + /* Set red, green, blue to values based on x, y, z */ + *(p++) = 255 - x * 8; + *(p++) = y * 8; + *(p++) = 255 - z * 8; + /* Fully opaque */ + *(p++) = 0xff; + } + + /* Set the padding between rows to 0xde */ + memset (p, 0xde, TEX_ROWSTRIDE - (TEX_WIDTH * 4)); + p += TEX_ROWSTRIDE - (TEX_WIDTH * 4); + } + /* Set the padding between images to 0xad */ + memset (p, 0xba, TEX_IMAGE_STRIDE - (TEX_HEIGHT * TEX_ROWSTRIDE)); + p += TEX_IMAGE_STRIDE - (TEX_HEIGHT * TEX_ROWSTRIDE); + } + + tex = cogl_texture_3d_new_from_data (TEX_WIDTH, TEX_HEIGHT, TEX_DEPTH, + COGL_TEXTURE_NO_AUTO_MIPMAP, + COGL_PIXEL_FORMAT_RGBA_8888, + COGL_PIXEL_FORMAT_ANY, + TEX_ROWSTRIDE, + TEX_IMAGE_STRIDE, + data, + &error); + + if (tex == COGL_INVALID_HANDLE) + { + g_assert (error != NULL); + g_warning ("Failed to create 3D texture: %s", error->message); + g_assert_not_reached (); + } + + g_free (data); + + return tex; +} + +static void +draw_frame (void) +{ + CoglHandle tex = create_texture_3d (); + CoglHandle material = cogl_material_new (); + typedef struct { float x, y, s, t, r; } Vert; + CoglHandle vbo, indices; + Vert *verts, *v; + int i; + + cogl_material_set_layer (material, 0, tex); + cogl_handle_unref (tex); + cogl_material_set_layer_filters (material, 0, + COGL_MATERIAL_FILTER_NEAREST, + COGL_MATERIAL_FILTER_NEAREST); + cogl_set_source (material); + cogl_handle_unref (material); + + /* Render the texture repeated horizontally twice using a regular + cogl rectangle. This should end up with the r texture coordinates + as zero */ + cogl_rectangle_with_texture_coords (0.0f, 0.0f, TEX_WIDTH * 2, TEX_HEIGHT, + 0.0f, 0.0f, 2.0f, 1.0f); + + /* Render all of the images in the texture using coordinates from a VBO */ + v = verts = g_new (Vert, 4 * TEX_DEPTH); + for (i = 0; i < TEX_DEPTH; i++) + { + float r = (i + 0.5f) / TEX_DEPTH; + + v->x = i * TEX_WIDTH; + v->y = TEX_HEIGHT; + v->s = 0; + v->t = 0; + v->r = r; + v++; + + v->x = i * TEX_WIDTH; + v->y = TEX_HEIGHT * 2; + v->s = 0; + v->t = 1; + v->r = r; + v++; + + v->x = i * TEX_WIDTH + TEX_WIDTH; + v->y = TEX_HEIGHT * 2; + v->s = 1; + v->t = 1; + v->r = r; + v++; + + v->x = i * TEX_WIDTH + TEX_WIDTH; + v->y = TEX_HEIGHT; + v->s = 1; + v->t = 0; + v->r = r; + v++; + } + + vbo = cogl_vertex_buffer_new (4 * TEX_DEPTH); + cogl_vertex_buffer_add (vbo, "gl_Vertex", + 2, COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, + sizeof (Vert), + &verts->x); + cogl_vertex_buffer_add (vbo, "gl_MultiTexCoord0", + 3, COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, + sizeof (Vert), + &verts->s); + cogl_vertex_buffer_submit (vbo); + + g_free (verts); + + indices = cogl_vertex_buffer_indices_get_for_quads (6 * TEX_DEPTH); + + cogl_vertex_buffer_draw_elements (vbo, + COGL_VERTICES_MODE_TRIANGLES, + indices, + 0, TEX_DEPTH * 4 - 1, + 0, TEX_DEPTH * 6); + + cogl_handle_unref (vbo); +} + +static void +validate_block (int block_x, int block_y, int z) +{ + guint8 *data, *p; + int x, y; + + p = data = g_malloc (TEX_WIDTH * TEX_HEIGHT * 4); + + cogl_read_pixels (block_x * TEX_WIDTH, block_y * TEX_HEIGHT, + TEX_WIDTH, TEX_HEIGHT, + COGL_READ_PIXELS_COLOR_BUFFER, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + data); + + for (y = 0; y < TEX_HEIGHT; y++) + for (x = 0; x < TEX_WIDTH; x++) + { + g_assert_cmpint (p[0], ==, 255 - x * 8); + g_assert_cmpint (p[1], ==, y * 8); + g_assert_cmpint (p[2], ==, 255 - z * 8); + p += 4; + } + + g_free (data); +} + +static void +validate_result (void) +{ + int i; + + validate_block (0, 0, 0); + + for (i = 0; i < TEX_DEPTH; i++) + validate_block (i, 1, i); +} + +static void +on_paint (void) +{ + draw_frame (); + + validate_result (); + + /* Comment this out to see what the test paints */ + clutter_main_quit (); +} + +void +test_cogl_texture_3d (TestConformSimpleFixture *fixture, + gconstpointer data) +{ + ClutterActor *stage; + guint paint_handler; + + stage = clutter_stage_get_default (); + + /* Check whether GL supports the rectangle extension. If not we'll + just assume the test passes */ + if (cogl_features_available (COGL_FEATURE_TEXTURE_3D)) + { + clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); + + paint_handler = g_signal_connect_after (stage, "paint", + G_CALLBACK (on_paint), NULL); + + clutter_actor_show (stage); + + clutter_main (); + + g_signal_handler_disconnect (stage, paint_handler); + + if (g_test_verbose ()) + g_print ("OK\n"); + } + else if (g_test_verbose ()) + g_print ("Skipping\n"); +} + diff --git a/tests/conform/test-conform-main.c b/tests/conform/test-conform-main.c index c9d716e5e..1bfe3565e 100644 --- a/tests/conform/test-conform-main.c +++ b/tests/conform/test-conform-main.c @@ -206,6 +206,7 @@ main (int argc, char **argv) TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_sub_texture); TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_pixel_array); TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_texture_rectangle); + TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_texture_3d); TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_wrap_modes); TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_texture_pixmap_x11); TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_texture_get_set_data);