mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
Add a conformance test for clutter_texture_new_from_actor
This contains four tests :- - A regular onscreen source with a clone next to it - An offscreen source with a clone. This is currently commented out because it no longer works. - An onscreen source with a rectangular clip and a clone. - An onscreen source with a clip from a path and a clone. The sources are all a 2x2 grid of colors. Each clone is tested that it either contains the color that should be at that grid position or that the stage color is showing through if the source is clipped.
This commit is contained in:
parent
fec13f6202
commit
b41a81fb08
@ -35,6 +35,7 @@ test_conformance_SOURCES = \
|
||||
test-materials.c \
|
||||
test-group.c \
|
||||
test-actor-size.c \
|
||||
test-texture-fbo.c \
|
||||
$(NULL)
|
||||
|
||||
# For convenience, this provides a way to easily run individual unit tests:
|
||||
|
@ -147,6 +147,7 @@ main (int argc, char **argv)
|
||||
TEST_CONFORM_SIMPLE ("/texture", test_backface_culling);
|
||||
TEST_CONFORM_SIMPLE ("/texture", test_npot_texture);
|
||||
TEST_CONFORM_SIMPLE ("/texture", test_premult);
|
||||
TEST_CONFORM_SIMPLE ("/texture", test_texture_fbo);
|
||||
|
||||
TEST_CONFORM_SIMPLE ("/path", test_path);
|
||||
|
||||
|
255
tests/conform/test-texture-fbo.c
Normal file
255
tests/conform/test-texture-fbo.c
Normal file
@ -0,0 +1,255 @@
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "test-conform-common.h"
|
||||
|
||||
#define SOURCE_SIZE 32
|
||||
#define SOURCE_DIVISIONS_X 2
|
||||
#define SOURCE_DIVISIONS_Y 2
|
||||
#define DIVISION_WIDTH (SOURCE_SIZE / SOURCE_DIVISIONS_X)
|
||||
#define DIVISION_HEIGHT (SOURCE_SIZE / SOURCE_DIVISIONS_Y)
|
||||
|
||||
static const ClutterColor
|
||||
corner_colors[SOURCE_DIVISIONS_X * SOURCE_DIVISIONS_Y] =
|
||||
{
|
||||
{ 0xff, 0x00, 0x00, 0xff },
|
||||
{ 0x00, 0xff, 0x00, 0xff },
|
||||
{ 0x00, 0x00, 0xff, 0xff },
|
||||
{ 0xff, 0x00, 0xff, 0xff }
|
||||
};
|
||||
|
||||
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
||||
|
||||
typedef struct _TestState
|
||||
{
|
||||
ClutterActor *stage;
|
||||
guint frame;
|
||||
} TestState;
|
||||
|
||||
static ClutterActor *
|
||||
create_source (void)
|
||||
{
|
||||
int x, y;
|
||||
ClutterActor *group = clutter_group_new ();
|
||||
|
||||
/* Create a group with a different coloured rectangle at each
|
||||
corner */
|
||||
for (y = 0; y < SOURCE_DIVISIONS_Y; y++)
|
||||
for (x = 0; x < SOURCE_DIVISIONS_X; x++)
|
||||
{
|
||||
ClutterActor *rect = clutter_rectangle_new ();
|
||||
clutter_actor_set_size (rect, DIVISION_WIDTH, DIVISION_HEIGHT);
|
||||
clutter_actor_set_position (rect,
|
||||
DIVISION_WIDTH * x,
|
||||
DIVISION_HEIGHT * y);
|
||||
clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect),
|
||||
corner_colors +
|
||||
(y * SOURCE_DIVISIONS_X + x));
|
||||
clutter_container_add (CLUTTER_CONTAINER (group), rect, NULL);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
static void
|
||||
pre_paint_clip_cb (void)
|
||||
{
|
||||
/* Generate a clip path that clips out the top left division */
|
||||
cogl_path_move_to (DIVISION_WIDTH, 0);
|
||||
cogl_path_line_to (SOURCE_SIZE, 0);
|
||||
cogl_path_line_to (SOURCE_SIZE, SOURCE_SIZE);
|
||||
cogl_path_line_to (0, SOURCE_SIZE);
|
||||
cogl_path_line_to (0, DIVISION_HEIGHT);
|
||||
cogl_path_line_to (DIVISION_WIDTH, DIVISION_HEIGHT);
|
||||
cogl_path_close ();
|
||||
cogl_clip_push_from_path ();
|
||||
}
|
||||
|
||||
static void
|
||||
post_paint_clip_cb (void)
|
||||
{
|
||||
cogl_clip_pop ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
validate_part (TestState *state,
|
||||
int xpos, int ypos,
|
||||
int clip_flags)
|
||||
{
|
||||
int x, y;
|
||||
gboolean pass = TRUE;
|
||||
|
||||
/* Check whether the center of each division is the right color */
|
||||
for (y = 0; y < SOURCE_DIVISIONS_Y; y++)
|
||||
for (x = 0; x < SOURCE_DIVISIONS_X; x++)
|
||||
{
|
||||
guchar *pixels;
|
||||
const ClutterColor *correct_color;
|
||||
|
||||
/* Read the center pixels of this division */
|
||||
pixels = clutter_stage_read_pixels (CLUTTER_STAGE (state->stage),
|
||||
x * DIVISION_WIDTH +
|
||||
DIVISION_WIDTH / 2 + xpos,
|
||||
y * DIVISION_HEIGHT +
|
||||
DIVISION_HEIGHT / 2 + ypos,
|
||||
1, 1);
|
||||
|
||||
/* If this division is clipped then it should be the stage
|
||||
color */
|
||||
if ((clip_flags & (1 << ((y * SOURCE_DIVISIONS_X) + x))))
|
||||
correct_color = &stage_color;
|
||||
else
|
||||
/* Otherwise it should be the color for this division */
|
||||
correct_color = corner_colors + (y * SOURCE_DIVISIONS_X) + x;
|
||||
|
||||
if (pixels == NULL ||
|
||||
pixels[0] != correct_color->red ||
|
||||
pixels[1] != correct_color->green ||
|
||||
pixels[2] != correct_color->blue)
|
||||
pass = FALSE;
|
||||
|
||||
g_free (pixels);
|
||||
}
|
||||
|
||||
return pass;
|
||||
}
|
||||
|
||||
static void
|
||||
validate_result (TestState *state)
|
||||
{
|
||||
int ypos = 0;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Testing onscreen clone...\n");
|
||||
g_assert (validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 0));
|
||||
ypos++;
|
||||
|
||||
#if 0 /* this doesn't work */
|
||||
if (g_test_verbose ())
|
||||
g_print ("Testing offscreen clone...\n");
|
||||
g_assert (validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 0));
|
||||
#endif
|
||||
ypos++;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Testing onscreen clone with rectangular clip...\n");
|
||||
g_assert (validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, ~1));
|
||||
ypos++;
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("Testing onscreen clone with path clip...\n");
|
||||
g_assert (validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 1));
|
||||
ypos++;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* XXX: Experiments have shown that for some buggy drivers, when using
|
||||
* glReadPixels there is some kind of race, so we delay our test for a
|
||||
* few frames and a few seconds:
|
||||
*/
|
||||
/* Need to increment frame first because clutter_stage_read_pixels
|
||||
fires a redraw */
|
||||
frame_num = state->frame++;
|
||||
if (frame_num == 2)
|
||||
validate_result (state);
|
||||
else if (frame_num < 2)
|
||||
g_usleep (G_USEC_PER_SEC);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
queue_redraw (gpointer stage)
|
||||
{
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
test_texture_fbo (TestConformSimpleFixture *fixture,
|
||||
gconstpointer data)
|
||||
{
|
||||
TestState state;
|
||||
guint idle_source;
|
||||
ClutterActor *actor;
|
||||
int ypos = 0;
|
||||
|
||||
state.frame = 0;
|
||||
|
||||
state.stage = clutter_stage_get_default ();
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (state.stage), &stage_color);
|
||||
|
||||
/* Onscreen source with clone next to it */
|
||||
actor = create_source ();
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE);
|
||||
actor = clutter_texture_new_from_actor (actor);
|
||||
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
ypos++;
|
||||
|
||||
/* Offscreen source with clone */
|
||||
#if 0 /* this doesn't work */
|
||||
actor = create_source ();
|
||||
actor = clutter_texture_new_from_actor (actor);
|
||||
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
#endif
|
||||
ypos++;
|
||||
|
||||
/* Source clipped to the top left division */
|
||||
actor = create_source ();
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE);
|
||||
clutter_actor_set_clip (actor, 0, 0, DIVISION_WIDTH, DIVISION_HEIGHT);
|
||||
actor = clutter_texture_new_from_actor (actor);
|
||||
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
ypos++;
|
||||
|
||||
/* Source clipped to everything but top left division using a
|
||||
path */
|
||||
actor = create_source ();
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE);
|
||||
g_signal_connect (actor, "paint",
|
||||
G_CALLBACK (pre_paint_clip_cb), NULL);
|
||||
g_signal_connect_after (actor, "paint",
|
||||
G_CALLBACK (post_paint_clip_cb), NULL);
|
||||
actor = clutter_texture_new_from_actor (actor);
|
||||
clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE);
|
||||
clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL);
|
||||
ypos++;
|
||||
|
||||
/* 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);
|
||||
|
||||
g_signal_connect_after (state.stage, "paint", G_CALLBACK (on_paint), &state);
|
||||
|
||||
clutter_actor_show_all (state.stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_source_remove (idle_source);
|
||||
|
||||
/* Remove all of the actors from the stage */
|
||||
clutter_container_foreach (CLUTTER_CONTAINER (state.stage),
|
||||
(ClutterCallback) clutter_actor_destroy,
|
||||
NULL);
|
||||
|
||||
if (g_test_verbose ())
|
||||
g_print ("OK\n");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user