Exemplo n.º 1
0
CoglBool
cogl_wayland_texture_set_region_from_shm_buffer (CoglTexture *texture,
        int src_x,
        int src_y,
        int width,
        int height,
        struct wl_shm_buffer *
        shm_buffer,
        int dst_x,
        int dst_y,
        int level,
        CoglError **error)
{
    const uint8_t *data = wl_shm_buffer_get_data (shm_buffer);
    int32_t stride = wl_shm_buffer_get_stride (shm_buffer);
    CoglPixelFormat format;
    int bpp;

    shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL);
    bpp = _cogl_pixel_format_get_bytes_per_pixel (format);

    return cogl_texture_set_region (COGL_TEXTURE (texture),
                                    width, height,
                                    format,
                                    stride,
                                    data + src_x * bpp + src_y * stride,
                                    dst_x, dst_y,
                                    level,
                                    error);
}
Exemplo n.º 2
0
static VALUE
rb_cogl_texture_set_region (VALUE self, VALUE src_x, VALUE src_y,
                            VALUE dst_x, VALUE dst_y,
                            VALUE dst_width, VALUE dst_height,
                            VALUE width_arg, VALUE height_arg,
                            VALUE format, VALUE rowstride_arg,
                            VALUE data_arg)
{
  guint width = NUM2UINT (width_arg);
  guint height = NUM2UINT (height_arg);
  guint rowstride;
  const char *data = StringValuePtr (data_arg);

  /* If there is no rowstride then try to guess what it will be from
     the format */
  if (NIL_P (rowstride_arg) || (rowstride = NUM2UINT (rowstride_arg)) == 0)
    rowstride = width * rb_cogl_texture_get_format_bpp (NUM2UINT (format));

  /* Make sure the string is long enough */
  if (RSTRING_LEN (data_arg) < height * rowstride)
    rb_raise (rb_eArgError, "data string too short");

  if (!cogl_texture_set_region (rb_cogl_texture_get_handle (self),
                                NUM2INT (src_x), NUM2INT (src_y),
                                NUM2INT (dst_x), NUM2INT (dst_y),
                                NUM2UINT (dst_width), NUM2UINT (dst_height),
                                width, height,
                                NUM2UINT (format),
                                rowstride,
                                (const guchar *) data))
    rb_raise (rb_c_cogl_texture_error, "texture set region failed");

  return self;
}
Exemplo n.º 3
0
CoglTexture *
meta_texture_rectangle_new (unsigned int width,
                            unsigned int height,
                            CoglPixelFormat format,
                            unsigned int rowstride,
                            const guint8 *data)
{
  ClutterBackend *backend =
    clutter_get_default_backend ();
  CoglContext *context =
    clutter_backend_get_cogl_context (backend);
  CoglTextureRectangle *tex_rect;

  tex_rect = cogl_texture_rectangle_new_with_size (context, width, height);
  if (tex_rect == NULL)
    return NULL;

  if (data)
    cogl_texture_set_region (COGL_TEXTURE (tex_rect),
                             0, 0, /* src_x/y */
                             0, 0, /* dst_x/y */
                             width, height, /* dst_width/height */
                             width, height, /* width/height */
                             format,
                             rowstride,
                             data);

  return COGL_TEXTURE (tex_rect);
}
Exemplo n.º 4
0
static gboolean rc_area_changed_cb(gpointer data)
{
	RendererClutter *rc = (RendererClutter *)data;
	PixbufRenderer *pr = rc->pr;

	RendererClutterAreaParam *par = rc->pending_updates->data;

	gint h = MAX_REGION_AREA / par->w;
	if (h == 0) h = 1;
	if (h > par->h) h = par->h;


	DEBUG_3("%s upload start", get_exec_time());
	if (pr->pixbuf)
		{
		CoglHandle texture = clutter_texture_get_cogl_texture(CLUTTER_TEXTURE(rc->texture));

		cogl_texture_set_region(texture,
					par->x + GET_RIGHT_PIXBUF_OFFSET(rc),
					par->y,
					par->x,
					par->y,
					par->w,
					h,
					par->w,
					h,
					gdk_pixbuf_get_has_alpha(pr->pixbuf) ? COGL_PIXEL_FORMAT_BGRA_8888 : COGL_PIXEL_FORMAT_BGR_888,
					gdk_pixbuf_get_rowstride(pr->pixbuf),
					gdk_pixbuf_get_pixels(pr->pixbuf));
		}
	DEBUG_3("%s upload end", get_exec_time());
	rc_area_clip_add(rc, par->x, par->y, par->w, h);


	par->y += h;
	par->h -= h;

	if (par->h == 0)
		{
		rc->pending_updates = g_list_remove(rc->pending_updates, par);
		g_free(par);
		}
	if (!rc->pending_updates)
		{
		clutter_actor_queue_redraw(CLUTTER_ACTOR(rc->texture));
		rc->idle_update = 0;

		/* FIXME: find a better place for this */
		if (!rc->clut_updated) rc_prepare_post_process_lut(rc);

		return FALSE;
		}

	rc_schedule_texture_upload(rc);

	return FALSE; /* it was rescheduled, possibly with different prio */
}
Exemplo n.º 5
0
static void
clutter_cairo_texture_context_destroy (void *data)
{
  ClutterCairoTextureContext *ctxt = data;
  ClutterCairoTexture *cairo = ctxt->cairo;
  ClutterCairoTexturePrivate *priv = cairo->priv;
  guint8 *cairo_data;
  gint cairo_width, cairo_height, cairo_stride;
  gint surface_width, surface_height;
  CoglHandle cogl_texture;

  if (priv->cr_surface == NULL)
    return;

  /* for any other surface type, we presume that there exists a native
   * communication between Cairo and GL that is triggered by cairo_destroy().
   *
   * for instance, cairo-drm will flush the outstanding modifications to the
   * surface upon context destruction and so the texture is automatically
   * updated.
   */
  if (cairo_surface_get_type (priv->cr_surface) != CAIRO_SURFACE_TYPE_IMAGE)
    goto out;

  surface_width  = cairo_image_surface_get_width (priv->cr_surface);
  surface_height = cairo_image_surface_get_height (priv->cr_surface);

  cairo_width  = MIN (ctxt->rect.width, surface_width);
  cairo_height = MIN (ctxt->rect.height, surface_height);

  cogl_texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (cairo));
  if (!cairo_width || !cairo_height || cogl_texture == COGL_INVALID_HANDLE)
    {
      g_slice_free (ClutterCairoTextureContext, ctxt);
      return;
    }

  cairo_stride = cairo_image_surface_get_stride (priv->cr_surface);
  cairo_data = cairo_image_surface_get_data (priv->cr_surface);
  cairo_data += cairo_stride * ctxt->rect.y;
  cairo_data += 4 * ctxt->rect.x;

  cogl_texture_set_region (cogl_texture,
                           0, 0,
                           ctxt->rect.x, ctxt->rect.y,
                           cairo_width, cairo_height,
                           cairo_width, cairo_height,
                           CLUTTER_CAIRO_FORMAT_ARGB32,
                           cairo_stride,
                           cairo_data);

