mirror of
https://github.com/brl/mutter.git
synced 2024-12-22 19:12:04 +00:00
Merge from stable: fix texture tiling
Revert to copying GdkPixbuf areas to correctly implement the texture tiling. This fixes segmentation faults occurring with cards with a small texture memory area.
This commit is contained in:
parent
09487c904a
commit
e89f08560d
@ -383,8 +383,10 @@ texture_upload_data (ClutterTexture *texture,
|
|||||||
gint bpp)
|
gint bpp)
|
||||||
{
|
{
|
||||||
ClutterTexturePrivate *priv;
|
ClutterTexturePrivate *priv;
|
||||||
int x, y, i = 0;
|
gint x, y;
|
||||||
|
gint i = 0;
|
||||||
gboolean create_textures = FALSE;
|
gboolean create_textures = FALSE;
|
||||||
|
GdkPixbuf *master_pixbuf = NULL;
|
||||||
|
|
||||||
priv = texture->priv;
|
priv = texture->priv;
|
||||||
|
|
||||||
@ -467,6 +469,13 @@ texture_upload_data (ClutterTexture *texture,
|
|||||||
|
|
||||||
g_return_if_fail (priv->x_tiles != NULL && priv->y_tiles != NULL);
|
g_return_if_fail (priv->x_tiles != NULL && priv->y_tiles != NULL);
|
||||||
|
|
||||||
|
master_pixbuf = gdk_pixbuf_new_from_data (data,
|
||||||
|
GDK_COLORSPACE_RGB,
|
||||||
|
has_alpha,
|
||||||
|
8,
|
||||||
|
width, height, rowstride,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
if (priv->tiles == NULL)
|
if (priv->tiles == NULL)
|
||||||
{
|
{
|
||||||
priv->tiles = g_new (GLuint, priv->n_x_tiles * priv->n_y_tiles);
|
priv->tiles = g_new (GLuint, priv->n_x_tiles * priv->n_y_tiles);
|
||||||
@ -477,42 +486,31 @@ texture_upload_data (ClutterTexture *texture,
|
|||||||
for (x = 0; x < priv->n_x_tiles; x++)
|
for (x = 0; x < priv->n_x_tiles; x++)
|
||||||
for (y = 0; y < priv->n_y_tiles; y++)
|
for (y = 0; y < priv->n_y_tiles; y++)
|
||||||
{
|
{
|
||||||
guchar *tmp;
|
GdkPixbuf *pixtmp;
|
||||||
gint src_h, src_w, dy;
|
gint src_h, src_w;
|
||||||
|
|
||||||
src_w = priv->x_tiles[x].size;
|
src_w = priv->x_tiles[x].size;
|
||||||
src_h = priv->y_tiles[y].size;
|
src_h = priv->y_tiles[y].size;
|
||||||
|
|
||||||
/* fixme - gslice ? */
|
pixtmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
|
||||||
tmp = g_malloc (sizeof (guchar) * priv->x_tiles[x].size
|
has_alpha,
|
||||||
* priv->y_tiles[y].size
|
8,
|
||||||
* bpp);
|
src_w, src_h);
|
||||||
|
|
||||||
/* clip */
|
/* clip */
|
||||||
if (priv->x_tiles[x].pos + src_w > priv->width)
|
if (priv->x_tiles[x].pos + src_w > priv->width)
|
||||||
{
|
|
||||||
src_w = priv->width - priv->x_tiles[x].pos;
|
src_w = priv->width - priv->x_tiles[x].pos;
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->y_tiles[y].pos + src_h > priv->height)
|
if (priv->y_tiles[y].pos + src_h > priv->height)
|
||||||
{
|
|
||||||
src_h = priv->height - priv->y_tiles[y].pos;
|
src_h = priv->height - priv->y_tiles[y].pos;
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (TEXTURE,
|
gdk_pixbuf_copy_area (master_pixbuf,
|
||||||
"copying tile %i,%i - %ix%i to 0,0 %ix%i",
|
priv->x_tiles[x].pos,
|
||||||
priv->x_tiles[x].pos, priv->y_tiles[y].pos,
|
priv->y_tiles[y].pos,
|
||||||
src_w, src_h,
|
src_w,
|
||||||
priv->x_tiles[x].size,
|
src_h,
|
||||||
priv->y_tiles[y].size);
|
pixtmp,
|
||||||
|
0, 0);
|
||||||
for (dy = 0; dy < src_h; dy++)
|
|
||||||
{
|
|
||||||
memcpy (tmp + (dy * src_w * bpp),
|
|
||||||
data + ((priv->y_tiles[y].pos + dy) * rowstride)
|
|
||||||
+ (priv->x_tiles[x].pos * bpp),
|
|
||||||
(src_w * bpp));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CLUTTER_DUMP_TILES
|
#ifdef CLUTTER_DUMP_TILES
|
||||||
{
|
{
|
||||||
@ -549,15 +547,13 @@ texture_upload_data (ClutterTexture *texture,
|
|||||||
|
|
||||||
if (create_textures)
|
if (create_textures)
|
||||||
{
|
{
|
||||||
glTexImage2D(priv->target_type,
|
glTexImage2D (priv->target_type, 0, GL_RGBA,
|
||||||
0,
|
gdk_pixbuf_get_width (pixtmp),
|
||||||
(bpp == 4) ? GL_RGBA : GL_RGB,
|
gdk_pixbuf_get_height (pixtmp),
|
||||||
priv->x_tiles[x].size,
|
|
||||||
priv->y_tiles[y].size,
|
|
||||||
0,
|
0,
|
||||||
priv->pixel_format,
|
priv->pixel_format,
|
||||||
priv->pixel_type,
|
priv->pixel_type,
|
||||||
tmp);
|
gdk_pixbuf_get_pixels (pixtmp));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -565,17 +561,19 @@ texture_upload_data (ClutterTexture *texture,
|
|||||||
*/
|
*/
|
||||||
glTexSubImage2D (priv->target_type, 0,
|
glTexSubImage2D (priv->target_type, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
priv->x_tiles[x].size,
|
gdk_pixbuf_get_width (pixtmp),
|
||||||
priv->y_tiles[y].size,
|
gdk_pixbuf_get_height (pixtmp),
|
||||||
priv->pixel_format,
|
priv->pixel_format,
|
||||||
priv->pixel_type,
|
priv->pixel_type,
|
||||||
tmp);
|
gdk_pixbuf_get_pixels (pixtmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(tmp);
|
g_object_unref (pixtmp);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_object_unref (master_pixbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -754,8 +752,7 @@ clutter_texture_set_property (GObject *object,
|
|||||||
case PROP_USE_TILES:
|
case PROP_USE_TILES:
|
||||||
priv->is_tiled = g_value_get_boolean (value);
|
priv->is_tiled = g_value_get_boolean (value);
|
||||||
|
|
||||||
if (priv->target_type == GL_TEXTURE_RECTANGLE_ARB &&
|
if (priv->target_type == GL_TEXTURE_RECTANGLE_ARB && priv->is_tiled)
|
||||||
priv->is_tiled)
|
|
||||||
priv->target_type = GL_TEXTURE_2D;
|
priv->target_type = GL_TEXTURE_2D;
|
||||||
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Texture is tiled ? %s",
|
CLUTTER_NOTE (TEXTURE, "Texture is tiled ? %s",
|
||||||
@ -1052,9 +1049,9 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
|
|||||||
|
|
||||||
if (!priv->is_tiled)
|
if (!priv->is_tiled)
|
||||||
{
|
{
|
||||||
pixels = g_malloc (priv->width * priv->height * bpp);
|
pixels = g_malloc (((priv->width * bpp + 3) &~ 3) * priv->height);
|
||||||
|
|
||||||
if (pixels == NULL)
|
if (!pixels)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
glBindTexture(priv->target_type, priv->tiles[0]);
|
glBindTexture(priv->target_type, priv->tiles[0]);
|
||||||
@ -1075,7 +1072,7 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
|
|||||||
8,
|
8,
|
||||||
priv->width,
|
priv->width,
|
||||||
priv->height,
|
priv->height,
|
||||||
priv->width * bpp,
|
((priv->width * bpp + 3) &~ 3),
|
||||||
pixbuf_destroy_notify,
|
pixbuf_destroy_notify,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
@ -1100,7 +1097,7 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
|
|||||||
src_w = priv->x_tiles[x].size;
|
src_w = priv->x_tiles[x].size;
|
||||||
src_h = priv->y_tiles[y].size;
|
src_h = priv->y_tiles[y].size;
|
||||||
|
|
||||||
pixels = g_malloc (src_w * src_h * bpp);
|
pixels = g_malloc (((src_w * bpp) &~ 3) * src_h);
|
||||||
|
|
||||||
glBindTexture(priv->target_type, priv->tiles[i]);
|
glBindTexture(priv->target_type, priv->tiles[i]);
|
||||||
|
|
||||||
@ -1113,14 +1110,21 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
|
|||||||
priv->pixel_type,
|
priv->pixel_type,
|
||||||
(GLvoid *) pixels);
|
(GLvoid *) pixels);
|
||||||
|
|
||||||
tmp_pixb
|
/* Clip */
|
||||||
= gdk_pixbuf_new_from_data ((const guchar*)pixels,
|
if (priv->x_tiles[x].pos + src_w > priv->width)
|
||||||
|
src_w = priv->width - priv->x_tiles[x].pos;
|
||||||
|
|
||||||
|
if (priv->y_tiles[y].pos + src_h > priv->height)
|
||||||
|
src_h = priv->height = priv->y_tiles[y].pos;
|
||||||
|
|
||||||
|
tmp_pixb =
|
||||||
|
gdk_pixbuf_new_from_data ((const guchar*)pixels,
|
||||||
GDK_COLORSPACE_RGB,
|
GDK_COLORSPACE_RGB,
|
||||||
(priv->pixel_format == GL_RGBA),
|
(priv->pixel_format == GL_RGBA),
|
||||||
8,
|
8,
|
||||||
src_w,
|
src_w,
|
||||||
src_h,
|
src_h,
|
||||||
src_w * bpp,
|
((src_w * bpp + 3) &~ 3),
|
||||||
pixbuf_destroy_notify,
|
pixbuf_destroy_notify,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user