void test_primitive_and_journal (void) { CoglPrimitive *primitives[2]; CoglPipeline *pipeline; setup_orthographic_modelview (); create_primitives (primitives); pipeline = create_pipeline (); /* Set a clip to clip all three rectangles to just the bottom half. * The journal flushes its own clip state so this verifies that the * clip state is correctly restored for the second primitive. */ cogl_framebuffer_push_rectangle_clip (test_fb, 0, 50, 300, 100); cogl_primitive_draw (primitives[0], test_fb, pipeline); /* Draw a rectangle using the journal in-between the two primitives. * This should test that the journal gets flushed correctly and that * the modelview matrix is restored. Half of the rectangle should be * overriden by the second primitive */ cogl_framebuffer_draw_rectangle (test_fb, pipeline, 100, 0, /* x1/y1 */ 300, 100 /* x2/y2 */); cogl_primitive_draw (primitives[1], test_fb, pipeline); /* Check the three rectangles */ test_utils_check_region (test_fb, 1, 51, 98, 48, 0xff0000ff); test_utils_check_region (test_fb, 101, 51, 98, 48, 0x00ff00ff); test_utils_check_region (test_fb, 201, 51, 98, 48, 0x0000ffff); /* Check that the top half of all of the rectangles was clipped */ test_utils_check_region (test_fb, 1, 1, 298, 48, 0x000000ff); cogl_framebuffer_pop_clip (test_fb); if (cogl_test_verbose ()) g_print ("OK\n"); }
void _cogl_pango_display_list_render (CoglFramebuffer *fb, CoglPangoDisplayList *dl, const CoglColor *color) { GSList *l; for (l = dl->nodes; l; l = l->next) { CoglPangoDisplayListNode *node = l->data; CoglColor draw_color; if (node->pipeline == NULL) { if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE) node->pipeline = _cogl_pango_pipeline_cache_get (dl->pipeline_cache, node->d.texture.texture); else node->pipeline = _cogl_pango_pipeline_cache_get (dl->pipeline_cache, NULL); } if (node->color_override) /* Use the override color but preserve the alpha from the draw color */ cogl_color_init_from_4ub (&draw_color, cogl_color_get_red_byte (&node->color), cogl_color_get_green_byte (&node->color), cogl_color_get_blue_byte (&node->color), cogl_color_get_alpha_byte (color)); else draw_color = *color; cogl_color_premultiply (&draw_color); cogl_pipeline_set_color (node->pipeline, &draw_color); switch (node->type) { case COGL_PANGO_DISPLAY_LIST_TEXTURE: _cogl_framebuffer_draw_display_list_texture (fb, node->pipeline, node); break; case COGL_PANGO_DISPLAY_LIST_RECTANGLE: cogl_framebuffer_draw_rectangle (fb, node->pipeline, node->d.rectangle.x_1, node->d.rectangle.y_1, node->d.rectangle.x_2, node->d.rectangle.y_2); break; case COGL_PANGO_DISPLAY_LIST_TRAPEZOID: cogl_primitive_draw (node->d.trapezoid.primitive, fb, node->pipeline); break; } } }
static gboolean paint_cb (void *user_data) { Data *data = user_data; CoglError *error = NULL; const CoglGLES2Vtable *gles2 = data->gles2_vtable; /* Draw scene with GLES2 */ if (!cogl_push_gles2_context (data->ctx, data->gles2_ctx, data->fb, data->fb, &error)) { g_error ("Failed to push gles2 context: %s\n", error->message); } /* Clear offscreen framebuffer with a random color */ gles2->glClearColor (g_random_double (), g_random_double (), g_random_double (), 1.0f); gles2->glClear (GL_COLOR_BUFFER_BIT); cogl_pop_gles2_context (data->ctx); /* Draw scene with Cogl */ cogl_primitive_draw (data->triangle, data->fb, data->pipeline); cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); return FALSE; /* remove the callback */ }
static test_draw_frame_and_swap (TestData *data) { if (data->context) { cogl_primitive_draw (data->triangle); cogl_framebuffer_swap_buffers (data->fb); } }
static void paint (void) { CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); int width = cogl_framebuffer_get_width (test_fb); int half_width = width / 2; int height = cogl_framebuffer_get_height (test_fb); CoglVertexP2 tri0_vertices[] = { { 0, 0 }, { 0, height }, { half_width, height }, }; CoglVertexP2C4 tri1_vertices[] = { { half_width, 0, 0x80, 0x80, 0x80, 0x80 }, { half_width, height, 0x80, 0x80, 0x80, 0x80 }, { width, height, 0x80, 0x80, 0x80, 0x80 }, }; CoglPrimitive *tri0; CoglPrimitive *tri1; cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 0); tri0 = cogl_primitive_new_p2 (test_ctx, COGL_VERTICES_MODE_TRIANGLES, 3, tri0_vertices); tri1 = cogl_primitive_new_p2c4 (test_ctx, COGL_VERTICES_MODE_TRIANGLES, 3, tri1_vertices); /* Check that cogl correctly handles the case where we draw * different primitives same pipeline and switch from using the * opaque color associated with the pipeline and using a colour * attribute with an alpha component which implies blending is * required. * * If Cogl gets this wrong then then in all likelyhood the second * primitive will be drawn with blending still disabled. */ cogl_primitive_draw (tri0, test_fb, pipeline); cogl_primitive_draw (tri1, test_fb, pipeline); test_utils_check_pixel_and_alpha (test_fb, half_width + 5, height - 5, 0x80808080); }
static void test_float_verts (TestState *state, int offset_x, int offset_y) { CoglAttribute *attributes[2]; CoglAttributeBuffer *buffer; CoglPrimitive *primitive; 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); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, 6, /* n_vertices */ attributes, 2); /* n_attributes */ cogl_primitive_draw (primitive, test_fb, state->pipeline); cogl_object_unref (primitive); 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 paint (Data *data) { CoglFramebuffer *fb = data->fb; float rotation; cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR|COGL_BUFFER_BIT_DEPTH, 0, 0, 0, 1); cogl_framebuffer_push_matrix (fb); cogl_framebuffer_translate (fb, data->framebuffer_width / 2, data->framebuffer_height / 2, 0); cogl_framebuffer_scale (fb, 75, 75, 75); /* Update the rotation based on the time the application has been running so that we get a linear animation regardless of the frame rate */ rotation = g_timer_elapsed (data->timer, NULL) * 60.0f; /* Rotate the cube separately around each axis. * * Note: Cogl matrix manipulation follows the same rules as for * OpenGL. We use column-major matrices and - if you consider the * transformations happening to the model - then they are combined * in reverse order which is why the rotation is done last, since * we want it to be a rotation around the origin, before it is * scaled and translated. */ cogl_framebuffer_rotate (fb, rotation, 0, 0, 1); cogl_framebuffer_rotate (fb, rotation, 0, 1, 0); cogl_framebuffer_rotate (fb, rotation, 1, 0, 0); cogl_primitive_draw (data->prim, fb, data->crate_pipeline); cogl_framebuffer_pop_matrix (fb); /* And finally render our Pango layouts... */ cogl_pango_show_layout (fb, data->hello_label, (data->framebuffer_width / 2) - (data->hello_label_width / 2), (data->framebuffer_height / 2) - (data->hello_label_height / 2), &white); }
void cogl_path_stroke (CoglPath *path, CoglFramebuffer *framebuffer, CoglPipeline *pipeline) { CoglPathData *data; CoglPipeline *copy = NULL; unsigned int path_start; int path_num = 0; CoglPathNode *node; _COGL_RETURN_IF_FAIL (cogl_is_path (path)); _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (framebuffer)); _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); data = path->data; if (data->path_nodes->len == 0) return; if (cogl_pipeline_get_n_layers (pipeline) != 0) { copy = cogl_pipeline_copy (pipeline); _cogl_pipeline_prune_to_n_layers (copy, 0); pipeline = copy; } _cogl_path_build_stroke_attribute_buffer (path); for (path_start = 0; path_start < data->path_nodes->len; path_start += node->path_size) { CoglPrimitive *primitive; node = &g_array_index (data->path_nodes, CoglPathNode, path_start); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINE_STRIP, node->path_size, &data->stroke_attributes[path_num], 1); cogl_primitive_draw (primitive, framebuffer, pipeline); cogl_object_unref (primitive); path_num++; } if (copy) cogl_object_unref (copy); }
static void redraw (Data *data) { CoglFramebuffer *fb = data->fb; cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_framebuffer_push_matrix (fb); cogl_framebuffer_translate (fb, data->center_x, -data->center_y, 0.0f); cogl_primitive_draw (data->triangle, fb, data->pipeline); cogl_framebuffer_pop_matrix (fb); cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); }
static CoglBool paint_cb (void *user_data) { CoglandCompositor *compositor = user_data; GList *l; for (l = compositor->outputs; l; l = l->next) { CoglandOutput *output = l->data; CoglFramebuffer *fb = output->onscreen; GList *l2; cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_primitive_draw (compositor->triangle, fb, compositor->triangle_pipeline); for (l2 = compositor->surfaces; l2; l2 = l2->next) { CoglandSurface *surface = l2->data; if (surface->texture) { CoglTexture2D *texture = surface->texture; CoglPipeline *pipeline = cogl_pipeline_new (compositor->cogl_context); cogl_pipeline_set_layer_texture (pipeline, 0, texture); cogl_framebuffer_draw_rectangle (fb, pipeline, -1, 1, 1, -1); cogl_object_unref (pipeline); } } cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); } while (!wl_list_empty (&compositor->frame_callbacks)) { CoglandFrameCallback *callback = wl_container_of (compositor->frame_callbacks.next, callback, link); wl_callback_send_done (callback->resource, get_time ()); wl_resource_destroy (callback->resource); } compositor->redraw_idle = 0; return G_SOURCE_REMOVE; }
static gboolean paint_cb (void *user_data) { CoglandCompositor *compositor = user_data; GList *l; for (l = compositor->outputs; l; l = l->next) { CoglandOutput *output = l->data; CoglFramebuffer *fb = COGL_FRAMEBUFFER (output->onscreen); GList *l2; cogl_push_framebuffer (fb); #if 0 cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR); #else cogl_clear (&black, COGL_BUFFER_BIT_COLOR); #endif cogl_primitive_draw (compositor->triangle); for (l2 = compositor->surfaces; l2; l2 = l2->next) { CoglandSurface *surface = l2->data; if (surface->buffer) { CoglTexture2D *texture = surface->buffer->texture; cogl_set_source_texture (texture); cogl_rectangle (-1, 1, 1, -1); } wl_display_post_frame (compositor->wayland_display, &surface->wayland_surface, get_time ()); } cogl_framebuffer_swap_buffers (fb); cogl_pop_framebuffer (); } return TRUE; }
/** * mash_data_render: * @self: A #MashData instance * * Renders the data contained in the model to the Clutter * scene. The current Cogl source material will be used to affect the * appearance of the model. This function is not usually called * directly but instead the #MashData instance is added to a * #MashModel and this function will be automatically called by * the paint method of the model. */ void mash_data_render (MashData *self, CoglPipeline* pl){ MashDataPrivate *priv; g_return_if_fail (MASH_IS_DATA (self)); priv = self->priv; if (priv->loaded_data.prim != NULL){ CoglFramebuffer *fb = /*(CoglFramebuffer*)*/ cogl_get_draw_framebuffer(); cogl_primitive_draw(priv->loaded_data.prim, fb, pl); } else if(priv->loaded_data.vertices_vbo != NULL && priv->loaded_data.indices != NULL){ cogl_vertex_buffer_draw_elements (priv->loaded_data.vertices_vbo, COGL_VERTICES_MODE_TRIANGLES, priv->loaded_data.indices, priv->loaded_data.min_index, priv->loaded_data.max_index, 0, priv->loaded_data.n_triangles * 3); } }
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"); }
// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // If text or lines are blurry when integrating ImGui in your engine: // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplGtk3Cogl_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); int fb_width = (int)(io.DisplaySize.x * io.DisplayFramebufferScale.x); int fb_height = (int)(io.DisplaySize.y * io.DisplayFramebufferScale.y); if (fb_width == 0 || fb_height == 0) return; draw_data->ScaleClipRects(io.DisplayFramebufferScale); cogl_framebuffer_orthographic(g_Framebuffer, 0, 0, io.DisplaySize.x, io.DisplaySize.y, -1, 1); CoglContext *context = cogl_framebuffer_get_context(g_Framebuffer); for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; int idx_buffer_offset = 0; CoglAttributeBuffer *vertices = cogl_attribute_buffer_new(context, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), cmd_list->VtxBuffer.Data); #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) CoglAttribute *attrs[3] = { cogl_attribute_new(vertices, "cogl_position_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, pos), 2, COGL_ATTRIBUTE_TYPE_FLOAT), cogl_attribute_new(vertices, "cogl_tex_coord0_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, uv), 2, COGL_ATTRIBUTE_TYPE_FLOAT), cogl_attribute_new(vertices, "cogl_color_in", sizeof(ImDrawVert), OFFSETOF(ImDrawVert, col), 4, COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE) }; #undef OFFSETOF CoglPrimitive *primitive = cogl_primitive_new_with_attributes(COGL_VERTICES_MODE_TRIANGLES, cmd_list->VtxBuffer.Size, attrs, 3); CoglIndices *indices = cogl_indices_new(context, sizeof(ImDrawIdx) == 2 ? COGL_INDICES_TYPE_UNSIGNED_SHORT : COGL_INDICES_TYPE_UNSIGNED_INT, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; cogl_indices_set_offset(indices, sizeof(ImDrawIdx) * idx_buffer_offset); cogl_primitive_set_indices(primitive, indices, pcmd->ElemCount); if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { bool has_texture = pcmd->TextureId != NULL; CoglPipeline *pipeline = has_texture ? (cogl_is_pipeline(pcmd->TextureId) ? (CoglPipeline *) pcmd->TextureId : g_ImagePipeline) : g_ColorPipeline; if (has_texture && pipeline == g_ImagePipeline) { cogl_pipeline_set_layer_texture(g_ImagePipeline, 0, COGL_TEXTURE(pcmd->TextureId)); } cogl_framebuffer_push_scissor_clip(g_Framebuffer, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y); cogl_primitive_draw(primitive, g_Framebuffer, pipeline); cogl_framebuffer_pop_clip(g_Framebuffer); } idx_buffer_offset += pcmd->ElemCount; } for (int i = 0; i < 3; i++) cogl_object_unref(attrs[i]); cogl_object_unref(primitive); cogl_object_unref(vertices); cogl_object_unref(indices); } }
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 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"); }
static void emit_vertex_buffer_geometry (CoglFramebuffer *fb, CoglPipeline *pipeline, CoglPangoDisplayListNode *node) { CoglContext *ctx = fb->context; /* It's expensive to go through the Cogl journal for large runs * of text in part because the journal transforms the quads in software * to avoid changing the modelview matrix. So for larger runs of text * we load the vertices into a VBO, and this has the added advantage * that if the text doesn't change from frame to frame the VBO can * be re-used avoiding the repeated cost of validating the data and * mapping it into the GPU... */ if (node->d.texture.primitive == NULL) { CoglAttributeBuffer *buffer; CoglVertexP2T2 *verts, *v; int n_verts; CoglBool allocated = FALSE; CoglAttribute *attributes[2]; CoglPrimitive *prim; int i; CoglError *ignore_error = NULL; n_verts = node->d.texture.rectangles->len * 4; buffer = cogl_attribute_buffer_new_with_size (ctx, n_verts * sizeof (CoglVertexP2T2)); if ((verts = cogl_buffer_map (COGL_BUFFER (buffer), COGL_BUFFER_ACCESS_WRITE, COGL_BUFFER_MAP_HINT_DISCARD, &ignore_error)) == NULL) { cogl_error_free (ignore_error); verts = g_new (CoglVertexP2T2, n_verts); allocated = TRUE; } v = verts; /* Copy the rectangles into the buffer and expand into four vertices instead of just two */ for (i = 0; i < node->d.texture.rectangles->len; i++) { const CoglPangoDisplayListRectangle *rectangle = &g_array_index (node->d.texture.rectangles, CoglPangoDisplayListRectangle, i); v->x = rectangle->x_1; v->y = rectangle->y_1; v->s = rectangle->s_1; v->t = rectangle->t_1; v++; v->x = rectangle->x_1; v->y = rectangle->y_2; v->s = rectangle->s_1; v->t = rectangle->t_2; v++; v->x = rectangle->x_2; v->y = rectangle->y_2; v->s = rectangle->s_2; v->t = rectangle->t_2; v++; v->x = rectangle->x_2; v->y = rectangle->y_1; v->s = rectangle->s_2; v->t = rectangle->t_1; v++; } if (allocated) { cogl_buffer_set_data (COGL_BUFFER (buffer), 0, /* offset */ verts, sizeof (CoglVertexP2T2) * n_verts, NULL); g_free (verts); } else cogl_buffer_unmap (COGL_BUFFER (buffer)); attributes[0] = cogl_attribute_new (buffer, "cogl_position_in", sizeof (CoglVertexP2T2), G_STRUCT_OFFSET (CoglVertexP2T2, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (buffer, "cogl_tex_coord0_in", sizeof (CoglVertexP2T2), G_STRUCT_OFFSET (CoglVertexP2T2, s), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); prim = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, n_verts, attributes, 2 /* n_attributes */); #ifdef CLUTTER_COGL_HAS_GL if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUADS)) cogl_primitive_set_mode (prim, GL_QUADS); else #endif { /* GLES doesn't support GL_QUADS so instead we use a VBO with indexed vertices to generate GL_TRIANGLES from the quads */ CoglIndices *indices = cogl_get_rectangle_indices (ctx, node->d.texture.rectangles->len); cogl_primitive_set_indices (prim, indices, node->d.texture.rectangles->len * 6); } node->d.texture.primitive = prim; cogl_object_unref (buffer); cogl_object_unref (attributes[0]); cogl_object_unref (attributes[1]); } cogl_primitive_draw (node->d.texture.primitive, fb, pipeline); }
static void test_byte_verts (TestState *state, int offset_x, int offset_y) { CoglAttribute *attributes[2]; CoglAttributeBuffer *buffer, *unnorm_buffer; CoglPrimitive *primitive; 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); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, 6, /* n_vertices */ attributes, 2); /* n_attributes */ cogl_primitive_draw (primitive, test_fb, state->pipeline); cogl_object_unref (primitive); 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); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, 3, /* n_vertices */ attributes, 2); /* n_attributes */ cogl_primitive_draw (primitive, test_fb, state->pipeline); cogl_object_unref (primitive); 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 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 paint (Data *data) { int i; float diff_time; /* Update all of the firework's positions */ for (i = 0; i < N_FIREWORKS; i++) { Firework *firework = data->fireworks + i; if ((fabsf (firework->x - firework->start_x) > 2.0f) || firework->y < -1.0f) { firework->size = g_random_double_range (0.001f, 0.1f); firework->start_x = 1.0f + firework->size; firework->start_y = -1.0f; firework->initial_x_velocity = g_random_double_range (-0.1f, -2.0f); firework->initial_y_velocity = g_random_double_range (0.1f, 4.0f); g_timer_reset (firework->timer); /* Pick a random color out of six */ if (g_random_boolean ()) { memset (&firework->color, 0, sizeof (Color)); ((uint8_t *) &firework->color)[g_random_int_range (0, 3)] = 255; } else { memset (&firework->color, 255, sizeof (Color)); ((uint8_t *) &firework->color)[g_random_int_range (0, 3)] = 0; } firework->color.alpha = 255; /* Fire some of the fireworks from the other side */ if (g_random_boolean ()) { firework->start_x = -firework->start_x; firework->initial_x_velocity = -firework->initial_x_velocity; } } diff_time = g_timer_elapsed (firework->timer, NULL); firework->x = (firework->start_x + firework->initial_x_velocity * diff_time); firework->y = ((firework->initial_y_velocity * diff_time + 0.5f * GRAVITY * diff_time * diff_time) + firework->start_y); } diff_time = g_timer_elapsed (data->last_spark_time, NULL); if (diff_time < 0.0f || diff_time >= TIME_PER_SPARK) { /* Add a new spark for each firework, overwriting the oldest ones */ for (i = 0; i < N_FIREWORKS; i++) { Spark *spark = data->sparks + data->next_spark_num; Firework *firework = data->fireworks + i; spark->x = (firework->x + g_random_double_range (-firework->size / 2.0f, firework->size / 2.0f)); spark->y = (firework->y + g_random_double_range (-firework->size / 2.0f, firework->size / 2.0f)); spark->base_color = firework->color; data->next_spark_num = (data->next_spark_num + 1) & (N_SPARKS - 1); } /* Update the colour of each spark */ for (i = 0; i < N_SPARKS; i++) { float color_value; /* First spark is the oldest */ Spark *spark = data->sparks + ((data->next_spark_num + i) & (N_SPARKS - 1)); color_value = i / (N_SPARKS - 1.0f); spark->color.red = spark->base_color.red * color_value; spark->color.green = spark->base_color.green * color_value; spark->color.blue = spark->base_color.blue * color_value; spark->color.alpha = 255.0f * color_value; } g_timer_reset (data->last_spark_time); } cogl_buffer_set_data (data->attribute_buffer, 0, /* offset */ data->sparks, sizeof (data->sparks), NULL /* error */); cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_primitive_draw (data->primitive, data->fb, data->pipeline); cogl_onscreen_swap_buffers (data->fb); }
static void draw_frame (TestState *state) { CoglTexture *tex = create_texture_3d (test_ctx); CoglPipeline *pipeline = cogl_pipeline_new (test_ctx); typedef struct { float x, y, s, t, r; } Vert; CoglPrimitive *primitive; CoglAttributeBuffer *attribute_buffer; CoglAttribute *attributes[2]; Vert *verts, *v; int i; cogl_pipeline_set_layer_texture (pipeline, 0, tex); cogl_object_unref (tex); cogl_pipeline_set_layer_filters (pipeline, 0, COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST); /* Render the texture repeated horizontally twice using a regular cogl rectangle. This should end up with the r texture coordinates as zero */ cogl_framebuffer_draw_textured_rectangle (test_fb, pipeline, 0.0f, 0.0f, TEX_WIDTH * 2, TEX_HEIGHT, 0.0f, 0.0f, 2.0f, 1.0f); /* Render all of the images in the texture using coordinates from a CoglPrimitive */ v = verts = g_new (Vert, 4 * TEX_DEPTH); for (i = 0; i < TEX_DEPTH; i++) { float r = (i + 0.5f) / TEX_DEPTH; v->x = i * TEX_WIDTH; v->y = TEX_HEIGHT; v->s = 0; v->t = 0; v->r = r; v++; v->x = i * TEX_WIDTH; v->y = TEX_HEIGHT * 2; v->s = 0; v->t = 1; v->r = r; v++; v->x = i * TEX_WIDTH + TEX_WIDTH; v->y = TEX_HEIGHT * 2; v->s = 1; v->t = 1; v->r = r; v++; v->x = i * TEX_WIDTH + TEX_WIDTH; v->y = TEX_HEIGHT; v->s = 1; v->t = 0; v->r = r; v++; } attribute_buffer = cogl_attribute_buffer_new (test_ctx, 4 * TEX_DEPTH * sizeof (Vert), verts); attributes[0] = cogl_attribute_new (attribute_buffer, "cogl_position_in", sizeof (Vert), G_STRUCT_OFFSET (Vert, x), 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); attributes[1] = cogl_attribute_new (attribute_buffer, "cogl_tex_coord_in", sizeof (Vert), G_STRUCT_OFFSET (Vert, s), 3, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT); primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, 6 * TEX_DEPTH, attributes, 2 /* n_attributes */); cogl_primitive_set_indices (primitive, cogl_get_rectangle_indices (test_ctx, TEX_DEPTH), 6 * TEX_DEPTH); cogl_primitive_draw (primitive, test_fb, pipeline); g_free (verts); cogl_object_unref (primitive); cogl_object_unref (attributes[0]); cogl_object_unref (attributes[1]); cogl_object_unref (attribute_buffer); cogl_object_unref (pipeline); }