out:
  g_slice_free (ClutterCairoTextureContext, ctxt);
  clutter_actor_queue_redraw (CLUTTER_ACTOR (cairo));
}
Exemplo n.º 6
0
static void
shm_buffer_damaged (struct wl_buffer *wayland_buffer,
                    int32_t x,
                    int32_t y,
                    int32_t width,
                    int32_t height)
{
  CoglandBuffer *buffer = wayland_buffer->user_data;

  if (buffer->texture)
    {
      CoglPixelFormat format;

      switch (wl_shm_buffer_get_format (wayland_buffer))
        {
#if G_BYTE_ORDER == G_BIG_ENDIAN
          case WL_SHM_FORMAT_ARGB8888:
            format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
            break;
          case WL_SHM_FORMAT_XRGB8888:
            format = COGL_PIXEL_FORMAT_ARGB_8888;
            break;
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
          case WL_SHM_FORMAT_ARGB8888:
            format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
            break;
          case WL_SHM_FORMAT_XRGB8888:
            format = COGL_PIXEL_FORMAT_BGRA_8888;
            break;
#endif
          default:
            g_warn_if_reached ();
            format = COGL_PIXEL_FORMAT_ARGB_8888;
        }

      cogl_texture_set_region (COGL_TEXTURE (buffer->texture),
                               x, y,
                               x, y,
                               width, height,
                               width, height,
                               format,
                               wl_shm_buffer_get_stride (wayland_buffer),
                               wl_shm_buffer_get_data (wayland_buffer));
    }
}
Exemplo n.º 7
0
static void
_cogl_blit_get_tex_data_blit (CoglBlitData *data,
                              unsigned int src_x,
                              unsigned int src_y,
                              unsigned int dst_x,
                              unsigned int dst_y,
                              unsigned int width,
                              unsigned int height)
{
  cogl_texture_set_region (data->dst_tex,
                           src_x, src_y,
                           dst_x, dst_y,
                           width, height,
                           data->src_width, data->src_height,
                           data->format,
                           data->src_width * data->bpp,
                           data->image_data);
}
Exemplo n.º 8
0
static CoglHandle
data_to_cogl_handle (const guchar *data,
                     gboolean      has_alpha,
                     int           width,
                     int           height,
                     int           rowstride,
                     gboolean      add_padding)
{
    CoglHandle texture, offscreen;
    CoglColor clear_color;
    guint size;

    size = MAX (width, height);

    if (!add_padding || width == height)
        return cogl_texture_new_from_data (width,
                                           height,
                                           COGL_TEXTURE_NONE,
                                           has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
                                           COGL_PIXEL_FORMAT_ANY,
                                           rowstride,
                                           data);

    texture = cogl_texture_new_with_size (size, size,
                                          COGL_TEXTURE_NO_SLICING,
                                          COGL_PIXEL_FORMAT_ANY);

    offscreen = cogl_offscreen_new_to_texture (texture);
    cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0);
    cogl_push_framebuffer (offscreen);
    cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
    cogl_pop_framebuffer ();
    cogl_handle_unref (offscreen);

    cogl_texture_set_region (texture,
                             0, 0,
                             (size - width) / 2, (size - height) / 2,
                             width, height,
                             width, height,
                             has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
                             rowstride,
                             data);
    return texture;
}
static CoglHandle
pixbuf_to_cogl_handle (GdkPixbuf *pixbuf,
                       gboolean   add_padding)
{
  CoglHandle texture, offscreen;
  CoglColor clear_color;
  int width, height;
  guint size;

  width = gdk_pixbuf_get_width (pixbuf);
  height = gdk_pixbuf_get_height (pixbuf);
  size = MAX (width, height);

  if (!add_padding || width == height)
    return cogl_texture_new_from_data (width,
                                       height,
                                       COGL_TEXTURE_NONE,
                                       gdk_pixbuf_get_has_alpha (pixbuf) ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
                                       COGL_PIXEL_FORMAT_ANY,
                                       gdk_pixbuf_get_rowstride (pixbuf),
                                       gdk_pixbuf_get_pixels (pixbuf));

  texture = cogl_texture_new_with_size (size, size,
                                        COGL_TEXTURE_NO_SLICING,
                                        COGL_PIXEL_FORMAT_ANY);

  offscreen = cogl_offscreen_new_to_texture (texture);
  cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0);
  cogl_push_framebuffer (offscreen);
  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
  cogl_pop_framebuffer ();
  cogl_handle_unref (offscreen);

  cogl_texture_set_region (texture,
                           0, 0,
                           (size - width) / 2, (size - height) / 2,
                           width, height,
                           width, height,
                           gdk_pixbuf_get_has_alpha (pixbuf) ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
                           gdk_pixbuf_get_rowstride (pixbuf),
                           gdk_pixbuf_get_pixels (pixbuf));
  return texture;
}
Exemplo n.º 10
0
static void
shm_buffer_damaged (struct wl_buffer *wayland_buffer,
		    gint32 x,
                    gint32 y,
                    gint32 width,
                    gint32 height)
{
  CoglandBuffer *buffer = wayland_buffer->user_data;

  if (buffer->texture)
    {
      cogl_texture_set_region (buffer->texture,
                               x, y,
                               x, y,
                               width, height,
                               width, height,
                               get_buffer_format (wayland_buffer),
                               wl_shm_buffer_get_stride (wayland_buffer),
                               wl_shm_buffer_get_data (wayland_buffer));
    }
}
Exemplo n.º 11
0
static CoglHandle
data_to_cogl_handle (const guchar *data,
                     gboolean      has_alpha,
                     int           width,
                     int           height,
                     int           rowstride,
                     gboolean      add_padding)
{
  CoglHandle texture, offscreen;
  CoglColor clear_color;
  guint size;
  GError *error;

  size = MAX (width, height);

  if (!add_padding || width == height)
    return cogl_texture_new_from_data (width,
                                       height,
                                       COGL_TEXTURE_NONE,
                                       has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
                                       COGL_PIXEL_FORMAT_ANY,
                                       rowstride,
                                       data);

  texture = cogl_texture_new_with_size (size, size,
                                        COGL_TEXTURE_NO_SLICING,
                                        COGL_PIXEL_FORMAT_ANY);

  offscreen = cogl_offscreen_new_with_texture (texture);

  error = NULL;
  if (!cogl_framebuffer_allocate (offscreen, &error))
    {
      g_warning ("Failed to allocate FBO (sized %d): %s", size, error->message);

      cogl_object_unref (texture);
      cogl_object_unref (offscreen);
      g_clear_error (&error);

      return cogl_texture_new_from_data (width,
                                         height,
                                         COGL_TEXTURE_NONE,
                                         has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
                                         COGL_PIXEL_FORMAT_ANY,
                                         rowstride,
                                         data);
  }

  cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0);
  cogl_push_framebuffer (offscreen);
  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
  cogl_pop_framebuffer ();
  cogl_handle_unref (offscreen);

  cogl_texture_set_region (texture,
                           0, 0,
                           (size - width) / 2, (size - height) / 2,
                           width, height,
                           width, height,
                           has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
                           rowstride,
                           data);
  return texture;
}
Exemplo n.º 12
0
/**
 * clutter_image_set_area:
 * @image: a #ClutterImage
 * @data: (array): the image data, as an array of bytes
 * @pixel_format: the Cogl pixel format of the image data
 * @rect: a rectangle indicating the area that should be set
 * @row_stride: the length of each row inside @data
 * @error: return location for a #GError, or %NULL
 *
 * Sets the image data to be display by @image, using @rect to indicate
 * the position and size of the image data to be set.
 *
 * If the @image does not have any image data set when this function is
 * called, a new texture will be created with the size of the width and
 * height of the rectangle, i.e. calling this function on a newly created
 * #ClutterImage will be the equivalent of calling clutter_image_set_data().
 *
 * If the image data was successfully loaded, the @image will be invalidated.
 *
 * In case of error, the @error value will be set, and this function will
 * return %FALSE.
 *
 * The image data is copied in texture memory.
 *
 * Return value: %TRUE if the image data was successfully loaded,
 *   and %FALSE otherwise.
 *
 * Since: 1.10
 */
