2 #include <cogl-pango/cogl-pango.h>
4 /* The state for this example... */
9 int framebuffer_height;
16 CoglPipeline *crate_pipeline;
18 CoglPangoFontMap *pango_font_map;
19 PangoContext *pango_context;
20 PangoFontDescription *pango_font_desc;
22 PangoLayout *hello_label;
23 int hello_label_width;
24 int hello_label_height;
32 /* A static identity matrix initialized for convenience. */
33 static CoglMatrix identity;
34 /* static colors initialized for convenience. */
35 static CoglColor white;
37 /* A cube modelled using 4 vertices for each face.
39 * We use an index buffer when drawing the cube later so the GPU will
40 * actually read each face as 2 separate triangles.
42 static CoglVertexP3T2 vertices[] =
45 { /* pos = */ -1.0f, -1.0f, 1.0f, /* tex coords = */ 0.0f, 1.0f},
46 { /* pos = */ 1.0f, -1.0f, 1.0f, /* tex coords = */ 1.0f, 1.0f},
47 { /* pos = */ 1.0f, 1.0f, 1.0f, /* tex coords = */ 1.0f, 0.0f},
48 { /* pos = */ -1.0f, 1.0f, 1.0f, /* tex coords = */ 0.0f, 0.0f},
51 { /* pos = */ -1.0f, -1.0f, -1.0f, /* tex coords = */ 1.0f, 0.0f},
52 { /* pos = */ -1.0f, 1.0f, -1.0f, /* tex coords = */ 1.0f, 1.0f},
53 { /* pos = */ 1.0f, 1.0f, -1.0f, /* tex coords = */ 0.0f, 1.0f},
54 { /* pos = */ 1.0f, -1.0f, -1.0f, /* tex coords = */ 0.0f, 0.0f},
57 { /* pos = */ -1.0f, 1.0f, -1.0f, /* tex coords = */ 0.0f, 1.0f},
58 { /* pos = */ -1.0f, 1.0f, 1.0f, /* tex coords = */ 0.0f, 0.0f},
59 { /* pos = */ 1.0f, 1.0f, 1.0f, /* tex coords = */ 1.0f, 0.0f},
60 { /* pos = */ 1.0f, 1.0f, -1.0f, /* tex coords = */ 1.0f, 1.0f},
63 { /* pos = */ -1.0f, -1.0f, -1.0f, /* tex coords = */ 1.0f, 1.0f},
64 { /* pos = */ 1.0f, -1.0f, -1.0f, /* tex coords = */ 0.0f, 1.0f},
65 { /* pos = */ 1.0f, -1.0f, 1.0f, /* tex coords = */ 0.0f, 0.0f},
66 { /* pos = */ -1.0f, -1.0f, 1.0f, /* tex coords = */ 1.0f, 0.0f},
69 { /* pos = */ 1.0f, -1.0f, -1.0f, /* tex coords = */ 1.0f, 0.0f},
70 { /* pos = */ 1.0f, 1.0f, -1.0f, /* tex coords = */ 1.0f, 1.0f},
71 { /* pos = */ 1.0f, 1.0f, 1.0f, /* tex coords = */ 0.0f, 1.0f},
72 { /* pos = */ 1.0f, -1.0f, 1.0f, /* tex coords = */ 0.0f, 0.0f},
75 { /* pos = */ -1.0f, -1.0f, -1.0f, /* tex coords = */ 0.0f, 0.0f},
76 { /* pos = */ -1.0f, -1.0f, 1.0f, /* tex coords = */ 1.0f, 0.0f},
77 { /* pos = */ -1.0f, 1.0f, 1.0f, /* tex coords = */ 1.0f, 1.0f},
78 { /* pos = */ -1.0f, 1.0f, -1.0f, /* tex coords = */ 0.0f, 1.0f}
84 CoglFramebuffer *fb = data->fb;
87 cogl_framebuffer_clear4f (fb,
88 COGL_BUFFER_BIT_COLOR|COGL_BUFFER_BIT_DEPTH,
91 cogl_framebuffer_push_matrix (fb);
93 cogl_framebuffer_translate (fb,
94 data->framebuffer_width / 2,
95 data->framebuffer_height / 2,
98 cogl_framebuffer_scale (fb, 75, 75, 75);
100 /* Update the rotation based on the time the application has been
101 running so that we get a linear animation regardless of the frame
103 rotation = g_timer_elapsed (data->timer, NULL) * 60.0f;
105 /* Rotate the cube separately around each axis.
107 * Note: Cogl matrix manipulation follows the same rules as for
108 * OpenGL. We use column-major matrices and - if you consider the
109 * transformations happening to the model - then they are combined
110 * in reverse order which is why the rotation is done last, since
111 * we want it to be a rotation around the origin, before it is
112 * scaled and translated.
114 cogl_framebuffer_rotate (fb, rotation, 0, 0, 1);
115 cogl_framebuffer_rotate (fb, rotation, 0, 1, 0);
116 cogl_framebuffer_rotate (fb, rotation, 1, 0, 0);
118 cogl_framebuffer_draw_primitive (fb, data->crate_pipeline, data->prim);
120 cogl_framebuffer_pop_matrix (fb);
122 /* And finally render our Pango layouts... */
124 cogl_pango_render_layout (data->hello_label,
125 (data->framebuffer_width / 2) -
126 (data->hello_label_width / 2),
127 (data->framebuffer_height / 2) -
128 (data->hello_label_height / 2),
133 swap_notify_cb (CoglFramebuffer *framebuffer,
136 Data *data = user_data;
138 data->swap_ready = TRUE;
142 main (int argc, char **argv)
145 CoglOnscreen *onscreen;
147 GError *error = NULL;
149 PangoRectangle hello_label_size;
150 float fovy, aspect, z_near, z_2d, z_far;
151 CoglDepthState depth_state;
152 gboolean has_swap_notify;
154 ctx = cogl_context_new (NULL, &error);
156 fprintf (stderr, "Failed to create context: %s\n", error->message);
160 onscreen = cogl_onscreen_new (ctx, 640, 480);
161 fb = COGL_FRAMEBUFFER (onscreen);
163 data.framebuffer_width = cogl_framebuffer_get_width (fb);
164 data.framebuffer_height = cogl_framebuffer_get_height (fb);
166 data.timer = g_timer_new ();
168 cogl_onscreen_show (onscreen);
170 cogl_push_framebuffer (fb);
171 cogl_set_viewport (0, 0, data.framebuffer_width, data.framebuffer_height);
173 fovy = 60; /* y-axis field of view */
174 aspect = (float)data.framebuffer_width/(float)data.framebuffer_height;
175 z_near = 0.1; /* distance to near clipping plane */
176 z_2d = 1000; /* position to 2d plane */
177 z_far = 2000; /* distance to far clipping plane */
179 cogl_perspective (fovy, aspect, z_near, z_far);
181 /* Since the pango renderer emits geometry in pixel/device coordinates
182 * and the anti aliasing is implemented with the assumption that the
183 * geometry *really* does end up pixel aligned, we setup a modelview
184 * matrix so that for geometry in the plane z = 0 we exactly map x
185 * coordinates in the range [0,stage_width] and y coordinates in the
186 * range [0,stage_height] to the framebuffer extents with (0,0) being
189 * This is roughly what Clutter does for a ClutterStage, but this
190 * demonstrates how it is done manually using Cogl.
192 cogl_matrix_init_identity (&data.view);
193 cogl_matrix_view_2d_in_perspective (&data.view, fovy, aspect, z_near, z_2d,
194 data.framebuffer_width,
195 data.framebuffer_height);
196 cogl_set_modelview_matrix (&data.view);
197 cogl_pop_framebuffer ();
199 /* Initialize some convenient constants */
200 cogl_matrix_init_identity (&identity);
201 cogl_color_set_from_4ub (&white, 0xff, 0xff, 0xff, 0xff);
203 /* rectangle indices allow the GPU to interpret a list of quads (the
204 * faces of our cube) as a list of triangles.
206 * Since this is a very common thing to do
207 * cogl_get_rectangle_indices() is a convenience function for
208 * accessing internal index buffers that can be shared.
210 data.indices = cogl_get_rectangle_indices (ctx, 6 /* n_rectangles */);
211 data.prim = cogl_primitive_new_p3t2 (ctx, COGL_VERTICES_MODE_TRIANGLES,
212 G_N_ELEMENTS (vertices),
214 /* Each face will have 6 indices so we have 6 * 6 indices in total... */
215 cogl_primitive_set_indices (data.prim,
219 /* Load a jpeg crate texture from a file */
220 printf ("crate.jpg (CC by-nc-nd http://bit.ly/9kP45T) ShadowRunner27 http://bit.ly/m1YXLh\n");
221 data.texture = cogl_texture_new_from_file (COGL_EXAMPLES_DATA "crate.jpg",
222 COGL_TEXTURE_NO_SLICING,
223 COGL_PIXEL_FORMAT_ANY,
226 g_error ("Failed to load texture: %s", error->message);
228 /* a CoglPipeline conceptually describes all the state for vertex
229 * processing, fragment processing and blending geometry. When
230 * drawing the geometry for the crate this pipeline says to sample a
231 * single texture during fragment processing... */
232 data.crate_pipeline = cogl_pipeline_new (ctx);
233 cogl_pipeline_set_layer_texture (data.crate_pipeline, 0, data.texture);
235 /* Since the box is made of multiple triangles that will overlap
236 * when drawn and we don't control the order they are drawn in, we
237 * enable depth testing to make sure that triangles that shouldn't
238 * be visible get culled by the GPU. */
239 cogl_depth_state_init (&depth_state);
240 cogl_depth_state_set_test_enabled (&depth_state, TRUE);
242 cogl_pipeline_set_depth_state (data.crate_pipeline, &depth_state, NULL);
244 /* Setup a Pango font map and context */
246 data.pango_font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new());
248 cogl_pango_font_map_set_use_mipmapping (data.pango_font_map, TRUE);
250 data.pango_context = cogl_pango_font_map_create_context (data.pango_font_map);
252 data.pango_font_desc = pango_font_description_new ();
253 pango_font_description_set_family (data.pango_font_desc, "Sans");
254 pango_font_description_set_size (data.pango_font_desc, 30 * PANGO_SCALE);
256 /* Setup the "Hello Cogl" text */
258 data.hello_label = pango_layout_new (data.pango_context);
259 pango_layout_set_font_description (data.hello_label, data.pango_font_desc);
260 pango_layout_set_text (data.hello_label, "Hello Cogl", -1);
262 pango_layout_get_extents (data.hello_label, NULL, &hello_label_size);
263 data.hello_label_width = PANGO_PIXELS (hello_label_size.width);
264 data.hello_label_height = PANGO_PIXELS (hello_label_size.height);
266 cogl_push_framebuffer (fb);
268 data.swap_ready = TRUE;
271 cogl_has_feature (ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT);
274 cogl_onscreen_add_swap_buffers_callback (COGL_ONSCREEN (fb),
280 CoglPollFD *poll_fds;
287 cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
290 cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout);
292 if (!has_swap_notify)
294 /* If the winsys doesn't support swap event notification
295 then we'll just redraw constantly */
296 data.swap_ready = TRUE;
300 g_poll ((GPollFD *) poll_fds, n_poll_fds,
301 timeout == -1 ? -1 : timeout / 1000);
303 cogl_poll_dispatch (ctx, poll_fds, n_poll_fds);