Beispiel #1
0
static gboolean
_cogl_blit_framebuffer_begin (CoglBlitData *data)
{
  CoglHandle dst_fbo, src_fbo;
  gboolean ret;

  _COGL_GET_CONTEXT (ctx, FALSE);

  /* We can only blit between FBOs if both textures are the same
     format and the blit framebuffer extension is supported */
  if ((cogl_texture_get_format (data->src_tex) & ~COGL_A_BIT) !=
      (cogl_texture_get_format (data->dst_tex) & ~COGL_A_BIT) ||
      !(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT))
    return FALSE;

  dst_fbo = _cogl_offscreen_new_to_texture_full
    (data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);

  if (dst_fbo == COGL_INVALID_HANDLE)
    ret = FALSE;
  else
    {
      if (!cogl_framebuffer_allocate (dst_fbo, NULL))
        ret = FALSE;
      else
        {
          src_fbo = _cogl_offscreen_new_to_texture_full
            (data->src_tex,
             COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL,
             0 /* level */);

          if (src_fbo == COGL_INVALID_HANDLE)
            ret = FALSE;
          else
            {
              if (!cogl_framebuffer_allocate (src_fbo, NULL))
                ret = FALSE;
              else
                _cogl_push_framebuffers (dst_fbo, src_fbo);

              cogl_handle_unref (src_fbo);
            }
        }

      cogl_handle_unref (dst_fbo);
    }

  return ret;
}
Beispiel #2
0
static VALUE
rb_cogl_texture_get_format (VALUE self)
{
  CoglHandle tex = rb_cogl_texture_get_handle (self);

  return UINT2NUM (cogl_texture_get_format (tex));
}
CoglPipeline *
_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
                                CoglHandle texture)
{
  CoglPangoPipelineCacheEntry *entry;
  PipelineDestroyNotifyData *destroy_data;
  static CoglUserDataKey pipeline_destroy_notify_key;

  /* Look for an existing entry */
  entry = g_hash_table_lookup (cache->hash_table, texture);

  if (entry)
    return cogl_object_ref (entry->pipeline);

  /* No existing pipeline was found so let's create another */
  entry = g_slice_new (CoglPangoPipelineCacheEntry);

  if (texture)
    {
      CoglPipeline *base;

      entry->texture = cogl_object_ref (texture);

      if (cogl_texture_get_format (entry->texture) == COGL_PIXEL_FORMAT_A_8)
        base = get_base_texture_alpha_pipeline (cache);
      else
        base = get_base_texture_rgba_pipeline (cache);

      entry->pipeline = cogl_pipeline_copy (base);

      cogl_pipeline_set_layer_texture (entry->pipeline, 0 /* layer */, texture);
    }
  else
    {
      entry->texture = NULL;
      entry->pipeline = cogl_pipeline_new ();
    }

  /* Add a weak reference to the pipeline so we can remove it from the
     hash table when it is destroyed */
  destroy_data = g_slice_new (PipelineDestroyNotifyData);
  destroy_data->cache = cache;
  destroy_data->texture = texture;
  cogl_object_set_user_data (entry->pipeline,
                             &pipeline_destroy_notify_key,
                             destroy_data,
                             pipeline_destroy_notify_cb);

  g_hash_table_insert (cache->hash_table,
                       texture ? cogl_object_ref (texture) : NULL,
                       entry);

  /* This doesn't take a reference on the pipeline so that it will use
     the newly created reference */
  return entry->pipeline;
}
static CoglPixelFormat
_cogl_texture_pixmap_x11_get_format (CoglTexture *tex)
{
  CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
  CoglHandle child_tex;

  child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);

  /* Forward on to the child texture */
  return cogl_texture_get_format (child_tex);
}
Beispiel #5
0
static gboolean
_cogl_blit_get_tex_data_begin (CoglBlitData *data)
{
  data->format = cogl_texture_get_format (data->src_tex);
  data->bpp = _cogl_get_format_bpp (data->format);

  data->image_data = g_malloc (data->bpp * data->src_width *
                               data->src_height);
  cogl_texture_get_data (data->src_tex, data->format,
                         data->src_width * data->bpp, data->image_data);

  return TRUE;
}
Beispiel #6
0
unsigned int
cogl_texture_get_rowstride (CoglHandle handle)
{
  CoglTexture *tex;

  if (!cogl_is_texture (handle))
    return 0;

  /* FIXME: This function should go away. It previously just returned
     the rowstride that was used to upload the data as far as I can
     tell. This is not helpful */

  tex = COGL_TEXTURE (handle);

  /* Just guess at a suitable rowstride */
  return (_cogl_get_format_bpp (cogl_texture_get_format (tex))
          * cogl_texture_get_width (tex));
}
Beispiel #7
0
gboolean
_cogl_texture_set_region_from_bitmap (CoglHandle    handle,
                                      int           src_x,
                                      int           src_y,
                                      int           dst_x,
                                      int           dst_y,
                                      unsigned int  dst_width,
                                      unsigned int  dst_height,
                                      CoglBitmap   *bmp)
{
  CoglTexture *tex = COGL_TEXTURE (handle);
  GLenum       closest_gl_format;
  GLenum       closest_gl_type;
  gboolean     ret;

  /* Shortcut out early if the image is empty */
  if (dst_width == 0 || dst_height == 0)
    return TRUE;

  /* Prepare the bitmap so that it will do the premultiplication
     conversion */
  bmp = _cogl_texture_prepare_for_upload (bmp,
                                          cogl_texture_get_format (handle),
                                          NULL,
                                          NULL,
                                          &closest_gl_format,
                                          &closest_gl_type);

  ret = tex->vtable->set_region (handle,
                                 src_x, src_y,
                                 dst_x, dst_y,
                                 dst_width, dst_height,
                                 bmp);

  cogl_object_unref (bmp);

  return ret;
}
Beispiel #8
0
static VALUE
rb_cogl_texture_get_data (int argc, VALUE *argv, VALUE self)
{
  CoglHandle tex = rb_cogl_texture_get_handle (self);
  VALUE format_arg, rowstride_arg;
  CoglPixelFormat format;
  guint rowstride;
  VALUE data;

  rb_scan_args (argc, argv, "02", &format_arg, &rowstride_arg);

  format = NIL_P (format_arg)
    ? cogl_texture_get_format (tex) : NUM2UINT (format_arg);
  rowstride = (NIL_P (rowstride_arg) || NUM2UINT (rowstride_arg) == 0)
    ? cogl_texture_get_rowstride (tex) : NUM2UINT (rowstride_arg);

  data = rb_str_buf_new (rowstride * cogl_texture_get_height (tex));
  cogl_texture_get_data (tex, format, rowstride,
                         (guchar *) RSTRING (data)->ptr);

  RSTRING (data)->len = rowstride * cogl_texture_get_height (tex);

  return data;
}
Beispiel #9
0
int
main (int argc, char *argv[])
{
  ClutterActor   *video;
  GdkPixbuf      *shot = NULL;
  gint            duration;
  CoglHandle      tex_id;
  CoglPixelFormat format;
  gint            size;
  gint            width;
  gint            height; 
  gint            rowstride;
  guchar         *data = NULL;

#ifdef USE_HELIX
  clutter_helix_init (&argc, &argv);
#else
  gst_init (&argc, &argv);
#endif
  clutter_init (&argc, &argv);

  if (argc < 3)
    {
      g_print ("Usage: %s <path to movie file> <output png>\n", argv[0]);
      exit(-1);
    }

  totem_resources_monitor_start (argv[1], 60 * G_USEC_PER_SEC);

#ifdef USE_HELIX
  video = clutter_helix_video_texture_new ();
#else
  video = clutter_gst_video_texture_new ();
#endif

  if (argv[1][0] == '/')
    clutter_media_set_filename(CLUTTER_MEDIA(video), argv[1]);
  else
    clutter_media_set_uri(CLUTTER_MEDIA(video), argv[1]);
  clutter_media_set_volume (CLUTTER_MEDIA(video), 0);
  clutter_media_set_playing (CLUTTER_MEDIA(video), TRUE);

  do {

    while (g_main_context_pending (NULL))
      g_main_context_iteration (NULL, FALSE);

    duration = clutter_media_get_duration (CLUTTER_MEDIA(video));

  } while (duration == 0);

  clutter_actor_realize (video);

  clutter_media_set_position (CLUTTER_MEDIA(video), duration/3);

  do {

    while (g_main_context_pending (NULL))
      g_main_context_iteration (NULL, FALSE);

  } while (clutter_media_get_position (CLUTTER_MEDIA(video)) <= duration/3);

  tex_id = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (video));
  if (tex_id)
    {
      format = cogl_texture_get_format (tex_id);
      size = cogl_texture_get_data (tex_id, format, 0, NULL);
      width = cogl_texture_get_width (tex_id);
      height = cogl_texture_get_height (tex_id);
      rowstride = cogl_texture_get_rowstride (tex_id);
      
      data = (guchar*) g_malloc (sizeof(guchar) * size);
      if (!data)
	g_error ("malloc");;

      cogl_texture_get_data (tex_id, format, rowstride, data);


      shot = gdk_pixbuf_new_from_data (data, 
				       GDK_COLORSPACE_RGB, 
				       FALSE, 
				       8,
				       width, 
				       height, 
				       rowstride, 
				       NULL, 
				       NULL);
      
    }

  totem_resources_monitor_stop ();

  if (shot)
    {
      GdkPixbuf *thumb, *pic;
      gint       x, y, nw, nh, w, h, size;
      
      size = 128;

      /* FIXME swap RGB pixels */

      w = clutter_actor_get_width (video);
      h = clutter_actor_get_height (video);
      
      nh = ( h * size) / w;

      if (nh <= size)
	{
	  nw = size;
	  x = 0;
	  y = (size - nh) / 2;
	}
      else
	{
	  nw  = ( w * size ) / h;
	  nh = size;
	  x = (size - nw) / 2;
	  y = 0;
	}

      thumb = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, size, size);
      gdk_pixbuf_fill (thumb, 0x000000FF);

      pic = gdk_pixbuf_scale_simple (shot, nw, nh, GDK_INTERP_BILINEAR);
      gdk_pixbuf_copy_area  (pic, 0, 0, nw, nh, thumb, x, y);
      
      if (!gdk_pixbuf_save (thumb, argv[2], "png", NULL, NULL))
	{
	  g_error ("%s: Pixbuf save failed\n", argv[0]);
	  exit(-1);
	}

      g_object_unref (shot);
      g_object_unref (thumb);
      g_object_unref (pic);

      exit(0);
    }

  exit (-1);
}
Beispiel #10
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);
}
Beispiel #11
0
int
cogl_texture_get_data (CoglHandle       handle,
		       CoglPixelFormat  format,
		       unsigned int     rowstride,
		       guint8          *data)
{
  CoglTexture     *tex;
  int              bpp;
  int              byte_size;
  CoglPixelFormat  closest_format;
  int              closest_bpp;
  GLenum           closest_gl_format;
  GLenum           closest_gl_type;
  CoglBitmap      *target_bmp;
  CoglBitmap      *new_bmp;
  guint8          *src;
  guint8          *dst;
  int              y;
  int              tex_width;
  int              tex_height;

  CoglTextureGetData tg_data;

  if (!cogl_is_texture (handle))
    return 0;

  tex = COGL_TEXTURE (handle);

  /* Default to internal format if none specified */
  if (format == COGL_PIXEL_FORMAT_ANY)
    format = cogl_texture_get_format (handle);

  tex_width = cogl_texture_get_width (handle);
  tex_height = cogl_texture_get_height (handle);

  /* Rowstride from texture width if none specified */
  bpp = _cogl_get_format_bpp (format);
  if (rowstride == 0)
    rowstride = tex_width * bpp;

  /* Return byte size if only that requested */
  byte_size = tex_height * rowstride;
  if (data == NULL)
    return byte_size;

  closest_format =
    _cogl_texture_driver_find_best_gl_get_data_format (format,
                                                       &closest_gl_format,
                                                       &closest_gl_type);
  closest_bpp = _cogl_get_format_bpp (closest_format);

  /* Is the requested format supported? */
  if (closest_format == format)
    /* Target user data directly */
    target_bmp = _cogl_bitmap_new_from_data (data,
                                             format,
                                             tex_width,
                                             tex_height,
                                             rowstride,
                                             NULL, NULL);
  else
    {
      int target_rowstride = tex_width * closest_bpp;
      guint8 *target_data = g_malloc (tex_height * target_rowstride);
      target_bmp = _cogl_bitmap_new_from_data (target_data,
                                               closest_format,
                                               tex_width,
                                               tex_height,
                                               target_rowstride,
                                               (CoglBitmapDestroyNotify) g_free,
                                               NULL);
    }

  tg_data.orig_width = tex_width;
  tg_data.orig_height = tex_height;
  tg_data.target_bmp = target_bmp;
  tg_data.target_bits = _cogl_bitmap_map (target_bmp, COGL_BUFFER_ACCESS_WRITE,
                                          COGL_BUFFER_MAP_HINT_DISCARD);
  if (tg_data.target_bits == NULL)
    {
      cogl_object_unref (target_bmp);
      return 0;
    }
  tg_data.success = TRUE;

  /* Iterating through the subtextures allows piecing together
   * the data for a sliced texture, and allows us to do the
   * read-from-framebuffer logic here in a simple fashion rather than
   * passing offsets down through the code. */
  _cogl_texture_foreach_sub_texture_in_region (handle,
                                               0, 0, 1, 1,
                                               texture_get_cb,
                                               &tg_data);

  _cogl_bitmap_unmap (target_bmp);

  /* XXX: In some cases _cogl_texture_2d_download_from_gl may fail
   * to read back the texture data; such as for GLES which doesn't
   * support glGetTexImage, so here we fallback to drawing the
   * texture and reading the pixels from the framebuffer. */
  if (!tg_data.success)
    _cogl_texture_draw_and_read (tex, target_bmp,
                                 closest_gl_format,
                                 closest_gl_type);

  /* Was intermediate used? */
  if (closest_format != format)
    {
      guint8 *new_bmp_data;
      int new_bmp_rowstride;

      /* Convert to requested format */
      new_bmp = _cogl_bitmap_convert_format_and_premult (target_bmp,
                                                         format);

      /* Free intermediate data and return if failed */
      cogl_object_unref (target_bmp);

      if (new_bmp == NULL)
        return 0;

      new_bmp_rowstride = _cogl_bitmap_get_rowstride (new_bmp);
      new_bmp_data = _cogl_bitmap_map (new_bmp, COGL_BUFFER_ACCESS_WRITE,
                                       COGL_BUFFER_MAP_HINT_DISCARD);

      if (new_bmp_data == NULL)
        {
          cogl_object_unref (new_bmp);
          return 0;
        }

      /* Copy to user buffer */
      for (y = 0; y < tex_height; ++y)
        {
          src = new_bmp_data + y * new_bmp_rowstride;
          dst = data + y * rowstride;
          memcpy (dst, src, tex_width * bpp);
        }

      _cogl_bitmap_unmap (new_bmp);

      /* Free converted data */
      cogl_object_unref (new_bmp);
    }

  return byte_size;
}
Beispiel #12
0
/* Reads back the contents of a texture by rendering it to the framebuffer
 * and reading back the resulting pixels.
 *
 * NB: Normally this approach isn't normally used since we can just use
 * glGetTexImage, but may be used as a fallback in some circumstances.
 */