gboolean
clutter_image_set_area (ClutterImage                 *image,
                        const guint8                 *data,
                        CoglPixelFormat               pixel_format,
                        const cairo_rectangle_int_t  *area,
                        guint                         row_stride,
                        GError                      **error)
{
  ClutterImagePrivate *priv;

  g_return_val_if_fail (CLUTTER_IS_IMAGE (image), FALSE);
  g_return_val_if_fail (data != NULL, FALSE);
  g_return_val_if_fail (area != NULL, FALSE);

  priv = image->priv;

  if (priv->texture == NULL)
    {
      CoglTextureFlags flags = COGL_TEXTURE_NONE;

      if (area->width >= 512 && area->height >= 512)
        flags |= COGL_TEXTURE_NO_ATLAS;

      priv->texture = cogl_texture_new_from_data (area->width,
                                                  area->height,
                                                  flags,
                                                  pixel_format,
                                                  COGL_PIXEL_FORMAT_ANY,
                                                  row_stride,
                                                  data);
    }
  else
    {
      gboolean res;

      res = cogl_texture_set_region (priv->texture,
                                     0, 0,
                                     area->x, area->y,
                                     area->width, area->height,
                                     area->width, area->height,
                                     pixel_format,
                                     row_stride,
                                     data);

      if (!res)
        {
          cogl_object_unref (priv->texture);
          priv->texture = NULL;
        }
    }

  if (priv->texture == NULL)
    {
      g_set_error_literal (error, CLUTTER_IMAGE_ERROR,
                           CLUTTER_IMAGE_ERROR_INVALID_DATA,
                           _("Unable to load image data"));
      return FALSE;
    }

  clutter_content_invalidate (CLUTTER_CONTENT (image));

  return TRUE;
}
Exemplo n.º 13
0
void
test_alpha_textures (void)
{
  CoglTexture *tex1, *tex2;
  CoglPipeline *pipeline1, *pipeline2;
  int fb_width = cogl_framebuffer_get_width (test_fb);
  int fb_height = cogl_framebuffer_get_height (test_fb);
  uint8_t replacement_data[1] = { 0xff };

  create_pipeline (&tex1, &pipeline1);

  cogl_framebuffer_draw_rectangle (test_fb,
                                   pipeline1,
                                   -1.0f, 1.0f, /* x1/y1 */
                                   1.0f, 0.0f /* x2/y2 */);

  create_pipeline (&tex2, &pipeline2);

  cogl_texture_set_region (tex2,
                           1, 1, /* width / height */
                           COGL_PIXEL_FORMAT_A_8,
                           1, /* rowstride */
                           replacement_data,
                           1, 1, /* dst_x/y */
                           0, /* level */
                           NULL); /* abort on error */

  cogl_framebuffer_draw_rectangle (test_fb,
                                   pipeline2,
                                   -1.0f, 0.0f, /* x1/y1 */
                                   1.0f, -1.0f /* x2/y2 */);

  cogl_object_unref (tex1);
  cogl_object_unref (tex2);
  cogl_object_unref (pipeline1);
  cogl_object_unref (pipeline2);

  /* Unmodified texture */
  test_utils_check_pixel (test_fb,
                          fb_width / 4,
                          fb_height / 8,
                          0x000000ff);
  test_utils_check_pixel (test_fb,
                          fb_width * 3 / 4,
                          fb_height / 8,
                          0x444444ff);
  test_utils_check_pixel (test_fb,
                          fb_width / 4,
                          fb_height * 3 / 8,
                          0x888888ff);
  test_utils_check_pixel (test_fb,
                          fb_width * 3 / 4,
                          fb_height * 3 / 8,
                          0xccccccff);

  /* Modified texture */
  test_utils_check_pixel (test_fb,
                          fb_width / 4,
                          fb_height * 5 / 8,
                          0x000000ff);
  test_utils_check_pixel (test_fb,
                          fb_width * 3 / 4,
                          fb_height * 5 / 8,
                          0x444444ff);
  test_utils_check_pixel (test_fb,
                          fb_width / 4,
                          fb_height * 7 / 8,
                          0x888888ff);
  test_utils_check_pixel (test_fb,
                          fb_width * 3 / 4,
                          fb_height * 7 / 8,
                          0xffffffff);

  if (cogl_test_verbose ())
    g_print ("OK\n");
}
Exemplo n.º 14
0
static void
_cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap)
{
  Display *display;
  CoglPixelFormat image_format;
  XImage *image;
  int src_x, src_y;
  int x, y, width, height;

  display = cogl_xlib_get_display ();

  /* If the damage region is empty then there's nothing to do */
  if (tex_pixmap->damage_rect.x2 == tex_pixmap->damage_rect.x1)
    return;

  x = tex_pixmap->damage_rect.x1;
  y = tex_pixmap->damage_rect.y1;
  width = tex_pixmap->damage_rect.x2 - x;
  height = tex_pixmap->damage_rect.y2 - y;

  /* We lazily create the texture the first time it is needed in case
     this texture can be entirely handled using the GLX texture
     instead */
  if (tex_pixmap->tex == COGL_INVALID_HANDLE)
    {
      CoglPixelFormat texture_format;

      texture_format = (tex_pixmap->depth >= 32
                        ? COGL_PIXEL_FORMAT_RGBA_8888_PRE
                        : COGL_PIXEL_FORMAT_RGB_888);

      tex_pixmap->tex = cogl_texture_new_with_size (tex_pixmap->width,
                                                    tex_pixmap->height,
                                                    COGL_TEXTURE_NONE,
                                                    texture_format);
    }

  if (tex_pixmap->image == NULL)
    {
      /* If we also haven't got a shm segment then this must be the
         first time we've tried to update, so lets try allocating shm
         first */
      if (tex_pixmap->shm_info.shmid == -1)
        try_alloc_shm (tex_pixmap);

      if (tex_pixmap->shm_info.shmid == -1)
        {
          COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetImage", tex_pixmap);

          /* We'll fallback to using a regular XImage. We'll download
             the entire area instead of a sub region because presumably
             if this is the first update then the entire pixmap is
             needed anyway and it saves trying to manually allocate an
             XImage at the right size */
          tex_pixmap->image = XGetImage (display,
                                         tex_pixmap->pixmap,
                                         0, 0,
                                         tex_pixmap->width, tex_pixmap->height,
                                         AllPlanes, ZPixmap);
          image = tex_pixmap->image;
          src_x = x;
          src_y = y;
        }
      else
        {
          COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XShmGetImage",
                     tex_pixmap);

          /* Create a temporary image using the beginning of the
             shared memory segment and the right size for the region
             we want to update. We need to reallocate the XImage every
             time because there is no XShmGetSubImage. */
          image = XShmCreateImage (display,
                                   tex_pixmap->visual,
                                   tex_pixmap->depth,
                                   ZPixmap,
                                   NULL,
                                   &tex_pixmap->shm_info,
                                   width,
                                   height);
          image->data = tex_pixmap->shm_info.shmaddr;
          src_x = 0;
          src_y = 0;

          XShmGetImage (display, tex_pixmap->pixmap, image, x, y, AllPlanes);
        }
    }
  else
    {
      COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetSubImage", tex_pixmap);

      image = tex_pixmap->image;
      src_x = x;
      src_y = y;

      XGetSubImage (display,
                    tex_pixmap->pixmap,
                    x, y, width, height,
                    AllPlanes, ZPixmap,
                    image,
                    x, y);
    }

  /* xlib doesn't appear to fill in image->{red,green,blue}_mask so
     this just assumes that the image is stored as ARGB from most
     significant byte to to least significant. If the format is little
     endian that means the order will be BGRA in memory */

  switch (image->bits_per_pixel)
    {
    default:
    case 32:
      {
        /* If the pixmap is actually non-packed-pixel RGB format then
           the texture would have been created in RGB_888 format so Cogl
           will ignore the alpha channel and effectively pack it for
           us */
        image_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;

        /* If the format is actually big endian then the alpha
           component will come first */
        if (image->byte_order == MSBFirst)
          image_format |= COGL_AFIRST_BIT;
      }
      break;

    case 24:
      image_format = COGL_PIXEL_FORMAT_RGB_888;
      break;

    case 16:
      /* FIXME: this should probably swap the orders around if the
         endianness does not match */
      image_format = COGL_PIXEL_FORMAT_RGB_565;
      break;
    }

  if (image->bits_per_pixel != 16)
    {
      /* If the image is in little-endian then the order in memory is
         reversed */
      if (image->byte_order == LSBFirst)
        image_format |= COGL_BGR_BIT;
    }

  cogl_texture_set_region (tex_pixmap->tex,
                           src_x, src_y,
                           x, y, width, height,
                           image->width,
                           image->height,
                           image_format,
                           image->bytes_per_line,
                           (const guint8 *) image->data);

  /* If we have a shared memory segment then the XImage would be a
     temporary one with no data allocated so we can just XFree it */
  if (tex_pixmap->shm_info.shmid != -1)
    XFree (image);

  memset (&tex_pixmap->damage_rect, 0, sizeof (CoglDamageRectangle));
}
Exemplo n.º 15
0
CoglHandle
meta_texture_rectangle_new (unsigned int width,
                            unsigned int height,
                            CoglTextureFlags flags,
                            CoglPixelFormat format,
                            GLenum internal_gl_format,
                            GLenum internal_format,
                            unsigned int rowstride,
                            const guint8 *data)
{
  CoglHandle cogl_tex = COGL_INVALID_HANDLE;

#ifdef GL_TEXTURE_RECTANGLE_ARB

  static CoglUserDataKey user_data_key;
  GLint old_binding;
  GLuint tex;

  if (pf_glGenTextures == NULL)
    {
      pf_glGetIntegerv = (void *) cogl_get_proc_address ("glGetIntegerv");
      pf_glTexImage2D = (void *) cogl_get_proc_address ("glTexImage2D");
      pf_glGenTextures = (void *) cogl_get_proc_address ("glGenTextures");
      pf_glDeleteTextures = (void *) cogl_get_proc_address ("glDeleteTextures");
      pf_glBindTexture = (void *) cogl_get_proc_address ("glBindTexture");
    }

  pf_glGenTextures (1, &tex);
  pf_glGetIntegerv (GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding);
  pf_glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
  pf_glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
                   internal_gl_format, width, height,
                   0, internal_gl_format,
                   GL_UNSIGNED_BYTE, NULL);
  pf_glBindTexture (GL_TEXTURE_RECTANGLE_ARB, old_binding);

  cogl_tex = cogl_texture_new_from_foreign (tex,
                                            GL_TEXTURE_RECTANGLE_ARB,
                                            width, height,
                                            0, 0, /* no waste */
                                            internal_format);

  /* Cogl won't destroy the GL texture when a foreign texture is used
     so we need to destroy it manually. We can set a destroy
     notification callback to do this transparently */
  cogl_object_set_user_data (cogl_tex,
                             &user_data_key,
                             GUINT_TO_POINTER (tex),
                             rectangle_texture_destroy_cb);

  /* Use cogl_texture_set_region instead of uploading the data
     directly with GL calls so that we can let Cogl deal with setting
     the pixel store parameters and handling format conversion */
  if (data)
    cogl_texture_set_region (cogl_tex,
                             0, 0, /* src x/y */
                             0, 0, /* dst x/y */
                             width, height, /* dst width/height */
                             width, height, /* src width/height */
                             format,
                             rowstride,
                             data);

