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 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 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) { Data data; CoglOnscreen *onscreen; GError *error = NULL; GSource *cogl_source; GMainLoop *loop; CoglRenderer *renderer; CoglDisplay *display; renderer = cogl_renderer_new (); cogl_renderer_add_constraint (renderer, COGL_RENDERER_CONSTRAINT_SUPPORTS_COGL_GLES2); display = cogl_display_new (renderer, NULL); data.ctx = cogl_context_new (display, NULL); onscreen = cogl_onscreen_new (data.ctx, 300, 300); cogl_onscreen_show (onscreen); data.fb = COGL_FRAMEBUFFER (onscreen); data.gles2_ctx = cogl_gles2_context_new (data.ctx, &error); if (!data.gles2_ctx) g_error ("Failed to create GLES2 context: %s\n", error->message); /* 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_reshape (cogl_framebuffer_get_width (data.fb), cogl_framebuffer_get_height (data.fb)); /* Initialize the gears */ gears_init(); cogl_pop_gles2_context (data.ctx); cogl_source = cogl_glib_source_new (data.ctx, G_PRIORITY_DEFAULT); g_source_attach (cogl_source, NULL); if (cogl_has_feature (data.ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT)) cogl_onscreen_add_swap_buffers_callback (COGL_ONSCREEN (data.fb), swap_complete_cb, &data); g_idle_add (paint_cb, &data); data.timer = g_timer_new (); data.frames = 0; data.last_elapsed = 0; loop = g_main_loop_new (NULL, TRUE); g_main_loop_run (loop); return 0; }
int main (int argc, char **argv) { Data data; CoglOnscreen *onscreen; CoglError *error = NULL; CoglVertexP2C4 triangle_vertices[] = { {0, 0.7, 0xff, 0x00, 0x00, 0xff}, {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff}, {0.7, -0.7, 0x00, 0x00, 0xff, 0xff} }; GSource *cogl_source; GMainLoop *loop; CoglRenderer *renderer; CoglDisplay *display; renderer = cogl_renderer_new (); cogl_renderer_add_constraint (renderer, COGL_RENDERER_CONSTRAINT_SUPPORTS_COGL_GLES2); display = cogl_display_new (renderer, NULL); data.ctx = cogl_context_new (display, NULL); onscreen = cogl_onscreen_new (data.ctx, 640, 480); cogl_onscreen_show (onscreen); data.fb = COGL_FRAMEBUFFER (onscreen); /* Prepare onscreen primitive */ data.triangle = cogl_primitive_new_p2c4 (data.ctx, COGL_VERTICES_MODE_TRIANGLES, 3, triangle_vertices); data.pipeline = cogl_pipeline_new (data.ctx); data.offscreen_texture = COGL_TEXTURE ( cogl_texture_2d_new_with_size (data.ctx, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT, COGL_PIXEL_FORMAT_ANY)); data.offscreen = cogl_offscreen_new_to_texture (data.offscreen_texture); data.gles2_ctx = cogl_gles2_context_new (data.ctx, &error); if (!data.gles2_ctx) { g_error ("Failed to create GLES2 context: %s\n", error->message); } data.gles2_vtable = cogl_gles2_context_get_vtable (data.gles2_ctx); /* 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); } cogl_pop_gles2_context (data.ctx); cogl_source = cogl_glib_source_new (data.ctx, G_PRIORITY_DEFAULT); g_source_attach (cogl_source, NULL); cogl_onscreen_add_frame_callback (COGL_ONSCREEN (data.fb), frame_event_cb, &data, NULL); /* destroy notify */ g_idle_add (paint_cb, &data); loop = g_main_loop_new (NULL, TRUE); g_main_loop_run (loop); return 0; }
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); }
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_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); }