Ejemplo n.º 1
0
CoglTexture *
st_cogl_texture_new_with_size_wrapper           (int width,
                                                 int height,
                                    CoglTextureFlags flags,
                                     CoglPixelFormat internal_format)
{
    CoglTexture *texture = NULL;

    if (hardware_supports_npot_sizes ())
      {
        texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (cogl_context,
                                                               width,
                                                               height
#if COGL_VERSION < COGL_VERSION_ENCODE (1, 18, 0)
                                                              ,CLUTTER_CAIRO_FORMAT_ARGB32
#endif
                                                              ));
      }
    else
      {
        texture = cogl_texture_new_with_size (width, height,
                                              flags,
                                              internal_format);
      }

    return texture;
}
Ejemplo n.º 2
0
static void
create_gles2_context (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, NULL);
  if (!*gles2_ctx)
    g_error ("Failed to create GLES2 context: %s\n", error->message);

  *gles2 = cogl_gles2_context_get_vtable (*gles2_ctx);
}
Ejemplo n.º 3
0
static CoglTexture2D *
_cogl_atlas_create_texture (CoglAtlas *atlas,
                            int width,
                            int height)
{
  CoglTexture2D *tex;
  CoglError *ignore_error = NULL;

  _COGL_GET_CONTEXT (ctx, NULL);

  if ((atlas->flags & COGL_ATLAS_CLEAR_TEXTURE))
    {
      uint8_t *clear_data;
      CoglBitmap *clear_bmp;
      int bpp = _cogl_pixel_format_get_bytes_per_pixel (atlas->texture_format);

      /* Create a buffer of zeroes to initially clear the texture */
      clear_data = g_malloc0 (width * height * bpp);
      clear_bmp = cogl_bitmap_new_for_data (ctx,
                                            width,
                                            height,
                                            atlas->texture_format,
                                            width * bpp,
                                            clear_data);

      tex = cogl_texture_2d_new_from_bitmap (clear_bmp);

      _cogl_texture_set_internal_format (COGL_TEXTURE (tex),
                                         atlas->texture_format);

      if (!cogl_texture_allocate (COGL_TEXTURE (tex), &ignore_error))
        {
          cogl_error_free (ignore_error);
          cogl_object_unref (tex);
          tex = NULL;
        }

      cogl_object_unref (clear_bmp);

      g_free (clear_data);
    }
  else
    {
      tex = cogl_texture_2d_new_with_size (ctx, width, height);

      _cogl_texture_set_internal_format (COGL_TEXTURE (tex),
                                         atlas->texture_format);

      if (!cogl_texture_allocate (COGL_TEXTURE (tex), &ignore_error))
        {
          cogl_error_free (ignore_error);
          cogl_object_unref (tex);
          tex = NULL;
        }
    }

  return tex;
}
Ejemplo n.º 4
0
CoglTexture *
cogl_texture_new_with_size (CoglContext *ctx,
                            int width,
			    int height,
                            CoglTextureFlags flags,
			    CoglPixelFormat internal_format)
{
  CoglTexture *tex;
  CoglError *skip_error = NULL;

  if ((_cogl_util_is_pot (width) && _cogl_util_is_pot (height)) ||
      (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
       cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP)))
    {
      /* First try creating a fast-path non-sliced texture */
      tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
                                                         width, height,
                                                         internal_format));

      /* TODO: instead of allocating storage here it would be better
       * if we had some api that let us just check that the size is
       * supported by the hardware so storage could be allocated
       * lazily when uploading data. */
      if (!cogl_texture_allocate (tex, &skip_error))
        {
          cogl_error_free (skip_error);
          cogl_object_unref (tex);
          tex = NULL;
        }
    }
  else
    tex = NULL;

  if (tex)
    {
      CoglBool auto_mipmap = !(flags & COGL_TEXTURE_NO_AUTO_MIPMAP);
      cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (tex),
                                              auto_mipmap);
    }
  else
    {
      /* If it fails resort to sliced textures */
      int max_waste = flags & COGL_TEXTURE_NO_SLICING ? -1 : COGL_TEXTURE_MAX_WASTE;
      cogl_error_free (skip_error);
      tex = COGL_TEXTURE (cogl_texture_2d_sliced_new_with_size (ctx,
                                                                width,
                                                                height,
                                                                max_waste,
                                                                internal_format));
    }

  return tex;
}
Ejemplo n.º 5
0
static CoglTexture *
create_migration_texture (CoglContext *ctx,
                          int width,
                          int height,
                          CoglPixelFormat internal_format)
{
  CoglTexture *tex;
  CoglError *skip_error = NULL;

  if ((_cogl_util_is_pot (width) && _cogl_util_is_pot (height)) ||
      (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
       cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP)))
    {
      /* First try creating a fast-path non-sliced texture */
      tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
                                                         width, height));

      _cogl_texture_set_internal_format (tex, internal_format);

      /* TODO: instead of allocating storage here it would be better
       * if we had some api that let us just check that the size is
       * supported by the hardware so storage could be allocated
       * lazily when uploading data. */
      if (!cogl_texture_allocate (tex, &skip_error))
        {
          cogl_error_free (skip_error);
          cogl_object_unref (tex);
          tex = NULL;
        }
    }
  else
    tex = NULL;

  if (!tex)
    {
      CoglTexture2DSliced *tex_2ds =
        cogl_texture_2d_sliced_new_with_size (ctx,
                                              width,
                                              height,
                                              COGL_TEXTURE_MAX_WASTE);

      _cogl_texture_set_internal_format (COGL_TEXTURE (tex_2ds),
                                         internal_format);

      tex = COGL_TEXTURE (tex_2ds);
    }

  return tex;
}
static CoglTexture * test_texture_new_with_size(CoglContext *ctx,
                                  int width, int height,
                                  CoglTextureComponents components)
{
  CoglTexture *tex;
  CoglError *skip_error = NULL;

  tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, width, height));
  cogl_texture_set_components(tex, components);
  cogl_primitive_texture_set_auto_mipmap(tex, TRUE);

  if (!cogl_texture_allocate(tex, &skip_error)) {
      cogl_error_free(skip_error);
      cogl_object_unref(tex);
      return NULL;
  }

  return tex;
}
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);
}
Ejemplo n.º 8
0
void
test_texture_no_allocate (void)
{
  uint8_t *tex_data;
  CoglTexture *texture;
  CoglTexture2D *texture_2d;
  CoglError *error = NULL;

  tex_data = g_malloc (BIG_TEX_WIDTH * BIG_TEX_HEIGHT * 4);

  /* NB: if we make the atlas and sliced texture APIs public then this
   * could changed to explicitly use that instead of the magic texture
   * API */

  /* Try to create an atlas texture that is too big so it will
   * internally be freed without allocating */
  texture =
    cogl_atlas_texture_new_from_data (test_ctx,
                                      BIG_TEX_WIDTH,
                                      BIG_TEX_HEIGHT,
                                      /* format */
                                      COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                      /* rowstride */
                                      BIG_TEX_WIDTH * 4,
                                      tex_data,
                                      &error);

  g_free (tex_data);

  /* It's ok if this causes an error, we just don't want it to
   * crash */

  if (texture == NULL)
    cogl_error_free (error);
  else
    cogl_object_unref (texture);

  /* Try to create a sliced texture without allocating it */
  texture =
    cogl_texture_2d_sliced_new_with_size (test_ctx,
                                          BIG_TEX_WIDTH,
                                          BIG_TEX_HEIGHT,
                                          COGL_TEXTURE_MAX_WASTE);
  cogl_object_unref (texture);

  /* 2D texture */
  texture_2d = cogl_texture_2d_new_with_size (test_ctx,
                                              64, 64);
  cogl_object_unref (texture_2d);

  /* 3D texture */
  if (cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_3D))
    {
      CoglTexture3D *texture_3d =
        cogl_texture_3d_new_with_size (test_ctx,
                                       64, 64, 64);
      cogl_object_unref (texture_3d);
    }

  /* Rectangle texture */
  if (cogl_has_feature (test_ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE))
    {
      CoglTextureRectangle *texture_rect =
        cogl_texture_rectangle_new_with_size (test_ctx,
                                              64, 64);
      cogl_object_unref (texture_rect);
    }
}
Ejemplo n.º 9
0
CoglTexture *
cogl_texture_new_with_size (unsigned int width,
			    unsigned int height,
                            CoglTextureFlags flags,
			    CoglPixelFormat internal_format)
{
  CoglTexture *tex;
  CoglError *skip_error = NULL;

  _COGL_GET_CONTEXT (ctx, NULL);

  if ((_cogl_util_is_pot (width) && _cogl_util_is_pot (height)) ||
      (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
       cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP)))
    {
      /* First try creating a fast-path non-sliced texture */
      tex = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, width, height));

      _cogl_texture_set_internal_format (tex, internal_format);

      if (!cogl_texture_allocate (tex, &skip_error))
        {
          cogl_error_free (skip_error);
          cogl_object_unref (tex);
          tex = NULL;
        }
    }
  else
    tex = NULL;

  if (!tex)
    {
      /* If it fails resort to sliced textures */
      int max_waste = flags & COGL_TEXTURE_NO_SLICING ? -1 : COGL_TEXTURE_MAX_WASTE;
      tex = COGL_TEXTURE (cogl_texture_2d_sliced_new_with_size (ctx,
                                                                width,
                                                                height,
                                                                max_waste));

      _cogl_texture_set_internal_format (tex, internal_format);
    }

  /* NB: This api existed before Cogl introduced lazy allocation of
   * textures and so we maintain its original synchronous allocation
   * semantics and return NULL if allocation fails... */
  if (!cogl_texture_allocate (tex, &skip_error))
    {
      cogl_error_free (skip_error);
      cogl_object_unref (tex);
      return NULL;
    }

  if (tex &&
      flags & COGL_TEXTURE_NO_AUTO_MIPMAP)
    {
      cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex),
                                           0, 0, 1, 1,
                                           COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
                                           COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE,
                                           set_auto_mipmap_cb,
                                           NULL);
    }

  return tex;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
