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:
Emmanuele Bassi 2007-04-19 15:24:20 +00:00
parent 09487c904a
commit e89f08560d

View File

@ -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;
gboolean create_textures = FALSE; gint i = 0;
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, 0,
priv->y_tiles[y].size, priv->pixel_format,
0, priv->pixel_type,
priv->pixel_format, gdk_pixbuf_get_pixels (pixtmp));
priv->pixel_type,
tmp);
} }
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);
} }
@ -1091,8 +1088,8 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
priv->width, priv->width,
priv->height); priv->height);
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++)
{ {
GdkPixbuf *tmp_pixb; GdkPixbuf *tmp_pixb;
gint src_h, src_w; gint src_h, src_w;
@ -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]);
@ -1111,18 +1108,25 @@ clutter_texture_get_pixbuf (ClutterTexture* texture)
0, 0,
priv->pixel_format, priv->pixel_format,
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)
GDK_COLORSPACE_RGB, src_w = priv->width - priv->x_tiles[x].pos;
(priv->pixel_format == GL_RGBA),
8, if (priv->y_tiles[y].pos + src_h > priv->height)
src_w, src_h = priv->height = priv->y_tiles[y].pos;
src_h,
src_w * bpp, tmp_pixb =
pixbuf_destroy_notify, gdk_pixbuf_new_from_data ((const guchar*)pixels,
NULL); GDK_COLORSPACE_RGB,
(priv->pixel_format == GL_RGBA),
8,
src_w,
src_h,
((src_w * bpp + 3) &~ 3),
pixbuf_destroy_notify,
NULL);
gdk_pixbuf_copy_area (tmp_pixb, gdk_pixbuf_copy_area (tmp_pixb,
0, 0,