From 10b16b4b7e06d7592a3d83ef209a39ba26eedbad Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 8 Apr 2010 17:18:40 +0100 Subject: [PATCH] Add a test case for cogl_path This tests various paths drawing rectangles and verifies that the expected pixels are filled in. Some of the paths are drawn by copying an existing path and modifying it which should test the copy-on-write code. --- tests/conform/Makefile.am | 1 + tests/conform/test-cogl-path.c | 179 ++++++++++++++++++++++++++++++ tests/conform/test-conform-main.c | 1 + 3 files changed, 181 insertions(+) create mode 100644 tests/conform/test-cogl-path.c diff --git a/tests/conform/Makefile.am b/tests/conform/Makefile.am index 63425d684..cf595e4c2 100644 --- a/tests/conform/Makefile.am +++ b/tests/conform/Makefile.am @@ -28,6 +28,7 @@ test_conformance_SOURCES = \ test-cogl-texture-mipmaps.c \ test-cogl-texture-rectangle.c \ test-cogl-pixel-buffer.c \ + test-cogl-path.c \ test-path.c \ test-pick.c \ test-clutter-rectangle.c \ diff --git a/tests/conform/test-cogl-path.c b/tests/conform/test-cogl-path.c new file mode 100644 index 000000000..3a8895780 --- /dev/null +++ b/tests/conform/test-cogl-path.c @@ -0,0 +1,179 @@ +#include +#include + +#include "test-conform-common.h" + +#define BLOCK_SIZE 16 + +/* Number of pixels at the border of a block quadrant to skip when verifying */ +#define TEST_INSET 1 + +static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff }; +static const ClutterColor block_color = { 0xff, 0xff, 0xff, 0xff }; + +typedef struct _TestState +{ + ClutterActor *stage; + guint frame; +} TestState; + +static void +draw_path_at (int x, int y) +{ + cogl_push_matrix (); + cogl_translate (x * BLOCK_SIZE, y * BLOCK_SIZE, 0.0f); + cogl_path_fill (); + cogl_pop_matrix (); +} + +static void +verify_block (int block_x, int block_y, int block_mask) +{ + guint8 data[BLOCK_SIZE * BLOCK_SIZE * 4]; + int qx, qy; + + /* Block mask represents which quarters of the block should be + filled. The bits from 0->3 represent the top left, top right, + bottom left and bottom right respectively */ + + cogl_read_pixels (block_x * BLOCK_SIZE, + block_y * BLOCK_SIZE, + BLOCK_SIZE, BLOCK_SIZE, + COGL_READ_PIXELS_COLOR_BUFFER, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + data); + + for (qy = 0; qy < 2; qy++) + for (qx = 0; qx < 2; qx++) + { + int bit = qx | (qy << 1); + const ClutterColor *color = + ((block_mask & (1 << bit)) ? &block_color : &stage_color); + int x, y; + + for (x = 0; x < BLOCK_SIZE / 2 - TEST_INSET * 2; x++) + for (y = 0; y < BLOCK_SIZE / 2 - TEST_INSET * 2; y++) + { + const guint8 *p = data + (qx * BLOCK_SIZE / 2 * 4 + + qy * BLOCK_SIZE * 4 * BLOCK_SIZE / 2 + + (x + TEST_INSET) * 4 + + (y + TEST_INSET) * BLOCK_SIZE * 4); + g_assert_cmpint (p[0], ==, color->red); + g_assert_cmpint (p[1], ==, color->green); + g_assert_cmpint (p[2], ==, color->blue); + } + } +} + +static void +on_paint (ClutterActor *actor, TestState *state) +{ + CoglHandle path_a, path_b, path_c; + + if (state->frame++ < 2) + return; + + cogl_set_source_color4ub (255, 255, 255, 255); + + /* Create a path filling just a quarter of a block */ + cogl_path_new (); + cogl_path_rectangle (BLOCK_SIZE / 2, BLOCK_SIZE / 2, + BLOCK_SIZE, BLOCK_SIZE); + path_a = cogl_handle_ref (cogl_path_get ()); + draw_path_at (0, 0); + + /* Create another path filling the whole block */ + cogl_path_rectangle (0, 0, BLOCK_SIZE, BLOCK_SIZE); + path_b = cogl_handle_ref (cogl_path_get ()); + draw_path_at (1, 0); + + /* Draw the first path again */ + cogl_path_set (path_a); + draw_path_at (2, 0); + + /* Draw a copy of path a */ + path_c = cogl_path_copy (path_a); + cogl_path_set (path_c); + draw_path_at (3, 0); + + /* Add another rectangle to path a. We'll use line_to's instead of + cogl_rectangle so that we don't create another sub-path because + that is more likely to break the copy */ + cogl_path_set (path_a); + cogl_path_line_to (0, BLOCK_SIZE / 2); + cogl_path_line_to (0, 0); + cogl_path_line_to (BLOCK_SIZE / 2, 0); + cogl_path_line_to (BLOCK_SIZE / 2, BLOCK_SIZE / 2); + draw_path_at (4, 0); + + /* Draw the copy again. It should not have changed */ + cogl_path_set (path_c); + draw_path_at (5, 0); + + /* Add another rectangle to path c */ + cogl_path_set (path_c); + cogl_path_line_to (BLOCK_SIZE / 2, 0); + cogl_path_line_to (BLOCK_SIZE, 0); + cogl_path_line_to (BLOCK_SIZE, BLOCK_SIZE / 2); + cogl_path_line_to (BLOCK_SIZE / 2, BLOCK_SIZE / 2); + draw_path_at (6, 0); + + /* Draw the original path again. It should not have changed */ + cogl_path_set (path_a); + draw_path_at (7, 0); + + cogl_handle_unref (path_a); + cogl_handle_unref (path_b); + cogl_handle_unref (path_c); + + verify_block (0, 0, 0x8 /* bottom right */); + verify_block (1, 0, 0xf /* all of them */); + verify_block (2, 0, 0x8 /* bottom right */); + verify_block (3, 0, 0x8 /* bottom right */); + verify_block (4, 0, 0x9 /* top left and bottom right */); + verify_block (5, 0, 0x8 /* bottom right */); + verify_block (6, 0, 0xa /* bottom right and top right */); + verify_block (7, 0, 0x9 /* top_left and bottom right */); + + /* Comment this out if you want visual feedback of what this test + * paints. + */ + clutter_main_quit (); +} + +static gboolean +queue_redraw (gpointer stage) +{ + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); + + return TRUE; +} + +void +test_cogl_path (TestConformSimpleFixture *fixture, + gconstpointer data) +{ + TestState state; + unsigned int idle_source; + unsigned int paint_handler; + + state.stage = clutter_stage_get_default (); + clutter_stage_set_color (CLUTTER_STAGE (state.stage), &stage_color); + + /* We force continuous redrawing of the stage, since we need to skip + * the first few frames, and we wont be doing anything else that + * will trigger redrawing. */ + idle_source = g_idle_add (queue_redraw, state.stage); + paint_handler = g_signal_connect_after (state.stage, "paint", + G_CALLBACK (on_paint), &state); + + clutter_actor_show (state.stage); + clutter_main (); + + g_signal_handler_disconnect (state.stage, paint_handler); + g_source_remove (idle_source); + + if (g_test_verbose ()) + g_print ("OK\n"); +} + diff --git a/tests/conform/test-conform-main.c b/tests/conform/test-conform-main.c index 5a0801e8e..e12823033 100644 --- a/tests/conform/test-conform-main.c +++ b/tests/conform/test-conform-main.c @@ -192,6 +192,7 @@ main (int argc, char **argv) TEST_CONFORM_SIMPLE ("/cogl", test_cogl_blend_strings); TEST_CONFORM_SIMPLE ("/cogl", test_cogl_premult); TEST_CONFORM_SIMPLE ("/cogl", test_cogl_readpixels); + TEST_CONFORM_SIMPLE ("/cogl", test_cogl_path); TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_npot_texture); TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_multitexture);