Use FBOs and use cogl_read_pixels() to efficiently read partial textures

* cogl_texture_get_data() is converted to use
   _cogl_texture_foreach_sub_texture_in_region() to iterate
  through the underlying textures.

 * When we need to read only a portion of the underlying
   texture, we set up a FBO and use _cogl_read_pixels()
   to read the portion we need. This is enormously more
   efficient for reading a small portion of a large atlas
   texture.

 * The CoglAtlasTexture, CoglSubTexture, and CoglTexture2dSliced
   implementation of get_texture() are removed.

http://bugzilla.clutter-project.org/show_bug.cgi?id=2414
This commit is contained in:
Owen W. Taylor
2010-11-12 11:02:13 -05:00
committed by Neil Roberts
parent 47ccbf472e
commit cda29a8011
4 changed files with 186 additions and 241 deletions

View File

@ -1335,153 +1335,6 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex,
return TRUE;
}
static gboolean
_cogl_texture_2d_sliced_download_from_gl (
CoglTexture2DSliced *tex_2ds,
CoglBitmap *target_bmp,
GLuint target_gl_format,
GLuint target_gl_type)
{
CoglSpan *x_span;
CoglSpan *y_span;
CoglHandle slice_tex;
int bpp;
int x, y;
CoglBitmap *slice_bmp;
CoglPixelFormat target_format = _cogl_bitmap_get_format (target_bmp);
bpp = _cogl_get_format_bpp (target_format);
/* Iterate vertical slices */
for (y = 0; y < tex_2ds->slice_y_spans->len; ++y)
{
y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y);
/* Iterate horizontal slices */
for (x = 0; x < tex_2ds->slice_x_spans->len; ++x)
{
/*if (x != 0 || y != 1) continue;*/
x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x);
/* Pick the sliced texture */
slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle,
y * tex_2ds->slice_x_spans->len + x);
/* If there's any waste we need to copy manually
(no glGetTexSubImage) */
if (y_span->waste != 0 || x_span->waste != 0)
{
int rowstride = x_span->size * bpp;
guint8 *data = g_malloc (rowstride * y_span->size);
/* Setup temp bitmap for slice subregion */
slice_bmp = _cogl_bitmap_new_from_data (data,
target_format,
x_span->size,
y_span->size,
rowstride,
(CoglBitmapDestroyNotify)
g_free,
NULL);
/* Setup gl alignment to 0,0 top-left corner */
_cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp);
if (!cogl_texture_get_data (slice_tex,
target_format,
rowstride,
data))
{
/* Free temp bitmap */
cogl_object_unref (slice_bmp);
return FALSE;
}
/* Copy portion of slice from temp to target bmp */
_cogl_bitmap_copy_subregion (slice_bmp,
target_bmp,
0, 0,
x_span->start,
y_span->start,
x_span->size - x_span->waste,
y_span->size - y_span->waste);
/* Free temp bitmap */
cogl_object_unref (slice_bmp);
}
else
{
guint8 *data;
GLvoid *dst;
gboolean ret;
int rowstride = _cogl_bitmap_get_rowstride (target_bmp);
data = _cogl_bitmap_map (target_bmp,
COGL_BUFFER_ACCESS_WRITE,
0);
if (data == NULL)
return FALSE;
dst = data + x_span->start * bpp + y_span->start * rowstride;
_cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp);
/* Download slice image data */
ret = cogl_texture_get_data (slice_tex,
target_format,
rowstride,
dst);
_cogl_bitmap_unmap (target_bmp);
if (!ret)
return ret;
}
}
}
return TRUE;
}
static gboolean
_cogl_texture_2d_sliced_get_data (CoglTexture *tex,
CoglPixelFormat format,
unsigned int rowstride,
guint8 *data)
{
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
int bpp;
GLenum gl_format;
GLenum gl_type;
CoglBitmap *target_bmp;
gboolean ret;
bpp = _cogl_get_format_bpp (format);
_cogl_pixel_format_to_gl (format,
NULL, /* internal format */
&gl_format,
&gl_type);
target_bmp = _cogl_bitmap_new_from_data (data,
format,
tex_2ds->width,
tex_2ds->height,
rowstride,
NULL, /* destroy_fn */
NULL /* destroy_fn_data */);
/* Retrieve data from slices */
ret = _cogl_texture_2d_sliced_download_from_gl (tex_2ds,
target_bmp,
gl_format,
gl_type);
cogl_object_unref (target_bmp);
return ret;
}
static CoglPixelFormat
_cogl_texture_2d_sliced_get_format (CoglTexture *tex)
{
@ -1528,7 +1381,7 @@ static const CoglTextureVtable
cogl_texture_2d_sliced_vtable =
{
_cogl_texture_2d_sliced_set_region,
_cogl_texture_2d_sliced_get_data,
NULL, /* get_data */
_cogl_texture_2d_sliced_foreach_sub_texture_in_region,
_cogl_texture_2d_sliced_get_max_waste,
_cogl_texture_2d_sliced_is_sliced,