#endif /* GL_TEXTURE_RECTANGLE_ARB */

  return cogl_tex;
}
Exemplo n.º 16
0
static gboolean
process (GeglOperation       *operation,
         GeglBuffer          *input,
         const GeglRectangle *result,
         gint                 level)
{
    GeglProperties   *o            = GEGL_PROPERTIES (operation);
    const Babl       *input_format;
    const Babl       *data_format;
    gint              bps;
    gint              row_stride;
    gint              n_components;
    guchar           *data;
    CoglPixelFormat   cogl_pixel_format;

    g_object_get (input, "format", &input_format, NULL);

    /* cogl doesnt support anything more than 8bit bps */
    bps          = 8;
    n_components = babl_format_get_n_components (input_format);

    switch (n_components)
    {
        case 1:
            data_format = babl_format ("Y'");
            cogl_pixel_format = COGL_PIXEL_FORMAT_G_8;
            break;

        default:
            if (babl_format_has_alpha (input_format)) {
                data_format = babl_format_new (babl_model ("R'G'B'A"),
                                    babl_type ("u8"),
                                    babl_component ("B'"),
                                    babl_component ("G'"),
                                    babl_component ("R'"),
                                    babl_component ("A"),
                                    NULL);
                cogl_pixel_format = COGL_PIXEL_FORMAT_BGRA_8888;
                n_components = 4;
            }
            else {
                data_format = babl_format_new (babl_model ("R'G'B'"),
                                    babl_type ("u8"),
                                    babl_component ("B'"),
                                    babl_component ("G'"),
                                    babl_component ("R'"),
                                    NULL);
                cogl_pixel_format = COGL_PIXEL_FORMAT_BGR_888;
                n_components = 3;
            }

            break;
    }

    row_stride = result->width * n_components * bps/8;

    data = g_malloc (result->height * row_stride);
    gegl_buffer_get (input,
                     result,  /* rect */
                     1.0,     /* scale */
                     data_format,
                     data,
                     GEGL_AUTO_ROWSTRIDE,
                     GEGL_ABYSS_NONE);

    if (data)
    {
        if (o->texture == NULL)
        {
            CoglTextureFlags flags = COGL_TEXTURE_NONE;

            if (result->width >= 512 && result->height >= 512) {
                flags |= COGL_TEXTURE_NO_ATLAS;
            }

            o->texture = cogl_texture_new_from_data (result->width,
                                                     result->height,
                                                     flags,
                                                     cogl_pixel_format,
                                                     COGL_PIXEL_FORMAT_ANY,
                                                     row_stride,
                                                     data);
        }
        else
        {
            gboolean success;

            success = cogl_texture_set_region (COGL_TEXTURE (o->texture),
                                               0, 0,
                                               result->x, result->y,
                                               result->width, result->height,
                                               result->width, result->height,
                                               cogl_pixel_format,
                                               row_stride,
                                               data);

            if (!success)
            {
                cogl_object_unref (o->texture);
                o->texture = NULL;
            }
        }
    }
    else
    {
        g_warning (G_STRLOC ": inexistant data, unable to create CoglTexture.");
    }

    return TRUE;
}
static void
st_drawing_area_paint (ClutterActor *self)
{
  StDrawingArea *area = ST_DRAWING_AREA (self);
  StDrawingAreaPrivate *priv = area->priv;
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
  ClutterActorBox allocation_box;
  ClutterActorBox content_box;
  int width, height;
  CoglColor color;
  guint8 paint_opacity;

  (CLUTTER_ACTOR_CLASS (st_drawing_area_parent_class))->paint (self);

  clutter_actor_get_allocation_box (self, &allocation_box);
  st_theme_node_get_content_box (theme_node, &allocation_box, &content_box);

  width = (int)(0.5 + content_box.x2 - content_box.x1);
  height = (int)(0.5 + content_box.y2 - content_box.y1);

  if (priv->material == COGL_INVALID_HANDLE)
    priv->material = cogl_material_new ();

  if (priv->texture != COGL_INVALID_HANDLE &&
      (width != cogl_texture_get_width (priv->texture) ||
       height != cogl_texture_get_height (priv->texture)))
    {
      cogl_handle_unref (priv->texture);
      priv->texture = COGL_INVALID_HANDLE;
    }

  if (width > 0 && height > 0)
    {
      if (priv->texture == COGL_INVALID_HANDLE)
        {
          priv->texture = cogl_texture_new_with_size (width, height,
                                                      COGL_TEXTURE_NONE,
                                                      CLUTTER_CAIRO_FORMAT_ARGB32);
          priv->needs_repaint = TRUE;
        }

      if (priv->needs_repaint)
        {
          cairo_surface_t *surface;

          surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
          priv->context = cairo_create (surface);
          priv->in_repaint = TRUE;
          priv->needs_repaint = FALSE;

          g_signal_emit ((GObject*)area, st_drawing_area_signals[REPAINT], 0);

          priv->in_repaint = FALSE;
          cairo_destroy (priv->context);
          priv->context = NULL;

          cogl_texture_set_region (priv->texture, 0, 0, 0, 0, width, height, width, height,
                                   CLUTTER_CAIRO_FORMAT_ARGB32,
                                   cairo_image_surface_get_stride (surface),
                                   cairo_image_surface_get_data (surface));

          cairo_surface_destroy (surface);
        }
    }

  cogl_material_set_layer (priv->material, 0, priv->texture);

  if (priv->texture)
    {
      paint_opacity = clutter_actor_get_paint_opacity (self);
      cogl_color_set_from_4ub (&color,
                               paint_opacity, paint_opacity, paint_opacity, paint_opacity);
      cogl_material_set_color (priv->material, &color);

      cogl_set_source (priv->material);
      cogl_rectangle_with_texture_coords (content_box.x1, content_box.y1,
                                          width, height,
                                          0.0f, 0.0f, 1.0f, 1.0f);
    }
}
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");
}