mutter/tests/conform/test-primitive.c
Robert Bragg bbcbece6c9 tests: Improve thoroughness and reporting of make test
This patch reworks our conformance testing framework because it seems
that glib's gtesting framework isn't really well suited to our use case.
For example we weren't able to test windows builds given the way we
were using it and also for each test we'd like to repeat the test
with several different environments so we can test important driver and
feature combinations.

This patch instead switches away to a simplified but custom approach for
running our unit tests. We hope that having a more bespoke setup will
enable us to easily extend it to focus on the details important to us.

Notable changes with this new approach are:

We can now run 'make test' for our mingw windows builds.

We've got rid of all the test-*report* make rules and we're just left
with 'make test'

'make test' now runs each test several times with different driver and
feature combinations checking the result for each run. 'make test' will
then output a concise table of all of the results.

The combinations tested are:
- OpenGL Fixed Function
- OpenGL ARBfp
- OpenGL GLSL
- OpenGL No NPOT texture support
- OpenGLES 2.0
- OpenGLES 2.0 No NPOT texture support

Reviewed-by: Neil Roberts <neil@linux.intel.com>
2012-02-24 14:42:31 +00:00

338 lines
9.8 KiB
C

#include <cogl/cogl.h>
#include <string.h>
#include <stdlib.h>
#include "test-utils.h"
typedef struct _TestState
{
CoglContext *ctx;
int fb_width;
int fb_height;
CoglFramebuffer *fb;
} TestState;
#define PRIM_COLOR 0xff00ffff
#define TEX_COLOR 0x0000ffff
#define N_ATTRIBS 8
typedef CoglPrimitive * (* TestPrimFunc) (CoglContext *ctx, guint32 *expected_color);
static CoglPrimitive *
test_prim_p2 (CoglContext *ctx, guint32 *expected_color)
{
static const CoglVertexP2 verts[] =
{ { 0, 0 }, { 0, 10 }, { 10, 0 } };
return cogl_primitive_new_p2 (ctx,
COGL_VERTICES_MODE_TRIANGLES,
3, /* n_vertices */
verts);
}
static CoglPrimitive *
test_prim_p3 (CoglContext *ctx, guint32 *expected_color)
{
static const CoglVertexP3 verts[] =
{ { 0, 0, 0 }, { 0, 10, 0 }, { 10, 0, 0 } };
return cogl_primitive_new_p3 (ctx,
COGL_VERTICES_MODE_TRIANGLES,
3, /* n_vertices */
verts);
}
static CoglPrimitive *
test_prim_p2c4 (CoglContext *ctx, guint32 *expected_color)
{
static const CoglVertexP2C4 verts[] =
{ { 0, 0, 255, 255, 0, 255 },
{ 0, 10, 255, 255, 0, 255 },
{ 10, 0, 255, 255, 0, 255 } };
*expected_color = 0xffff00ff;
return cogl_primitive_new_p2c4 (ctx,
COGL_VERTICES_MODE_TRIANGLES,
3, /* n_vertices */
verts);
}
static CoglPrimitive *
test_prim_p3c4 (CoglContext *ctx, guint32 *expected_color)
{
static const CoglVertexP3C4 verts[] =
{ { 0, 0, 0, 255, 255, 0, 255 },
{ 0, 10, 0, 255, 255, 0, 255 },
{ 10, 0, 0, 255, 255, 0, 255 } };
*expected_color = 0xffff00ff;
return cogl_primitive_new_p3c4 (ctx,
COGL_VERTICES_MODE_TRIANGLES,
3, /* n_vertices */
verts);
}
static CoglPrimitive *
test_prim_p2t2 (CoglContext *ctx, guint32 *expected_color)
{
static const CoglVertexP2T2 verts[] =
{ { 0, 0, 1, 0 },
{ 0, 10, 1, 0 },
{ 10, 0, 1, 0 } };
*expected_color = TEX_COLOR;
return cogl_primitive_new_p2t2 (ctx,
COGL_VERTICES_MODE_TRIANGLES,
3, /* n_vertices */
verts);
}
static CoglPrimitive *
test_prim_p3t2 (CoglContext *ctx, guint32 *expected_color)
{
static const CoglVertexP3T2 verts[] =
{ { 0, 0, 0, 1, 0 },
{ 0, 10, 0, 1, 0 },
{ 10, 0, 0, 1, 0 } };
*expected_color = TEX_COLOR;
return cogl_primitive_new_p3t2 (ctx,
COGL_VERTICES_MODE_TRIANGLES,
3, /* n_vertices */
verts);
}
static CoglPrimitive *
test_prim_p2t2c4 (CoglContext *ctx, guint32 *expected_color)
{
static const CoglVertexP2T2C4 verts[] =
{ { 0, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff },
{ 0, 10, 1, 0, 0xff, 0xff, 0xf0, 0xff },
{ 10, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff } };
/* The blue component of the texture color should be replaced with 0xf0 */
*expected_color = (TEX_COLOR & 0xffff00ff) | 0x0000f000;
return cogl_primitive_new_p2t2c4 (ctx,
COGL_VERTICES_MODE_TRIANGLES,
3, /* n_vertices */
verts);
}
static CoglPrimitive *
test_prim_p3t2c4 (CoglContext *ctx, guint32 *expected_color)
{
static const CoglVertexP3T2C4 verts[] =
{ { 0, 0, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff },
{ 0, 10, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff },
{ 10, 0, 0, 1, 0, 0xff, 0xff, 0xf0, 0xff } };
/* The blue component of the texture color should be replaced with 0xf0 */
*expected_color = (TEX_COLOR & 0xffff00ff) | 0x0000f000;
return cogl_primitive_new_p3t2c4 (ctx,
COGL_VERTICES_MODE_TRIANGLES,
3, /* n_vertices */
verts);
}
static const TestPrimFunc
test_prim_funcs[] =
{
test_prim_p2,
test_prim_p3,
test_prim_p2c4,
test_prim_p3c4,
test_prim_p2t2,
test_prim_p3t2,
test_prim_p2t2c4,
test_prim_p3t2c4
};
static void
test_paint (TestState *state)
{
CoglPipeline *pipeline;
CoglTexture *tex;
guint8 tex_data[6];
int i;
/* Create a two pixel texture. The first pixel is white and the
second pixel is tex_color. The assumption is that if no texture
coordinates are specified then it will default to 0,0 and get
white */
tex_data[0] = 255;
tex_data[1] = 255;
tex_data[2] = 255;
tex_data[3] = (TEX_COLOR >> 24) & 0xff;
tex_data[4] = (TEX_COLOR >> 16) & 0xff;
tex_data[5] = (TEX_COLOR >> 8) & 0xff;
tex = cogl_texture_new_from_data (2, 1, /* size */
COGL_TEXTURE_NO_ATLAS,
COGL_PIXEL_FORMAT_RGB_888,
COGL_PIXEL_FORMAT_ANY,
6, /* rowstride */
tex_data);
pipeline = cogl_pipeline_new (state->ctx);
cogl_pipeline_set_color4ub (pipeline,
(PRIM_COLOR >> 24) & 0xff,
(PRIM_COLOR >> 16) & 0xff,
(PRIM_COLOR >> 8) & 0xff,
(PRIM_COLOR >> 0) & 0xff);
cogl_pipeline_set_layer_texture (pipeline, 0, tex);
cogl_object_unref (tex);
for (i = 0; i < G_N_ELEMENTS (test_prim_funcs); i++)
{
CoglPrimitive *prim;
guint32 expected_color = PRIM_COLOR;
prim = test_prim_funcs[i] (state->ctx, &expected_color);
cogl_push_matrix ();
cogl_translate (i * 10, 0, 0);
cogl_framebuffer_draw_primitive (state->fb, pipeline, prim);
cogl_pop_matrix ();
test_utils_check_pixel (i * 10 + 2, 2, expected_color);
cogl_object_unref (prim);
}
cogl_object_unref (pipeline);
}
static gboolean
get_attributes_cb (CoglPrimitive *prim,
CoglAttribute *attrib,
void *user_data)
{
CoglAttribute ***p = user_data;
*((* p)++) = attrib;
return TRUE;
}
static int
compare_pointers (const void *a, const void *b)
{
CoglAttribute *pa = *(CoglAttribute **) a;
CoglAttribute *pb = *(CoglAttribute **) b;
if (pa < pb)
return -1;
else if (pa > pb)
return 1;
else
return 0;
}
static void
test_copy (TestState *state)
{
static const guint16 indices_data[2] = { 1, 2 };
CoglAttributeBuffer *buffer =
cogl_attribute_buffer_new (state->ctx, 100, NULL);
CoglAttribute *attributes[N_ATTRIBS];
CoglAttribute *attributes_a[N_ATTRIBS], *attributes_b[N_ATTRIBS];
CoglAttribute **p;
CoglPrimitive *prim_a, *prim_b;
CoglIndices *indices;
int i;
for (i = 0; i < N_ATTRIBS; i++)
{
char *name = g_strdup_printf ("foo_%i", i);
attributes[i] = cogl_attribute_new (buffer,
name,
16, /* stride */
16, /* offset */
2, /* components */
COGL_ATTRIBUTE_TYPE_FLOAT);
g_free (name);
}
prim_a = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES,
8, /* n_vertices */
attributes,
N_ATTRIBS);
indices = cogl_indices_new (state->ctx,
COGL_INDICES_TYPE_UNSIGNED_SHORT,
indices_data,
2 /* n_indices */);
cogl_primitive_set_first_vertex (prim_a, 12);
cogl_primitive_set_indices (prim_a, indices, 2);
prim_b = cogl_primitive_copy (prim_a);
p = attributes_a;
cogl_primitive_foreach_attribute (prim_a,
get_attributes_cb,
&p);
g_assert_cmpint (p - attributes_a, ==, N_ATTRIBS);
p = attributes_b;
cogl_primitive_foreach_attribute (prim_b,
get_attributes_cb,
&p);
g_assert_cmpint (p - attributes_b, ==, N_ATTRIBS);
qsort (attributes_a, N_ATTRIBS, sizeof (CoglAttribute *), compare_pointers);
qsort (attributes_b, N_ATTRIBS, sizeof (CoglAttribute *), compare_pointers);
g_assert (memcmp (attributes_a, attributes_b, sizeof (attributes_a)) == 0);
g_assert_cmpint (cogl_primitive_get_first_vertex (prim_a),
==,
cogl_primitive_get_first_vertex (prim_b));
g_assert_cmpint (cogl_primitive_get_n_vertices (prim_a),
==,
cogl_primitive_get_n_vertices (prim_b));
g_assert_cmpint (cogl_primitive_get_mode (prim_a),
==,
cogl_primitive_get_mode (prim_b));
g_assert (cogl_primitive_get_indices (prim_a) ==
cogl_primitive_get_indices (prim_b));
cogl_object_unref (prim_a);
cogl_object_unref (prim_b);
cogl_object_unref (indices);
for (i = 0; i < N_ATTRIBS; i++)
cogl_object_unref (attributes[i]);
cogl_object_unref (buffer);
}
void
test_cogl_primitive (TestUtilsGTestFixture *fixture,
void *data)
{
TestUtilsSharedState *shared_state = data;
TestState state;
state.ctx = shared_state->ctx;
state.fb_width = cogl_framebuffer_get_width (shared_state->fb);
state.fb_height = cogl_framebuffer_get_height (shared_state->fb);
state.fb = shared_state->fb;
cogl_ortho (0, state.fb_width, /* left, right */
state.fb_height, 0, /* bottom, top */
-1, 100 /* z near, far */);
test_paint (&state);
test_copy (&state);
if (cogl_test_verbose ())
g_print ("OK\n");
}