CoglTexture *
rut_gaussian_blurrer_blur (RutGaussianBlurrer *blurrer,
                           CoglTexture *source)
{
  unsigned int src_w, src_h;
  CoglPixelFormat format;
  CoglOffscreen *offscreen;

  /* create the first FBO to render the x pass */
  src_w = cogl_texture_get_width (source);
  src_h = cogl_texture_get_height (source);
  format = cogl_texture_get_format (source);

  if (blurrer->width != src_w ||
      blurrer->height != src_h ||
      blurrer->format != format)
    {
      _rut_gaussian_blurrer_free_buffers (blurrer);
    }

  if (!blurrer->x_pass)
    {
      CoglError *error = NULL;
      CoglTexture2D *texture_2d =
        cogl_texture_2d_new_with_size (blurrer->ctx->cogl_context,
                                       src_w,
                                       src_h,
                                       format);
      if (error)
        {
          g_warning ("blurrer: could not create x pass texture: %s",
                     error->message);
        }
      blurrer->x_pass = COGL_TEXTURE (texture_2d);
      blurrer->width = src_w;
      blurrer->height = src_h;
      blurrer->format = format;

      offscreen = cogl_offscreen_new_to_texture (blurrer->x_pass);
      blurrer->x_pass_fb = COGL_FRAMEBUFFER (offscreen);
      cogl_framebuffer_orthographic (blurrer->x_pass_fb,
                                     0, 0, src_w, src_h, -1, 100);
    }

  if (!blurrer->y_pass)
    {
      /* create the second FBO (final destination) to render the y pass */
      CoglTexture2D *texture_2d =
        cogl_texture_2d_new_with_size (blurrer->ctx->cogl_context,
                                       src_w,
                                       src_h,
                                       format);
      blurrer->destination = COGL_TEXTURE (texture_2d);
      blurrer->y_pass = blurrer->destination;

      offscreen = cogl_offscreen_new_to_texture (blurrer->destination);
      blurrer->y_pass_fb = COGL_FRAMEBUFFER (offscreen);
      cogl_framebuffer_orthographic (blurrer->y_pass_fb,
                                     0, 0, src_w, src_h, -1, 100);
    }

  set_blurrer_pipeline_texture (blurrer->x_pass_pipeline,
                                source, 1.0f / src_w, 0);
  set_blurrer_pipeline_texture (blurrer->y_pass_pipeline,
                                blurrer->x_pass, 0, 1.0f / src_h);

  /* x pass */
  cogl_framebuffer_draw_rectangle (blurrer->x_pass_fb,
                                   blurrer->x_pass_pipeline,
                                   0,
                                   0,
                                   blurrer->width,
                                   blurrer->height);

  /* y pass */
  cogl_framebuffer_draw_rectangle (blurrer->y_pass_fb,
                                   blurrer->y_pass_pipeline,
                                   0,
                                   0,
                                   blurrer->width,
                                   blurrer->height);

  return cogl_object_ref (blurrer->destination);
}
Ejemplo n.º 12
0
static gboolean
setup_framebuffers (StThemeNodeTransition *transition,
                    const ClutterActorBox *allocation)
{
  ClutterBackend *backend = clutter_get_default_backend ();
  CoglContext *ctx = clutter_backend_get_cogl_context (backend);
  StThemeNodeTransitionPrivate *priv = transition->priv;
  CoglColor clear_color = { 0, 0, 0, 0 };
  guint width, height;

  /* template material to avoid unnecessary shader compilation */
  static CoglHandle material_template = COGL_INVALID_HANDLE;

  width  = priv->offscreen_box.x2 - priv->offscreen_box.x1;
  height = priv->offscreen_box.y2 - priv->offscreen_box.y1;

  g_return_val_if_fail (width  > 0, FALSE);
  g_return_val_if_fail (height > 0, FALSE);

  if (priv->old_texture)
    cogl_handle_unref (priv->old_texture);
  priv->old_texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
                                                                   width,
                                                                   height
#if COGL_VERSION < COGL_VERSION_ENCODE (1, 18, 0)
                                                                   ,COGL_PIXEL_FORMAT_ANY
#endif
                                                                   ));

  if (priv->new_texture)
    cogl_handle_unref (priv->new_texture);
  priv->new_texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
                                                                   width,
                                                                   height
