summaryrefslogtreecommitdiff
path: root/cogl/tests/conform/test-multitexture.c
diff options
context:
space:
mode:
Diffstat (limited to 'cogl/tests/conform/test-multitexture.c')
-rw-r--r--cogl/tests/conform/test-multitexture.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/cogl/tests/conform/test-multitexture.c b/cogl/tests/conform/test-multitexture.c
new file mode 100644
index 000000000..da38766aa
--- /dev/null
+++ b/cogl/tests/conform/test-multitexture.c
@@ -0,0 +1,206 @@
+#include <clutter/clutter.h>
+#include <cogl/cogl.h>
+#include <string.h>
+
+#include "test-conform-common.h"
+
+static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
+
+#define QUAD_WIDTH 20
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define ALPHA 3
+
+typedef struct _TestState
+{
+ unsigned int padding;
+} TestState;
+
+static void
+assert_region_color (int x,
+ int y,
+ int width,
+ int height,
+ uint8_t red,
+ uint8_t green,
+ uint8_t blue,
+ uint8_t alpha)
+{
+ uint8_t *data = g_malloc0 (width * height * 4);
+ cogl_read_pixels (x, y, width, height,
+ COGL_READ_PIXELS_COLOR_BUFFER,
+ COGL_PIXEL_FORMAT_RGBA_8888_PRE,
+ data);
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++)
+ {
+ uint8_t *pixel = &data[y * width * 4 + x * 4];
+#if 1
+ g_assert (pixel[RED] == red &&
+ pixel[GREEN] == green &&
+ pixel[BLUE] == blue);
+#endif
+ }
+ g_free (data);
+}
+
+/* Creates a texture divided into 4 quads with colors arranged as follows:
+ * (The same value are used in all channels for each texel)
+ *
+ * |-----------|
+ * |0x11 |0x00 |
+ * |+ref | |
+ * |-----------|
+ * |0x00 |0x33 |
+ * | |+ref |
+ * |-----------|
+ *
+ *
+ */
+static CoglHandle
+make_texture (guchar ref)
+{
+ int x;
+ int y;
+ guchar *tex_data, *p;
+ CoglHandle tex;
+ guchar val;
+
+ tex_data = g_malloc (QUAD_WIDTH * QUAD_WIDTH * 16);
+
+ for (y = 0; y < QUAD_WIDTH * 2; y++)
+ for (x = 0; x < QUAD_WIDTH * 2; x++)
+ {
+ p = tex_data + (QUAD_WIDTH * 8 * y) + x * 4;
+ if (x < QUAD_WIDTH && y < QUAD_WIDTH)
+ val = 0x11 + ref;
+ else if (x >= QUAD_WIDTH && y >= QUAD_WIDTH)
+ val = 0x33 + ref;
+ else
+ val = 0x00;
+ p[0] = p[1] = p[2] = p[3] = val;
+ }
+
+ /* Note: we don't use COGL_PIXEL_FORMAT_ANY for the internal format here
+ * since we don't want to allow Cogl to premultiply our data. */
+ tex = test_utils_texture_new_from_data (QUAD_WIDTH * 2,
+ QUAD_WIDTH * 2,
+ TEST_UTILS_TEXTURE_NONE,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ COGL_PIXEL_FORMAT_RGBA_8888,
+ QUAD_WIDTH * 8,
+ tex_data);
+
+ g_free (tex_data);
+
+ return tex;
+}
+
+static void
+on_paint (ClutterActor *actor, TestState *state)
+{
+ CoglHandle tex0, tex1;
+ CoglHandle material;
+ CoglBool status;
+ CoglError *error = NULL;
+ float tex_coords[] = {
+ 0, 0, 0.5, 0.5, /* tex0 */
+ 0.5, 0.5, 1, 1 /* tex1 */
+ };
+
+ tex0 = make_texture (0x00);
+ tex1 = make_texture (0x11);
+
+ material = cogl_material_new ();
+
+ /* An arbitrary color which should be replaced by the first texture layer */
+ cogl_material_set_color4ub (material, 0x80, 0x80, 0x80, 0x80);
+ cogl_material_set_blend (material, "RGBA = ADD (SRC_COLOR, 0)", NULL);
+
+ cogl_material_set_layer (material, 0, tex0);
+ cogl_material_set_layer_combine (material, 0,
+ "RGBA = REPLACE (TEXTURE)", NULL);
+ /* We'll use nearest filtering mode on the textures, otherwise the
+ edge of the quad can pull in texels from the neighbouring
+ quarters of the texture due to imprecision */
+ cogl_material_set_layer_filters (material, 0,
+ COGL_MATERIAL_FILTER_NEAREST,
+ COGL_MATERIAL_FILTER_NEAREST);
+
+ cogl_material_set_layer (material, 1, tex1);
+ cogl_material_set_layer_filters (material, 1,
+ COGL_MATERIAL_FILTER_NEAREST,
+ COGL_MATERIAL_FILTER_NEAREST);
+ status = cogl_material_set_layer_combine (material, 1,
+ "RGBA = ADD (PREVIOUS, TEXTURE)",
+ &error);
+ if (!status)
+ {
+ /* It's not strictly a test failure; you need a more capable GPU or
+ * driver to test this texture combine string. */
+ g_debug ("Failed to setup texture combine string "
+ "RGBA = ADD (PREVIOUS, TEXTURE): %s",
+ error->message);
+ }
+
+ cogl_set_source (material);
+ cogl_rectangle_with_multitexture_coords (0, 0, QUAD_WIDTH, QUAD_WIDTH,
+ tex_coords, 8);
+
+ cogl_handle_unref (material);
+ cogl_handle_unref (tex0);
+ cogl_handle_unref (tex1);
+
+ /* See what we got... */
+
+ assert_region_color (0, 0, QUAD_WIDTH, QUAD_WIDTH,
+ 0x55, 0x55, 0x55, 0x55);
+
+ /* Comment this out if you want visual feedback for what this test paints */
+#if 1
+ clutter_main_quit ();
+#endif
+}
+
+static CoglBool
+queue_redraw (void *stage)
+{
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
+
+ return TRUE;
+}
+
+void
+test_multitexture (TestUtilsGTestFixture *fixture,
+ void *data)
+{
+ TestState state;
+ ClutterActor *stage;
+ ClutterActor *group;
+ unsigned int idle_source;
+
+ stage = clutter_stage_get_default ();
+
+ clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
+
+ group = clutter_group_new ();
+ clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
+
+ /* We force continuous redrawing incase someone comments out the
+ * clutter_main_quit and wants visual feedback for the test since we
+ * wont be doing anything else that will trigger redrawing. */
+ idle_source = g_idle_add (queue_redraw, stage);
+
+ g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);
+
+ clutter_actor_show_all (stage);
+
+ clutter_main ();
+
+ g_source_remove (idle_source);
+
+ if (cogl_test_verbose ())
+ g_print ("OK\n");
+}