Exemple #1
0
void
test_color_mask (void)
{
  TestState state;
  int i;

  state.width = cogl_framebuffer_get_width (test_fb);
  state.height = cogl_framebuffer_get_height (test_fb);

  for (i = 0; i < NUM_FBOS; i++)
    {
      state.tex[i] = test_utils_texture_new_with_size (test_ctx, 128, 128,
                                                 TEST_UTILS_TEXTURE_NO_ATLAS,
                                                 COGL_PIXEL_FORMAT_RGB_888);


      state.fbo[i] = COGL_FRAMEBUFFER (
        cogl_offscreen_new_to_texture (state.tex[i]));

      /* Clear the texture color bits */
      cogl_framebuffer_clear4f (state.fbo[i],
                                COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);

      cogl_framebuffer_set_color_mask (state.fbo[i],
                                       i == 0 ? COGL_COLOR_MASK_RED :
                                       i == 1 ? COGL_COLOR_MASK_GREEN :
                                       COGL_COLOR_MASK_BLUE);
    }

  paint (&state);

  if (cogl_test_verbose ())
    g_print ("OK\n");
}
Exemple #2
0
void
test_path_clip (void)
{
  CoglPath *path;
  CoglPipeline *pipeline;
  int fb_width, fb_height;

  fb_width = cogl_framebuffer_get_width (test_fb);
  fb_height = cogl_framebuffer_get_height (test_fb);

  cogl_framebuffer_orthographic (test_fb,
                                 0, 0, fb_width, fb_height, -1, 100);

  path = cogl_path_new ();

  cogl_framebuffer_clear4f (test_fb,
                            COGL_BUFFER_BIT_COLOR,
                            1.0f, 0.0f, 0.0f, 1.0f);

  /* Make an L-shape with the top right corner left untouched */
  cogl_path_move_to (path, 0, fb_height);
  cogl_path_line_to (path, fb_width, fb_height);
  cogl_path_line_to (path, fb_width, fb_height / 2);
  cogl_path_line_to (path, fb_width / 2, fb_height / 2);
  cogl_path_line_to (path, fb_width / 2, 0);
  cogl_path_line_to (path, 0, 0);
  cogl_path_close (path);

  cogl_framebuffer_push_path_clip (test_fb, path);

  /* Try to fill the framebuffer with a blue rectangle. This should be
   * clipped to leave the top right quadrant as is */
  pipeline = cogl_pipeline_new (test_ctx);
  cogl_pipeline_set_color4ub (pipeline, 0, 0, 255, 255);
  cogl_framebuffer_draw_rectangle (test_fb,
                                   pipeline,
                                   0, 0, fb_width, fb_height);

  cogl_framebuffer_pop_clip (test_fb);

  cogl_object_unref (pipeline);
  cogl_object_unref (path);

  /* Check each of the four quadrants */
  test_utils_check_pixel (test_fb,
                          fb_width / 4, fb_height / 4,
                          0x0000ffff);
  test_utils_check_pixel (test_fb,
                          fb_width * 3 / 4, fb_height / 4,
                          0xff0000ff);
  test_utils_check_pixel (test_fb,
                          fb_width / 4, fb_height * 3 / 4,
                          0x0000ffff);
  test_utils_check_pixel (test_fb,
                          fb_width * 3 / 4, fb_height * 3 / 4,
                          0x0000ffff);

  if (cogl_test_verbose ())
    g_print ("OK\n");
}
Exemple #3
0
void
test_fence (void)
{
  GSource *cogl_source;
  int fb_width = cogl_framebuffer_get_width (test_fb);
  int fb_height = cogl_framebuffer_get_height (test_fb);
  CoglFenceClosure *closure;

  cogl_source = cogl_glib_source_new (test_ctx, G_PRIORITY_DEFAULT);
  g_source_attach (cogl_source, NULL);
  loop = g_main_loop_new (NULL, TRUE);

  cogl_framebuffer_orthographic (test_fb, 0, 0, fb_width, fb_height, -1, 100);
  cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR,
                            0.0f, 1.0f, 0.0f, 0.0f);

  closure = cogl_framebuffer_add_fence_callback (test_fb,
                                                 callback,
                                                 MAGIC_CHUNK_O_DATA);
  g_assert (closure != NULL);

  g_timeout_add_seconds (5, timeout, NULL);

  g_main_loop_run (loop);

  if (cogl_test_verbose ())
    g_print ("OK\n");
}
Exemple #4
0
static void
test_multi_texture (TestState *state)
{
  CoglPipeline *pipeline;
  CoglTexture3D *tex_3d;
  CoglTexture2D *tex_2d;
  uint8_t tex_data[4];

  cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);

  /* Tests a pipeline that is using multi-texturing to combine a 3D
     texture with a 2D texture. The texture from another layer is
     sampled with TEXTURE_? just to pick up a specific bug that was
     happening with the ARBfp fragend */

  pipeline = cogl_pipeline_new (test_ctx);

  tex_data[0] = 0xff;
  tex_data[1] = 0x00;
  tex_data[2] = 0x00;
  tex_data[3] = 0xff;
  tex_2d = cogl_texture_2d_new_from_data (test_ctx,
                                          1, 1, /* width/height */
                                          COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                          4, /* rowstride */
                                          tex_data,
                                          NULL);
  cogl_pipeline_set_layer_texture (pipeline, 0, tex_2d);

  tex_data[0] = 0x00;
  tex_data[1] = 0xff;
  tex_data[2] = 0x00;
  tex_data[3] = 0xff;
  tex_3d = cogl_texture_3d_new_from_data (test_ctx,
                                          1, 1, 1, /* width/height/depth */
                                          COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                          4, /* rowstride */
                                          4, /* image_stride */
                                          tex_data,
                                          NULL);
  cogl_pipeline_set_layer_texture (pipeline, 1, tex_3d);

  cogl_pipeline_set_layer_combine (pipeline, 0,
                                   "RGBA = REPLACE(PREVIOUS)",
                                   NULL);
  cogl_pipeline_set_layer_combine (pipeline, 1,
                                   "RGBA = ADD(TEXTURE_0, TEXTURE_1)",
                                   NULL);

  cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 10, 10);

  test_utils_check_pixel (test_fb, 5, 5, 0xffff00ff);

  cogl_object_unref (tex_2d);
  cogl_object_unref (tex_3d);
  cogl_object_unref (pipeline);
}
static void
paint (TestState *state)
{
  cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);

  test_float_verts (state, 0, 0);
  test_byte_verts (state, 0, 10);
  test_short_verts (state, 0, 20);
}
Exemple #6
0
void
test_point_size (void)
{
    int fb_width = cogl_framebuffer_get_width (test_fb);
    int fb_height = cogl_framebuffer_get_height (test_fb);
    int point_size;
    int x_pos;

    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, 0.0f, 0.0f, 1.0f);

    /* Try a rendering a single point with a few different point
       sizes */
    for (x_pos = 0, point_size = MAX_POINT_SIZE;
            point_size >= 4;
            x_pos += POINT_BOX_SIZE, point_size /= 2)
    {
        CoglPipeline *pipeline = cogl_pipeline_new (test_ctx);
        CoglVertexP2 point = { x_pos + POINT_BOX_SIZE / 2,
                               POINT_BOX_SIZE / 2
                             };
        CoglPrimitive *prim =
            cogl_primitive_new_p2 (test_ctx,
                                   COGL_VERTICES_MODE_POINTS,
                                   1, /* n_vertices */
                                   &point);

        cogl_pipeline_set_point_size (pipeline, point_size);
        cogl_pipeline_set_color4ub (pipeline, 0, 255, 0, 255);
        cogl_framebuffer_draw_primitive (test_fb,
                                         pipeline,
                                         prim);

        cogl_object_unref (prim);
        cogl_object_unref (pipeline);
    }

    /* Verify all of the points where drawn at the right size */
    for (x_pos = 0, point_size = MAX_POINT_SIZE;
            point_size >= 4;
            x_pos += POINT_BOX_SIZE, point_size /= 2)
        verify_point_size (test_fb,
                           x_pos + POINT_BOX_SIZE / 2,
                           POINT_BOX_SIZE / 2,
                           point_size);

    if (cogl_test_verbose ())
        g_print ("OK\n");
}
Exemple #7
0
static void
paint (TestState *state)
{
  cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);

  paint_color_pipelines (state);
  paint_matrix_pipeline (state->matrix_pipeline);
  paint_vector_pipeline (state->vector_pipeline);
  paint_int_pipeline (state->int_pipeline);
}
Exemple #8
0
static void
paint (TestState *state)
{
  CoglPipeline *white = cogl_pipeline_new (test_ctx);
  int i;

  cogl_pipeline_set_color4f (white, 1, 1, 1, 1);


  cogl_framebuffer_draw_rectangle (state->fbo[0],
                                   white,
                                   -1.0, -1.0, 1.0, 1.0);

  cogl_framebuffer_draw_rectangle (state->fbo[1],
                                   white,
                                   -1.0, -1.0, 1.0, 1.0);

  cogl_framebuffer_draw_rectangle (state->fbo[2],
                                   white,
                                   -1.0, -1.0, 1.0, 1.0);

  cogl_object_unref (white);

  cogl_framebuffer_clear4f (test_fb,
                            COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH,
                            0.5, 0.5, 0.5, 1.0);

  /* Render all of the textures to the screen */
  for (i = 0; i < NUM_FBOS; i++)
    {
      CoglPipeline *pipeline = cogl_pipeline_new (test_ctx);
      cogl_pipeline_set_layer_texture (pipeline, 0, state->tex[i]);
      cogl_framebuffer_draw_rectangle (test_fb, pipeline,
                                       2.0f / NUM_FBOS * i - 1.0f, -1.0f,
                                       2.0f / NUM_FBOS * (i + 1) - 1.0f, 1.0f);
      cogl_object_unref (pipeline);
    }

  /* Verify all of the fbos drew the right color */
  for (i = 0; i < NUM_FBOS; i++)
    {
      uint8_t expected_colors[NUM_FBOS][4] =
        { { 0xff, 0x00, 0x00, 0xff },
          { 0x00, 0xff, 0x00, 0xff },
          { 0x00, 0x00, 0xff, 0xff } };

      test_utils_check_pixel_rgb (test_fb,
                                  state->width * (i + 0.5f) / NUM_FBOS,
                                  state->height / 2,
                                  expected_colors[i][0],
                                  expected_colors[i][1],
                                  expected_colors[i][2]);
    }
}
Exemple #9
0
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 */
}
Exemple #10
0
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_framebuffer_draw_primitive (fb, data->crate_pipeline, data->prim);

  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);
}
Exemple #11
0
static void
paint (TestState *state)
{
  CoglPipeline *pipeline = cogl_pipeline_new (test_ctx);
  CoglTexture *tex;
  CoglError *error = NULL;
  CoglSnippet *snippet;

  cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);

  /* Set the primary vertex color as red */
  cogl_pipeline_set_color4f (pipeline, 1, 0, 0, 1);

  /* Override the vertex color in the texture environment with a
     constant green color provided by a texture */
  tex = create_dummy_texture ();
  cogl_pipeline_set_layer_texture (pipeline, 0, tex);
  cogl_object_unref (tex);
  if (!cogl_pipeline_set_layer_combine (pipeline, 0,
                                        "RGBA=REPLACE(TEXTURE)",
                                        &error))
    {
      g_warning ("Error setting layer combine: %s", error->message);
      g_assert_not_reached ();
    }

  /* Set up a dummy vertex shader that does nothing but the usual
     modelview-projection transform */
  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
                              NULL, /* no declarations */
                              NULL); /* no "post" code */
  cogl_snippet_set_replace (snippet,
                            "  cogl_position_out = "
                            "cogl_modelview_projection_matrix * "
                            "cogl_position_in;\n"
                            "  cogl_color_out = cogl_color_in;\n"
                            "  cogl_tex_coord0_out = cogl_tex_coord_in;\n");

  /* Draw something without the snippet */
  cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 50, 50);

  /* Draw it again using the snippet. It should look exactly the same */
  cogl_pipeline_add_snippet (pipeline, snippet);
  cogl_object_unref (snippet);

  cogl_framebuffer_draw_rectangle (test_fb, pipeline, 50, 0, 100, 50);

  cogl_object_unref (pipeline);
}
Exemple #12
0
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));
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #15
0
void
rut_camera_flush (RutCamera *camera)
{
  _rut_camera_flush_transforms (camera);

  if (camera->clear_fb)
    {
      cogl_framebuffer_clear4f (camera->fb,
                                COGL_BUFFER_BIT_COLOR |
                                COGL_BUFFER_BIT_DEPTH |
                                COGL_BUFFER_BIT_STENCIL,
                                cogl_color_get_red_float (&camera->bg_color),
                                cogl_color_get_green_float (&camera->bg_color),
                                cogl_color_get_blue_float (&camera->bg_color),
                                cogl_color_get_alpha_float (&camera->bg_color));
    }
}
Exemple #16
0
int
main (int argc, char **argv)
{
    CoglContext *ctx;
    CoglOnscreen *onscreen;
    CoglFramebuffer *fb;
    CoglPipeline *pipeline;
    GError *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;

    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);
    cogl_onscreen_show (onscreen);
    fb = COGL_FRAMEBUFFER (onscreen);

    triangle = cogl_primitive_new_p2c4 (ctx, COGL_VERTICES_MODE_TRIANGLES,
                                        3, triangle_vertices);

    pipeline = cogl_pipeline_new ();

    for (;;) {
        CoglPollFD *poll_fds;
        int n_poll_fds;
        gint64 timeout;

        cogl_framebuffer_clear4f (fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);
        cogl_framebuffer_draw_primitive (fb, pipeline, triangle);
        cogl_framebuffer_swap_buffers (fb);

        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;
}
Exemple #17
0
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);
}
Exemple #18
0
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 void init()
{
    CoglError *error = NULL;
    CoglDisplay *display;
    CoglRenderer *renderer;
    CoglBool missing_requirement;

    //g_setenv ("COGL_X11_SYNC", "1", 0);

    test_ctx = cogl_context_new (NULL, &error);
    if (!test_ctx) {
        g_message ("Failed to create a CoglContext: %s", error->message);
        exit(1);
    }

    display = cogl_context_get_display (test_ctx);
    renderer = cogl_display_get_renderer (display);

    if (!check_flags (renderer)) {
        g_message ("WARNING: Missing required feature[s] for this test\n");
        exit(1);
    }

    {
        //TODO: get all monitors size to test
        CoglOffscreen *offscreen;
        CoglTexture2D *tex = cogl_texture_2d_new_with_size (test_ctx,
                FB_WIDTH, FB_HEIGHT);
        offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex));
        test_fb = COGL_FRAMEBUFFER (offscreen);
    }

    if (!cogl_framebuffer_allocate (test_fb, &error)) {
        g_message ("Failed to allocate framebuffer: %s", error->message);
        exit(1);
    }

    cogl_framebuffer_clear4f (test_fb,
            COGL_BUFFER_BIT_COLOR |
            COGL_BUFFER_BIT_DEPTH |
            COGL_BUFFER_BIT_STENCIL,
            0, 0, 0, 1);
}
Exemple #20
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);
}
Exemple #21
0
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");
}
Exemple #22
0
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
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);
}
Exemple #24
0
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");
}
static void
paint_test_backface_culling (TestState *state,
                             CoglFramebuffer *framebuffer)
{
  int draw_num;
  CoglPipeline *base_pipeline = cogl_pipeline_new (test_ctx);

  cogl_framebuffer_orthographic (framebuffer,
                                 0, 0,
                                 state->width,
                                 state->height,
                                 -1,
                                 100);

  cogl_framebuffer_clear4f (framebuffer,
                            COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_STENCIL,
                            0, 0, 0, 1);

  cogl_pipeline_set_layer_texture (base_pipeline, 0, state->texture);

  cogl_pipeline_set_layer_filters (base_pipeline, 0,
                                   COGL_PIPELINE_FILTER_NEAREST,
                                   COGL_PIPELINE_FILTER_NEAREST);

  /* Render the scene eight times to test all of the combinations of
     cull face mode and winding orders */
  for (draw_num = 0; draw_num < 8; draw_num++)
    {
      float x1 = 0, x2, y1 = 0, y2 = (float)(TEXTURE_RENDER_SIZE);
      CoglTextureVertex verts[4];
      CoglPipeline *pipeline;

      cogl_framebuffer_push_matrix (framebuffer);
      cogl_framebuffer_translate (framebuffer,
                                  0, TEXTURE_RENDER_SIZE * draw_num, 0);

      pipeline = cogl_pipeline_copy (base_pipeline);

      cogl_pipeline_set_front_face_winding (pipeline, FRONT_WINDING (draw_num));
      cogl_pipeline_set_cull_face_mode (pipeline, CULL_FACE_MODE (draw_num));

      memset (verts, 0, sizeof (verts));

      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a front-facing texture */
      cogl_framebuffer_draw_rectangle (framebuffer, pipeline, x1, y1, x2, y2);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a front-facing texture with flipped texcoords */
      cogl_framebuffer_draw_textured_rectangle (framebuffer,
                                                pipeline,
                                                x1, y1, x2, y2,
                                                1.0, 0.0, 0.0, 1.0);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a back-facing texture */
      cogl_framebuffer_draw_rectangle (framebuffer, pipeline, x2, y1, x1, y2);

      cogl_framebuffer_pop_matrix (framebuffer);

      cogl_object_unref (pipeline);
    }

  cogl_object_unref (base_pipeline);
}
Exemple #26
0
Fichier : msaa.c Projet : jsdir/_
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;
}
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);
}