2011-05-05 22:34:38 +00:00
|
|
|
#include <cogl/cogl.h>
|
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
#include <string.h>
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
#include "test-utils.h"
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
/* Size the texture so that it is just off a power of two to encourage
|
2011-05-05 22:34:38 +00:00
|
|
|
it so use software tiling when NPOTs aren't available */
|
|
|
|
#define TEXTURE_SIZE 257
|
|
|
|
|
|
|
|
/* Amount of pixels to skip off the top, bottom, left and right of the
|
|
|
|
texture when reading back the stage */
|
2011-11-08 14:02:47 +00:00
|
|
|
#define TEST_INSET 2
|
2011-05-05 22:34:38 +00:00
|
|
|
|
|
|
|
/* Size to actually render the texture at */
|
2011-11-08 14:02:47 +00:00
|
|
|
#define TEXTURE_RENDER_SIZE 8
|
2011-05-05 22:34:38 +00:00
|
|
|
|
|
|
|
typedef struct _TestState
|
|
|
|
{
|
2012-02-18 16:03:10 +00:00
|
|
|
CoglContext *ctx;
|
2011-09-19 14:24:36 +00:00
|
|
|
CoglFramebuffer *fb;
|
2011-05-05 22:34:38 +00:00
|
|
|
CoglHandle texture;
|
2011-09-19 14:24:36 +00:00
|
|
|
CoglFramebuffer *offscreen;
|
2011-05-05 22:34:38 +00:00
|
|
|
CoglHandle offscreen_tex;
|
2011-09-19 14:24:36 +00:00
|
|
|
int width, height;
|
2011-05-05 22:34:38 +00:00
|
|
|
} TestState;
|
|
|
|
|
2011-11-08 14:02:47 +00:00
|
|
|
static void
|
2011-05-05 22:34:38 +00:00
|
|
|
validate_part (int xnum, int ynum, gboolean shown)
|
|
|
|
{
|
2011-11-08 14:02:47 +00:00
|
|
|
test_utils_check_region (xnum * TEXTURE_RENDER_SIZE + TEST_INSET,
|
|
|
|
ynum * TEXTURE_RENDER_SIZE + TEST_INSET,
|
|
|
|
TEXTURE_RENDER_SIZE - TEST_INSET * 2,
|
|
|
|
TEXTURE_RENDER_SIZE - TEST_INSET * 2,
|
|
|
|
shown ? 0xff0000ff : 0x000000ff);
|
|
|
|
}
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-11-08 14:02:47 +00:00
|
|
|
/* We draw everything 16 times. The draw number is used as a bitmask
|
|
|
|
to test all of the combinations of enabling legacy state, both
|
|
|
|
winding orders and all four culling modes */
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-11-08 14:02:47 +00:00
|
|
|
#define USE_LEGACY_STATE(draw_num) (((draw_num) & 0x01) >> 0)
|
|
|
|
#define FRONT_WINDING(draw_num) (((draw_num) & 0x02) >> 1)
|
|
|
|
#define CULL_FACE_MODE(draw_num) (((draw_num) & 0x0c) >> 2)
|
2011-05-05 22:34:38 +00:00
|
|
|
|
|
|
|
static void
|
2011-09-19 14:24:36 +00:00
|
|
|
paint_test_backface_culling (TestState *state)
|
2011-05-05 22:34:38 +00:00
|
|
|
{
|
2011-11-08 14:02:47 +00:00
|
|
|
int draw_num;
|
2012-02-18 16:03:10 +00:00
|
|
|
CoglPipeline *base_pipeline = cogl_pipeline_new (state->ctx);
|
2011-09-19 14:24:36 +00:00
|
|
|
CoglColor clear_color;
|
|
|
|
|
|
|
|
cogl_ortho (0, state->width, /* left, right */
|
|
|
|
state->height, 0, /* bottom, top */
|
|
|
|
-1, 100 /* z near, far */);
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
cogl_color_init_from_4ub (&clear_color, 0x00, 0x00, 0x00, 0xff);
|
|
|
|
cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_STENCIL);
|
|
|
|
|
2011-11-08 14:02:47 +00:00
|
|
|
cogl_pipeline_set_layer_texture (base_pipeline, 0, state->texture);
|
2011-09-19 14:24:36 +00:00
|
|
|
|
2011-11-08 14:02:47 +00:00
|
|
|
cogl_pipeline_set_layer_filters (base_pipeline, 0,
|
2011-09-19 14:24:36 +00:00
|
|
|
COGL_PIPELINE_FILTER_NEAREST,
|
|
|
|
COGL_PIPELINE_FILTER_NEAREST);
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-11-08 14:02:47 +00:00
|
|
|
/* Render the scene sixteen times to test all of the combinations of
|
|
|
|
cull face mode, legacy state and winding orders */
|
|
|
|
for (draw_num = 0; draw_num < 16; draw_num++)
|
2011-05-05 22:34:38 +00:00
|
|
|
{
|
|
|
|
float x1 = 0, x2, y1 = 0, y2 = (float)(TEXTURE_RENDER_SIZE);
|
|
|
|
CoglTextureVertex verts[4];
|
2011-11-08 14:02:47 +00:00
|
|
|
CoglPipeline *pipeline;
|
|
|
|
|
|
|
|
cogl_push_matrix ();
|
|
|
|
cogl_translate (0, TEXTURE_RENDER_SIZE * draw_num, 0);
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-11-08 14:02:47 +00:00
|
|
|
pipeline = cogl_pipeline_copy (base_pipeline);
|
|
|
|
|
|
|
|
cogl_set_backface_culling_enabled (USE_LEGACY_STATE (draw_num));
|
|
|
|
cogl_pipeline_set_front_face_winding (pipeline, FRONT_WINDING (draw_num));
|
|
|
|
cogl_pipeline_set_cull_face_mode (pipeline, CULL_FACE_MODE (draw_num));
|
|
|
|
|
|
|
|
cogl_push_source (pipeline);
|
2011-05-05 22:34:38 +00:00
|
|
|
|
|
|
|
memset (verts, 0, sizeof (verts));
|
|
|
|
|
|
|
|
x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
|
|
|
|
|
|
|
|
/* Draw a front-facing texture */
|
|
|
|
cogl_rectangle (x1, y1, x2, y2);
|
|
|
|
|
|
|
|
x1 = x2;
|
|
|
|
x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
|
|
|
|
|
|
|
|
/* Draw a front-facing texture with flipped texcoords */
|
|
|
|
cogl_rectangle_with_texture_coords (x1, y1, x2, y2,
|
|
|
|
1.0, 0.0, 0.0, 1.0);
|
|
|
|
|
|
|
|
x1 = x2;
|
|
|
|
x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
|
|
|
|
|
|
|
|
/* Draw a back-facing texture */
|
|
|
|
cogl_rectangle (x2, y1, x1, y2);
|
|
|
|
|
|
|
|
x1 = x2;
|
|
|
|
x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
|
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
/* If the texture is sliced then cogl_polygon doesn't work so
|
|
|
|
we'll just use a solid color instead */
|
|
|
|
if (cogl_texture_is_sliced (state->texture))
|
|
|
|
cogl_set_source_color4ub (255, 0, 0, 255);
|
|
|
|
|
|
|
|
/* Draw a front-facing polygon */
|
2011-05-05 22:34:38 +00:00
|
|
|
verts[0].x = x1; verts[0].y = y2;
|
|
|
|
verts[1].x = x2; verts[1].y = y2;
|
|
|
|
verts[2].x = x2; verts[2].y = y1;
|
|
|
|
verts[3].x = x1; verts[3].y = y1;
|
|
|
|
verts[0].tx = 0; verts[0].ty = 0;
|
|
|
|
verts[1].tx = 1.0; verts[1].ty = 0;
|
|
|
|
verts[2].tx = 1.0; verts[2].ty = 1.0;
|
|
|
|
verts[3].tx = 0; verts[3].ty = 1.0;
|
|
|
|
cogl_polygon (verts, 4, FALSE);
|
|
|
|
|
|
|
|
x1 = x2;
|
|
|
|
x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
|
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
/* Draw a back-facing polygon */
|
2011-05-05 22:34:38 +00:00
|
|
|
verts[0].x = x1; verts[0].y = y1;
|
|
|
|
verts[1].x = x2; verts[1].y = y1;
|
|
|
|
verts[2].x = x2; verts[2].y = y2;
|
|
|
|
verts[3].x = x1; verts[3].y = y2;
|
|
|
|
verts[0].tx = 0; verts[0].ty = 0;
|
|
|
|
verts[1].tx = 1.0; verts[1].ty = 0;
|
|
|
|
verts[2].tx = 1.0; verts[2].ty = 1.0;
|
|
|
|
verts[3].tx = 0; verts[3].ty = 1.0;
|
|
|
|
cogl_polygon (verts, 4, FALSE);
|
|
|
|
|
|
|
|
x1 = x2;
|
|
|
|
x2 = x1 + (float)(TEXTURE_RENDER_SIZE);
|
|
|
|
|
2011-11-08 14:02:47 +00:00
|
|
|
cogl_pop_matrix ();
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-11-08 14:02:47 +00:00
|
|
|
cogl_pop_source ();
|
|
|
|
cogl_object_unref (pipeline);
|
2011-05-05 22:34:38 +00:00
|
|
|
}
|
|
|
|
|
2011-11-08 14:02:47 +00:00
|
|
|
cogl_object_unref (base_pipeline);
|
2011-09-19 14:24:36 +00:00
|
|
|
}
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
static void
|
|
|
|
validate_result (int y_offset)
|
|
|
|
{
|
2011-11-08 14:02:47 +00:00
|
|
|
int draw_num;
|
|
|
|
|
|
|
|
for (draw_num = 0; draw_num < 16; draw_num++)
|
|
|
|
{
|
|
|
|
gboolean cull_front, cull_back;
|
|
|
|
CoglPipelineCullFaceMode cull_mode;
|
|
|
|
|
|
|
|
if (USE_LEGACY_STATE (draw_num))
|
|
|
|
cull_mode = COGL_PIPELINE_CULL_FACE_MODE_BACK;
|
|
|
|
else
|
|
|
|
cull_mode = CULL_FACE_MODE (draw_num);
|
|
|
|
|
|
|
|
switch (cull_mode)
|
|
|
|
{
|
|
|
|
case COGL_PIPELINE_CULL_FACE_MODE_NONE:
|
|
|
|
cull_front = FALSE;
|
|
|
|
cull_back = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_CULL_FACE_MODE_FRONT:
|
|
|
|
cull_front = TRUE;
|
|
|
|
cull_back = FALSE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_CULL_FACE_MODE_BACK:
|
|
|
|
cull_front = FALSE;
|
|
|
|
cull_back = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case COGL_PIPELINE_CULL_FACE_MODE_BOTH:
|
|
|
|
cull_front = TRUE;
|
|
|
|
cull_back = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FRONT_WINDING (draw_num) == COGL_WINDING_CLOCKWISE)
|
|
|
|
{
|
|
|
|
gboolean tmp = cull_front;
|
|
|
|
cull_front = cull_back;
|
|
|
|
cull_back = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Front-facing texture */
|
|
|
|
validate_part (0, y_offset + draw_num, !cull_front);
|
|
|
|
/* Front-facing texture with flipped tex coords */
|
|
|
|
validate_part (1, y_offset + draw_num, !cull_front);
|
|
|
|
/* Back-facing texture */
|
|
|
|
validate_part (2, y_offset + draw_num, !cull_back);
|
|
|
|
/* Front-facing texture polygon */
|
|
|
|
validate_part (3, y_offset + draw_num, !cull_front);
|
|
|
|
/* Back-facing texture polygon */
|
|
|
|
validate_part (4, y_offset + draw_num, !cull_back);
|
|
|
|
}
|
2011-05-05 22:34:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-09-19 14:24:36 +00:00
|
|
|
paint (TestState *state)
|
2011-05-05 22:34:38 +00:00
|
|
|
{
|
|
|
|
float stage_viewport[4];
|
|
|
|
CoglMatrix stage_projection;
|
|
|
|
CoglMatrix stage_modelview;
|
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
paint_test_backface_culling (state);
|
2011-05-05 22:34:38 +00:00
|
|
|
|
|
|
|
/*
|
2011-09-19 14:24:36 +00:00
|
|
|
* Now repeat the test but rendered to an offscreen
|
|
|
|
* framebuffer. Note that by default the conformance tests are
|
|
|
|
* always run to an offscreen buffer but we might as well have this
|
|
|
|
* check anyway in case it is being run with COGL_TEST_ONSCREEN=1
|
2011-05-05 22:34:38 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
cogl_get_viewport (stage_viewport);
|
|
|
|
cogl_get_projection_matrix (&stage_projection);
|
|
|
|
cogl_get_modelview_matrix (&stage_modelview);
|
|
|
|
|
|
|
|
cogl_push_framebuffer (state->offscreen);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
paint_test_backface_culling (state);
|
2011-05-05 22:34:38 +00:00
|
|
|
|
|
|
|
cogl_pop_framebuffer ();
|
|
|
|
|
|
|
|
/* Incase we want feedback of what was drawn offscreen we draw it
|
|
|
|
* to the stage... */
|
|
|
|
cogl_set_source_texture (state->offscreen_tex);
|
2011-11-08 14:02:47 +00:00
|
|
|
cogl_rectangle (0, TEXTURE_RENDER_SIZE * 16,
|
2011-09-19 14:24:36 +00:00
|
|
|
stage_viewport[2],
|
2011-11-08 14:02:47 +00:00
|
|
|
stage_viewport[3] + TEXTURE_RENDER_SIZE * 16);
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
validate_result (0);
|
2011-11-08 14:02:47 +00:00
|
|
|
validate_result (16);
|
2011-05-05 22:34:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static CoglHandle
|
|
|
|
make_texture (void)
|
|
|
|
{
|
|
|
|
guchar *tex_data, *p;
|
|
|
|
CoglHandle tex;
|
|
|
|
|
|
|
|
tex_data = g_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4);
|
|
|
|
|
|
|
|
for (p = tex_data + TEXTURE_SIZE * TEXTURE_SIZE * 4; p > tex_data;)
|
|
|
|
{
|
|
|
|
*(--p) = 255;
|
|
|
|
*(--p) = 0;
|
|
|
|
*(--p) = 0;
|
|
|
|
*(--p) = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
tex = cogl_texture_new_from_data (TEXTURE_SIZE,
|
|
|
|
TEXTURE_SIZE,
|
2011-09-19 14:24:36 +00:00
|
|
|
COGL_TEXTURE_NO_ATLAS,
|
2011-05-05 22:34:38 +00:00
|
|
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
|
|
|
COGL_PIXEL_FORMAT_ANY,
|
|
|
|
TEXTURE_SIZE * 4,
|
|
|
|
tex_data);
|
|
|
|
|
|
|
|
g_free (tex_data);
|
|
|
|
|
|
|
|
return tex;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
test_cogl_backface_culling (TestUtilsGTestFixture *fixture,
|
|
|
|
void *data)
|
|
|
|
{
|
2011-09-19 14:24:36 +00:00
|
|
|
TestUtilsSharedState *shared_state = data;
|
2011-05-05 22:34:38 +00:00
|
|
|
TestState state;
|
|
|
|
CoglHandle tex;
|
|
|
|
|
2012-02-18 16:03:10 +00:00
|
|
|
state.ctx = shared_state->ctx;
|
2011-09-19 14:24:36 +00:00
|
|
|
state.fb = shared_state->fb;
|
|
|
|
state.width = cogl_framebuffer_get_width (shared_state->fb);
|
|
|
|
state.height = cogl_framebuffer_get_height (shared_state->fb);
|
2011-05-05 22:34:38 +00:00
|
|
|
|
|
|
|
state.offscreen = COGL_INVALID_HANDLE;
|
|
|
|
|
|
|
|
state.texture = make_texture ();
|
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
tex = cogl_texture_new_with_size (state.width, state.height,
|
2011-05-05 22:34:38 +00:00
|
|
|
COGL_TEXTURE_NO_SLICING,
|
|
|
|
COGL_PIXEL_FORMAT_ANY); /* internal fmt */
|
2012-02-18 15:22:15 +00:00
|
|
|
state.offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (tex));
|
2011-05-05 22:34:38 +00:00
|
|
|
state.offscreen_tex = tex;
|
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
paint (&state);
|
2011-05-05 22:34:38 +00:00
|
|
|
|
2011-09-19 14:24:36 +00:00
|
|
|
cogl_object_unref (state.offscreen);
|
2011-05-05 22:34:38 +00:00
|
|
|
cogl_handle_unref (state.offscreen_tex);
|
|
|
|
cogl_handle_unref (state.texture);
|
|
|
|
|
2012-02-23 12:30:51 +00:00
|
|
|
if (cogl_test_verbose ())
|
2011-05-05 22:34:38 +00:00
|
|
|
g_print ("OK\n");
|
|
|
|
}
|
|
|
|
|