4ca1e491da
This greatly speeds up running all the conformance tests by no longer delaying many of the tests for a number of dummy frames to be painted. We used to skip frames because we thought there was a problem with the driver's glReadPixels implementation. Although we have seen driver issues at times the real reason the delay was needed was because resizing the stage usually happens asynchronously (because a non synchronous X request is used by clutter_stage_set_size()). We now force all X requests to be synchronized for the conformance tests so this is no longer a problem and we can avoid these hacks.
225 lines
6.2 KiB
C
225 lines
6.2 KiB
C
#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 };
|
|
|
|
/* Non-power-of-two sized texture that should cause slicing */
|
|
#define TEXTURE_SIZE 257
|
|
/* Number of times to split the texture up on each axis */
|
|
#define PARTS 2
|
|
/* The texture is split into four parts, each with a different colour */
|
|
#define PART_SIZE (TEXTURE_SIZE / PARTS)
|
|
|
|
/* Amount of pixels to skip off the top, bottom, left and right of the
|
|
texture when reading back the stage */
|
|
#define TEST_INSET 4
|
|
|
|
/* Size to actually render the texture at */
|
|
#define TEXTURE_RENDER_SIZE 128
|
|
/* The size of a part once rendered */
|
|
#define PART_RENDER_SIZE (TEXTURE_RENDER_SIZE / PARTS)
|
|
|
|
static const ClutterColor corner_colors[PARTS * PARTS] =
|
|
{
|
|
/* Top left - red */ { 255, 0, 0, 255 },
|
|
/* Top right - green */ { 0, 255, 0, 255 },
|
|
/* Bottom left - blue */ { 0, 0, 255, 255 },
|
|
/* Bottom right - yellow */ { 255, 255, 0, 255 }
|
|
};
|
|
|
|
typedef struct _TestState
|
|
{
|
|
guint frame;
|
|
CoglHandle texture;
|
|
} TestState;
|
|
|
|
static gboolean
|
|
validate_part (int xnum, int ynum, const ClutterColor *color)
|
|
{
|
|
guchar *pixels, *p;
|
|
ClutterActor *stage = clutter_stage_get_default ();
|
|
gboolean ret = TRUE;
|
|
|
|
/* Read the appropriate part but skip out a few pixels around the
|
|
edges */
|
|
pixels = clutter_stage_read_pixels (CLUTTER_STAGE (stage),
|
|
xnum * PART_RENDER_SIZE + TEST_INSET,
|
|
ynum * PART_RENDER_SIZE + TEST_INSET,
|
|
PART_RENDER_SIZE - TEST_INSET * 2,
|
|
PART_RENDER_SIZE - TEST_INSET * 2);
|
|
|
|
/* Make sure every pixels is the appropriate color */
|
|
for (p = pixels;
|
|
p < pixels + ((PART_RENDER_SIZE - TEST_INSET * 2)
|
|
* (PART_RENDER_SIZE - TEST_INSET * 2));
|
|
p += 4)
|
|
{
|
|
if (p[0] != color->red)
|
|
ret = FALSE;
|
|
if (p[1] != color->green)
|
|
ret = FALSE;
|
|
if (p[2] != color->blue)
|
|
ret = FALSE;
|
|
}
|
|
|
|
g_free (pixels);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
validate_result (TestState *state)
|
|
{
|
|
/* Validate that all four corners of the texture are drawn in the
|
|
right color */
|
|
g_assert (validate_part (0, 0, corner_colors + 0));
|
|
g_assert (validate_part (1, 0, corner_colors + 1));
|
|
g_assert (validate_part (0, 1, corner_colors + 2));
|
|
g_assert (validate_part (1, 1, corner_colors + 3));
|
|
|
|
/* Comment this out if you want visual feedback of what this test
|
|
* paints.
|
|
*/
|
|
clutter_main_quit ();
|
|
}
|
|
|
|
static void
|
|
on_paint (ClutterActor *actor, TestState *state)
|
|
{
|
|
int frame_num;
|
|
|
|
/* Just render the texture in the top left corner */
|
|
cogl_set_source_texture (state->texture);
|
|
cogl_rectangle (0, 0, TEXTURE_RENDER_SIZE, TEXTURE_RENDER_SIZE);
|
|
|
|
/* XXX: validate_result calls clutter_stage_read_pixels which will result in
|
|
* another paint run so to avoid infinite recursion we only aim to validate
|
|
* the first frame. */
|
|
frame_num = state->frame++;
|
|
if (frame_num == 1)
|
|
validate_result (state);
|
|
}
|
|
|
|
static gboolean
|
|
queue_redraw (gpointer stage)
|
|
{
|
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static CoglHandle
|
|
make_texture (void)
|
|
{
|
|
guchar *tex_data, *p;
|
|
CoglHandle tex;
|
|
int partx, party, width, height;
|
|
|
|
p = tex_data = g_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4);
|
|
|
|
/* Make a texture with a different color for each part */
|
|
for (party = 0; party < PARTS; party++)
|
|
{
|
|
height = (party < PARTS - 1
|
|
? PART_SIZE
|
|
: TEXTURE_SIZE - PART_SIZE * (PARTS - 1));
|
|
|
|
for (partx = 0; partx < PARTS; partx++)
|
|
{
|
|
const ClutterColor *color = corner_colors + party * PARTS + partx;
|
|
width = (partx < PARTS - 1
|
|
? PART_SIZE
|
|
: TEXTURE_SIZE - PART_SIZE * (PARTS - 1));
|
|
|
|
while (width-- > 0)
|
|
{
|
|
*(p++) = color->red;
|
|
*(p++) = color->green;
|
|
*(p++) = color->blue;
|
|
*(p++) = color->alpha;
|
|
}
|
|
}
|
|
|
|
while (--height > 0)
|
|
{
|
|
memcpy (p, p - TEXTURE_SIZE * 4, TEXTURE_SIZE * 4);
|
|
p += TEXTURE_SIZE * 4;
|
|
}
|
|
}
|
|
|
|
tex = cogl_texture_new_from_data (TEXTURE_SIZE,
|
|
TEXTURE_SIZE,
|
|
COGL_TEXTURE_NO_ATLAS,
|
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
|
COGL_PIXEL_FORMAT_ANY,
|
|
TEXTURE_SIZE * 4,
|
|
tex_data);
|
|
|
|
g_free (tex_data);
|
|
|
|
if (g_test_verbose ())
|
|
{
|
|
if (cogl_texture_is_sliced (tex))
|
|
g_print ("Texture is sliced\n");
|
|
else
|
|
g_print ("Texture is not sliced\n");
|
|
}
|
|
|
|
/* The texture should be sliced unless NPOTs are supported */
|
|
g_assert (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)
|
|
? !cogl_texture_is_sliced (tex)
|
|
: cogl_texture_is_sliced (tex));
|
|
|
|
return tex;
|
|
}
|
|
|
|
void
|
|
test_cogl_npot_texture (TestConformSimpleFixture *fixture,
|
|
gconstpointer data)
|
|
{
|
|
TestState state;
|
|
ClutterActor *stage;
|
|
ClutterActor *group;
|
|
guint idle_source;
|
|
|
|
if (g_test_verbose ())
|
|
{
|
|
if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT))
|
|
g_print ("NPOT textures are supported\n");
|
|
else
|
|
g_print ("NPOT textures are not supported\n");
|
|
}
|
|
|
|
state.frame = 0;
|
|
|
|
state.texture = make_texture ();
|
|
|
|
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 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, stage);
|
|
|
|
g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);
|
|
|
|
clutter_actor_show_all (stage);
|
|
|
|
clutter_main ();
|
|
|
|
g_source_remove (idle_source);
|
|
|
|
cogl_handle_unref (state.texture);
|
|
|
|
if (g_test_verbose ())
|
|
g_print ("OK\n");
|
|
}
|
|
|