diff --git a/clutter/cogl/cogl/cogl-atlas-texture.c b/clutter/cogl/cogl/cogl-atlas-texture.c index 1f32a04bc..54e87e7ea 100644 --- a/clutter/cogl/cogl/cogl-atlas-texture.c +++ b/clutter/cogl/cogl/cogl-atlas-texture.c @@ -595,7 +595,7 @@ _cogl_atlas_texture_set_region (CoglTexture *tex, data); } -static int +static gboolean _cogl_atlas_texture_get_data (CoglTexture *tex, CoglPixelFormat format, unsigned int rowstride, diff --git a/clutter/cogl/cogl/cogl-sub-texture.c b/clutter/cogl/cogl/cogl-sub-texture.c index 8fbcc4dca..bfae32bc7 100644 --- a/clutter/cogl/cogl/cogl-sub-texture.c +++ b/clutter/cogl/cogl/cogl-sub-texture.c @@ -448,7 +448,7 @@ _cogl_sub_texture_copy_region (guint8 *dst, } } -static int +static gboolean _cogl_sub_texture_get_data (CoglTexture *tex, CoglPixelFormat format, unsigned int rowstride, @@ -457,7 +457,7 @@ _cogl_sub_texture_get_data (CoglTexture *tex, CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); unsigned int full_rowstride; guint8 *full_data; - int byte_size, full_size; + gboolean ret = TRUE; int bpp; int full_tex_width, full_tex_height; @@ -466,30 +466,16 @@ _cogl_sub_texture_get_data (CoglTexture *tex, texture_get_sub_data virtual and it can just munge the texture coordinates */ - /* Default to internal format if none specified */ - if (format == COGL_PIXEL_FORMAT_ANY) - format = cogl_texture_get_format (sub_tex->full_texture); - full_tex_width = cogl_texture_get_width (sub_tex->full_texture); full_tex_height = cogl_texture_get_height (sub_tex->full_texture); - /* Rowstride from texture width if none specified */ bpp = _cogl_get_format_bpp (format); - if (rowstride == 0) - rowstride = sub_tex->sub_width * bpp; - - /* Return byte size if only that requested */ - byte_size = sub_tex->sub_height * rowstride; - if (data == NULL) - return byte_size; full_rowstride = _cogl_get_format_bpp (format) * full_tex_width; full_data = g_malloc (full_rowstride * full_tex_height); - full_size = cogl_texture_get_data (sub_tex->full_texture, format, - full_rowstride, full_data); - - if (full_size) + if (cogl_texture_get_data (sub_tex->full_texture, format, + full_rowstride, full_data)) _cogl_sub_texture_copy_region (data, full_data, 0, 0, sub_tex->sub_x, @@ -500,11 +486,11 @@ _cogl_sub_texture_get_data (CoglTexture *tex, full_rowstride, bpp); else - byte_size = 0; + ret = FALSE; g_free (full_data); - return byte_size; + return ret; } static CoglPixelFormat diff --git a/clutter/cogl/cogl/cogl-texture-2d-sliced.c b/clutter/cogl/cogl/cogl-texture-2d-sliced.c index 2a41721ba..3f95eef51 100644 --- a/clutter/cogl/cogl/cogl-texture-2d-sliced.c +++ b/clutter/cogl/cogl/cogl-texture-2d-sliced.c @@ -1633,96 +1633,27 @@ _cogl_texture_2d_sliced_get_data (CoglTexture *tex, { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); int bpp; - int byte_size; - CoglPixelFormat closest_format; - int closest_bpp; - GLenum closest_gl_format; - GLenum closest_gl_type; + GLenum gl_format; + GLenum gl_type; CoglBitmap target_bmp; - CoglBitmap new_bmp; - gboolean success; - guint8 *src; - guint8 *dst; - int y; - /* Default to internal format if none specified */ - if (format == COGL_PIXEL_FORMAT_ANY) - format = tex_2ds->format; - - /* Rowstride from texture width if none specified */ bpp = _cogl_get_format_bpp (format); - if (rowstride == 0) - rowstride = tex_2ds->width * bpp; - /* Return byte size if only that requested */ - byte_size = tex_2ds->height * rowstride; - if (data == NULL) - return byte_size; - - closest_format = - _cogl_texture_driver_find_best_gl_get_data_format (format, - &closest_gl_format, - &closest_gl_type); - closest_bpp = _cogl_get_format_bpp (closest_format); + _cogl_pixel_format_to_gl (format, + NULL, /* internal format */ + &gl_format, + &gl_type); target_bmp.width = tex_2ds->width; target_bmp.height = tex_2ds->height; - - /* Is the requested format supported? */ - if (closest_format == format) - { - /* Target user data directly */ - target_bmp.format = format; - target_bmp.rowstride = rowstride; - target_bmp.data = data; - } - else - { - /* Target intermediate buffer */ - target_bmp.format = closest_format; - target_bmp.rowstride = target_bmp.width * closest_bpp; - target_bmp.data = g_malloc (target_bmp.height * target_bmp.rowstride); - } + target_bmp.format = format; + target_bmp.rowstride = rowstride; + target_bmp.data = data; /* Retrieve data from slices */ - if (!_cogl_texture_2d_sliced_download_from_gl (tex_2ds, &target_bmp, - closest_gl_format, - closest_gl_type)) - { - /* XXX: In some cases _cogl_texture_2d_sliced_download_from_gl may - * fail to read back the texture data; such as for GLES which doesn't - * support glGetTexImage, so here we fallback to drawing the texture - * and reading the pixels from the framebuffer. */ - _cogl_texture_draw_and_read (tex, &target_bmp, - closest_gl_format, - closest_gl_type); - } - - /* Was intermediate used? */ - if (closest_format != format) - { - /* Convert to requested format */ - success = _cogl_bitmap_convert_format_and_premult (&target_bmp, - &new_bmp, - format); - - /* Free intermediate data and return if failed */ - g_free (target_bmp.data); - if (!success) return 0; - - /* Copy to user buffer */ - for (y = 0; y < new_bmp.height; ++y) - { - src = new_bmp.data + y * new_bmp.rowstride; - dst = data + y * rowstride; - memcpy (dst, src, new_bmp.rowstride); - } - - /* Free converted data */ - g_free (new_bmp.data); - } - - return byte_size; + return _cogl_texture_2d_sliced_download_from_gl (tex_2ds, &target_bmp, + gl_format, + gl_type); } static CoglPixelFormat diff --git a/clutter/cogl/cogl/cogl-texture-2d.c b/clutter/cogl/cogl/cogl-texture-2d.c index d4d6c8aa2..32eccb143 100644 --- a/clutter/cogl/cogl/cogl-texture-2d.c +++ b/clutter/cogl/cogl/cogl-texture-2d.c @@ -513,7 +513,7 @@ _cogl_texture_2d_set_region (CoglTexture *tex, return TRUE; } -static int +static gboolean _cogl_texture_2d_get_data (CoglTexture *tex, CoglPixelFormat format, unsigned int rowstride, @@ -521,103 +521,25 @@ _cogl_texture_2d_get_data (CoglTexture *tex, { CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); int bpp; - int byte_size; - CoglPixelFormat closest_format; - int closest_bpp; - GLenum closest_gl_format; - GLenum closest_gl_type; - CoglBitmap target_bmp; - CoglBitmap new_bmp; - gboolean success; - guint8 *src; - guint8 *dst; - int y; + GLenum gl_format; + GLenum gl_type; - /* Default to internal format if none specified */ - if (format == COGL_PIXEL_FORMAT_ANY) - format = tex_2d->format; - - /* Rowstride from texture width if none specified */ bpp = _cogl_get_format_bpp (format); - if (rowstride == 0) - rowstride = tex_2d->width * bpp; - /* Return byte size if only that requested */ - byte_size = tex_2d->height * rowstride; - if (data == NULL) - return byte_size; + _cogl_pixel_format_to_gl (format, + NULL, /* internal format */ + &gl_format, + &gl_type); - closest_format = - _cogl_texture_driver_find_best_gl_get_data_format (format, - &closest_gl_format, - &closest_gl_type); - closest_bpp = _cogl_get_format_bpp (closest_format); - - target_bmp.width = tex_2d->width; - target_bmp.height = tex_2d->height; - - /* Is the requested format supported? */ - if (closest_format == format) - { - /* Target user data directly */ - target_bmp.format = format; - target_bmp.rowstride = rowstride; - target_bmp.data = data; - } - else - { - /* Target intermediate buffer */ - target_bmp.format = closest_format; - target_bmp.rowstride = target_bmp.width * closest_bpp; - target_bmp.data = g_malloc (target_bmp.height * target_bmp.rowstride); - } - - _cogl_texture_driver_prep_gl_for_pixels_download (target_bmp.rowstride, - closest_bpp); + _cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp); _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, tex_2d->gl_texture, FALSE); - if (!_cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_2D, - closest_gl_format, - closest_gl_type, - target_bmp.data)) - { - /* XXX: In some cases _cogl_texture_2d_download_from_gl may - * fail to read back the texture data; such as for GLES which doesn't - * support glGetTexImage, so here we fallback to drawing the texture - * and reading the pixels from the framebuffer. */ - _cogl_texture_draw_and_read (tex, &target_bmp, - closest_gl_format, - closest_gl_type); - } - - /* Was intermediate used? */ - if (closest_format != format) - { - /* Convert to requested format */ - success = _cogl_bitmap_convert_format_and_premult (&target_bmp, - &new_bmp, - format); - - /* Free intermediate data and return if failed */ - g_free (target_bmp.data); - if (!success) - return 0; - - /* Copy to user buffer */ - for (y = 0; y < new_bmp.height; ++y) - { - src = new_bmp.data + y * new_bmp.rowstride; - dst = data + y * rowstride; - memcpy (dst, src, new_bmp.width); - } - - /* Free converted data */ - g_free (new_bmp.data); - } - - return byte_size; + return _cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_2D, + gl_format, + gl_type, + data); } static CoglPixelFormat diff --git a/clutter/cogl/cogl/cogl-texture-private.h b/clutter/cogl/cogl/cogl-texture-private.h index 56b109951..78330c618 100644 --- a/clutter/cogl/cogl/cogl-texture-private.h +++ b/clutter/cogl/cogl/cogl-texture-private.h @@ -81,10 +81,15 @@ struct _CoglTextureVtable unsigned int rowstride, const guint8 *data); - int (* get_data) (CoglTexture *tex, - CoglPixelFormat format, - unsigned int rowstride, - guint8 *data); + /* This should copy the image data of the texture into @data. The + requested format will have been first passed through + _cogl_texture_driver_find_best_gl_get_data_format so it should + always be a format that is valid for GL (ie, no conversion should + be necessary). */ + gboolean (* get_data) (CoglTexture *tex, + CoglPixelFormat format, + unsigned int rowstride, + guint8 *data); void (* foreach_sub_texture_in_region) (CoglTexture *tex, float virtual_tx_1, diff --git a/clutter/cogl/cogl/cogl-texture-rectangle.c b/clutter/cogl/cogl/cogl-texture-rectangle.c index f797f50c0..2a61e78d3 100644 --- a/clutter/cogl/cogl/cogl-texture-rectangle.c +++ b/clutter/cogl/cogl/cogl-texture-rectangle.c @@ -507,111 +507,33 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex, return TRUE; } -static int +static gboolean _cogl_texture_rectangle_get_data (CoglTexture *tex, CoglPixelFormat format, unsigned int rowstride, guint8 *data) { - CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex); - int bpp; - int byte_size; - CoglPixelFormat closest_format; - int closest_bpp; - GLenum closest_gl_format; - GLenum closest_gl_type; - CoglBitmap target_bmp; - CoglBitmap new_bmp; - gboolean success; - guint8 *src; - guint8 *dst; - int y; + CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex); + int bpp; + GLenum gl_format; + GLenum gl_type; - /* Default to internal format if none specified */ - if (format == COGL_PIXEL_FORMAT_ANY) - format = tex_rect->format; - - /* Rowstride from texture width if none specified */ bpp = _cogl_get_format_bpp (format); - if (rowstride == 0) - rowstride = tex_rect->width * bpp; - /* Return byte size if only that requested */ - byte_size = tex_rect->height * rowstride; - if (data == NULL) - return byte_size; + _cogl_pixel_format_to_gl (format, + NULL, /* internal format */ + &gl_format, + &gl_type); - closest_format = - _cogl_texture_driver_find_best_gl_get_data_format (format, - &closest_gl_format, - &closest_gl_type); - closest_bpp = _cogl_get_format_bpp (closest_format); - - target_bmp.width = tex_rect->width; - target_bmp.height = tex_rect->height; - - /* Is the requested format supported? */ - if (closest_format == format) - { - /* Target user data directly */ - target_bmp.format = format; - target_bmp.rowstride = rowstride; - target_bmp.data = data; - } - else - { - /* Target intermediate buffer */ - target_bmp.format = closest_format; - target_bmp.rowstride = target_bmp.width * closest_bpp; - target_bmp.data = g_malloc (target_bmp.height * target_bmp.rowstride); - } - - _cogl_texture_driver_prep_gl_for_pixels_download (target_bmp.rowstride, - closest_bpp); + _cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp); GE( _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, tex_rect->gl_texture, FALSE) ); - if (!_cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_RECTANGLE_ARB, - closest_gl_format, - closest_gl_type, - target_bmp.data)) - { - /* XXX: In some cases _cogl_texture_rectangle_download_from_gl may - * fail to read back the texture data; such as for GLES which doesn't - * support glGetTexImage, so here we fallback to drawing the texture - * and reading the pixels from the framebuffer. */ - _cogl_texture_draw_and_read (tex, &target_bmp, - closest_gl_format, - closest_gl_type); - } - - /* Was intermediate used? */ - if (closest_format != format) - { - /* Convert to requested format */ - success = _cogl_bitmap_convert_format_and_premult (&target_bmp, - &new_bmp, - format); - - /* Free intermediate data and return if failed */ - g_free (target_bmp.data); - if (!success) - return 0; - - /* Copy to user buffer */ - for (y = 0; y < new_bmp.height; ++y) - { - src = new_bmp.data + y * new_bmp.rowstride; - dst = data + y * rowstride; - memcpy (dst, src, new_bmp.width); - } - - /* Free converted data */ - g_free (new_bmp.data); - } - - return byte_size; + return _cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_RECTANGLE_ARB, + gl_format, + gl_type, + data); } static CoglPixelFormat diff --git a/clutter/cogl/cogl/cogl-texture.c b/clutter/cogl/cogl/cogl-texture.c index dd24ad341..c7be4b26b 100644 --- a/clutter/cogl/cogl/cogl-texture.c +++ b/clutter/cogl/cogl/cogl-texture.c @@ -1084,13 +1084,105 @@ cogl_texture_get_data (CoglHandle handle, unsigned int rowstride, guint8 *data) { - CoglTexture *tex; + CoglTexture *tex; + int bpp; + int byte_size; + CoglPixelFormat closest_format; + int closest_bpp; + GLenum closest_gl_format; + GLenum closest_gl_type; + CoglBitmap target_bmp; + CoglBitmap new_bmp; + gboolean success; + guint8 *src; + guint8 *dst; + int y; + int tex_width; + int tex_height; if (!cogl_is_texture (handle)) return FALSE; tex = COGL_TEXTURE (handle); - return tex->vtable->get_data (handle, format, rowstride, data); -} + /* Default to internal format if none specified */ + if (format == COGL_PIXEL_FORMAT_ANY) + format = cogl_texture_get_format (handle); + tex_width = cogl_texture_get_width (handle); + tex_height = cogl_texture_get_height (handle); + + /* Rowstride from texture width if none specified */ + bpp = _cogl_get_format_bpp (format); + if (rowstride == 0) + rowstride = tex_width * bpp; + + /* Return byte size if only that requested */ + byte_size = tex_height * rowstride; + if (data == NULL) + return byte_size; + + closest_format = + _cogl_texture_driver_find_best_gl_get_data_format (format, + &closest_gl_format, + &closest_gl_type); + closest_bpp = _cogl_get_format_bpp (closest_format); + + target_bmp.width = tex_width; + target_bmp.height = tex_height; + + /* Is the requested format supported? */ + if (closest_format == format) + { + /* Target user data directly */ + target_bmp.format = format; + target_bmp.rowstride = rowstride; + target_bmp.data = data; + } + else + { + /* Target intermediate buffer */ + target_bmp.format = closest_format; + target_bmp.rowstride = target_bmp.width * closest_bpp; + target_bmp.data = g_malloc (target_bmp.height * target_bmp.rowstride); + } + + if (!tex->vtable->get_data (tex, + target_bmp.format, + target_bmp.rowstride, + target_bmp.data)) + /* XXX: In some cases _cogl_texture_2d_download_from_gl may fail + * to read back the texture data; such as for GLES which doesn't + * support glGetTexImage, so here we fallback to drawing the + * texture and reading the pixels from the framebuffer. */ + _cogl_texture_draw_and_read (tex, &target_bmp, + closest_gl_format, + closest_gl_type); + + /* Was intermediate used? */ + if (closest_format != format) + { + /* Convert to requested format */ + success = _cogl_bitmap_convert_format_and_premult (&target_bmp, + &new_bmp, + format); + + /* Free intermediate data and return if failed */ + g_free (target_bmp.data); + if (!success) + return 0; + + /* Copy to user buffer */ + for (y = 0; y < new_bmp.height; ++y) + { + src = new_bmp.data + y * new_bmp.rowstride; + dst = data + y * rowstride; + memcpy (dst, src, new_bmp.width); + } + + /* Free converted data */ + g_free (new_bmp.data); + } + + return byte_size; +} diff --git a/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c b/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c index e57e41bcd..c8ee42fc1 100644 --- a/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c +++ b/clutter/cogl/cogl/winsys/cogl-texture-pixmap-x11.c @@ -1129,7 +1129,7 @@ _cogl_texture_pixmap_x11_set_region (CoglTexture *tex, return FALSE; } -static int +static gboolean _cogl_texture_pixmap_x11_get_data (CoglTexture *tex, CoglPixelFormat format, unsigned int rowstride,