void test_path_clip (void) { CoglPath *path; CoglPipeline *pipeline; int fb_width, fb_height; fb_width = cogl_framebuffer_get_width (test_fb); fb_height = cogl_framebuffer_get_height (test_fb); cogl_framebuffer_orthographic (test_fb, 0, 0, fb_width, fb_height, -1, 100); path = cogl_path_new (); cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 1.0f, 0.0f, 0.0f, 1.0f); /* Make an L-shape with the top right corner left untouched */ cogl_path_move_to (path, 0, fb_height); cogl_path_line_to (path, fb_width, fb_height); cogl_path_line_to (path, fb_width, fb_height / 2); cogl_path_line_to (path, fb_width / 2, fb_height / 2); cogl_path_line_to (path, fb_width / 2, 0); cogl_path_line_to (path, 0, 0); cogl_path_close (path); cogl_framebuffer_push_path_clip (test_fb, path); /* Try to fill the framebuffer with a blue rectangle. This should be * clipped to leave the top right quadrant as is */ pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_color4ub (pipeline, 0, 0, 255, 255); cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, fb_width, fb_height); cogl_framebuffer_pop_clip (test_fb); cogl_object_unref (pipeline); cogl_object_unref (path); /* Check each of the four quadrants */ test_utils_check_pixel (test_fb, fb_width / 4, fb_height / 4, 0x0000ffff); test_utils_check_pixel (test_fb, fb_width * 3 / 4, fb_height / 4, 0xff0000ff); test_utils_check_pixel (test_fb, fb_width / 4, fb_height * 3 / 4, 0x0000ffff); test_utils_check_pixel (test_fb, fb_width * 3 / 4, fb_height * 3 / 4, 0x0000ffff); if (cogl_test_verbose ()) g_print ("OK\n"); }
static void validate_result (CoglFramebuffer *framebuffer) { /* Non-shader version */ test_utils_check_pixel (framebuffer, 25, 25, 0x00ff0000); /* Shader version */ test_utils_check_pixel (framebuffer, 75, 25, 0x00ff0000); }
static void test_float_verts (TestState *state, int offset_x, int offset_y) { CoglAttribute *attributes[2]; CoglAttributeBuffer *buffer; static const FloatVert float_verts[] = { { 0, 10, /**/ 1, 0, 0, 1 }, { 10, 10, /**/ 1, 0, 0, 1 }, { 5, 0, /**/ 1, 0, 0, 1 }, { 10, 10, /**/ 0, 1, 0, 1 }, { 20, 10, /**/ 0, 1, 0, 1 }, { 15, 0, /**/ 0, 1, 0, 1 } }; buffer = cogl_attribute_buffer_new (test_ctx, sizeof (float_verts), float_verts); attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (FloatVert), G_STRUCT_OFFSET (FloatVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_SHORT); attributes[1] = cogl_attribute_new (buffer, "color", sizeof (FloatVert), G_STRUCT_OFFSET (FloatVert, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x, offset_y, 0.0f); cogl_framebuffer_draw_attributes (test_fb, state->pipeline, COGL_VERTICES_MODE_TRIANGLES, 0, /* first_vertex */ 6, /* n_vertices */ attributes, 2 /* n_attributes */); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[1]); cogl_object_unref (attributes[0]); cogl_object_unref (buffer); test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); }
static void test_depth (TestState *state, int x, int y, TestDepthState *rect0_state, TestDepthState *rect1_state, TestDepthState *rect2_state, CoglBool legacy_mode, uint32_t expected_result) { CoglBool missing_feature = FALSE; if (rect0_state) missing_feature |= !draw_rectangle (state, x, y, rect0_state, legacy_mode); if (rect1_state) missing_feature |= !draw_rectangle (state, x, y, rect1_state, legacy_mode); if (rect2_state) missing_feature |= !draw_rectangle (state, x, y, rect2_state, legacy_mode); /* We don't consider it an error that we can't test something * the driver doesn't support. */ if (missing_feature) return; test_utils_check_pixel (test_fb, x * QUAD_WIDTH + (QUAD_WIDTH / 2), y * QUAD_WIDTH + (QUAD_WIDTH / 2), expected_result); }
static void check_quad (int quad_x, int quad_y, guint32 color) { test_utils_check_pixel (x * QUAD_WIDTH + (QUAD_WIDTH / 2), y * QUAD_WIDTH + (QUAD_WIDTH / 2), color); }
static void test_multi_texture (TestState *state) { CoglPipeline *pipeline; CoglTexture3D *tex_3d; CoglTexture2D *tex_2d; uint8_t tex_data[4]; cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); /* Tests a pipeline that is using multi-texturing to combine a 3D texture with a 2D texture. The texture from another layer is sampled with TEXTURE_? just to pick up a specific bug that was happening with the ARBfp fragend */ pipeline = cogl_pipeline_new (test_ctx); tex_data[0] = 0xff; tex_data[1] = 0x00; tex_data[2] = 0x00; tex_data[3] = 0xff; tex_2d = cogl_texture_2d_new_from_data (test_ctx, 1, 1, /* width/height */ COGL_PIXEL_FORMAT_RGBA_8888_PRE, 4, /* rowstride */ tex_data, NULL); cogl_pipeline_set_layer_texture (pipeline, 0, tex_2d); tex_data[0] = 0x00; tex_data[1] = 0xff; tex_data[2] = 0x00; tex_data[3] = 0xff; tex_3d = cogl_texture_3d_new_from_data (test_ctx, 1, 1, 1, /* width/height/depth */ COGL_PIXEL_FORMAT_RGBA_8888_PRE, 4, /* rowstride */ 4, /* image_stride */ tex_data, NULL); cogl_pipeline_set_layer_texture (pipeline, 1, tex_3d); cogl_pipeline_set_layer_combine (pipeline, 0, "RGBA = REPLACE(PREVIOUS)", NULL); cogl_pipeline_set_layer_combine (pipeline, 1, "RGBA = ADD(TEXTURE_0, TEXTURE_1)", NULL); cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 10, 10); test_utils_check_pixel (test_fb, 5, 5, 0xffff00ff); cogl_object_unref (tex_2d); cogl_object_unref (tex_3d); cogl_object_unref (pipeline); }
void callback (CoglFence *fence, void *user_data) { int fb_width = cogl_framebuffer_get_width (test_fb); int fb_height = cogl_framebuffer_get_height (test_fb); test_utils_check_pixel (test_fb, fb_width - 1, fb_height - 1, 0x00ff0000); g_assert (user_data == MAGIC_CHUNK_O_DATA && "callback data not mangled"); g_main_loop_quit (loop); }
static void test_color (CoglPipeline *pipeline, uint32_t color, int pos) { cogl_framebuffer_draw_rectangle (test_fb, pipeline, pos * TEST_SQUARE_SIZE, 0, pos * TEST_SQUARE_SIZE + TEST_SQUARE_SIZE, TEST_SQUARE_SIZE); test_utils_check_pixel (test_fb, pos * TEST_SQUARE_SIZE + TEST_SQUARE_SIZE / 2, TEST_SQUARE_SIZE / 2, color); }
static void verify_point_size (CoglFramebuffer *test_fb, int x_pos, int y_pos, int point_size) { int y, x; for (y = 0; y < 4; y++) for (x = 0; x < 4; x++) { CoglBool in_point = x >= 1 && x <= 2 && y >= 1 && y <= 2; uint32_t expected_pixel = in_point ? 0x00ff00ff : 0xff0000ff; test_utils_check_pixel (test_fb, calc_coord_offset (x_pos, x, point_size), calc_coord_offset (y_pos, y, point_size), expected_pixel); } }
static void test_short_verts (TestState *state, int offset_x, int offset_y) { CoglAttribute *attributes[2]; CoglAttributeBuffer *buffer; CoglPipeline *pipeline, *pipeline2; CoglSnippet *snippet; CoglPrimitive *primitive; static const ShortVert short_verts[] = { { -10, -10, /**/ 0xffff, 0, 0, 0xffff }, { -1, -10, /**/ 0xffff, 0, 0, 0xffff }, { -5, -1, /**/ 0xffff, 0, 0, 0xffff } }; pipeline = cogl_pipeline_copy (state->pipeline); cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255); buffer = cogl_attribute_buffer_new (test_ctx, sizeof (short_verts), short_verts); attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (ShortVert), G_STRUCT_OFFSET (ShortVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_SHORT); attributes[1] = cogl_attribute_new (buffer, "color", sizeof (ShortVert), G_STRUCT_OFFSET (ShortVert, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT); cogl_attribute_set_normalized (attributes[1], TRUE); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x + 10.0f, offset_y + 10.0f, 0.0f); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, 3, /* n_vertices */ attributes, 2); /* n_attributes */ cogl_primitive_draw (primitive, test_fb, pipeline); cogl_object_unref (primitive); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[0]); /* Test again treating the attribute as unsigned */ attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (ShortVert), G_STRUCT_OFFSET (ShortVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT); /* XXX: this is a hack to force the pipeline to use the glsl backend * because we know it's not possible to test short vertex position * components with the legacy GL backend since which might otherwise * be used internally... */ pipeline2 = cogl_pipeline_new (test_ctx); snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, "attribute vec4 color;", "cogl_color_out = vec4 (0.0, 1.0, 0.0, 1.0);"); cogl_pipeline_add_snippet (pipeline2, snippet); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x + 10.0f - 65525.0f, offset_y - 65525, 0.0f); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, 3, /* n_vertices */ attributes, 1); /* n_attributes */ cogl_primitive_draw (primitive, test_fb, pipeline2); cogl_object_unref (primitive); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[0]); cogl_object_unref (pipeline2); cogl_object_unref (pipeline); cogl_object_unref (buffer); test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); }
static void test_byte_verts (TestState *state, int offset_x, int offset_y) { CoglAttribute *attributes[2]; CoglAttributeBuffer *buffer, *unnorm_buffer; static const ByteVert norm_verts[] = { { 0, 10, /**/ 255, 0, 0, 255 }, { 10, 10, /**/ 255, 0, 0, 255 }, { 5, 0, /**/ 255, 0, 0, 255 }, { 10, 10, /**/ 0, 255, 0, 255 }, { 20, 10, /**/ 0, 255, 0, 255 }, { 15, 0, /**/ 0, 255, 0, 255 } }; static const ByteVert unnorm_verts[] = { { 0, 0, /**/ 0, 0, 1, 1 }, { 0, 0, /**/ 0, 0, 1, 1 }, { 0, 0, /**/ 0, 0, 1, 1 }, }; buffer = cogl_attribute_buffer_new (test_ctx, sizeof (norm_verts), norm_verts); attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (ByteVert), G_STRUCT_OFFSET (ByteVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_SHORT); attributes[1] = cogl_attribute_new (buffer, "color", sizeof (ByteVert), G_STRUCT_OFFSET (ByteVert, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE); cogl_attribute_set_normalized (attributes[1], TRUE); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x, offset_y, 0.0f); cogl_framebuffer_draw_attributes (test_fb, state->pipeline, COGL_VERTICES_MODE_TRIANGLES, 0, /* first_vertex */ 6, /* n_vertices */ attributes, 2 /* n_attributes */); cogl_object_unref (attributes[1]); /* Test again with unnormalized attributes */ unnorm_buffer = cogl_attribute_buffer_new (test_ctx, sizeof (unnorm_verts), unnorm_verts); attributes[1] = cogl_attribute_new (unnorm_buffer, "color", sizeof (ByteVert), G_STRUCT_OFFSET (ByteVert, r), 4, /* n_components */ COGL_ATTRIBUTE_TYPE_BYTE); cogl_framebuffer_translate (test_fb, 20, 0, 0); cogl_framebuffer_draw_attributes (test_fb, state->pipeline, COGL_VERTICES_MODE_TRIANGLES, 0, /* first_vertex */ 3, /* n_vertices */ attributes, 2 /* n_attributes */); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[0]); cogl_object_unref (attributes[1]); cogl_object_unref (buffer); cogl_object_unref (unnorm_buffer); test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); test_utils_check_pixel (test_fb, offset_x + 25, offset_y + 5, 0x0000ffff); }
static void check_pos (int pos, uint32_t color) { test_utils_check_pixel (test_fb, pos * 10 + 5, 5, color); }
static void test_short_verts (TestState *state, int offset_x, int offset_y) { CoglAttribute *attributes[1]; CoglAttributeBuffer *buffer; CoglPipeline *pipeline, *pipeline2; CoglSnippet *snippet; static const ShortVert short_verts[] = { { -10, -10 }, { -1, -10 }, { -5, -1 } }; pipeline = cogl_pipeline_new (test_ctx); snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_TRANSFORM, "attribute vec2 pos;", NULL); cogl_snippet_set_replace (snippet, "cogl_position_out = " "cogl_modelview_projection_matrix * " "vec4 (pos, 0.0, 1.0);"); cogl_pipeline_add_snippet (pipeline, snippet); cogl_object_unref (snippet); cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255); buffer = cogl_attribute_buffer_new (test_ctx, sizeof (short_verts), short_verts); attributes[0] = cogl_attribute_new (buffer, "pos", sizeof (ShortVert), G_STRUCT_OFFSET (ShortVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_SHORT); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x + 10.0f, offset_y + 10.0f, 0.0f); cogl_framebuffer_draw_attributes (test_fb, pipeline, COGL_VERTICES_MODE_TRIANGLES, 0, /* first_vertex */ 3, /* n_vertices */ attributes, 1 /* n_attributes */); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[0]); /* Test again treating the attribute as unsigned */ attributes[0] = cogl_attribute_new (buffer, "pos", sizeof (ShortVert), G_STRUCT_OFFSET (ShortVert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT); pipeline2 = cogl_pipeline_copy (pipeline); cogl_pipeline_set_color4ub (pipeline2, 0, 255, 0, 255); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, offset_x + 10.0f - 65525.0f, offset_y - 65525, 0.0f); cogl_framebuffer_draw_attributes (test_fb, pipeline2, COGL_VERTICES_MODE_TRIANGLES, 0, /* first_vertex */ 3, /* n_vertices */ attributes, 1 /* n_attributes */); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (attributes[0]); cogl_object_unref (pipeline2); cogl_object_unref (pipeline); cogl_object_unref (buffer); test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff); test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff); }
static void test_push_pop_multi_context (void) { CoglTexture *offscreen_texture0; CoglOffscreen *offscreen0; CoglPipeline *pipeline0; CoglGLES2Context *gles2_ctx0; const CoglGLES2Vtable *gles20; CoglTexture *offscreen_texture1; CoglOffscreen *offscreen1; CoglPipeline *pipeline1; CoglGLES2Context *gles2_ctx1; const CoglGLES2Vtable *gles21; GError *error = NULL; create_gles2_context (&offscreen_texture0, &offscreen0, &pipeline0, &gles2_ctx0, &gles20); create_gles2_context (&offscreen_texture1, &offscreen1, &pipeline1, &gles2_ctx1, &gles21); cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 1, 1, 1, 1); if (!cogl_push_gles2_context (test_ctx, gles2_ctx0, COGL_FRAMEBUFFER (offscreen0), COGL_FRAMEBUFFER (offscreen0), &error)) { g_error ("Failed to push gles2 context 0: %s\n", error->message); } gles20->glClearColor (1, 0, 0, 1); gles20->glClear (GL_COLOR_BUFFER_BIT); if (!cogl_push_gles2_context (test_ctx, gles2_ctx1, COGL_FRAMEBUFFER (offscreen1), COGL_FRAMEBUFFER (offscreen1), &error)) { g_error ("Failed to push gles2 context 1: %s\n", error->message); } gles21->glClearColor (0, 1, 0, 1); gles21->glClear (GL_COLOR_BUFFER_BIT); cogl_pop_gles2_context (test_ctx); cogl_pop_gles2_context (test_ctx); test_utils_check_pixel (test_fb, 0, 0, 0xffffffff); cogl_framebuffer_draw_rectangle (test_fb, pipeline0, -1, 1, 1, -1); test_utils_check_pixel (test_fb, 0, 0, 0xff0000ff); cogl_framebuffer_draw_rectangle (test_fb, pipeline1, -1, 1, 1, -1); test_utils_check_pixel (test_fb, 0, 0, 0x00ff00ff); }
static void test_blend (TestState *state, int x, int y, uint32_t src_color, uint32_t dst_color, const char *blend_string, uint32_t blend_constant, uint32_t expected_result) { /* src color */ uint8_t Sr = MASK_RED (src_color); uint8_t Sg = MASK_GREEN (src_color); uint8_t Sb = MASK_BLUE (src_color); uint8_t Sa = MASK_ALPHA (src_color); /* dest color */ uint8_t Dr = MASK_RED (dst_color); uint8_t Dg = MASK_GREEN (dst_color); uint8_t Db = MASK_BLUE (dst_color); uint8_t Da = MASK_ALPHA (dst_color); /* blend constant - when applicable */ uint8_t Br = MASK_RED (blend_constant); uint8_t Bg = MASK_GREEN (blend_constant); uint8_t Bb = MASK_BLUE (blend_constant); uint8_t Ba = MASK_ALPHA (blend_constant); CoglColor blend_const_color; CoglPipeline *pipeline; CoglBool status; CoglError *error = NULL; int y_off; int x_off; /* First write out the destination color without any blending... */ pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_color4ub (pipeline, Dr, Dg, Db, Da); cogl_pipeline_set_blend (pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL); cogl_framebuffer_draw_rectangle (test_fb, pipeline, x * QUAD_WIDTH, y * QUAD_WIDTH, x * QUAD_WIDTH + QUAD_WIDTH, y * QUAD_WIDTH + QUAD_WIDTH); cogl_object_unref (pipeline); /* * Now blend a rectangle over our well defined destination: */ pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_color4ub (pipeline, Sr, Sg, Sb, Sa); status = cogl_pipeline_set_blend (pipeline, blend_string, &error); if (!status) { /* It's not strictly a test failure; you need a more capable GPU or * driver to test this blend string. */ if (cogl_test_verbose ()) { g_debug ("Failed to test blend string %s: %s", blend_string, error->message); g_print ("Skipping\n"); } return; } cogl_color_init_from_4ub (&blend_const_color, Br, Bg, Bb, Ba); cogl_pipeline_set_blend_constant (pipeline, &blend_const_color); cogl_framebuffer_draw_rectangle (test_fb, pipeline, x * QUAD_WIDTH, y * QUAD_WIDTH, x * QUAD_WIDTH + QUAD_WIDTH, y * QUAD_WIDTH + QUAD_WIDTH); cogl_object_unref (pipeline); /* See what we got... */ y_off = y * QUAD_WIDTH + (QUAD_WIDTH / 2); x_off = x * QUAD_WIDTH + (QUAD_WIDTH / 2); if (cogl_test_verbose ()) { g_print ("test_blend (%d, %d):\n%s\n", x, y, blend_string); g_print (" src color = %02x, %02x, %02x, %02x\n", Sr, Sg, Sb, Sa); g_print (" dst color = %02x, %02x, %02x, %02x\n", Dr, Dg, Db, Da); if (blend_constant != BLEND_CONSTANT_UNUSED) g_print (" blend constant = %02x, %02x, %02x, %02x\n", Br, Bg, Bb, Ba); else g_print (" blend constant = UNUSED\n"); } test_utils_check_pixel (test_fb, x_off, y_off, expected_result); }
static void test_gles2_read_pixels (void) { CoglTexture *offscreen_texture; CoglOffscreen *offscreen; CoglPipeline *pipeline; CoglGLES2Context *gles2_ctx; const CoglGLES2Vtable *gles2; GError *error = NULL; GLubyte pixel[3]; GLuint fbo_handle; create_gles2_context (&offscreen_texture, &offscreen, &pipeline, &gles2_ctx, &gles2); cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 1, 1, 1, 1); if (!cogl_push_gles2_context (test_ctx, gles2_ctx, COGL_FRAMEBUFFER (offscreen), COGL_FRAMEBUFFER (offscreen), &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } gles2->glClearColor (1, 0, 0, 1); gles2->glClear (GL_COLOR_BUFFER_BIT); gles2->glReadPixels (0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel); g_assert (pixel[0] == 0xff); g_assert (pixel[1] == 0); g_assert (pixel[2] == 0); fbo_handle = create_gles2_framebuffer (gles2, 256, 256); gles2->glBindFramebuffer (GL_FRAMEBUFFER, fbo_handle); gles2->glClearColor (0, 1, 0, 1); gles2->glClear (GL_COLOR_BUFFER_BIT); gles2->glReadPixels (0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel); g_assert (pixel[0] == 0); g_assert (pixel[1] == 0xff); g_assert (pixel[2] == 0); gles2->glBindFramebuffer (GL_FRAMEBUFFER, 0); gles2->glClearColor (0, 1, 1, 1); gles2->glClear (GL_COLOR_BUFFER_BIT); gles2->glReadPixels (0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel); g_assert (pixel[0] == 0); g_assert (pixel[1] == 0xff); g_assert (pixel[2] == 0xff); cogl_pop_gles2_context (test_ctx); test_utils_check_pixel (test_fb, 0, 0, 0xffffffff); /* Bind different read and write buffers */ if (!cogl_push_gles2_context (test_ctx, gles2_ctx, COGL_FRAMEBUFFER (offscreen), test_fb, &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } gles2->glReadPixels (0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel); g_assert (pixel[0] == 0); g_assert (pixel[1] == 0xff); g_assert (pixel[2] == 0xff); cogl_pop_gles2_context (test_ctx); test_utils_check_pixel (test_fb, 0, 0, 0xffffffff); /* Bind different read and write buffers (the other way around from * before so when we test with COGL_TEST_ONSCREEN=1 we will read * from an onscreen framebuffer) */ if (!cogl_push_gles2_context (test_ctx, gles2_ctx, test_fb, COGL_FRAMEBUFFER (offscreen), &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } gles2->glReadPixels (0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &pixel); g_assert (pixel[0] == 0xff); g_assert (pixel[1] == 0xff); g_assert (pixel[2] == 0xff); cogl_pop_gles2_context (test_ctx); }
void test_map_buffer_range (void) { CoglTexture2D *tex; CoglPipeline *pipeline; int fb_width, fb_height; CoglAttributeBuffer *buffer; CoglVertexP2T2 *data; CoglAttribute *pos_attribute; CoglAttribute *tex_coord_attribute; CoglPrimitive *primitive; tex = cogl_texture_2d_new_from_data (test_ctx, 2, 2, /* width/height */ COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_PIXEL_FORMAT_ANY, 2 * 4, /* rowstride */ tex_data, NULL /* error */); pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_layer_texture (pipeline, 0, COGL_TEXTURE (tex)); cogl_pipeline_set_layer_filters (pipeline, 0, /* layer */ COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST); cogl_pipeline_set_layer_wrap_mode (pipeline, 0, /* layer */ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); fb_width = cogl_framebuffer_get_width (test_fb); fb_height = cogl_framebuffer_get_height (test_fb); buffer = cogl_attribute_buffer_new (test_ctx, sizeof (vertex_data), vertex_data); /* Replace the texture coordinates of the third vertex with the * coordinates for a green texel */ data = cogl_buffer_map_range (COGL_BUFFER (buffer), sizeof (vertex_data[0]) * 2, sizeof (vertex_data[0]), COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_MAP_HINT_DISCARD_RANGE, NULL); /* don't catch errors */ g_assert (data != NULL); data->x = vertex_data[2].x; data->y = vertex_data[2].y; data->s = 1.0f; data->t = 0.0f; cogl_buffer_unmap (COGL_BUFFER (buffer)); pos_attribute = cogl_attribute_new (buffer, "cogl_position_in", sizeof (vertex_data[0]), offsetof (CoglVertexP2T2, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); tex_coord_attribute = cogl_attribute_new (buffer, "cogl_tex_coord_in", sizeof (vertex_data[0]), offsetof (CoglVertexP2T2, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); primitive = cogl_primitive_new (COGL_VERTICES_MODE_TRIANGLE_STRIP, 4, /* n_vertices */ pos_attribute, tex_coord_attribute, NULL); cogl_primitive_draw (primitive, test_fb, pipeline); cogl_object_unref (primitive); /* Top left pixel should be the one that is replaced to be green */ test_utils_check_pixel (test_fb, 1, 1, 0x00ff00ff); /* The other three corners should be left as red */ test_utils_check_pixel (test_fb, fb_width - 2, 1, 0xff0000ff); test_utils_check_pixel (test_fb, 1, fb_height - 2, 0xff0000ff); test_utils_check_pixel (test_fb, fb_width - 2, fb_height - 2, 0xff0000ff); cogl_object_unref (buffer); cogl_object_unref (pos_attribute); cogl_object_unref (tex_coord_attribute); cogl_object_unref (pipeline); cogl_object_unref (tex); if (cogl_test_verbose ()) g_print ("OK\n"); }
static void test_tex_combine (TestState *state, int x, int y, uint32_t tex0_color, uint32_t tex1_color, uint32_t combine_constant, const char *combine_string, uint32_t expected_result) { CoglTexture *tex0, *tex1; /* combine constant - when applicable */ uint8_t Cr = MASK_RED (combine_constant); uint8_t Cg = MASK_GREEN (combine_constant); uint8_t Cb = MASK_BLUE (combine_constant); uint8_t Ca = MASK_ALPHA (combine_constant); CoglColor combine_const_color; CoglPipeline *pipeline; CoglBool status; CoglError *error = NULL; int y_off; int x_off; tex0 = make_texture (tex0_color); tex1 = make_texture (tex1_color); pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_color4ub (pipeline, 0x80, 0x80, 0x80, 0x80); cogl_pipeline_set_blend (pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL); cogl_pipeline_set_layer_texture (pipeline, 0, tex0); cogl_pipeline_set_layer_combine (pipeline, 0, "RGBA = REPLACE (TEXTURE)", NULL); cogl_pipeline_set_layer_texture (pipeline, 1, tex1); status = cogl_pipeline_set_layer_combine (pipeline, 1, combine_string, &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 test texture combine string %s: %s", combine_string, error->message); } cogl_color_init_from_4ub (&combine_const_color, Cr, Cg, Cb, Ca); cogl_pipeline_set_layer_combine_constant (pipeline, 1, &combine_const_color); cogl_framebuffer_draw_rectangle (test_fb, pipeline, x * QUAD_WIDTH, y * QUAD_WIDTH, x * QUAD_WIDTH + QUAD_WIDTH, y * QUAD_WIDTH + QUAD_WIDTH); cogl_object_unref (pipeline); cogl_object_unref (tex0); cogl_object_unref (tex1); /* See what we got... */ y_off = y * QUAD_WIDTH + (QUAD_WIDTH / 2); x_off = x * QUAD_WIDTH + (QUAD_WIDTH / 2); if (cogl_test_verbose ()) { g_print ("test_tex_combine (%d, %d):\n%s\n", x, y, combine_string); g_print (" texture 0 color = 0x%08lX\n", (unsigned long)tex0_color); g_print (" texture 1 color = 0x%08lX\n", (unsigned long)tex1_color); if (combine_constant != TEX_CONSTANT_UNUSED) g_print (" combine constant = %02x, %02x, %02x, %02x\n", Cr, Cg, Cb, Ca); else g_print (" combine constant = UNUSED\n"); } test_utils_check_pixel (test_fb, x_off, y_off, expected_result); }
static void do_test (CoglBool check_orientation) { int fb_width = cogl_framebuffer_get_width (test_fb); int fb_height = cogl_framebuffer_get_height (test_fb); CoglPrimitive *prim; CoglError *error = NULL; CoglTexture2D *tex_2d; CoglPipeline *pipeline, *solid_pipeline; CoglBool res; int tex_height; cogl_framebuffer_orthographic (test_fb, 0, 0, /* x_1, y_1 */ fb_width, /* x_2 */ fb_height /* y_2 */, -1, 100 /* near/far */); cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 1.0f, 1.0f, 1.0f, 1.0f); /* If we're not checking the orientation of the point sprite then * we'll set the height of the texture to 1 so that the vertical * orientation does not matter */ if (check_orientation) tex_height = 2; else tex_height = 1; tex_2d = cogl_texture_2d_new_from_data (test_ctx, 2, tex_height, /* width/height */ COGL_PIXEL_FORMAT_RGB_888, COGL_PIXEL_FORMAT_ANY, 6, /* row stride */ tex_data, &error); g_assert (tex_2d != NULL); g_assert (error == NULL); pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_layer_texture (pipeline, 0, COGL_TEXTURE (tex_2d)); res = cogl_pipeline_set_layer_point_sprite_coords_enabled (pipeline, /* layer_index */ 0, /* enable */ TRUE, &error); g_assert (res == TRUE); g_assert (error == NULL); cogl_pipeline_set_layer_filters (pipeline, 0, /* layer_index */ COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST); cogl_pipeline_set_point_size (pipeline, POINT_SIZE); prim = cogl_primitive_new_p2t2 (test_ctx, COGL_VERTICES_MODE_POINTS, 1, /* n_vertices */ &point); cogl_primitive_draw (prim, test_fb, pipeline); /* Render the primitive again without point sprites to make sure disabling it works */ solid_pipeline = cogl_pipeline_copy (pipeline); cogl_pipeline_set_layer_point_sprite_coords_enabled (solid_pipeline, /* layer_index */ 0, /* enable */ FALSE, &error); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, POINT_SIZE * 2, /* x */ 0.0f, /* y */ 0.0f /* z */); cogl_primitive_draw (prim, test_fb, solid_pipeline); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (prim); cogl_object_unref (solid_pipeline); cogl_object_unref (pipeline); cogl_object_unref (tex_2d); test_utils_check_pixel (test_fb, POINT_SIZE - POINT_SIZE / 4, POINT_SIZE - POINT_SIZE / 4, 0x0000ffff); test_utils_check_pixel (test_fb, POINT_SIZE + POINT_SIZE / 4, POINT_SIZE - POINT_SIZE / 4, 0x00ff00ff); test_utils_check_pixel (test_fb, POINT_SIZE - POINT_SIZE / 4, POINT_SIZE + POINT_SIZE / 4, check_orientation ? 0x00ffffff : 0x0000ffff); test_utils_check_pixel (test_fb, POINT_SIZE + POINT_SIZE / 4, POINT_SIZE + POINT_SIZE / 4, check_orientation ? 0xff0000ff : 0x00ff00ff); /* When rendering without the point sprites all of the texture coordinates should be 0,0 so it should get the top-left texel which is blue */ test_utils_check_region (test_fb, POINT_SIZE * 3 - POINT_SIZE / 2 + 1, POINT_SIZE - POINT_SIZE / 2 + 1, POINT_SIZE - 2, POINT_SIZE - 2, 0x0000ffff); if (cogl_test_verbose ()) g_print ("OK\n"); }
static void check_pos (int pos, guint32 color) { test_utils_check_pixel (pos * 10 + 5, 5, color); }
static void test_push_pop_single_context (void) { CoglTexture *offscreen_texture; CoglOffscreen *offscreen; CoglPipeline *pipeline; CoglGLES2Context *gles2_ctx; const CoglGLES2Vtable *gles2; GError *error = NULL; offscreen_texture = COGL_TEXTURE ( cogl_texture_2d_new_with_size (test_ctx, cogl_framebuffer_get_width (test_fb), cogl_framebuffer_get_height (test_fb), COGL_PIXEL_FORMAT_ANY, NULL)); offscreen = cogl_offscreen_new_to_texture (offscreen_texture); pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_layer_texture (pipeline, 0, offscreen_texture); gles2_ctx = cogl_gles2_context_new (test_ctx, &error); if (!gles2_ctx) g_error ("Failed to create GLES2 context: %s\n", error->message); gles2 = cogl_gles2_context_get_vtable (gles2_ctx); /* Clear onscreen to 0xffff00 using GLES2 */ if (!cogl_push_gles2_context (test_ctx, gles2_ctx, test_fb, test_fb, &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } gles2->glClearColor (1, 1, 0, 1); gles2->glClear (GL_COLOR_BUFFER_BIT); cogl_pop_gles2_context (test_ctx); test_utils_check_pixel (test_fb, 0, 0, 0xffff00ff); /* Clear offscreen to 0xff0000 using GLES2 and then copy the result * onscreen. * * If we fail to bind the new context here then we'd probably end up * clearing onscreen to 0xff0000 and copying 0xffff00 to onscreen * instead. */ if (!cogl_push_gles2_context (test_ctx, gles2_ctx, COGL_FRAMEBUFFER (offscreen), COGL_FRAMEBUFFER (offscreen), &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } gles2->glClearColor (1, 0, 0, 1); gles2->glClear (GL_COLOR_BUFFER_BIT); cogl_pop_gles2_context (test_ctx); cogl_framebuffer_draw_rectangle (test_fb, pipeline, -1, 1, 1, -1); /* NB: Cogl doesn't automatically support mid-scene modifications * of textures and so we explicitly flush the drawn rectangle to the * framebuffer now otherwise it may be batched until after the * offscreen texture has been modified again. */ cogl_flush (); /* Clear the offscreen framebuffer to blue using GLES2 before * reading back from the onscreen framebuffer in case we mistakenly * read from the offscreen framebuffer and get a false positive */ if (!cogl_push_gles2_context (test_ctx, gles2_ctx, COGL_FRAMEBUFFER (offscreen), COGL_FRAMEBUFFER (offscreen), &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } gles2->glClearColor (0, 0, 1, 1); gles2->glClear (GL_COLOR_BUFFER_BIT); cogl_pop_gles2_context (test_ctx); test_utils_check_pixel (test_fb, 0, 0, 0xff0000ff); /* Now copy the offscreen blue clear to the onscreen framebufer and * check that too */ cogl_framebuffer_draw_rectangle (test_fb, pipeline, -1, 1, 1, -1); test_utils_check_pixel (test_fb, 0, 0, 0x0000ffff); if (!cogl_push_gles2_context (test_ctx, gles2_ctx, test_fb, test_fb, &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } gles2->glClearColor (1, 0, 1, 1); gles2->glClear (GL_COLOR_BUFFER_BIT); cogl_pop_gles2_context (test_ctx); test_utils_check_pixel (test_fb, 0, 0, 0xff00ffff); cogl_object_unref (gles2_ctx); cogl_object_unref (pipeline); }
static void do_test (CoglBool check_orientation, CoglBool use_glsl) { int fb_width = cogl_framebuffer_get_width (test_fb); int fb_height = cogl_framebuffer_get_height (test_fb); CoglPrimitive *prim; CoglError *error = NULL; CoglTexture2D *tex_2d; CoglPipeline *pipeline, *solid_pipeline; int tex_height; cogl_framebuffer_orthographic (test_fb, 0, 0, /* x_1, y_1 */ fb_width, /* x_2 */ fb_height /* y_2 */, -1, 100 /* near/far */); cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 1.0f, 1.0f, 1.0f, 1.0f); /* If we're not checking the orientation of the point sprite then * we'll set the height of the texture to 1 so that the vertical * orientation does not matter */ if (check_orientation) tex_height = 2; else tex_height = 1; tex_2d = cogl_texture_2d_new_from_data (test_ctx, 2, tex_height, /* width/height */ COGL_PIXEL_FORMAT_RGB_888, COGL_PIXEL_FORMAT_ANY, 6, /* row stride */ tex_data, &error); g_assert (tex_2d != NULL); g_assert (error == NULL); pipeline = cogl_pipeline_new (test_ctx); cogl_pipeline_set_layer_texture (pipeline, 0, tex_2d); cogl_pipeline_set_layer_filters (pipeline, 0, /* layer_index */ COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST); cogl_pipeline_set_point_size (pipeline, POINT_SIZE); /* If we're using GLSL then we don't need to enable point sprite * coords and we can just directly reference cogl_point_coord in the * snippet */ if (use_glsl) { CoglSnippet *snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP, NULL, /* declarations */ NULL /* post */); static const char source[] = " cogl_texel = texture2D (cogl_sampler, cogl_point_coord);\n"; cogl_snippet_set_replace (snippet, source); /* Keep a reference to the original pipeline because there is no * way to remove a snippet in order to recreate the solid * pipeline */ solid_pipeline = cogl_pipeline_copy (pipeline); cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); cogl_object_unref (snippet); } else { CoglBool res = cogl_pipeline_set_layer_point_sprite_coords_enabled (pipeline, /* layer_index */ 0, /* enable */ TRUE, &error); g_assert (res == TRUE); g_assert (error == NULL); solid_pipeline = cogl_pipeline_copy (pipeline); res = cogl_pipeline_set_layer_point_sprite_coords_enabled (solid_pipeline, /* layer_index */ 0, /* enable */ FALSE, &error); g_assert (res == TRUE); g_assert (error == NULL); } prim = cogl_primitive_new_p2t2 (test_ctx, COGL_VERTICES_MODE_POINTS, 1, /* n_vertices */ &point); cogl_primitive_draw (prim, test_fb, pipeline); /* Render the primitive again without point sprites to make sure disabling it works */ cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, POINT_SIZE * 2, /* x */ 0.0f, /* y */ 0.0f /* z */); cogl_primitive_draw (prim, test_fb, solid_pipeline); cogl_framebuffer_pop_matrix (test_fb); cogl_object_unref (prim); cogl_object_unref (solid_pipeline); cogl_object_unref (pipeline); cogl_object_unref (tex_2d); test_utils_check_pixel (test_fb, POINT_SIZE - POINT_SIZE / 4, POINT_SIZE - POINT_SIZE / 4, 0x0000ffff); test_utils_check_pixel (test_fb, POINT_SIZE + POINT_SIZE / 4, POINT_SIZE - POINT_SIZE / 4, 0x00ff00ff); test_utils_check_pixel (test_fb, POINT_SIZE - POINT_SIZE / 4, POINT_SIZE + POINT_SIZE / 4, check_orientation ? 0x00ffffff : 0x0000ffff); test_utils_check_pixel (test_fb, POINT_SIZE + POINT_SIZE / 4, POINT_SIZE + POINT_SIZE / 4, check_orientation ? 0xff0000ff : 0x00ff00ff); /* When rendering without the point sprites all of the texture coordinates should be 0,0 so it should get the top-left texel which is blue */ test_utils_check_region (test_fb, POINT_SIZE * 3 - POINT_SIZE / 2 + 1, POINT_SIZE - POINT_SIZE / 2 + 1, POINT_SIZE - 2, POINT_SIZE - 2, 0x0000ffff); if (cogl_test_verbose ()) g_print ("OK\n"); }
void test_alpha_textures (void) { CoglTexture *tex1, *tex2; CoglPipeline *pipeline1, *pipeline2; int fb_width = cogl_framebuffer_get_width (test_fb); int fb_height = cogl_framebuffer_get_height (test_fb); uint8_t replacement_data[1] = { 0xff }; create_pipeline (&tex1, &pipeline1); cogl_framebuffer_draw_rectangle (test_fb, pipeline1, -1.0f, 1.0f, /* x1/y1 */ 1.0f, 0.0f /* x2/y2 */); create_pipeline (&tex2, &pipeline2); cogl_texture_set_region (tex2, 1, 1, /* width / height */ COGL_PIXEL_FORMAT_A_8, 1, /* rowstride */ replacement_data, 1, 1, /* dst_x/y */ 0, /* level */ NULL); /* abort on error */ cogl_framebuffer_draw_rectangle (test_fb, pipeline2, -1.0f, 0.0f, /* x1/y1 */ 1.0f, -1.0f /* x2/y2 */); cogl_object_unref (tex1); cogl_object_unref (tex2); cogl_object_unref (pipeline1); cogl_object_unref (pipeline2); /* Unmodified texture */ test_utils_check_pixel (test_fb, fb_width / 4, fb_height / 8, 0x000000ff); test_utils_check_pixel (test_fb, fb_width * 3 / 4, fb_height / 8, 0x444444ff); test_utils_check_pixel (test_fb, fb_width / 4, fb_height * 3 / 8, 0x888888ff); test_utils_check_pixel (test_fb, fb_width * 3 / 4, fb_height * 3 / 8, 0xccccccff); /* Modified texture */ test_utils_check_pixel (test_fb, fb_width / 4, fb_height * 5 / 8, 0x000000ff); test_utils_check_pixel (test_fb, fb_width * 3 / 4, fb_height * 5 / 8, 0x444444ff); test_utils_check_pixel (test_fb, fb_width / 4, fb_height * 7 / 8, 0x888888ff); test_utils_check_pixel (test_fb, fb_width * 3 / 4, fb_height * 7 / 8, 0xffffffff); if (cogl_test_verbose ()) g_print ("OK\n"); }