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 CoglBool paint_cb (void *user_data) { Data *data = user_data; cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_framebuffer_draw_primitive (data->fb, data->pipeline, data->triangle); cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); return FALSE; /* remove the callback */ }
static void clutter_stage_win32_redraw (ClutterStageWindow *stage_window) { ClutterStageWin32 *stage_win32 = CLUTTER_STAGE_WIN32 (stage_window); /* this will cause the stage implementation to be painted */ _clutter_stage_do_paint (stage_win32->wrapper, NULL); cogl_flush (); if (stage_win32->onscreen) cogl_onscreen_swap_buffers (COGL_FRAMEBUFFER (stage_win32->onscreen)); }
static gboolean paint_cb (void *user_data) { Data *data = user_data; double elapsed = g_timer_elapsed (data->timer, NULL); double dt = elapsed - data->last_elapsed; GError *error = NULL; /* 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); } gears_draw (); cogl_pop_gles2_context (data->ctx); cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); /* advance rotation for next frame */ angle += 70.0 * dt; /* 70 degrees per second */ if (angle > 3600.0) angle -= 3600.0; data->frames++; if (elapsed > 5.0) { GLfloat fps = data->frames / elapsed; printf ("%d frames in %3.1f seconds = %6.3f FPS\n", data->frames, elapsed, fps); g_timer_reset (data->timer); data->last_elapsed = 0; data->frames = 0; }else data->last_elapsed = elapsed; /* If the driver can deliver swap complete events then we can remove * the idle paint callback until we next get a swap complete event * otherwise we keep the idle paint callback installed and simply * paint as fast as the driver will allow... */ if (cogl_has_feature (data->ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT)) return FALSE; /* remove the callback */ else return TRUE; }
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 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 = COGL_FRAMEBUFFER (output->onscreen); GList *l2; cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_framebuffer_draw_primitive (fb, compositor->triangle_pipeline, compositor->triangle); for (l2 = compositor->surfaces; l2; l2 = l2->next) { CoglandSurface *surface = l2->data; if (surface->buffer) { CoglTexture2D *texture = surface->buffer->texture; CoglPipeline *pipeline = cogl_pipeline_new (compositor->cogl_context); cogl_pipeline_set_layer_texture (pipeline, 0, COGL_TEXTURE (texture)); cogl_framebuffer_draw_rectangle (fb, pipeline, -1, 1, 1, -1); cogl_object_unref (pipeline); } } cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb)); } while (!g_queue_is_empty (&compositor->frame_callbacks)) { CoglandFrameCallback *callback = g_queue_peek_head (&compositor->frame_callbacks); wl_resource_post_event (&callback->resource, WL_CALLBACK_DONE, get_time ()); wl_resource_destroy (&callback->resource, 0); } return TRUE; }
static CoglBool paint_cb (void *user_data) { Data *data = user_data; cogl_framebuffer_clear4f (data->fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_framebuffer_draw_primitive (data->fb, data->pipeline, data->triangle); cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); /* If the driver can deliver swap complete events then we can remove * the idle paint callback until we next get a swap complete event * otherwise we keep the idle paint callback installed and simply * paint as fast as the driver will allow... */ if (cogl_has_feature (data->ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT)) return FALSE; /* remove the callback */ else return TRUE; }
static gboolean paint_cb (void *user_data) { Data *data = user_data; double elapsed = g_timer_elapsed (data->timer, NULL); double dt = elapsed - data->last_elapsed; CoglError *error = NULL; /* 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); } gears_draw (); cogl_pop_gles2_context (data->ctx); cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); /* advance rotation for next frame */ angle += 70.0 * dt; /* 70 degrees per second */ if (angle > 3600.0) angle -= 3600.0; data->frames++; if (elapsed > 5.0) { GLfloat fps = data->frames / elapsed; printf ("%d frames in %3.1f seconds = %6.3f FPS\n", data->frames, elapsed, fps); g_timer_reset (data->timer); data->last_elapsed = 0; data->frames = 0; }else data->last_elapsed = elapsed; return FALSE; /* remove the callback */ }
int main (int argc, char **argv) { CoglOnscreenTemplate *onscreen_template; CoglDisplay *display; CoglContext *ctx; CoglOnscreen *onscreen; CoglFramebuffer *fb; CoglError *error = NULL; CoglVertexP2C4 triangle_vertices[] = { {0, 0.7, 0xff, 0x00, 0x00, 0x80}, {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} }; CoglPrimitive *triangle; CoglTexture *tex; CoglOffscreen *offscreen; CoglFramebuffer *offscreen_fb; CoglPipeline *pipeline; onscreen_template = cogl_onscreen_template_new (NULL); cogl_onscreen_template_set_samples_per_pixel (onscreen_template, 4); display = cogl_display_new (NULL, onscreen_template); if (!cogl_display_setup (display, &error)) { fprintf (stderr, "Platform doesn't support onscreen 4x msaa rendering: %s\n", error->message); return 1; } ctx = cogl_context_new (display, &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); cogl_framebuffer_set_samples_per_pixel (fb, 4); if (!cogl_framebuffer_allocate (fb, &error)) { fprintf (stderr, "Failed to allocate 4x msaa offscreen framebuffer, " "disabling msaa for onscreen rendering: %s\n", error->message); cogl_error_free (error); cogl_framebuffer_set_samples_per_pixel (fb, 0); error = NULL; if (!cogl_framebuffer_allocate (fb, &error)) { fprintf (stderr, "Failed to allocate framebuffer: %s\n", error->message); return 1; } } cogl_onscreen_show (onscreen); tex = cogl_texture_new_with_size (ctx, 320, 480, COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY); offscreen = cogl_offscreen_new_to_texture (tex); offscreen_fb = COGL_FRAMEBUFFER (offscreen); cogl_framebuffer_set_samples_per_pixel (offscreen_fb, 4); if (!cogl_framebuffer_allocate (offscreen_fb, &error)) { cogl_error_free (error); error = NULL; fprintf (stderr, "Failed to allocate 4x msaa offscreen framebuffer, " "disabling msaa for offscreen rendering"); cogl_framebuffer_set_samples_per_pixel (offscreen_fb, 0); } triangle = cogl_primitive_new_p2c4 (ctx, COGL_VERTICES_MODE_TRIANGLES, 3, triangle_vertices); pipeline = cogl_pipeline_new (ctx); for (;;) { CoglPollFD *poll_fds; int n_poll_fds; int64_t timeout; CoglPipeline *texture_pipeline; cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1); cogl_framebuffer_push_matrix (fb); cogl_framebuffer_scale (fb, 0.5, 1, 1); cogl_framebuffer_translate (fb, -1, 0, 0); cogl_framebuffer_draw_primitive (fb, pipeline, triangle); cogl_framebuffer_pop_matrix (fb); cogl_framebuffer_draw_primitive (fb, pipeline, triangle); cogl_framebuffer_resolve_samples (offscreen_fb); texture_pipeline = cogl_pipeline_new (ctx); cogl_pipeline_set_layer_texture (texture_pipeline, 0, tex); cogl_framebuffer_draw_rectangle (fb, texture_pipeline, 0, 1, 1, -1); cogl_object_unref (texture_pipeline); cogl_onscreen_swap_buffers (onscreen); cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout); g_poll ((GPollFD *) poll_fds, n_poll_fds, 0); cogl_poll_dispatch (ctx, poll_fds, n_poll_fds); } return 0; }
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 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 (Data *data) { /* The cogl pipeline needs to be retrieved from the sink before every draw. This is due to the cogl-gst sink creating a new cogl pipeline for each frame by copying the previous one and attaching the new frame to it. */ CoglPipeline* current = cogl_gst_video_sink_get_pipeline (data->sink); data->video_pipeline = current; if (data->video_output.x) { int x = data->video_output.x; /* Letterboxed with vertical borders */ cogl_framebuffer_draw_rectangle (data->fb, data->border_pipeline, 0, 0, x, data->onscreen_height); cogl_framebuffer_draw_rectangle (data->fb, data->border_pipeline, data->onscreen_width - x, 0, data->onscreen_width, data->onscreen_height); cogl_framebuffer_draw_rectangle (data->fb, data->video_pipeline, x, 0, x + data->video_output.width, data->onscreen_height); } else if (data->video_output.y) { int y = data->video_output.y; /* Letterboxed with horizontal borders */ cogl_framebuffer_draw_rectangle (data->fb, data->border_pipeline, 0, 0, data->onscreen_width, y); cogl_framebuffer_draw_rectangle (data->fb, data->border_pipeline, 0, data->onscreen_height - y, data->onscreen_width, data->onscreen_height); cogl_framebuffer_draw_rectangle (data->fb, data->video_pipeline, 0, y, data->onscreen_width, y + data->video_output.height); } else { cogl_framebuffer_draw_rectangle (data->fb, data->video_pipeline, 0, 0, data->onscreen_width, data->onscreen_height); } cogl_onscreen_swap_buffers (COGL_ONSCREEN (data->fb)); }