mirror of
https://github.com/brl/mutter.git
synced 2025-02-09 10:04:08 +00:00
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:
parent
519b6fe6f2
commit
8b4034cd06
@ -439,21 +439,6 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
|
|||||||
bmp);
|
bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
_cogl_atlas_texture_get_data (CoglTexture *tex,
|
|
||||||
CoglPixelFormat format,
|
|
||||||
unsigned int rowstride,
|
|
||||||
guint8 *data)
|
|
||||||
{
|
|
||||||
CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
|
|
||||||
|
|
||||||
/* Forward on to the sub texture */
|
|
||||||
return cogl_texture_get_data (atlas_tex->sub_texture,
|
|
||||||
format,
|
|
||||||
rowstride,
|
|
||||||
data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CoglPixelFormat
|
static CoglPixelFormat
|
||||||
_cogl_atlas_texture_get_format (CoglTexture *tex)
|
_cogl_atlas_texture_get_format (CoglTexture *tex)
|
||||||
{
|
{
|
||||||
@ -632,7 +617,7 @@ static const CoglTextureVtable
|
|||||||
cogl_atlas_texture_vtable =
|
cogl_atlas_texture_vtable =
|
||||||
{
|
{
|
||||||
_cogl_atlas_texture_set_region,
|
_cogl_atlas_texture_set_region,
|
||||||
_cogl_atlas_texture_get_data,
|
NULL, /* get_data */
|
||||||
_cogl_atlas_texture_foreach_sub_texture_in_region,
|
_cogl_atlas_texture_foreach_sub_texture_in_region,
|
||||||
_cogl_atlas_texture_get_max_waste,
|
_cogl_atlas_texture_get_max_waste,
|
||||||
_cogl_atlas_texture_is_sliced,
|
_cogl_atlas_texture_is_sliced,
|
||||||
|
@ -416,74 +416,6 @@ _cogl_sub_texture_set_region (CoglTexture *tex,
|
|||||||
bmp);
|
bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
_cogl_sub_texture_copy_region (guint8 *dst,
|
|
||||||
const guint8 *src,
|
|
||||||
int dst_x, int dst_y,
|
|
||||||
int src_x, int src_y,
|
|
||||||
int width, int height,
|
|
||||||
int dst_rowstride,
|
|
||||||
int src_rowstride,
|
|
||||||
int bpp)
|
|
||||||
{
|
|
||||||
int y;
|
|
||||||
|
|
||||||
dst += dst_x * bpp + dst_y * dst_rowstride;
|
|
||||||
src += src_x * bpp + src_y * src_rowstride;
|
|
||||||
|
|
||||||
for (y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
memcpy (dst, src, bpp * width);
|
|
||||||
dst += dst_rowstride;
|
|
||||||
src += src_rowstride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
_cogl_sub_texture_get_data (CoglTexture *tex,
|
|
||||||
CoglPixelFormat format,
|
|
||||||
unsigned int rowstride,
|
|
||||||
guint8 *data)
|
|
||||||
{
|
|
||||||
CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
|
|
||||||
unsigned int full_rowstride;
|
|
||||||
guint8 *full_data;
|
|
||||||
gboolean ret = TRUE;
|
|
||||||
int bpp;
|
|
||||||
int full_tex_width, full_tex_height;
|
|
||||||
|
|
||||||
/* FIXME: This gets the full data from the full texture and then
|
|
||||||
copies a subregion of that. It would be better if there was a
|
|
||||||
texture_get_sub_data virtual and it can just munge the texture
|
|
||||||
coordinates */
|
|
||||||
|
|
||||||
full_tex_width = cogl_texture_get_width (sub_tex->full_texture);
|
|
||||||
full_tex_height = cogl_texture_get_height (sub_tex->full_texture);
|
|
||||||
|
|
||||||
bpp = _cogl_get_format_bpp (format);
|
|
||||||
|
|
||||||
full_rowstride = _cogl_get_format_bpp (format) * full_tex_width;
|
|
||||||
full_data = g_malloc (full_rowstride * full_tex_height);
|
|
||||||
|
|
||||||
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,
|
|
||||||
sub_tex->sub_y,
|
|
||||||
sub_tex->sub_width,
|
|
||||||
sub_tex->sub_height,
|
|
||||||
rowstride,
|
|
||||||
full_rowstride,
|
|
||||||
bpp);
|
|
||||||
else
|
|
||||||
ret = FALSE;
|
|
||||||
|
|
||||||
g_free (full_data);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CoglPixelFormat
|
static CoglPixelFormat
|
||||||
_cogl_sub_texture_get_format (CoglTexture *tex)
|
_cogl_sub_texture_get_format (CoglTexture *tex)
|
||||||
{
|
{
|
||||||
@ -520,7 +452,7 @@ static const CoglTextureVtable
|
|||||||
cogl_sub_texture_vtable =
|
cogl_sub_texture_vtable =
|
||||||
{
|
{
|
||||||
_cogl_sub_texture_set_region,
|
_cogl_sub_texture_set_region,
|
||||||
_cogl_sub_texture_get_data,
|
NULL, /* get_data */
|
||||||
_cogl_sub_texture_foreach_sub_texture_in_region,
|
_cogl_sub_texture_foreach_sub_texture_in_region,
|
||||||
_cogl_sub_texture_get_max_waste,
|
_cogl_sub_texture_get_max_waste,
|
||||||
_cogl_sub_texture_is_sliced,
|
_cogl_sub_texture_is_sliced,
|
||||||
|
@ -1335,153 +1335,6 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex,
|
|||||||
return TRUE;
|
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
|
static CoglPixelFormat
|
||||||
_cogl_texture_2d_sliced_get_format (CoglTexture *tex)
|
_cogl_texture_2d_sliced_get_format (CoglTexture *tex)
|
||||||
{
|
{
|
||||||
@ -1528,7 +1381,7 @@ static const CoglTextureVtable
|
|||||||
cogl_texture_2d_sliced_vtable =
|
cogl_texture_2d_sliced_vtable =
|
||||||
{
|
{
|
||||||
_cogl_texture_2d_sliced_set_region,
|
_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_foreach_sub_texture_in_region,
|
||||||
_cogl_texture_2d_sliced_get_max_waste,
|
_cogl_texture_2d_sliced_get_max_waste,
|
||||||
_cogl_texture_2d_sliced_is_sliced,
|
_cogl_texture_2d_sliced_is_sliced,
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007,2008,2009 Intel Corporation.
|
* Copyright (C) 2007,2008,2009 Intel Corporation.
|
||||||
|
* Copyright (C) 2010 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include "cogl-bitmap-private.h"
|
#include "cogl-bitmap-private.h"
|
||||||
#include "cogl-buffer-private.h"
|
#include "cogl-buffer-private.h"
|
||||||
#include "cogl-pixel-array-private.h"
|
#include "cogl-pixel-array-private.h"
|
||||||
|
#include "cogl-private.h"
|
||||||
#include "cogl-texture-private.h"
|
#include "cogl-texture-private.h"
|
||||||
#include "cogl-texture-driver.h"
|
#include "cogl-texture-driver.h"
|
||||||
#include "cogl-texture-2d-sliced-private.h"
|
#include "cogl-texture-2d-sliced-private.h"
|
||||||
@ -1181,6 +1183,169 @@ _cogl_texture_draw_and_read (CoglHandle handle,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
get_texture_bits_via_offscreen (CoglHandle texture_handle,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
guint8 *dst_bits,
|
||||||
|
unsigned int dst_rowstride,
|
||||||
|
CoglPixelFormat dst_format)
|
||||||
|
{
|
||||||
|
CoglFramebuffer *framebuffer;
|
||||||
|
|
||||||
|
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||||
|
|
||||||
|
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
framebuffer = _cogl_offscreen_new_to_texture_full
|
||||||
|
(texture_handle,
|
||||||
|
COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (framebuffer == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
cogl_push_framebuffer (framebuffer);
|
||||||
|
|
||||||
|
_cogl_read_pixels_with_rowstride (x, y, width, height,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
dst_format, dst_bits, dst_rowstride);
|
||||||
|
|
||||||
|
cogl_pop_framebuffer ();
|
||||||
|
|
||||||
|
cogl_object_unref (framebuffer);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
get_texture_bits_via_copy (CoglHandle texture_handle,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
guint8 *dst_bits,
|
||||||
|
unsigned int dst_rowstride,
|
||||||
|
CoglPixelFormat dst_format)
|
||||||
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (texture_handle);
|
||||||
|
unsigned int full_rowstride;
|
||||||
|
guint8 *full_bits;
|
||||||
|
gboolean ret = TRUE;
|
||||||
|
int bpp;
|
||||||
|
int full_tex_width, full_tex_height;
|
||||||
|
|
||||||
|
full_tex_width = cogl_texture_get_width (texture_handle);
|
||||||
|
full_tex_height = cogl_texture_get_height (texture_handle);
|
||||||
|
|
||||||
|
bpp = _cogl_get_format_bpp (dst_format);
|
||||||
|
|
||||||
|
full_rowstride = bpp * full_tex_width;
|
||||||
|
full_bits = g_malloc (full_rowstride * full_tex_height);
|
||||||
|
|
||||||
|
if (tex->vtable->get_data (tex,
|
||||||
|
dst_format,
|
||||||
|
full_rowstride,
|
||||||
|
full_bits))
|
||||||
|
{
|
||||||
|
guint8 *dst = dst_bits;
|
||||||
|
guint8 *src = full_bits + x * bpp + y * full_rowstride;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < height; i++)
|
||||||
|
{
|
||||||
|
memcpy (dst, src, bpp * width);
|
||||||
|
dst += dst_rowstride;
|
||||||
|
src += full_rowstride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = FALSE;
|
||||||
|
|
||||||
|
g_free (full_bits);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int orig_width;
|
||||||
|
int orig_height;
|
||||||
|
CoglBitmap *target_bmp;
|
||||||
|
guint8 *target_bits;
|
||||||
|
gboolean success;
|
||||||
|
} CoglTextureGetData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
texture_get_cb (CoglHandle texture_handle,
|
||||||
|
const float *subtexture_coords,
|
||||||
|
const float *virtual_coords,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (texture_handle);
|
||||||
|
CoglTextureGetData *tg_data = user_data;
|
||||||
|
CoglPixelFormat format = _cogl_bitmap_get_format (tg_data->target_bmp);
|
||||||
|
int bpp = _cogl_get_format_bpp (format);
|
||||||
|
unsigned int rowstride = _cogl_bitmap_get_rowstride (tg_data->target_bmp);
|
||||||
|
int subtexture_width = cogl_texture_get_width (texture_handle);
|
||||||
|
int subtexture_height = cogl_texture_get_height (texture_handle);
|
||||||
|
|
||||||
|
int x_in_subtexture = (int) (0.5 + subtexture_width * subtexture_coords[0]);
|
||||||
|
int y_in_subtexture = (int) (0.5 + subtexture_height * subtexture_coords[1]);
|
||||||
|
int width = ((int) (0.5 + subtexture_width * subtexture_coords[2])
|
||||||
|
- x_in_subtexture);
|
||||||
|
int height = ((int) (0.5 + subtexture_height * subtexture_coords[3])
|
||||||
|
- y_in_subtexture);
|
||||||
|
int x_in_bitmap = (int) (0.5 + tg_data->orig_width * virtual_coords[0]);
|
||||||
|
int y_in_bitmap = (int) (0.5 + tg_data->orig_height * virtual_coords[1]);
|
||||||
|
|
||||||
|
guint8 *dst_bits;
|
||||||
|
|
||||||
|
if (!tg_data->success)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dst_bits = tg_data->target_bits + x_in_bitmap * bpp + y_in_bitmap * rowstride;
|
||||||
|
|
||||||
|
/* If we can read everything as a single slice, then go ahead and do that
|
||||||
|
* to avoid allocating an FBO. We'll leave it up to the GL implementation to
|
||||||
|
* do glGetTexImage as efficiently as possible. (GLES doesn't have that,
|
||||||
|
* so we'll fall through) */
|
||||||
|
if (x_in_subtexture == 0 && y_in_subtexture == 0 &&
|
||||||
|
width == subtexture_width && height == subtexture_height)
|
||||||
|
{
|
||||||
|
if (tex->vtable->get_data (tex,
|
||||||
|
format,
|
||||||
|
rowstride,
|
||||||
|
dst_bits))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next best option is a FBO and glReadPixels */
|
||||||
|
if (get_texture_bits_via_offscreen (texture_handle,
|
||||||
|
x_in_subtexture, y_in_subtexture,
|
||||||
|
width, height,
|
||||||
|
dst_bits,
|
||||||
|
rowstride,
|
||||||
|
format))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Getting ugly: read the entire texture, copy out the part we want */
|
||||||
|
if (get_texture_bits_via_copy (texture_handle,
|
||||||
|
x_in_subtexture, y_in_subtexture,
|
||||||
|
width, height,
|
||||||
|
dst_bits,
|
||||||
|
rowstride,
|
||||||
|
format))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* No luck, the caller will fall back to the draw-to-backbuffer and
|
||||||
|
* read implementation */
|
||||||
|
tg_data->success = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cogl_texture_get_data (CoglHandle handle,
|
cogl_texture_get_data (CoglHandle handle,
|
||||||
CoglPixelFormat format,
|
CoglPixelFormat format,
|
||||||
@ -1196,13 +1361,14 @@ cogl_texture_get_data (CoglHandle handle,
|
|||||||
GLenum closest_gl_type;
|
GLenum closest_gl_type;
|
||||||
CoglBitmap *target_bmp;
|
CoglBitmap *target_bmp;
|
||||||
CoglBitmap *new_bmp;
|
CoglBitmap *new_bmp;
|
||||||
gboolean success;
|
|
||||||
guint8 *src;
|
guint8 *src;
|
||||||
guint8 *dst;
|
guint8 *dst;
|
||||||
int y;
|
int y;
|
||||||
int tex_width;
|
int tex_width;
|
||||||
int tex_height;
|
int tex_height;
|
||||||
|
|
||||||
|
CoglTextureGetData tg_data;
|
||||||
|
|
||||||
if (!cogl_is_texture (handle))
|
if (!cogl_is_texture (handle))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1253,17 +1419,26 @@ cogl_texture_get_data (CoglHandle handle,
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dst = _cogl_bitmap_map (target_bmp, COGL_BUFFER_ACCESS_WRITE,
|
tg_data.orig_width = tex_width;
|
||||||
COGL_BUFFER_MAP_HINT_DISCARD)) == NULL)
|
tg_data.orig_height = tex_height;
|
||||||
|
tg_data.target_bmp = target_bmp;
|
||||||
|
tg_data.target_bits = _cogl_bitmap_map (target_bmp, COGL_BUFFER_ACCESS_WRITE,
|
||||||
|
COGL_BUFFER_MAP_HINT_DISCARD);
|
||||||
|
if (tg_data.target_bits == NULL)
|
||||||
{
|
{
|
||||||
cogl_object_unref (target_bmp);
|
cogl_object_unref (target_bmp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
tg_data.success = TRUE;
|
||||||
|
|
||||||
success = tex->vtable->get_data (tex,
|
/* Iterating through the subtextures allows piecing together
|
||||||
closest_format,
|
* the data for a sliced texture, and allows us to do the
|
||||||
rowstride,
|
* read-from-framebuffer logic here in a simple fashion rather than
|
||||||
dst);
|
* passing offsets down through the code. */
|
||||||
|
_cogl_texture_foreach_sub_texture_in_region (handle,
|
||||||
|
0, 0, 1, 1,
|
||||||
|
texture_get_cb,
|
||||||
|
&tg_data);
|
||||||
|
|
||||||
_cogl_bitmap_unmap (target_bmp);
|
_cogl_bitmap_unmap (target_bmp);
|
||||||
|
|
||||||
@ -1271,7 +1446,7 @@ cogl_texture_get_data (CoglHandle handle,
|
|||||||
* to read back the texture data; such as for GLES which doesn't
|
* to read back the texture data; such as for GLES which doesn't
|
||||||
* support glGetTexImage, so here we fallback to drawing the
|
* support glGetTexImage, so here we fallback to drawing the
|
||||||
* texture and reading the pixels from the framebuffer. */
|
* texture and reading the pixels from the framebuffer. */
|
||||||
if (!success)
|
if (!tg_data.success)
|
||||||
_cogl_texture_draw_and_read (tex, target_bmp,
|
_cogl_texture_draw_and_read (tex, target_bmp,
|
||||||
closest_gl_format,
|
closest_gl_format,
|
||||||
closest_gl_type);
|
closest_gl_type);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user