#if COGL_VERSION < COGL_VERSION_ENCODE (1, 18, 0)
                                                                   ,COGL_PIXEL_FORMAT_ANY
#endif
                                                                   ));

  g_return_val_if_fail (priv->old_texture != COGL_INVALID_HANDLE, FALSE);
  g_return_val_if_fail (priv->new_texture != COGL_INVALID_HANDLE, FALSE);

  if (priv->old_offscreen)
    cogl_handle_unref (priv->old_offscreen);
  priv->old_offscreen = cogl_offscreen_new_to_texture (priv->old_texture);

  if (priv->new_offscreen)
    cogl_handle_unref (priv->new_offscreen);
  priv->new_offscreen = cogl_offscreen_new_to_texture (priv->new_texture);

  g_return_val_if_fail (priv->old_offscreen != COGL_INVALID_HANDLE, FALSE);
  g_return_val_if_fail (priv->new_offscreen != COGL_INVALID_HANDLE, FALSE);

  if (priv->material == NULL)
    {
      if (G_UNLIKELY (material_template == COGL_INVALID_HANDLE))
        {
          material_template = cogl_material_new ();

          cogl_material_set_layer_combine (material_template, 0,
                                           "RGBA = REPLACE (TEXTURE)",
                                           NULL);
          cogl_material_set_layer_combine (material_template, 1,
                                           "RGBA = INTERPOLATE (PREVIOUS, "
                                                               "TEXTURE, "
                                                               "CONSTANT[A])",
                                           NULL);
          cogl_material_set_layer_combine (material_template, 2,
                                           "RGBA = MODULATE (PREVIOUS, "
                                                            "PRIMARY)",
                                           NULL);
        }
      priv->material = cogl_material_copy (material_template);
    }

  cogl_material_set_layer (priv->material, 0, priv->new_texture);
  cogl_material_set_layer (priv->material, 1, priv->old_texture);

  cogl_push_framebuffer (priv->old_offscreen);
  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
  cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
              priv->offscreen_box.y2, priv->offscreen_box.y1,
              0.0, 1.0);
  st_theme_node_paint (priv->old_theme_node, allocation, 255);
  cogl_pop_framebuffer ();

  cogl_push_framebuffer (priv->new_offscreen);
  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
  cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
              priv->offscreen_box.y2, priv->offscreen_box.y1,
              0.0, 1.0);
  st_theme_node_paint (priv->new_theme_node, allocation, 255);
  cogl_pop_framebuffer ();

  return TRUE;
}
Ejemplo n.º 13
0
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);
}