mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
* clutter/clutter-texture.c: applied modified patch from Gwenole
Beuchesne adressing bug #635. Adressing a buffer overflow in clutter_texture_get_pixbuf() when tiling is forced.
This commit is contained in:
parent
b884bc4dd5
commit
17f54fd7b8
@ -1,3 +1,9 @@
|
||||
2008-02-05 Øyvind Kolås <pippin@o-hand.com>
|
||||
|
||||
* clutter/clutter-texture.c: applied modified patch from Gwenole
|
||||
Beuchesne adressing bug #635. Adressing a buffer overflow in
|
||||
clutter_texture_get_pixbuf() when tiling is forced.
|
||||
|
||||
2008-02-04 Emmanuele Bassi <ebassi@openedhand.com>
|
||||
|
||||
* clutter/clutter-shader.c (clutter_shader_constructor): Keep the
|
||||
|
@ -1153,6 +1153,54 @@ pixbuf_destroy_notify (guchar *pixels, gpointer data)
|
||||
g_free (pixels);
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
texture_get_tile_pixbuf (ClutterTexture *texture, COGLuint texture_id, int bpp)
|
||||
{
|
||||
ClutterTexturePrivate *priv;
|
||||
guchar *pixels = NULL;
|
||||
guint tex_width, tex_height;
|
||||
|
||||
priv = texture->priv;
|
||||
cogl_texture_bind (priv->target_type, texture_id);
|
||||
cogl_texture_set_alignment (priv->target_type, 4, tex_width);
|
||||
|
||||
tex_width = priv->width;
|
||||
tex_height = priv->height;
|
||||
|
||||
if (priv->target_type == CGL_TEXTURE_2D) /* POT */
|
||||
{
|
||||
tex_width = clutter_util_next_p2 (priv->width);
|
||||
tex_height = clutter_util_next_p2 (priv->height);
|
||||
}
|
||||
|
||||
g_print ("%i %i\n", tex_width, tex_height);
|
||||
|
||||
if ((pixels = g_malloc (((tex_width * bpp + 3) &~ 3) * tex_height)) == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Read data from GL texture and return as pixbuf */
|
||||
/* No such func in GLES... */
|
||||
glGetTexImage (priv->target_type,
|
||||
0,
|
||||
(priv->pixel_format == CGL_RGBA
|
||||
|| priv->pixel_format == CGL_BGRA) ?
|
||||
CGL_RGBA : CGL_RGB,
|
||||
PIXEL_TYPE,
|
||||
(GLvoid *)pixels);
|
||||
|
||||
|
||||
return gdk_pixbuf_new_from_data ((const guchar *)pixels,
|
||||
GDK_COLORSPACE_RGB,
|
||||
(priv->pixel_format == CGL_RGBA
|
||||
|| priv->pixel_format == CGL_BGRA),
|
||||
8,
|
||||
tex_width,
|
||||
tex_height,
|
||||
((tex_width * bpp + 3) &~ 3),
|
||||
pixbuf_destroy_notify,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_texture_get_pixbuf:
|
||||
* @texture: A #ClutterTexture
|
||||
@ -1169,8 +1217,8 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
|
||||
{
|
||||
#if HAVE_COGL_GL
|
||||
ClutterTexturePrivate *priv;
|
||||
GdkPixbuf *pixbuf = NULL;
|
||||
guchar *pixels = NULL;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPixbuf *pixtmp;
|
||||
int bpp = 4;
|
||||
|
||||
priv = texture->priv;
|
||||
@ -1184,38 +1232,40 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
|
||||
if (priv->pixel_format == CGL_RGB || priv->pixel_format == CGL_BGR)
|
||||
bpp = 3;
|
||||
|
||||
if (!priv->is_tiled)
|
||||
{
|
||||
pixels = g_malloc (((priv->width * bpp + 3) &~ 3) * priv->height);
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
priv->pixel_format == CGL_RGBA ||
|
||||
priv->pixel_format == CGL_BGRA,
|
||||
8, priv->width, priv->height);
|
||||
|
||||
if (!pixels)
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
|
||||
glBindTexture(priv->target_type, priv->tiles[0]);
|
||||
if (!priv->is_tiled)
|
||||
{
|
||||
pixtmp = texture_get_tile_pixbuf (texture, priv->tiles[0], bpp);
|
||||
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, priv->width);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
|
||||
if (pixtmp == NULL)
|
||||
{
|
||||
g_object_unref (pixbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* read data from gl text and return as pixbuf */
|
||||
/* No such func in gles... */
|
||||
glGetTexImage (priv->target_type,
|
||||
0,
|
||||
(priv->pixel_format == CGL_RGBA
|
||||
|| priv->pixel_format == CGL_BGRA) ?
|
||||
CGL_RGBA : CGL_RGB,
|
||||
PIXEL_TYPE,
|
||||
(GLvoid*)pixels);
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_data ((const guchar*)pixels,
|
||||
GDK_COLORSPACE_RGB,
|
||||
(priv->pixel_format == CGL_RGBA
|
||||
|| priv->pixel_format == CGL_BGRA),
|
||||
8,
|
||||
priv->width,
|
||||
priv->height,
|
||||
((priv->width * bpp + 3) &~ 3),
|
||||
pixbuf_destroy_notify,
|
||||
NULL);
|
||||
/* Avoid a copy if the texture has the same size as the pixbuf */
|
||||
if ((gdk_pixbuf_get_width (pixtmp) == priv->width &&
|
||||
gdk_pixbuf_get_height (pixtmp) == priv->height))
|
||||
{
|
||||
g_object_unref (pixbuf);
|
||||
pixbuf = pixtmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_pixbuf_copy_area (pixtmp,
|
||||
0, 0,
|
||||
priv->width, priv->height,
|
||||
pixbuf,
|
||||
0, 0);
|
||||
g_object_unref (pixtmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1223,49 +1273,22 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
|
||||
|
||||
i = 0;
|
||||
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||
(priv->pixel_format == CGL_RGBA
|
||||
|| priv->pixel_format == CGL_BGRA),
|
||||
8,
|
||||
priv->width,
|
||||
priv->height);
|
||||
|
||||
for (x = 0; x < priv->n_x_tiles; x++)
|
||||
for (y = 0; y < priv->n_y_tiles; y++)
|
||||
{
|
||||
GdkPixbuf *tmp_pixb;
|
||||
gint src_h, src_w;
|
||||
gint src_w, src_h;
|
||||
|
||||
pixtmp = texture_get_tile_pixbuf (texture, priv->tiles[i], bpp);
|
||||
|
||||
if (pixtmp == NULL)
|
||||
{
|
||||
g_object_unref (pixbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src_w = priv->x_tiles[x].size;
|
||||
src_h = priv->y_tiles[y].size;
|
||||
|
||||
pixels = g_malloc (((src_w * bpp + 3) &~ 3) * src_h);
|
||||
|
||||
glBindTexture(priv->target_type, priv->tiles[i]);
|
||||
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, src_w);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
|
||||
|
||||
glGetTexImage (priv->target_type,
|
||||
0,
|
||||
(priv->pixel_format == CGL_RGBA
|
||||
|| priv->pixel_format == CGL_BGRA) ?
|
||||
CGL_RGBA : CGL_RGB,
|
||||
PIXEL_TYPE,
|
||||
(GLvoid *) pixels);
|
||||
|
||||
tmp_pixb =
|
||||
gdk_pixbuf_new_from_data ((const guchar*)pixels,
|
||||
GDK_COLORSPACE_RGB,
|
||||
(priv->pixel_format == CGL_RGBA
|
||||
|| priv->pixel_format == CGL_BGRA),
|
||||
8,
|
||||
src_w,
|
||||
src_h,
|
||||
((src_w * bpp + 3) &~ 3),
|
||||
pixbuf_destroy_notify,
|
||||
NULL);
|
||||
|
||||
/* Clip */
|
||||
if (priv->x_tiles[x].pos + src_w > priv->width)
|
||||
src_w = priv->width - priv->x_tiles[x].pos;
|
||||
@ -1273,16 +1296,12 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
|
||||
if (priv->y_tiles[y].pos + src_h > priv->height)
|
||||
src_h = priv->height - priv->y_tiles[y].pos;
|
||||
|
||||
gdk_pixbuf_copy_area (tmp_pixb,
|
||||
0,
|
||||
0,
|
||||
src_w,
|
||||
src_h,
|
||||
gdk_pixbuf_copy_area (pixtmp,
|
||||
0, 0, src_w, src_h,
|
||||
pixbuf,
|
||||
priv->x_tiles[x].pos,
|
||||
priv->y_tiles[y].pos);
|
||||
priv->x_tiles[x].pos, priv->y_tiles[y].pos);
|
||||
|
||||
g_object_unref (tmp_pixb);
|
||||
g_object_unref (pixtmp);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user