gboolean
_cogl_texture_draw_and_read (CoglHandle   handle,
                             CoglBitmap  *target_bmp,
                             GLuint       target_gl_format,
                             GLuint       target_gl_type)
{
  int        bpp;
  CoglFramebuffer *framebuffer;
  int        viewport[4];
  CoglBitmap *alpha_bmp;
  CoglMatrixStack *projection_stack;
  CoglMatrixStack *modelview_stack;
  int target_width = _cogl_bitmap_get_width (target_bmp);
  int target_height = _cogl_bitmap_get_height (target_bmp);
  int target_rowstride = _cogl_bitmap_get_rowstride (target_bmp);

  _COGL_GET_CONTEXT (ctx, FALSE);

  bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);

  framebuffer = _cogl_get_draw_buffer ();
  /* Viewport needs to have some size and be inside the window for this */
  _cogl_framebuffer_get_viewport4fv (framebuffer, viewport);
  if (viewport[0] <  0 || viewport[1] <  0 ||
      viewport[2] <= 0 || viewport[3] <= 0)
    return FALSE;

  /* Setup orthographic projection into current viewport (0,0 in top-left
   * corner to draw the texture upside-down so we match the way cogl_read_pixels
   * works)
   */

  projection_stack = _cogl_framebuffer_get_projection_stack (framebuffer);
  _cogl_matrix_stack_push (projection_stack);
  _cogl_matrix_stack_load_identity (projection_stack);
  _cogl_matrix_stack_ortho (projection_stack,
                            0, (float)(viewport[2]),
                            (float)(viewport[3]), 0,
                            (float)(0),
                            (float)(100));

  modelview_stack = _cogl_framebuffer_get_modelview_stack (framebuffer);
  _cogl_matrix_stack_push (modelview_stack);
  _cogl_matrix_stack_load_identity (modelview_stack);

  /* Direct copy operation */

  if (ctx->texture_download_pipeline == COGL_INVALID_HANDLE)
    {
      ctx->texture_download_pipeline = cogl_pipeline_new ();
      cogl_pipeline_set_blend (ctx->texture_download_pipeline,
                               "RGBA = ADD (SRC_COLOR, 0)",
                               NULL);
    }

  cogl_push_source (ctx->texture_download_pipeline);

  cogl_pipeline_set_layer_texture (ctx->texture_download_pipeline, 0, handle);

  cogl_pipeline_set_layer_combine (ctx->texture_download_pipeline,
                                   0, /* layer */
                                   "RGBA = REPLACE (TEXTURE)",
                                   NULL);

  cogl_pipeline_set_layer_filters (ctx->texture_download_pipeline, 0,
                                   COGL_PIPELINE_FILTER_NEAREST,
                                   COGL_PIPELINE_FILTER_NEAREST);

  do_texture_draw_and_read (handle, target_bmp, viewport);

  /* Check whether texture has alpha and framebuffer not */
  /* FIXME: For some reason even if ALPHA_BITS is 8, the framebuffer
     still doesn't seem to have an alpha buffer. This might be just
     a PowerVR issue.
  GLint r_bits, g_bits, b_bits, a_bits;
  GE( glGetIntegerv (GL_ALPHA_BITS, &a_bits) );
  GE( glGetIntegerv (GL_RED_BITS, &r_bits) );
  GE( glGetIntegerv (GL_GREEN_BITS, &g_bits) );
  GE( glGetIntegerv (GL_BLUE_BITS, &b_bits) );
  printf ("R bits: %d\n", r_bits);
  printf ("G bits: %d\n", g_bits);
  printf ("B bits: %d\n", b_bits);
  printf ("A bits: %d\n", a_bits); */
  if ((cogl_texture_get_format (handle) & COGL_A_BIT)/* && a_bits == 0*/)
    {
      guint8 *srcdata;
      guint8 *dstdata;
      guint8 *srcpixel;
      guint8 *dstpixel;
      int     x,y;
      int     alpha_rowstride = bpp * target_width;

      if ((dstdata = _cogl_bitmap_map (target_bmp,
                                       COGL_BUFFER_ACCESS_WRITE,
                                       COGL_BUFFER_MAP_HINT_DISCARD)) == NULL)
        return FALSE;

      srcdata = g_malloc (alpha_rowstride * target_height);

      /* Create temp bitmap for alpha values */
      alpha_bmp = _cogl_bitmap_new_from_data (srcdata,
                                              COGL_PIXEL_FORMAT_RGBA_8888,
                                              target_width, target_height,
                                              alpha_rowstride,
                                              (CoglBitmapDestroyNotify) g_free,
                                              NULL);

      /* Draw alpha values into RGB channels */
      cogl_pipeline_set_layer_combine (ctx->texture_download_pipeline,
                                       0, /* layer */
                                       "RGBA = REPLACE (TEXTURE[A])",
                                       NULL);

      do_texture_draw_and_read (handle, alpha_bmp, viewport);

      /* Copy temp R to target A */

      for (y=0; y<target_height; ++y)
        {
          for (x=0; x<target_width; ++x)
            {
              srcpixel = srcdata + x*bpp;
              dstpixel = dstdata + x*bpp;
              dstpixel[3] = srcpixel[0];
            }
          srcdata += alpha_rowstride;
          dstdata += target_rowstride;
        }

      _cogl_bitmap_unmap (target_bmp);

      cogl_object_unref (alpha_bmp);
    }

  /* Restore old state */
  _cogl_matrix_stack_pop (modelview_stack);
  _cogl_matrix_stack_pop (projection_stack);

  /* restore the original pipeline */
  cogl_pop_source ();

  return TRUE;
}
static void
test_coglbox_init (TestCoglbox *self)
{
  TestCoglboxPrivate *priv;
  guint            width;
  guint            height;
  guint            rowstride;
  CoglPixelFormat  format;
  gint             size;
  guchar          *data;
  gint             x,y,t;
  guchar          *pixel;
  
  self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self);
  
  /* Load image from file */
  
  priv->cogl_tex_id[0] =
    cogl_texture_new_from_file ("redhand.png", 40, FALSE,
                                COGL_PIXEL_FORMAT_ANY, NULL);
  
  if (priv->cogl_tex_id[0] == COGL_INVALID_HANDLE)
    {
      printf ("Failed loading redhand.png image!\n");
      return;
    }
  
  printf("Texture loaded from file.\n");
  
  /* Obtain pixel data */
  
  format = cogl_texture_get_format (priv->cogl_tex_id[0]);
  g_assert(format == COGL_PIXEL_FORMAT_RGBA_8888 ||
           format == COGL_PIXEL_FORMAT_ARGB_8888);

  width = cogl_texture_get_width (priv->cogl_tex_id[0]);
  height = cogl_texture_get_height (priv->cogl_tex_id[0]);
  size = cogl_texture_get_data (priv->cogl_tex_id[0],
				format, 0, NULL);
  
  printf("size: %dx%d\n", width, height);
  printf("format: 0x%x\n", format);
  printf("bytesize: %d\n", size);
  
  data = (guchar*) g_malloc (sizeof(guchar) * size);
  
  cogl_texture_get_data (priv->cogl_tex_id[0],
			 format, 0, data);
  rowstride = cogl_texture_get_rowstride (priv->cogl_tex_id[0]);
  
  /* Create new texture from modified data */
  
  priv->cogl_tex_id[1] =
    cogl_texture_new_from_data (width, height, 0, FALSE,
                                format, format,
				rowstride, data);
  
  if (priv->cogl_tex_id[1] == COGL_INVALID_HANDLE)
    {
      printf ("Failed creating image from data!\n");
      return;
    }
  
  printf ("Texture created from data.\n");
  
  /* Modify data (swap red and green) */
  
  for (y=0; y<height; ++y)
    {
      for (x=0; x<width; ++x)
	{
	  pixel = data + y * rowstride + x * 4;
	  if (format == COGL_PIXEL_FORMAT_RGBA_8888)
	    {
	      t = pixel[0];
	      pixel[0] = pixel[1];
	      pixel[1] = t;
	    }
	  else
	    {
	      t = pixel[1];
	      pixel[1] = pixel[2];
	      pixel[2] = t;
	    }
	}
    }
  
  
  cogl_texture_set_region (priv->cogl_tex_id[1],
			   0, 0, 0, 0,
			   100, 100, width, height,
			   format, 0, data);
  
  cogl_texture_set_region (priv->cogl_tex_id[1],
			   100, 100, 100, 100,
			   100, 100, width, height,
			   format, 0, data);
  
  printf ("Subregion data updated.\n");
}