* clutter/clutter-texture.[ch]: (bug #675) added
clutter_texture_set_area_from_rgb_data, sharing some of the initialization infrastructure with clutter_texture_set_from_rgb_data.
This commit is contained in:
parent
41c9528b4d
commit
06fe42dde9
@ -1,3 +1,9 @@
|
|||||||
|
2007-12-19 Øyvind Kolås <pippin@o-hand.com>
|
||||||
|
|
||||||
|
* clutter/clutter-texture.[ch]: (bug #675) added
|
||||||
|
clutter_texture_set_area_from_rgb_data, sharing some of the
|
||||||
|
initialization infrastructure with clutter_texture_set_from_rgb_data.
|
||||||
|
|
||||||
2007-12-20 Emmanuele Bassi <ebassi@openedhand.com>
|
2007-12-20 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
* clutter/clutter-container.c:
|
* clutter/clutter-container.c:
|
||||||
|
@ -426,14 +426,14 @@ texture_free_gl_resources (ClutterTexture *texture)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void inline
|
||||||
texture_upload_data (ClutterTexture *texture,
|
texture_upload_data (ClutterTexture *texture,
|
||||||
const guchar *data,
|
const guchar *data,
|
||||||
gboolean has_alpha,
|
gboolean has_alpha,
|
||||||
gint width,
|
gint width,
|
||||||
gint height,
|
gint height,
|
||||||
gint rowstride,
|
gint rowstride,
|
||||||
gint bpp)
|
gint bpp)
|
||||||
{
|
{
|
||||||
ClutterTexturePrivate *priv;
|
ClutterTexturePrivate *priv;
|
||||||
gint x, y;
|
gint x, y;
|
||||||
@ -1247,6 +1247,79 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* internal helper function for initialization of
|
||||||
|
* clutter_texture_set_from_rgb_data and clutter_texture_set_area_from_rgb_data.
|
||||||
|
*/
|
||||||
|
static inline gboolean
|
||||||
|
texture_prepare_upload (gboolean initialize,
|
||||||
|
ClutterTexture *texture,
|
||||||
|
const guchar *data,
|
||||||
|
gboolean has_alpha,
|
||||||
|
gint width,
|
||||||
|
gint height,
|
||||||
|
gint rowstride,
|
||||||
|
gint bpp,
|
||||||
|
ClutterTextureFlags flags,
|
||||||
|
guchar **copy_data,
|
||||||
|
gboolean *texture_dirty,
|
||||||
|
gboolean *size_change)
|
||||||
|
{
|
||||||
|
ClutterTexturePrivate *priv;
|
||||||
|
COGLenum prev_format;
|
||||||
|
priv = texture->priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (data != NULL, FALSE);
|
||||||
|
/* Needed for GL_RGBA (internal format) and gdk pixbuf usage */
|
||||||
|
g_return_val_if_fail (bpp == 4, FALSE);
|
||||||
|
|
||||||
|
if (initialize)
|
||||||
|
{
|
||||||
|
*texture_dirty = *size_change =
|
||||||
|
(width != priv->width || height != priv->height) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_format = priv->pixel_format;
|
||||||
|
|
||||||
|
if (has_alpha)
|
||||||
|
priv->pixel_format = CGL_RGBA;
|
||||||
|
else
|
||||||
|
priv->pixel_format = CGL_RGB;
|
||||||
|
|
||||||
|
if (flags & CLUTTER_TEXTURE_RGB_FLAG_BGR)
|
||||||
|
{
|
||||||
|
#if HAVE_COGL_GL
|
||||||
|
if (has_alpha)
|
||||||
|
priv->pixel_format = CGL_BGRA;
|
||||||
|
else
|
||||||
|
priv->pixel_format = CGL_BGR;
|
||||||
|
#else
|
||||||
|
/* GLES has no BGR format*/
|
||||||
|
*copy_data = rgb_to_bgr (data, has_alpha, width, height, rowstride);
|
||||||
|
#endif /* HAVE_COGL_GL */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & CLUTTER_TEXTURE_RGB_FLAG_PREMULT)
|
||||||
|
*copy_data = un_pre_multiply_alpha (data, width, height, rowstride);
|
||||||
|
|
||||||
|
if (initialize)
|
||||||
|
{
|
||||||
|
if (prev_format != priv->pixel_format || priv->pixel_type != PIXEL_TYPE)
|
||||||
|
*texture_dirty = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (prev_format != priv->pixel_format || priv->pixel_type != PIXEL_TYPE)
|
||||||
|
{
|
||||||
|
g_warning ("%s: pixel format or type mismatch", G_STRFUNC);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->pixel_type = PIXEL_TYPE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_texture_set_from_rgb_data:
|
* clutter_texture_set_from_rgb_data:
|
||||||
* @texture: A #ClutterTexture
|
* @texture: A #ClutterTexture
|
||||||
@ -1277,47 +1350,16 @@ clutter_texture_set_from_rgb_data (ClutterTexture *texture,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
ClutterTexturePrivate *priv;
|
ClutterTexturePrivate *priv;
|
||||||
gboolean texture_dirty = TRUE, size_change = FALSE;
|
|
||||||
COGLenum prev_format;
|
|
||||||
guchar *copy_data = NULL;
|
guchar *copy_data = NULL;
|
||||||
|
gboolean texture_dirty = TRUE, size_change = FALSE;
|
||||||
|
|
||||||
priv = texture->priv;
|
priv = texture->priv;
|
||||||
|
if (!texture_prepare_upload (TRUE, texture, data, has_alpha, width, height, rowstride,
|
||||||
g_return_val_if_fail (data != NULL, FALSE);
|
bpp, flags, ©_data, &texture_dirty, &size_change))
|
||||||
|
|
||||||
/* Needed for GL_RGBA (internal format) and gdk pixbuf usage */
|
|
||||||
g_return_val_if_fail (bpp == 4, FALSE);
|
|
||||||
|
|
||||||
texture_dirty = size_change =
|
|
||||||
(width != priv->width || height != priv->height) ;
|
|
||||||
|
|
||||||
prev_format = priv->pixel_format;
|
|
||||||
|
|
||||||
if (has_alpha)
|
|
||||||
priv->pixel_format = CGL_RGBA;
|
|
||||||
else
|
|
||||||
priv->pixel_format = CGL_RGB;
|
|
||||||
|
|
||||||
if (flags & CLUTTER_TEXTURE_RGB_FLAG_BGR)
|
|
||||||
{
|
{
|
||||||
#if HAVE_COGL_GL
|
return FALSE;
|
||||||
if (has_alpha)
|
|
||||||
priv->pixel_format = CGL_BGRA;
|
|
||||||
else
|
|
||||||
priv->pixel_format = CGL_BGR;
|
|
||||||
#else
|
|
||||||
/* GLES has no BGR format*/
|
|
||||||
copy_data = rgb_to_bgr (data, has_alpha, width, height, rowstride);
|
|
||||||
#endif /* HAVE_COGL_GL */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & CLUTTER_TEXTURE_RGB_FLAG_PREMULT)
|
|
||||||
copy_data = un_pre_multiply_alpha (data, width, height, rowstride);
|
|
||||||
|
|
||||||
if (prev_format != priv->pixel_format || priv->pixel_type != PIXEL_TYPE)
|
|
||||||
texture_dirty = TRUE;
|
|
||||||
|
|
||||||
priv->pixel_type = PIXEL_TYPE;
|
|
||||||
priv->width = width;
|
priv->width = width;
|
||||||
priv->height = height;
|
priv->height = height;
|
||||||
|
|
||||||
@ -1781,3 +1823,253 @@ clutter_texture_is_tiled (ClutterTexture *texture)
|
|||||||
|
|
||||||
return texture->priv->is_tiled;
|
return texture->priv->is_tiled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void inline
|
||||||
|
texture_update_data (ClutterTexture *texture,
|
||||||
|
const guchar *data,
|
||||||
|
gboolean has_alpha,
|
||||||
|
gint x0,
|
||||||
|
gint y0,
|
||||||
|
gint width,
|
||||||
|
gint height,
|
||||||
|
gint rowstride,
|
||||||
|
gint bpp)
|
||||||
|
{
|
||||||
|
ClutterTexturePrivate *priv;
|
||||||
|
gint x, y;
|
||||||
|
gint i = 0;
|
||||||
|
gboolean create_textures = FALSE;
|
||||||
|
|
||||||
|
priv = texture->priv;
|
||||||
|
|
||||||
|
g_return_if_fail (data != NULL);
|
||||||
|
|
||||||
|
CLUTTER_MARK();
|
||||||
|
|
||||||
|
if (!priv->is_tiled)
|
||||||
|
{
|
||||||
|
g_assert (priv->tiles);
|
||||||
|
|
||||||
|
CLUTTER_NOTE (TEXTURE, "syncing for single tile");
|
||||||
|
|
||||||
|
cogl_texture_bind (priv->target_type, priv->tiles[0]);
|
||||||
|
cogl_texture_set_alignment (priv->target_type, 4, width);
|
||||||
|
|
||||||
|
cogl_texture_set_filters
|
||||||
|
(priv->target_type,
|
||||||
|
priv->filter_quality ? CGL_LINEAR : CGL_NEAREST,
|
||||||
|
priv->filter_quality ? CGL_LINEAR : CGL_NEAREST);
|
||||||
|
|
||||||
|
cogl_texture_set_wrap (priv->target_type,
|
||||||
|
priv->repeat_x ? CGL_REPEAT : CGL_CLAMP_TO_EDGE,
|
||||||
|
priv->repeat_y ? CGL_REPEAT : CGL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
priv->filter_quality = 1;
|
||||||
|
|
||||||
|
cogl_texture_sub_image_2d (priv->target_type,
|
||||||
|
x0,
|
||||||
|
y0,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
priv->pixel_format,
|
||||||
|
priv->pixel_type,
|
||||||
|
data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Multiple tiled texture */
|
||||||
|
|
||||||
|
CLUTTER_NOTE (TEXTURE,
|
||||||
|
"syncing for multiple tiles for %ix%i pixbuf",
|
||||||
|
priv->width, priv->height);
|
||||||
|
|
||||||
|
g_return_if_fail (priv->x_tiles != NULL && priv->y_tiles != NULL);
|
||||||
|
|
||||||
|
if (priv->tiles == NULL)
|
||||||
|
{
|
||||||
|
g_assert (0);
|
||||||
|
priv->tiles = g_new (COGLuint, priv->n_x_tiles * priv->n_y_tiles);
|
||||||
|
glGenTextures (priv->n_x_tiles * priv->n_y_tiles, priv->tiles);
|
||||||
|
create_textures = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (x = 0; x < priv->n_x_tiles; x++)
|
||||||
|
for (y = 0; y < priv->n_y_tiles; y++)
|
||||||
|
{
|
||||||
|
gint master_offset_x;
|
||||||
|
gint effective_x;
|
||||||
|
gint effective_width;
|
||||||
|
|
||||||
|
gint master_offset_y;
|
||||||
|
gint effective_y;
|
||||||
|
gint effective_height;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
-- first tile --
|
||||||
|
|--------------------- priv->width ------------------------------|
|
||||||
|
| <- priv->x_tiles[x].pos
|
||||||
|
|-----------| <- priv->x_tiles[x].size
|
||||||
|
|-------| <- x0
|
||||||
|
|------------| <- width
|
||||||
|
|--------------------| <- x0 + width
|
||||||
|
|-------| <- master_offset = -8
|
||||||
|
|-------| <- effective_x = 8
|
||||||
|
|---| <- effective_width
|
||||||
|
|
||||||
|
-- second tile ---
|
||||||
|
|
||||||
|
|--------------------- priv->width ------------------------------|
|
||||||
|
|-----------| <- priv->x_tiles[x].pos
|
||||||
|
|-----------| <- priv->x_tiles[x].size (src_w)
|
||||||
|
|-------| <- x0
|
||||||
|
|------------| <- width
|
||||||
|
|--------------------| <- x0 + width
|
||||||
|
|---| <- master_offset = 4
|
||||||
|
| <- effective_x (0 in between)
|
||||||
|
|--------| <- effective_width
|
||||||
|
|
||||||
|
|
||||||
|
XXXXXXXXXXXXXX <- master
|
||||||
|
|___________|___________|___________|___________|___________|_____%%%%%%|
|
||||||
|
*/
|
||||||
|
|
||||||
|
gint src_w, src_h;
|
||||||
|
|
||||||
|
src_w = priv->x_tiles[x].size;
|
||||||
|
src_h = priv->y_tiles[y].size;
|
||||||
|
|
||||||
|
/* skip tiles that do not intersect the updated region */
|
||||||
|
if ((priv->x_tiles[x].pos + src_w < x0 ||
|
||||||
|
priv->y_tiles[y].pos + src_h < y0 ||
|
||||||
|
priv->x_tiles[x].pos >= x0 + width ||
|
||||||
|
priv->y_tiles[y].pos >= y0 + height))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
master_offset_x = priv->x_tiles[x].pos - x0;
|
||||||
|
|
||||||
|
if (priv->x_tiles[x].pos > x0)
|
||||||
|
effective_x = 0;
|
||||||
|
else
|
||||||
|
effective_x = x0 - priv->x_tiles[x].pos;
|
||||||
|
|
||||||
|
effective_width = (x0 + width) - priv->x_tiles[x].pos;
|
||||||
|
|
||||||
|
if (effective_width > src_w - effective_x)
|
||||||
|
effective_width = src_w - effective_x;
|
||||||
|
|
||||||
|
master_offset_y = priv->y_tiles[y].pos - y0;
|
||||||
|
|
||||||
|
if (priv->y_tiles[y].pos > y0)
|
||||||
|
effective_y = 0;
|
||||||
|
else
|
||||||
|
effective_y = y0 - priv->y_tiles[y].pos;
|
||||||
|
|
||||||
|
effective_height = (y0 + height) - priv->y_tiles[y].pos;
|
||||||
|
if (effective_height > src_h - effective_y)
|
||||||
|
effective_height = src_h - effective_y;
|
||||||
|
|
||||||
|
if (master_offset_x < 0)
|
||||||
|
master_offset_x = 0;
|
||||||
|
if (master_offset_y < 0)
|
||||||
|
master_offset_y = 0;
|
||||||
|
|
||||||
|
if (master_offset_x + effective_width > width)
|
||||||
|
effective_width = width - master_offset_x;
|
||||||
|
if (master_offset_y + effective_height > height)
|
||||||
|
effective_height = height - master_offset_y;
|
||||||
|
|
||||||
|
cogl_texture_bind (priv->target_type, priv->tiles[i]);
|
||||||
|
|
||||||
|
cogl_texture_set_alignment (priv->target_type, 4, rowstride/4);
|
||||||
|
|
||||||
|
cogl_texture_set_filters
|
||||||
|
(priv->target_type,
|
||||||
|
priv->filter_quality ? CGL_LINEAR : CGL_NEAREST,
|
||||||
|
priv->filter_quality ? CGL_LINEAR : CGL_NEAREST);
|
||||||
|
|
||||||
|
cogl_texture_set_wrap (priv->target_type,
|
||||||
|
priv->repeat_x ? CGL_REPEAT : CGL_CLAMP_TO_EDGE,
|
||||||
|
priv->repeat_y ? CGL_REPEAT : CGL_CLAMP_TO_EDGE);
|
||||||
|
cogl_texture_sub_image_2d (priv->target_type,
|
||||||
|
effective_x,
|
||||||
|
effective_y,
|
||||||
|
effective_width,
|
||||||
|
effective_height,
|
||||||
|
priv->pixel_format,
|
||||||
|
priv->pixel_type,
|
||||||
|
data + (master_offset_y * width + master_offset_x) * 4);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_texture_set_area_from_rgb_data:
|
||||||
|
* @texture: A #ClutterTexture
|
||||||
|
* @data: Image data in RGB type colorspace.
|
||||||
|
* @has_alpha: Set to TRUE if image data has a alpha channel.
|
||||||
|
* @x: X coordinate of upper left corner of region to update.
|
||||||
|
* @y: Y coordinate of upper left corner of region to update.
|
||||||
|
* @width: Width in pixels of region to update.
|
||||||
|
* @height: Height in pixels of region to update.
|
||||||
|
* @rowstride: Distance in bytes between row starts.
|
||||||
|
* @bpp: bytes per pixel ( Currently only 4 supported )
|
||||||
|
* @flags: #ClutterTextureFlags
|
||||||
|
* @error: FIXME.
|
||||||
|
*
|
||||||
|
* Updates a subregion of the pixel data in a #ClutterTexture.
|
||||||
|
*
|
||||||
|
* Return value: TRUE on success, FALSE on failure.
|
||||||
|
*
|
||||||
|
* Since 0.6.
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
clutter_texture_set_area_from_rgb_data (ClutterTexture *texture,
|
||||||
|
const guchar *data,
|
||||||
|
gboolean has_alpha,
|
||||||
|
gint x,
|
||||||
|
gint y,
|
||||||
|
gint width,
|
||||||
|
gint height,
|
||||||
|
gint rowstride,
|
||||||
|
gint bpp,
|
||||||
|
ClutterTextureFlags flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ClutterTexturePrivate *priv;
|
||||||
|
guchar *copy_data = NULL;
|
||||||
|
|
||||||
|
priv = texture->priv;
|
||||||
|
|
||||||
|
if (!texture_prepare_upload (FALSE, texture, data, has_alpha, width, height, rowstride,
|
||||||
|
bpp, flags, ©_data, NULL, NULL))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture_update_data (texture,
|
||||||
|
copy_data != NULL ? copy_data : data,
|
||||||
|
has_alpha,
|
||||||
|
x, y,
|
||||||
|
width, height,
|
||||||
|
rowstride,
|
||||||
|
bpp);
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_SET_FLAGS (CLUTTER_ACTOR (texture), CLUTTER_ACTOR_REALIZED);
|
||||||
|
|
||||||
|
/* rename signal */
|
||||||
|
g_signal_emit (texture, texture_signals[PIXBUF_CHANGE], 0);
|
||||||
|
|
||||||
|
if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR(texture)))
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR(texture));
|
||||||
|
|
||||||
|
if (copy_data != NULL)
|
||||||
|
g_free (copy_data);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@ -94,7 +94,7 @@ struct _ClutterTextureClass
|
|||||||
* @CLUTTER_TEXTURE_YUV_FLAG_YUV2: FIXME
|
* @CLUTTER_TEXTURE_YUV_FLAG_YUV2: FIXME
|
||||||
*
|
*
|
||||||
* Flags for clutter_texture_set_from_rgb_data() and
|
* Flags for clutter_texture_set_from_rgb_data() and
|
||||||
* clutter_texture_set_from_rgb_data().
|
* clutter_texture_set_from_yuv_data().
|
||||||
*
|
*
|
||||||
* Since: 0.4
|
* Since: 0.4
|
||||||
*/
|
*/
|
||||||
@ -119,6 +119,19 @@ gboolean clutter_texture_set_from_rgb_data (ClutterTexture *texture,
|
|||||||
gint bpp,
|
gint bpp,
|
||||||
ClutterTextureFlags flags,
|
ClutterTextureFlags flags,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
gboolean clutter_texture_set_area_from_rgb_data (ClutterTexture *texture,
|
||||||
|
const guchar *data,
|
||||||
|
gboolean has_alpha,
|
||||||
|
gint x,
|
||||||
|
gint y,
|
||||||
|
gint width,
|
||||||
|
gint height,
|
||||||
|
gint rowstride,
|
||||||
|
gint bpp,
|
||||||
|
ClutterTextureFlags flags,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
gboolean clutter_texture_set_from_yuv_data (ClutterTexture *texture,
|
gboolean clutter_texture_set_from_yuv_data (ClutterTexture *texture,
|
||||||
const guchar *data,
|
const guchar *data,
|
||||||
gint width,
|
gint width,
|
||||||
|
Loading…
Reference in New Issue
Block a user