[tests] test-backface-culling: test culling with offscreen rendering

Since offscreen rendering is internally forced to be upside down Cogl
needs to reverse the glFrontFace winding order so as not to interfere
with the use of cogl_set_backface_culling_enabled()

This ensures we test that mechanism.
This commit is contained in:
Robert Bragg 2009-10-22 19:01:27 +01:00
parent 60b642f5d6
commit ffb592de59

View File

@ -5,8 +5,6 @@
#include "test-conform-common.h"
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
#ifdef CLUTTER_COGL_HAS_GL
/* Size the texture so that it is just off a power of two to enourage
@ -31,24 +29,31 @@ static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
typedef struct _TestState
{
guint frame;
CoglHandle texture;
CoglHandle offscreen;
CoglHandle offscreen_tex;
} TestState;
#include <gdk-pixbuf/gdk-pixbuf.h>
static gboolean
validate_part (int xnum, int ynum, gboolean shown)
{
guchar *pixels, *p;
ClutterActor *stage = clutter_stage_get_default ();
gboolean ret = TRUE;
pixels = g_malloc0 ((TEXTURE_RENDER_SIZE - TEST_INSET * 2)
* (TEXTURE_RENDER_SIZE - TEST_INSET * 2) * 4);
/* Read the appropriate part but skip out a few pixels around the
edges */
pixels = clutter_stage_read_pixels (CLUTTER_STAGE (stage),
xnum * TEXTURE_RENDER_SIZE + TEST_INSET,
cogl_read_pixels (xnum * TEXTURE_RENDER_SIZE + TEST_INSET,
ynum * TEXTURE_RENDER_SIZE + TEST_INSET,
TEXTURE_RENDER_SIZE - TEST_INSET * 2,
TEXTURE_RENDER_SIZE - TEST_INSET * 2);
TEXTURE_RENDER_SIZE - TEST_INSET * 2,
COGL_READ_PIXELS_COLOR_BUFFER,
COGL_PIXEL_FORMAT_RGBA_8888,
pixels);
/* Make sure every pixels is the appropriate color */
for (p = pixels;
@ -70,47 +75,9 @@ validate_part (int xnum, int ynum, gboolean shown)
}
static void
validate_result (TestState *state)
{
/* Front-facing texture */
g_assert (validate_part (0, 0, TRUE));
/* Front-facing texture with flipped tex coords */
g_assert (validate_part (1, 0, TRUE));
/* Back-facing texture */
g_assert (validate_part (2, 0, FALSE));
/* Front-facing texture polygon */
g_assert (validate_part (3, 0, TRUE));
/* Back-facing texture polygon */
g_assert (validate_part (4, 0, FALSE));
/* Regular rectangle */
g_assert (validate_part (5, 0, TRUE));
/* Backface culling disabled - everything should be shown */
/* Front-facing texture */
g_assert (validate_part (0, 1, TRUE));
/* Front-facing texture with flipped tex coords */
g_assert (validate_part (1, 1, TRUE));
/* Back-facing texture */
g_assert (validate_part (2, 1, TRUE));
/* Front-facing texture polygon */
g_assert (validate_part (3, 1, TRUE));
/* Back-facing texture polygon */
g_assert (validate_part (4, 1, TRUE));
/* Regular rectangle */
g_assert (validate_part (5, 1, TRUE));
/* Comment this out if you want visual feedback of what this test
* paints.
*/
clutter_main_quit ();
}
static void
on_paint (ClutterActor *actor, TestState *state)
do_test_backface_culling (TestState *state)
{
int i;
int frame_num;
CoglHandle material = cogl_material_new ();
cogl_material_set_layer_filters (material, 0,
@ -197,21 +164,91 @@ on_paint (ClutterActor *actor, TestState *state)
cogl_set_backface_culling_enabled (FALSE);
}
cogl_pop_matrix ();
cogl_handle_unref (material);
/* 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:
cogl_pop_matrix ();
/* Front-facing texture */
g_assert (validate_part (0, 0, TRUE));
/* Front-facing texture with flipped tex coords */
g_assert (validate_part (1, 0, TRUE));
/* Back-facing texture */
g_assert (validate_part (2, 0, FALSE));
/* Front-facing texture polygon */
g_assert (validate_part (3, 0, TRUE));
/* Back-facing texture polygon */
g_assert (validate_part (4, 0, FALSE));
/* Regular rectangle */
g_assert (validate_part (5, 0, TRUE));
/* Backface culling disabled - everything should be shown */
/* Front-facing texture */
g_assert (validate_part (0, 1, TRUE));
/* Front-facing texture with flipped tex coords */
g_assert (validate_part (1, 1, TRUE));
/* Back-facing texture */
g_assert (validate_part (2, 1, TRUE));
/* Front-facing texture polygon */
g_assert (validate_part (3, 1, TRUE));
/* Back-facing texture polygon */
g_assert (validate_part (4, 1, TRUE));
/* Regular rectangle */
g_assert (validate_part (5, 1, TRUE));
}
static void
on_paint (ClutterActor *actor, TestState *state)
{
CoglColor clr;
float stage_viewport[4];
CoglMatrix stage_projection;
CoglMatrix stage_modelview;
cogl_color_set_from_4ub (&clr, 0x00, 0x00, 0x00, 0xff);
do_test_backface_culling (state);
/* Since we are going to repeat the test rendering offscreen we clear the
* stage, just to minimize the chance of a some other bug causing us
* mistakenly reading back the results from the stage and giving a false
* posistive. */
cogl_clear (&clr, COGL_BUFFER_BIT_COLOR|COGL_BUFFER_BIT_STENCIL);
/*
* Now repeat the test but rendered to an offscreen draw buffer...
*/
/* 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);
cogl_get_viewport (stage_viewport);
cogl_get_projection_matrix (&stage_projection);
cogl_get_modelview_matrix (&stage_modelview);
cogl_push_draw_buffer ();
cogl_set_draw_buffer (0 /* unused */, state->offscreen);
cogl_clear (&clr, COGL_BUFFER_BIT_COLOR|COGL_BUFFER_BIT_STENCIL);
cogl_set_viewport (stage_viewport[0],
stage_viewport[1],
stage_viewport[2],
stage_viewport[3]);
cogl_set_projection_matrix (&stage_projection);
cogl_set_modelview_matrix (&stage_modelview);
do_test_backface_culling (state);
cogl_pop_draw_buffer ();
/* Incase we want feedback of what was drawn offscreen we draw it
* to the stage... */
cogl_set_source_texture (state->offscreen_tex);
cogl_rectangle (0, 0, stage_viewport[2], stage_viewport[3]);
/* Comment this out if you want visual feedback of what this test
* paints.
*/
clutter_main_quit ();
}
static gboolean
@ -256,15 +293,26 @@ test_backface_culling (TestConformSimpleFixture *fixture,
gconstpointer data)
{
TestState state;
CoglHandle tex;
ClutterActor *stage;
float stage_width;
float stage_height;
const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
ClutterActor *group;
guint idle_source;
state.frame = 0;
stage = clutter_stage_get_default ();
clutter_actor_get_size (stage, &stage_width, &stage_height);
state.offscreen = COGL_INVALID_HANDLE;
state.texture = make_texture ();
stage = clutter_stage_get_default ();
tex = cogl_texture_new_with_size (stage_width, stage_height,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_ANY); /* internal fmt */
state.offscreen = cogl_offscreen_new_to_texture (tex);
state.offscreen_tex = tex;
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
@ -284,6 +332,8 @@ test_backface_culling (TestConformSimpleFixture *fixture,
g_source_remove (idle_source);
cogl_handle_unref (state.offscreen);
cogl_handle_unref (state.offscreen_tex);
cogl_handle_unref (state.texture);
if (g_test_verbose ())