int main (int argc, char **argv) { CoglContext *ctx; CoglOnscreen *onscreen; CoglFramebuffer *fb; GError *error = NULL; Data data; PangoRectangle hello_label_size; float fovy, aspect, z_near, z_2d, z_far; CoglDepthState depth_state; CoglBool has_swap_notify; ctx = cogl_context_new (NULL, &error); if (!ctx) { fprintf (stderr, "Failed to create context: %s\n", error->message); return 1; } onscreen = cogl_onscreen_new (ctx, 640, 480); fb = COGL_FRAMEBUFFER (onscreen); data.fb = fb; data.framebuffer_width = cogl_framebuffer_get_width (fb); data.framebuffer_height = cogl_framebuffer_get_height (fb); data.timer = g_timer_new (); cogl_onscreen_show (onscreen); cogl_framebuffer_set_viewport (fb, 0, 0, data.framebuffer_width, data.framebuffer_height); fovy = 60; /* y-axis field of view */ aspect = (float)data.framebuffer_width/(float)data.framebuffer_height; z_near = 0.1; /* distance to near clipping plane */ z_2d = 1000; /* position to 2d plane */ z_far = 2000; /* distance to far clipping plane */ cogl_framebuffer_perspective (fb, fovy, aspect, z_near, z_far); /* Since the pango renderer emits geometry in pixel/device coordinates * and the anti aliasing is implemented with the assumption that the * geometry *really* does end up pixel aligned, we setup a modelview * matrix so that for geometry in the plane z = 0 we exactly map x * coordinates in the range [0,stage_width] and y coordinates in the * range [0,stage_height] to the framebuffer extents with (0,0) being * the top left. * * This is roughly what Clutter does for a ClutterStage, but this * demonstrates how it is done manually using Cogl. */ cogl_matrix_init_identity (&data.view); cogl_matrix_view_2d_in_perspective (&data.view, fovy, aspect, z_near, z_2d, data.framebuffer_width, data.framebuffer_height); cogl_framebuffer_set_modelview_matrix (fb, &data.view); /* Initialize some convenient constants */ cogl_matrix_init_identity (&identity); cogl_color_set_from_4ub (&white, 0xff, 0xff, 0xff, 0xff); /* rectangle indices allow the GPU to interpret a list of quads (the * faces of our cube) as a list of triangles. * * Since this is a very common thing to do * cogl_get_rectangle_indices() is a convenience function for * accessing internal index buffers that can be shared. */ data.indices = cogl_get_rectangle_indices (ctx, 6 /* n_rectangles */); data.prim = cogl_primitive_new_p3t2 (ctx, COGL_VERTICES_MODE_TRIANGLES, G_N_ELEMENTS (vertices), vertices); /* Each face will have 6 indices so we have 6 * 6 indices in total... */ cogl_primitive_set_indices (data.prim, data.indices, 6 * 6); /* Load a jpeg crate texture from a file */ printf ("crate.jpg (CC by-nc-nd http://bit.ly/9kP45T) ShadowRunner27 http://bit.ly/m1YXLh\n"); data.texture = cogl_texture_new_from_file (COGL_EXAMPLES_DATA "crate.jpg", COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY, &error); if (!data.texture) g_error ("Failed to load texture: %s", error->message); /* a CoglPipeline conceptually describes all the state for vertex * processing, fragment processing and blending geometry. When * drawing the geometry for the crate this pipeline says to sample a * single texture during fragment processing... */ data.crate_pipeline = cogl_pipeline_new (ctx); cogl_pipeline_set_layer_texture (data.crate_pipeline, 0, data.texture); /* Since the box is made of multiple triangles that will overlap * when drawn and we don't control the order they are drawn in, we * enable depth testing to make sure that triangles that shouldn't * be visible get culled by the GPU. */ cogl_depth_state_init (&depth_state); cogl_depth_state_set_test_enabled (&depth_state, TRUE); cogl_pipeline_set_depth_state (data.crate_pipeline, &depth_state, NULL); /* Setup a Pango font map and context */ data.pango_font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new (ctx)); cogl_pango_font_map_set_use_mipmapping (data.pango_font_map, TRUE); data.pango_context = pango_font_map_create_context (PANGO_FONT_MAP (data.pango_font_map)); data.pango_font_desc = pango_font_description_new (); pango_font_description_set_family (data.pango_font_desc, "Sans"); pango_font_description_set_size (data.pango_font_desc, 30 * PANGO_SCALE); /* Setup the "Hello Cogl" text */ data.hello_label = pango_layout_new (data.pango_context); pango_layout_set_font_description (data.hello_label, data.pango_font_desc); pango_layout_set_text (data.hello_label, "Hello Cogl", -1); pango_layout_get_extents (data.hello_label, NULL, &hello_label_size); data.hello_label_width = PANGO_PIXELS (hello_label_size.width); data.hello_label_height = PANGO_PIXELS (hello_label_size.height); data.swap_ready = TRUE; has_swap_notify = cogl_has_feature (ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT); if (has_swap_notify) cogl_onscreen_add_swap_buffers_callback (COGL_ONSCREEN (fb), swap_notify_cb, &data); while (1) { CoglPollFD *poll_fds; int n_poll_fds; int64_t timeout; if (data.swap_ready) { paint (&data); cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); } cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout); if (!has_swap_notify) { /* If the winsys doesn't support swap event notification then we'll just redraw constantly */ data.swap_ready = TRUE; timeout = 0; } g_poll ((GPollFD *) poll_fds, n_poll_fds, timeout == -1 ? -1 : timeout / 1000); cogl_poll_dispatch (ctx, poll_fds, n_poll_fds); } return 0; }
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 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); }