cogl-bitmap: Encapsulate the CoglBitmap even internally
The CoglBitmap struct is now only defined within cogl-bitmap.c so that all of its members can now only be accessed with accessor functions. To get to the data pointer for the bitmap image you must first call _cogl_bitmap_map and later call _cogl_bitmap_unmap. The map function takes the same arguments as cogl_pixel_array_map so that eventually we can make a bitmap optionally internally divert to a pixel array. There is a _cogl_bitmap_new_from_data function which constructs a new bitmap object and takes ownership of the data pointer. The function gets passed a destroy callback which gets called when the bitmap is freed. This is similar to how gdk_pixbuf_new_from_data works. Alternatively NULL can be passed for the destroy function which means that the caller will manage the life of the pointer (but must guarantee that it stays alive at least until the bitmap is freed). This mechanism is used instead of the old approach of creating a CoglBitmap struct on the stack and manually filling in the members. It could also later be used to create a CoglBitmap that owns a GdkPixbuf ref so that we don't necessarily have to copy the GdkPixbuf data when converting to a bitmap. There is also _cogl_bitmap_new_shared. This creates a bitmap using a reference to another CoglBitmap for the data. This is a bit of a hack but it is needed by the atlas texture backend which wants to divert the set_region virtual to another texture but it needs to override the format of the bitmap to ignore the premult flag.
This commit is contained in:
parent
fd886d9fc2
commit
fc12c42a83
@ -57,7 +57,7 @@ GQuark
|
|||||||
_cogl_handle_atlas_texture_get_type (void);
|
_cogl_handle_atlas_texture_get_type (void);
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_handle,
|
_cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
|
||||||
CoglTextureFlags flags,
|
CoglTextureFlags flags,
|
||||||
CoglPixelFormat internal_format);
|
CoglPixelFormat internal_format);
|
||||||
|
|
||||||
|
@ -442,72 +442,57 @@ _cogl_atlas_texture_set_region_with_border (CoglAtlasTexture *atlas_tex,
|
|||||||
int dst_y,
|
int dst_y,
|
||||||
unsigned int dst_width,
|
unsigned int dst_width,
|
||||||
unsigned int dst_height,
|
unsigned int dst_height,
|
||||||
int width,
|
CoglBitmap *bmp)
|
||||||
int height,
|
|
||||||
CoglPixelFormat format,
|
|
||||||
unsigned int rowstride,
|
|
||||||
const guint8 *data)
|
|
||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||||
|
|
||||||
/* Copy the central data */
|
/* Copy the central data */
|
||||||
if (!cogl_texture_set_region (ctx->atlas_texture,
|
if (!_cogl_texture_set_region_from_bitmap (ctx->atlas_texture,
|
||||||
src_x, src_y,
|
src_x, src_y,
|
||||||
dst_x + atlas_tex->rectangle.x + 1,
|
dst_x + atlas_tex->rectangle.x + 1,
|
||||||
dst_y + atlas_tex->rectangle.y + 1,
|
dst_y + atlas_tex->rectangle.y + 1,
|
||||||
dst_width,
|
dst_width,
|
||||||
dst_height,
|
dst_height,
|
||||||
width, height,
|
bmp))
|
||||||
format,
|
|
||||||
rowstride,
|
|
||||||
data))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Update the left edge pixels */
|
/* Update the left edge pixels */
|
||||||
if (dst_x == 0 &&
|
if (dst_x == 0 &&
|
||||||
!cogl_texture_set_region (ctx->atlas_texture,
|
!_cogl_texture_set_region_from_bitmap (ctx->atlas_texture,
|
||||||
src_x, src_y,
|
src_x, src_y,
|
||||||
atlas_tex->rectangle.x,
|
atlas_tex->rectangle.x,
|
||||||
dst_y + atlas_tex->rectangle.y + 1,
|
dst_y + atlas_tex->rectangle.y + 1,
|
||||||
1, dst_height,
|
1, dst_height,
|
||||||
width, height,
|
bmp))
|
||||||
format, rowstride,
|
|
||||||
data))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
/* Update the right edge pixels */
|
/* Update the right edge pixels */
|
||||||
if (dst_x + dst_width == atlas_tex->rectangle.width - 2 &&
|
if (dst_x + dst_width == atlas_tex->rectangle.width - 2 &&
|
||||||
!cogl_texture_set_region (ctx->atlas_texture,
|
!_cogl_texture_set_region_from_bitmap (ctx->atlas_texture,
|
||||||
src_x + dst_width - 1, src_y,
|
src_x + dst_width - 1, src_y,
|
||||||
atlas_tex->rectangle.x +
|
atlas_tex->rectangle.x +
|
||||||
atlas_tex->rectangle.width - 1,
|
atlas_tex->rectangle.width - 1,
|
||||||
dst_y + atlas_tex->rectangle.y + 1,
|
dst_y + atlas_tex->rectangle.y + 1,
|
||||||
1, dst_height,
|
1, dst_height,
|
||||||
width, height,
|
bmp))
|
||||||
format, rowstride,
|
|
||||||
data))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
/* Update the top edge pixels */
|
/* Update the top edge pixels */
|
||||||
if (dst_y == 0 &&
|
if (dst_y == 0 &&
|
||||||
!cogl_texture_set_region (ctx->atlas_texture,
|
!_cogl_texture_set_region_from_bitmap (ctx->atlas_texture,
|
||||||
src_x, src_y,
|
src_x, src_y,
|
||||||
dst_x + atlas_tex->rectangle.x + 1,
|
dst_x + atlas_tex->rectangle.x + 1,
|
||||||
atlas_tex->rectangle.y,
|
atlas_tex->rectangle.y,
|
||||||
dst_width, 1,
|
dst_width, 1,
|
||||||
width, height,
|
bmp))
|
||||||
format, rowstride,
|
|
||||||
data))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
/* Update the bottom edge pixels */
|
/* Update the bottom edge pixels */
|
||||||
if (dst_y + dst_height == atlas_tex->rectangle.height - 2 &&
|
if (dst_y + dst_height == atlas_tex->rectangle.height - 2 &&
|
||||||
!cogl_texture_set_region (ctx->atlas_texture,
|
!_cogl_texture_set_region_from_bitmap (ctx->atlas_texture,
|
||||||
src_x, src_y + dst_height - 1,
|
src_x, src_y + dst_height - 1,
|
||||||
dst_x + atlas_tex->rectangle.x + 1,
|
dst_x + atlas_tex->rectangle.x + 1,
|
||||||
atlas_tex->rectangle.y +
|
atlas_tex->rectangle.y +
|
||||||
atlas_tex->rectangle.height - 1,
|
atlas_tex->rectangle.height - 1,
|
||||||
dst_width, 1,
|
dst_width, 1,
|
||||||
width, height,
|
bmp))
|
||||||
format, rowstride,
|
|
||||||
data))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -528,18 +513,27 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
|
|||||||
/* If the texture is in the atlas then we need to copy the edge
|
/* If the texture is in the atlas then we need to copy the edge
|
||||||
pixels to the border */
|
pixels to the border */
|
||||||
if (atlas_tex->in_atlas)
|
if (atlas_tex->in_atlas)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
bmp = _cogl_bitmap_new_shared (bmp,
|
||||||
|
_cogl_bitmap_get_format (bmp) &
|
||||||
|
~COGL_PREMULT_BIT,
|
||||||
|
_cogl_bitmap_get_width (bmp),
|
||||||
|
_cogl_bitmap_get_height (bmp),
|
||||||
|
_cogl_bitmap_get_rowstride (bmp));
|
||||||
|
|
||||||
/* Upload the data ignoring the premult bit */
|
/* Upload the data ignoring the premult bit */
|
||||||
return _cogl_atlas_texture_set_region_with_border (atlas_tex,
|
ret = _cogl_atlas_texture_set_region_with_border (atlas_tex,
|
||||||
src_x, src_y,
|
src_x, src_y,
|
||||||
dst_x, dst_y,
|
dst_x, dst_y,
|
||||||
dst_width, dst_height,
|
dst_width, dst_height,
|
||||||
bmp->width,
|
bmp);
|
||||||
bmp->height,
|
|
||||||
bmp->format &
|
|
||||||
~COGL_PREMULT_BIT,
|
|
||||||
bmp->rowstride,
|
|
||||||
bmp->data);
|
|
||||||
|
|
||||||
|
cogl_object_unref (bmp);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
/* Otherwise we can just forward on to the sub texture */
|
/* Otherwise we can just forward on to the sub texture */
|
||||||
return _cogl_texture_set_region_from_bitmap (atlas_tex->sub_texture,
|
return _cogl_texture_set_region_from_bitmap (atlas_tex->sub_texture,
|
||||||
@ -909,21 +903,23 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_handle,
|
_cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
|
||||||
CoglTextureFlags flags,
|
CoglTextureFlags flags,
|
||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format)
|
||||||
{
|
{
|
||||||
CoglAtlasTexture *atlas_tex;
|
CoglAtlasTexture *atlas_tex;
|
||||||
CoglBitmap *bmp = (CoglBitmap *) bmp_handle;
|
CoglBitmap *dst_bmp;
|
||||||
CoglBitmap dst_bmp;
|
CoglBitmap *override_bmp;
|
||||||
gboolean dst_bmp_owner;
|
|
||||||
GLenum gl_intformat;
|
GLenum gl_intformat;
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
int bmp_width;
|
||||||
|
int bmp_height;
|
||||||
|
CoglPixelFormat bmp_format;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
g_return_val_if_fail (bmp_handle != COGL_INVALID_HANDLE, COGL_INVALID_HANDLE);
|
g_return_val_if_fail (cogl_is_bitmap (bmp), COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
/* Don't put textures in the atlas if the user has explicitly
|
/* Don't put textures in the atlas if the user has explicitly
|
||||||
requested to disable it */
|
requested to disable it */
|
||||||
@ -936,9 +932,13 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
if (flags)
|
if (flags)
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
|
bmp_width = _cogl_bitmap_get_width (bmp);
|
||||||
|
bmp_height = _cogl_bitmap_get_height (bmp);
|
||||||
|
bmp_format = _cogl_bitmap_get_format (bmp);
|
||||||
|
|
||||||
/* We can't atlas zero-sized textures because it breaks the atlas
|
/* We can't atlas zero-sized textures because it breaks the atlas
|
||||||
data structure */
|
data structure */
|
||||||
if (bmp->width < 1 || bmp->height < 1)
|
if (bmp_width < 1 || bmp_height < 1)
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
/* If we can't use FBOs or we can't read back texture data then it
|
/* If we can't use FBOs or we can't read back texture data then it
|
||||||
@ -948,9 +948,9 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
!cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
!cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
COGL_NOTE (ATLAS, "Adding texture of size %ix%i", bmp->width, bmp->height);
|
COGL_NOTE (ATLAS, "Adding texture of size %ix%i", bmp_width, bmp_height);
|
||||||
|
|
||||||
internal_format = _cogl_texture_determine_internal_format (bmp->format,
|
internal_format = _cogl_texture_determine_internal_format (bmp_format,
|
||||||
internal_format);
|
internal_format);
|
||||||
|
|
||||||
/* If the texture is in a strange format then we can't use it */
|
/* If the texture is in a strange format then we can't use it */
|
||||||
@ -968,8 +968,8 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
atlas_tex = g_new (CoglAtlasTexture, 1);
|
atlas_tex = g_new (CoglAtlasTexture, 1);
|
||||||
/* We need to fill in the texture size now because it is used in the
|
/* We need to fill in the texture size now because it is used in the
|
||||||
reserve_space function below. We add two pixels for the border */
|
reserve_space function below. We add two pixels for the border */
|
||||||
atlas_tex->rectangle.width = bmp->width + 2;
|
atlas_tex->rectangle.width = bmp_width + 2;
|
||||||
atlas_tex->rectangle.height = bmp->height + 2;
|
atlas_tex->rectangle.height = bmp_height + 2;
|
||||||
|
|
||||||
/* Try to make some space in the atlas for the texture */
|
/* Try to make some space in the atlas for the texture */
|
||||||
if (!_cogl_atlas_texture_reserve_space (atlas_tex,
|
if (!_cogl_atlas_texture_reserve_space (atlas_tex,
|
||||||
@ -980,14 +980,14 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_cogl_texture_prepare_for_upload (bmp,
|
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||||
internal_format,
|
internal_format,
|
||||||
&internal_format,
|
&internal_format,
|
||||||
&dst_bmp,
|
|
||||||
&dst_bmp_owner,
|
|
||||||
&gl_intformat,
|
&gl_intformat,
|
||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type))
|
&gl_type);
|
||||||
|
|
||||||
|
if (dst_bmp == NULL)
|
||||||
{
|
{
|
||||||
_cogl_atlas_remove_rectangle (ctx->atlas, &atlas_tex->rectangle);
|
_cogl_atlas_remove_rectangle (ctx->atlas, &atlas_tex->rectangle);
|
||||||
g_free (atlas_tex);
|
g_free (atlas_tex);
|
||||||
@ -1001,24 +1001,29 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
_cogl_atlas_texture_create_sub_texture (ctx->atlas_texture,
|
_cogl_atlas_texture_create_sub_texture (ctx->atlas_texture,
|
||||||
&atlas_tex->rectangle);
|
&atlas_tex->rectangle);
|
||||||
|
|
||||||
|
/* Make another bitmap so that we can override the format */
|
||||||
|
override_bmp = _cogl_bitmap_new_shared (dst_bmp,
|
||||||
|
_cogl_bitmap_get_format (dst_bmp) &
|
||||||
|
~COGL_PREMULT_BIT,
|
||||||
|
_cogl_bitmap_get_width (dst_bmp),
|
||||||
|
_cogl_bitmap_get_height (dst_bmp),
|
||||||
|
_cogl_bitmap_get_rowstride (dst_bmp));
|
||||||
|
cogl_object_unref (dst_bmp);
|
||||||
|
|
||||||
/* Defer to set_region so that we can share the code for copying the
|
/* Defer to set_region so that we can share the code for copying the
|
||||||
edge pixels to the border. We don't want to pass the actual
|
edge pixels to the border. We don't want to pass the actual
|
||||||
format of the converted texture because otherwise it will get
|
format of the converted texture because otherwise it will get
|
||||||
unpremultiplied. */
|
unpremultiplied. */
|
||||||
_cogl_atlas_texture_set_region_with_border (atlas_tex,
|
_cogl_atlas_texture_set_region_with_border (atlas_tex,
|
||||||
0, 0,
|
0, /* src_x */
|
||||||
0, 0,
|
0, /* src_y */
|
||||||
dst_bmp.width,
|
0, /* dst_x */
|
||||||
dst_bmp.height,
|
0, /* dst_y */
|
||||||
dst_bmp.width,
|
bmp_width, /* dst_width */
|
||||||
dst_bmp.height,
|
bmp_height, /* dst_height */
|
||||||
dst_bmp.format &
|
override_bmp);
|
||||||
~COGL_PREMULT_BIT,
|
|
||||||
dst_bmp.rowstride,
|
|
||||||
dst_bmp.data);
|
|
||||||
|
|
||||||
if (dst_bmp_owner)
|
cogl_object_unref (override_bmp);
|
||||||
g_free (dst_bmp.data);
|
|
||||||
|
|
||||||
return _cogl_atlas_texture_handle_new (atlas_tex);
|
return _cogl_atlas_texture_handle_new (atlas_tex);
|
||||||
}
|
}
|
||||||
|
@ -337,52 +337,61 @@ _cogl_bitmap_fallback_can_premult (CoglPixelFormat format)
|
|||||||
return ((format & COGL_UNORDERED_MASK) == COGL_PIXEL_FORMAT_32);
|
return ((format & COGL_UNORDERED_MASK) == COGL_PIXEL_FORMAT_32);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_fallback_convert (const CoglBitmap *bmp,
|
_cogl_bitmap_fallback_convert (CoglBitmap *src_bmp,
|
||||||
CoglBitmap *dst_bmp,
|
|
||||||
CoglPixelFormat dst_format)
|
CoglPixelFormat dst_format)
|
||||||
{
|
{
|
||||||
|
guint8 *src_data;
|
||||||
|
guint8 *dst_data;
|
||||||
guint8 *src;
|
guint8 *src;
|
||||||
guint8 *dst;
|
guint8 *dst;
|
||||||
int src_bpp;
|
int src_bpp;
|
||||||
int dst_bpp;
|
int dst_bpp;
|
||||||
|
int src_rowstride;
|
||||||
|
int dst_rowstride;
|
||||||
int x,y;
|
int x,y;
|
||||||
guint8 temp_rgba[4] = {0,0,0,0};
|
guint8 temp_rgba[4] = {0,0,0,0};
|
||||||
|
int width, height;
|
||||||
|
CoglPixelFormat src_format;
|
||||||
|
|
||||||
|
src_format = _cogl_bitmap_get_format (src_bmp);
|
||||||
|
src_rowstride = _cogl_bitmap_get_rowstride (src_bmp);
|
||||||
|
width = _cogl_bitmap_get_width (src_bmp);
|
||||||
|
height = _cogl_bitmap_get_height (src_bmp);
|
||||||
|
|
||||||
/* Make sure conversion supported */
|
/* Make sure conversion supported */
|
||||||
if (!_cogl_bitmap_fallback_can_convert (bmp->format, dst_format))
|
if (!_cogl_bitmap_fallback_can_convert (src_format, dst_format))
|
||||||
return FALSE;
|
return NULL;
|
||||||
|
|
||||||
src_bpp = _cogl_get_format_bpp (bmp->format);
|
src_data = _cogl_bitmap_map (src_bmp, COGL_BUFFER_ACCESS_READ, 0);
|
||||||
|
if (src_data == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
src_bpp = _cogl_get_format_bpp (src_format);
|
||||||
dst_bpp = _cogl_get_format_bpp (dst_format);
|
dst_bpp = _cogl_get_format_bpp (dst_format);
|
||||||
|
|
||||||
/* Initialize destination bitmap */
|
/* Initialize destination bitmap */
|
||||||
*dst_bmp = *bmp;
|
dst_rowstride = sizeof(guint8) * dst_bpp * width;
|
||||||
dst_bmp->rowstride = sizeof(guint8) * dst_bpp * dst_bmp->width;
|
|
||||||
/* Copy the premult bit if the new format has an alpha channel */
|
/* Copy the premult bit if the new format has an alpha channel */
|
||||||
if ((dst_format & COGL_A_BIT))
|
if ((dst_format & COGL_A_BIT))
|
||||||
dst_bmp->format = ((bmp->format & COGL_PREMULT_BIT) |
|
dst_format = ((src_format & COGL_PREMULT_BIT) |
|
||||||
(dst_format & COGL_UNPREMULT_MASK));
|
(dst_format & COGL_UNPREMULT_MASK));
|
||||||
else
|
|
||||||
dst_bmp->format = dst_format;
|
|
||||||
|
|
||||||
/* Allocate a new buffer to hold converted data */
|
/* Allocate a new buffer to hold converted data */
|
||||||
dst_bmp->data = g_malloc (sizeof(guint8)
|
dst_data = g_malloc (height * dst_rowstride);
|
||||||
* dst_bmp->height
|
|
||||||
* dst_bmp->rowstride);
|
|
||||||
|
|
||||||
/* FIXME: Optimize */
|
/* FIXME: Optimize */
|
||||||
for (y = 0; y < bmp->height; y++)
|
for (y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
src = (guint8*)bmp->data + y * bmp->rowstride;
|
src = src_data + y * src_rowstride;
|
||||||
dst = (guint8*)dst_bmp->data + y * dst_bmp->rowstride;
|
dst = dst_data + y * dst_rowstride;
|
||||||
|
|
||||||
for (x = 0; x < bmp->width; x++)
|
for (x = 0; x < width; x++)
|
||||||
{
|
{
|
||||||
/* FIXME: Would be nice to at least remove this inner
|
/* FIXME: Would be nice to at least remove this inner
|
||||||
* branching, but not sure it can be done without
|
* branching, but not sure it can be done without
|
||||||
* rewriting of the whole loop */
|
* rewriting of the whole loop */
|
||||||
switch (bmp->format & COGL_UNPREMULT_MASK)
|
switch (src_format & COGL_UNPREMULT_MASK)
|
||||||
{
|
{
|
||||||
case COGL_PIXEL_FORMAT_G_8:
|
case COGL_PIXEL_FORMAT_G_8:
|
||||||
_cogl_g_to_rgba (src, temp_rgba); break;
|
_cogl_g_to_rgba (src, temp_rgba); break;
|
||||||
@ -427,26 +436,46 @@ _cogl_bitmap_fallback_convert (const CoglBitmap *bmp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
_cogl_bitmap_unmap (src_bmp);
|
||||||
|
|
||||||
|
return _cogl_bitmap_new_from_data (dst_data,
|
||||||
|
dst_format,
|
||||||
|
width, height, dst_rowstride,
|
||||||
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_fallback_unpremult (CoglBitmap *bmp)
|
_cogl_bitmap_fallback_unpremult (CoglBitmap *bmp)
|
||||||
{
|
{
|
||||||
guint8 *p;
|
guint8 *p, *data;
|
||||||
int x,y;
|
int x,y;
|
||||||
|
CoglPixelFormat format;
|
||||||
|
int width, height;
|
||||||
|
int rowstride;
|
||||||
|
|
||||||
|
format = _cogl_bitmap_get_format (bmp);
|
||||||
|
width = _cogl_bitmap_get_width (bmp);
|
||||||
|
height = _cogl_bitmap_get_height (bmp);
|
||||||
|
rowstride = _cogl_bitmap_get_rowstride (bmp);
|
||||||
|
|
||||||
/* Make sure format supported for un-premultiplication */
|
/* Make sure format supported for un-premultiplication */
|
||||||
if (!_cogl_bitmap_fallback_can_unpremult (bmp->format))
|
if (!_cogl_bitmap_fallback_can_unpremult (format))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
for (y = 0; y < bmp->height; y++)
|
if ((data = _cogl_bitmap_map (bmp,
|
||||||
{
|
COGL_BUFFER_ACCESS_READ |
|
||||||
p = (guint8*) bmp->data + y * bmp->rowstride;
|
COGL_BUFFER_ACCESS_WRITE,
|
||||||
|
0)) == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (bmp->format & COGL_AFIRST_BIT)
|
for (y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
for (x = 0; x < bmp->width; x++)
|
p = (guint8*) data + y * rowstride;
|
||||||
|
|
||||||
|
if (format & COGL_AFIRST_BIT)
|
||||||
|
{
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
{
|
{
|
||||||
if (p[0] == 0)
|
if (p[0] == 0)
|
||||||
_cogl_unpremult_alpha_0 (p);
|
_cogl_unpremult_alpha_0 (p);
|
||||||
@ -457,7 +486,7 @@ _cogl_bitmap_fallback_unpremult (CoglBitmap *bmp)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (x = 0; x < bmp->width; x++)
|
for (x = 0; x < width; x++)
|
||||||
{
|
{
|
||||||
if (p[3] == 0)
|
if (p[3] == 0)
|
||||||
_cogl_unpremult_alpha_0 (p);
|
_cogl_unpremult_alpha_0 (p);
|
||||||
@ -468,7 +497,9 @@ _cogl_bitmap_fallback_unpremult (CoglBitmap *bmp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp->format &= ~COGL_PREMULT_BIT;
|
_cogl_bitmap_unmap (bmp);
|
||||||
|
|
||||||
|
_cogl_bitmap_set_format (bmp, format & ~COGL_PREMULT_BIT);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -476,20 +507,34 @@ _cogl_bitmap_fallback_unpremult (CoglBitmap *bmp)
|
|||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_fallback_premult (CoglBitmap *bmp)
|
_cogl_bitmap_fallback_premult (CoglBitmap *bmp)
|
||||||
{
|
{
|
||||||
guint8 *p;
|
guint8 *p, *data;
|
||||||
int x,y;
|
int x,y;
|
||||||
|
CoglPixelFormat format;
|
||||||
|
int width, height;
|
||||||
|
int rowstride;
|
||||||
|
|
||||||
|
format = _cogl_bitmap_get_format (bmp);
|
||||||
|
width = _cogl_bitmap_get_width (bmp);
|
||||||
|
height = _cogl_bitmap_get_height (bmp);
|
||||||
|
rowstride = _cogl_bitmap_get_rowstride (bmp);
|
||||||
|
|
||||||
/* Make sure format supported for un-premultiplication */
|
/* Make sure format supported for un-premultiplication */
|
||||||
if (!_cogl_bitmap_fallback_can_premult (bmp->format))
|
if (!_cogl_bitmap_fallback_can_premult (format))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
for (y = 0; y < bmp->height; y++)
|
if ((data = _cogl_bitmap_map (bmp,
|
||||||
{
|
COGL_BUFFER_ACCESS_READ |
|
||||||
p = (guint8*) bmp->data + y * bmp->rowstride;
|
COGL_BUFFER_ACCESS_WRITE,
|
||||||
|
0)) == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (bmp->format & COGL_AFIRST_BIT)
|
for (y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
for (x = 0; x < bmp->width; x++)
|
p = (guint8*) data + y * rowstride;
|
||||||
|
|
||||||
|
if (format & COGL_AFIRST_BIT)
|
||||||
|
{
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
{
|
{
|
||||||
_cogl_premult_alpha_first (p);
|
_cogl_premult_alpha_first (p);
|
||||||
p += 4;
|
p += 4;
|
||||||
@ -497,7 +542,7 @@ _cogl_bitmap_fallback_premult (CoglBitmap *bmp)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
x = bmp->width;
|
x = width;
|
||||||
|
|
||||||
#ifdef COGL_USE_PREMULT_SSE2
|
#ifdef COGL_USE_PREMULT_SSE2
|
||||||
|
|
||||||
@ -522,14 +567,15 @@ _cogl_bitmap_fallback_premult (CoglBitmap *bmp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bmp->format |= COGL_PREMULT_BIT;
|
_cogl_bitmap_unmap (bmp);
|
||||||
|
|
||||||
|
_cogl_bitmap_set_format (bmp, format | COGL_PREMULT_BIT);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_fallback_from_file (CoglBitmap *bmp,
|
_cogl_bitmap_fallback_from_file (const char *filename)
|
||||||
const char *filename)
|
|
||||||
{
|
{
|
||||||
/* FIXME: use jpeglib, libpng, etc. manually maybe */
|
/* FIXME: use jpeglib, libpng, etc. manually maybe */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -55,12 +55,11 @@ _cogl_bitmap_can_premult (CoglPixelFormat format)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_convert (const CoglBitmap *bmp,
|
_cogl_bitmap_convert (CoglBitmap *bmp,
|
||||||
CoglBitmap *dst_bmp,
|
|
||||||
CoglPixelFormat dst_format)
|
CoglPixelFormat dst_format)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -92,12 +91,10 @@ _cogl_bitmap_get_size_from_file (const char *filename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* the error does not contain the filename as the caller already has it */
|
/* the error does not contain the filename as the caller already has it */
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_from_file (CoglBitmap *bmp,
|
_cogl_bitmap_from_file (const char *filename,
|
||||||
const char *filename,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
g_assert (bmp != NULL);
|
|
||||||
g_assert (filename != NULL);
|
g_assert (filename != NULL);
|
||||||
g_assert (error == NULL || *error == NULL);
|
g_assert (error == NULL || *error == NULL);
|
||||||
|
|
||||||
@ -110,7 +107,7 @@ _cogl_bitmap_from_file (CoglBitmap *bmp,
|
|||||||
/* doesn't exist, not readable, etc. */
|
/* doesn't exist, not readable, etc. */
|
||||||
g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_FAILED,
|
g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_FAILED,
|
||||||
"%s", g_strerror (save_errno));
|
"%s", g_strerror (save_errno));
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unknown images would be cleanly caught as zero width/height below, but try
|
/* Unknown images would be cleanly caught as zero width/height below, but try
|
||||||
@ -122,7 +119,7 @@ _cogl_bitmap_from_file (CoglBitmap *bmp,
|
|||||||
CFRelease (image_source);
|
CFRelease (image_source);
|
||||||
g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_UNKNOWN_TYPE,
|
g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_UNKNOWN_TYPE,
|
||||||
"Unknown image type");
|
"Unknown image type");
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
CFRelease (type);
|
CFRelease (type);
|
||||||
|
|
||||||
@ -137,7 +134,7 @@ _cogl_bitmap_from_file (CoglBitmap *bmp,
|
|||||||
CFRelease (image);
|
CFRelease (image);
|
||||||
g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_CORRUPT_IMAGE,
|
g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_CORRUPT_IMAGE,
|
||||||
"Image has zero width or height");
|
"Image has zero width or height");
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate buffer big enough to hold pixel data */
|
/* allocate buffer big enough to hold pixel data */
|
||||||
@ -160,13 +157,12 @@ _cogl_bitmap_from_file (CoglBitmap *bmp,
|
|||||||
CGContextRelease (bitmap_context);
|
CGContextRelease (bitmap_context);
|
||||||
|
|
||||||
/* store bitmap info */
|
/* store bitmap info */
|
||||||
bmp->data = out_data;
|
return _cogl_bitmap_new_from_data (out_data,
|
||||||
bmp->format = COGL_PIXEL_FORMAT_ARGB_8888;
|
COGL_PIXEL_FORMAT_ARGB_8888,
|
||||||
bmp->width = width;
|
width, height,
|
||||||
bmp->height = height;
|
rowstride,
|
||||||
bmp->rowstride = rowstride;
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL);
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(USE_GDKPIXBUF)
|
#elif defined(USE_GDKPIXBUF)
|
||||||
@ -184,9 +180,8 @@ _cogl_bitmap_get_size_from_file (const char *filename,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_from_file (CoglBitmap *bmp,
|
_cogl_bitmap_from_file (const char *filename,
|
||||||
const char *filename,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GdkPixbuf *pixbuf;
|
GdkPixbuf *pixbuf;
|
||||||
@ -206,9 +201,6 @@ _cogl_bitmap_from_file (CoglBitmap *bmp,
|
|||||||
|
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
if (bmp == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Load from file using GdkPixbuf */
|
/* Load from file using GdkPixbuf */
|
||||||
pixbuf = gdk_pixbuf_new_from_file (filename, error);
|
pixbuf = gdk_pixbuf_new_from_file (filename, error);
|
||||||
if (pixbuf == NULL)
|
if (pixbuf == NULL)
|
||||||
@ -272,16 +264,16 @@ _cogl_bitmap_from_file (CoglBitmap *bmp,
|
|||||||
g_object_unref (pixbuf);
|
g_object_unref (pixbuf);
|
||||||
|
|
||||||
/* Store bitmap info */
|
/* Store bitmap info */
|
||||||
bmp->data = out_data; /* The stored data the same alignment constraints as a
|
/* The stored data the same alignment constraints as a gdkpixbuf but
|
||||||
* gdkpixbuf but stores a full rowstride in the last
|
* stores a full rowstride in the last scanline
|
||||||
* scanline
|
|
||||||
*/
|
*/
|
||||||
bmp->format = pixel_format;
|
return _cogl_bitmap_new_from_data (out_data,
|
||||||
bmp->width = width;
|
pixel_format,
|
||||||
bmp->height = height;
|
width,
|
||||||
bmp->rowstride = rowstride;
|
height,
|
||||||
|
rowstride,
|
||||||
return TRUE;
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -302,11 +294,11 @@ _cogl_bitmap_get_size_from_file (const char *filename,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_from_file (CoglBitmap *bmp,
|
_cogl_bitmap_from_file (const char *filename,
|
||||||
const char *filename,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
|
CoglBitmap *bmp;
|
||||||
int stb_pixel_format;
|
int stb_pixel_format;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
@ -314,9 +306,6 @@ _cogl_bitmap_from_file (CoglBitmap *bmp,
|
|||||||
|
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
if (bmp == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Load from file using stb */
|
/* Load from file using stb */
|
||||||
pixels = stbi_load (filename,
|
pixels = stbi_load (filename,
|
||||||
&width, &height, &stb_pixel_format,
|
&width, &height, &stb_pixel_format,
|
||||||
@ -325,14 +314,15 @@ _cogl_bitmap_from_file (CoglBitmap *bmp,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Store bitmap info */
|
/* Store bitmap info */
|
||||||
bmp->data = g_memdup (pixels, height * width * 4);
|
bmp = _cogl_bitmap_new_from_data (g_memdup (pixels, height * width * 4),
|
||||||
bmp->format = COGL_PIXEL_FORMAT_RGBA_8888;
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
bmp->width = width;
|
width, height,
|
||||||
bmp->height = height;
|
width * 4,
|
||||||
bmp->rowstride = width * 4;
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL);
|
||||||
|
|
||||||
free (pixels);
|
free (pixels);
|
||||||
|
|
||||||
return TRUE;
|
return bmp;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,16 +29,58 @@
|
|||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#include "cogl-handle.h"
|
#include "cogl-handle.h"
|
||||||
|
#include "cogl-buffer.h"
|
||||||
|
|
||||||
struct _CoglBitmap
|
/*
|
||||||
{
|
* CoglBitmapDestroyNotify:
|
||||||
CoglHandleObject _parent;
|
* @data: The image data
|
||||||
guint8 *data;
|
* @destroy_data: The callback closure data that was given to
|
||||||
CoglPixelFormat format;
|
* _cogl_bitmap_new_from_data().
|
||||||
int width;
|
*
|
||||||
int height;
|
* Function prototype that is used to destroy the bitmap data when
|
||||||
int rowstride;
|
* _cogl_bitmap_new_from_data() is called.
|
||||||
};
|
*/
|
||||||
|
typedef void (* CoglBitmapDestroyNotify) (guint8 *data, void *destroy_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _cogl_bitmap_new_from_data:
|
||||||
|
* @data: A pointer to the data. The bitmap will take ownership of this data.
|
||||||
|
* @format: The format of the pixel data.
|
||||||
|
* @width: The width of the bitmap.
|
||||||
|
* @height: The height of the bitmap.
|
||||||
|
* @rowstride: The rowstride of the bitmap (the number of bytes from
|
||||||
|
* the start of one row of the bitmap to the next).
|
||||||
|
* @destroy_fn: A function to be called when the bitmap is
|
||||||
|
* destroyed. This should free @data. %NULL can be used instead if
|
||||||
|
* no free is needed.
|
||||||
|
* @destroy_fn_data: This pointer will get passed to @destroy_fn.
|
||||||
|
*
|
||||||
|
* Creates a bitmap using some existing data. The data is not copied
|
||||||
|
* so the bitmap will take ownership of the data pointer. When the
|
||||||
|
* bitmap is freed @destroy_fn will be called to free the data.
|
||||||
|
*
|
||||||
|
* Return value: A new %CoglBitmap.
|
||||||
|
*/
|
||||||
|
CoglBitmap *
|
||||||
|
_cogl_bitmap_new_from_data (guint8 *data,
|
||||||
|
CoglPixelFormat format,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int rowstride,
|
||||||
|
CoglBitmapDestroyNotify destroy_fn,
|
||||||
|
gpointer destroy_fn_data);
|
||||||
|
|
||||||
|
/* The idea of this function is that it will create a bitmap that
|
||||||
|
shares the actual data with another bitmap. This is needed for the
|
||||||
|
atlas texture backend because it needs upload a bitmap to a sub
|
||||||
|
texture but override the format so that it ignores the premult
|
||||||
|
flag. */
|
||||||
|
CoglBitmap *
|
||||||
|
_cogl_bitmap_new_shared (CoglBitmap *shared_bmp,
|
||||||
|
CoglPixelFormat format,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int rowstride);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_can_convert (CoglPixelFormat src, CoglPixelFormat dst);
|
_cogl_bitmap_can_convert (CoglPixelFormat src, CoglPixelFormat dst);
|
||||||
@ -58,13 +100,11 @@ _cogl_bitmap_can_premult (CoglPixelFormat format);
|
|||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_fallback_can_premult (CoglPixelFormat format);
|
_cogl_bitmap_fallback_can_premult (CoglPixelFormat format);
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_convert (const CoglBitmap *bmp,
|
_cogl_bitmap_convert (CoglBitmap *bmp,
|
||||||
CoglBitmap *dst_bmp,
|
|
||||||
CoglPixelFormat dst_format);
|
CoglPixelFormat dst_format);
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_fallback_convert (const CoglBitmap *bmp,
|
_cogl_bitmap_fallback_convert (CoglBitmap *bmp,
|
||||||
CoglBitmap *dst_bmp,
|
|
||||||
CoglPixelFormat dst_format);
|
CoglPixelFormat dst_format);
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -79,22 +119,19 @@ _cogl_bitmap_premult (CoglBitmap *dst_bmp);
|
|||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_fallback_premult (CoglBitmap *dst_bmp);
|
_cogl_bitmap_fallback_premult (CoglBitmap *dst_bmp);
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_from_file (CoglBitmap *bmp,
|
_cogl_bitmap_from_file (const char *filename,
|
||||||
const char *filename,
|
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_fallback_from_file (CoglBitmap *bmp,
|
_cogl_bitmap_fallback_from_file (const char *filename);
|
||||||
const char *filename);
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_bitmap_convert_premult_status (CoglBitmap *bmp,
|
_cogl_bitmap_convert_premult_status (CoglBitmap *bmp,
|
||||||
CoglPixelFormat dst_format);
|
CoglPixelFormat dst_format);
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_convert_format_and_premult (const CoglBitmap *bmp,
|
_cogl_bitmap_convert_format_and_premult (CoglBitmap *bmp,
|
||||||
CoglBitmap *dst_bmp,
|
|
||||||
CoglPixelFormat dst_format);
|
CoglPixelFormat dst_format);
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -112,4 +149,28 @@ _cogl_bitmap_get_size_from_file (const char *filename,
|
|||||||
int *width,
|
int *width,
|
||||||
int *height);
|
int *height);
|
||||||
|
|
||||||
|
CoglPixelFormat
|
||||||
|
_cogl_bitmap_get_format (CoglBitmap *bitmap);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_bitmap_set_format (CoglBitmap *bitmap,
|
||||||
|
CoglPixelFormat format);
|
||||||
|
|
||||||
|
int
|
||||||
|
_cogl_bitmap_get_width (CoglBitmap *bitmap);
|
||||||
|
|
||||||
|
int
|
||||||
|
_cogl_bitmap_get_height (CoglBitmap *bitmap);
|
||||||
|
|
||||||
|
int
|
||||||
|
_cogl_bitmap_get_rowstride (CoglBitmap *bitmap);
|
||||||
|
|
||||||
|
guint8 *
|
||||||
|
_cogl_bitmap_map (CoglBitmap *bitmap,
|
||||||
|
CoglBufferAccess access,
|
||||||
|
CoglBufferMapHint hints);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_bitmap_unmap (CoglBitmap *bitmap);
|
||||||
|
|
||||||
#endif /* __COGL_BITMAP_H */
|
#endif /* __COGL_BITMAP_H */
|
||||||
|
@ -31,6 +31,25 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
struct _CoglBitmap
|
||||||
|
{
|
||||||
|
CoglHandleObject _parent;
|
||||||
|
CoglPixelFormat format;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int rowstride;
|
||||||
|
|
||||||
|
guint8 *data;
|
||||||
|
CoglBitmapDestroyNotify destroy_fn;
|
||||||
|
void *destroy_fn_data;
|
||||||
|
|
||||||
|
gboolean mapped;
|
||||||
|
|
||||||
|
/* If this is non-null then 'data' is ignored and instead it is
|
||||||
|
fetched from this shared bitmap. */
|
||||||
|
CoglBitmap *shared_bmp;
|
||||||
|
};
|
||||||
|
|
||||||
static void _cogl_bitmap_free (CoglBitmap *bmp);
|
static void _cogl_bitmap_free (CoglBitmap *bmp);
|
||||||
|
|
||||||
COGL_OBJECT_DEFINE (Bitmap, bitmap);
|
COGL_OBJECT_DEFINE (Bitmap, bitmap);
|
||||||
@ -38,8 +57,15 @@ COGL_OBJECT_DEFINE (Bitmap, bitmap);
|
|||||||
static void
|
static void
|
||||||
_cogl_bitmap_free (CoglBitmap *bmp)
|
_cogl_bitmap_free (CoglBitmap *bmp)
|
||||||
{
|
{
|
||||||
g_free (bmp->data);
|
g_assert (!bmp->mapped);
|
||||||
g_free (bmp);
|
|
||||||
|
if (bmp->destroy_fn)
|
||||||
|
bmp->destroy_fn (bmp->data, bmp->destroy_fn_data);
|
||||||
|
|
||||||
|
if (bmp->shared_bmp)
|
||||||
|
cogl_object_unref (bmp->shared_bmp);
|
||||||
|
|
||||||
|
g_slice_free (CoglBitmap, bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -83,45 +109,65 @@ _cogl_bitmap_convert_premult_status (CoglBitmap *bmp,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_bitmap_convert_format_and_premult (const CoglBitmap *bmp,
|
_cogl_bitmap_convert_format_and_premult (CoglBitmap *bmp,
|
||||||
CoglBitmap *dst_bmp,
|
|
||||||
CoglPixelFormat dst_format)
|
CoglPixelFormat dst_format)
|
||||||
{
|
{
|
||||||
|
CoglPixelFormat src_format = _cogl_bitmap_get_format (bmp);
|
||||||
|
CoglBitmap *dst_bmp;
|
||||||
|
|
||||||
/* Is base format different (not considering premult status)? */
|
/* Is base format different (not considering premult status)? */
|
||||||
if ((bmp->format & COGL_UNPREMULT_MASK) !=
|
if ((src_format & COGL_UNPREMULT_MASK) !=
|
||||||
(dst_format & COGL_UNPREMULT_MASK))
|
(dst_format & COGL_UNPREMULT_MASK))
|
||||||
{
|
{
|
||||||
/* Try converting using imaging library */
|
/* Try converting using imaging library */
|
||||||
if (!_cogl_bitmap_convert (bmp, dst_bmp, dst_format))
|
if ((dst_bmp = _cogl_bitmap_convert (bmp, dst_format)) == NULL)
|
||||||
{
|
{
|
||||||
/* ... or try fallback */
|
/* ... or try fallback */
|
||||||
if (!_cogl_bitmap_fallback_convert (bmp, dst_bmp, dst_format))
|
if ((dst_bmp = _cogl_bitmap_fallback_convert (bmp,
|
||||||
return FALSE;
|
dst_format)) == NULL)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
int rowstride = _cogl_bitmap_get_rowstride (bmp);
|
||||||
|
int height = _cogl_bitmap_get_height (bmp);
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
/* Copy the bitmap so that we can premultiply in-place */
|
/* Copy the bitmap so that we can premultiply in-place */
|
||||||
*dst_bmp = *bmp;
|
|
||||||
dst_bmp->data = g_memdup (bmp->data, bmp->rowstride * bmp->height);
|
if ((data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dst_bmp = _cogl_bitmap_new_from_data (g_memdup (data, height * rowstride),
|
||||||
|
src_format,
|
||||||
|
_cogl_bitmap_get_width (bmp),
|
||||||
|
height,
|
||||||
|
rowstride,
|
||||||
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
src_format = _cogl_bitmap_get_format (dst_bmp);
|
||||||
|
|
||||||
/* We only need to do a premult conversion if both formats have an
|
/* We only need to do a premult conversion if both formats have an
|
||||||
alpha channel. If we're converting from RGB to RGBA then the
|
alpha channel. If we're converting from RGB to RGBA then the
|
||||||
alpha will have been filled with 255 so the premult won't do
|
alpha will have been filled with 255 so the premult won't do
|
||||||
anything or if we are converting from RGBA to RGB we're losing
|
anything or if we are converting from RGBA to RGB we're losing
|
||||||
information so either converting or not will be wrong for
|
information so either converting or not will be wrong for
|
||||||
transparent pixels */
|
transparent pixels */
|
||||||
if ((dst_bmp->format & COGL_A_BIT) == COGL_A_BIT &&
|
if ((src_format & COGL_A_BIT) == COGL_A_BIT &&
|
||||||
(dst_format & COGL_A_BIT) == COGL_A_BIT &&
|
(dst_format & COGL_A_BIT) == COGL_A_BIT &&
|
||||||
!_cogl_bitmap_convert_premult_status (dst_bmp, dst_format))
|
!_cogl_bitmap_convert_premult_status (dst_bmp, dst_format))
|
||||||
{
|
{
|
||||||
g_free (dst_bmp->data);
|
cogl_object_unref (dst_bmp);
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return dst_bmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -143,8 +189,12 @@ _cogl_bitmap_copy_subregion (CoglBitmap *src,
|
|||||||
g_assert (src->format == dst->format);
|
g_assert (src->format == dst->format);
|
||||||
bpp = _cogl_get_format_bpp (src->format);
|
bpp = _cogl_get_format_bpp (src->format);
|
||||||
|
|
||||||
srcdata = src->data + src_y * src->rowstride + src_x * bpp;
|
if ((srcdata = _cogl_bitmap_map (src, COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
dstdata = dst->data + dst_y * dst->rowstride + dst_x * bpp;
|
{
|
||||||
|
if ((dstdata = _cogl_bitmap_map (dst, COGL_BUFFER_ACCESS_WRITE, 0)))
|
||||||
|
{
|
||||||
|
srcdata += src_y * src->rowstride + src_x * bpp;
|
||||||
|
dstdata += dst_y * dst->rowstride + dst_x * bpp;
|
||||||
|
|
||||||
for (line=0; line<height; ++line)
|
for (line=0; line<height; ++line)
|
||||||
{
|
{
|
||||||
@ -152,6 +202,12 @@ _cogl_bitmap_copy_subregion (CoglBitmap *src,
|
|||||||
srcdata += src->rowstride;
|
srcdata += src->rowstride;
|
||||||
dstdata += dst->rowstride;
|
dstdata += dst->rowstride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -162,30 +218,89 @@ cogl_bitmap_get_size_from_file (const char *filename,
|
|||||||
return _cogl_bitmap_get_size_from_file (filename, width, height);
|
return _cogl_bitmap_get_size_from_file (filename, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoglBitmap *
|
||||||
|
_cogl_bitmap_new_from_data (guint8 *data,
|
||||||
|
CoglPixelFormat format,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int rowstride,
|
||||||
|
CoglBitmapDestroyNotify destroy_fn,
|
||||||
|
void *destroy_fn_data)
|
||||||
|
{
|
||||||
|
CoglBitmap *bmp = g_slice_new (CoglBitmap);
|
||||||
|
|
||||||
|
bmp->format = format;
|
||||||
|
bmp->width = width;
|
||||||
|
bmp->height = height;
|
||||||
|
bmp->rowstride = rowstride;
|
||||||
|
bmp->data = data;
|
||||||
|
bmp->destroy_fn = destroy_fn;
|
||||||
|
bmp->destroy_fn_data = destroy_fn_data;
|
||||||
|
bmp->mapped = FALSE;
|
||||||
|
bmp->shared_bmp = NULL;
|
||||||
|
|
||||||
|
return _cogl_bitmap_object_new (bmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglBitmap *
|
||||||
|
_cogl_bitmap_new_shared (CoglBitmap *shared_bmp,
|
||||||
|
CoglPixelFormat format,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int rowstride)
|
||||||
|
{
|
||||||
|
CoglBitmap *bmp = _cogl_bitmap_new_from_data (NULL, /* data */
|
||||||
|
format,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
rowstride,
|
||||||
|
NULL, /* destroy_fn */
|
||||||
|
NULL /* destroy_fn_data */);
|
||||||
|
|
||||||
|
bmp->shared_bmp = cogl_object_ref (shared_bmp);
|
||||||
|
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
|
||||||
CoglBitmap *
|
CoglBitmap *
|
||||||
cogl_bitmap_new_from_file (const char *filename,
|
cogl_bitmap_new_from_file (const char *filename,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
CoglBitmap bmp;
|
CoglBitmap *bmp;
|
||||||
CoglBitmap *ret;
|
|
||||||
|
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
|
g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
/* Try loading with imaging backend */
|
if ((bmp = _cogl_bitmap_from_file (filename, error)) == NULL)
|
||||||
if (!_cogl_bitmap_from_file (&bmp, filename, error))
|
|
||||||
{
|
{
|
||||||
/* Try fallback */
|
/* Try fallback */
|
||||||
if (!_cogl_bitmap_fallback_from_file (&bmp, filename))
|
if ((bmp = _cogl_bitmap_fallback_from_file (filename))
|
||||||
return NULL;
|
&& error && *error)
|
||||||
else if (error && *error)
|
|
||||||
{
|
{
|
||||||
g_error_free (*error);
|
g_error_free (*error);
|
||||||
*error = NULL;
|
*error = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = g_memdup (&bmp, sizeof (CoglBitmap));
|
return bmp;
|
||||||
return _cogl_bitmap_object_new (ret);
|
}
|
||||||
|
|
||||||
|
CoglPixelFormat
|
||||||
|
_cogl_bitmap_get_format (CoglBitmap *bitmap)
|
||||||
|
{
|
||||||
|
return bitmap->format;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_bitmap_set_format (CoglBitmap *bitmap,
|
||||||
|
CoglPixelFormat format)
|
||||||
|
{
|
||||||
|
bitmap->format = format;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_cogl_bitmap_get_width (CoglBitmap *bitmap)
|
||||||
|
{
|
||||||
|
return bitmap->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
GQuark
|
GQuark
|
||||||
@ -193,3 +308,46 @@ cogl_bitmap_error_quark (void)
|
|||||||
{
|
{
|
||||||
return g_quark_from_static_string ("cogl-bitmap-error-quark");
|
return g_quark_from_static_string ("cogl-bitmap-error-quark");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_cogl_bitmap_get_height (CoglBitmap *bitmap)
|
||||||
|
{
|
||||||
|
return bitmap->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_cogl_bitmap_get_rowstride (CoglBitmap *bitmap)
|
||||||
|
{
|
||||||
|
return bitmap->rowstride;
|
||||||
|
}
|
||||||
|
|
||||||
|
guint8 *
|
||||||
|
_cogl_bitmap_map (CoglBitmap *bitmap,
|
||||||
|
CoglBufferAccess access,
|
||||||
|
CoglBufferMapHint hints)
|
||||||
|
{
|
||||||
|
/* Divert to another bitmap if this data is shared */
|
||||||
|
if (bitmap->shared_bmp)
|
||||||
|
return _cogl_bitmap_map (bitmap->shared_bmp, access, hints);
|
||||||
|
|
||||||
|
g_assert (!bitmap->mapped);
|
||||||
|
bitmap->mapped = TRUE;
|
||||||
|
|
||||||
|
/* Currently the bitmap is always in regular memory so we can just
|
||||||
|
directly return the pointer */
|
||||||
|
return bitmap->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_bitmap_unmap (CoglBitmap *bitmap)
|
||||||
|
{
|
||||||
|
/* Divert to another bitmap if this data is shared */
|
||||||
|
if (bitmap->shared_bmp)
|
||||||
|
return _cogl_bitmap_unmap (bitmap->shared_bmp);
|
||||||
|
|
||||||
|
g_assert (bitmap->mapped);
|
||||||
|
bitmap->mapped = FALSE;
|
||||||
|
|
||||||
|
/* Currently the bitmap is always in regular memory so we don't need
|
||||||
|
to do anything */
|
||||||
|
}
|
||||||
|
@ -65,7 +65,7 @@ _cogl_texture_2d_new_with_size (unsigned int width,
|
|||||||
CoglPixelFormat internal_format);
|
CoglPixelFormat internal_format);
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_texture_2d_new_from_bitmap (CoglHandle bmp_handle,
|
_cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
|
||||||
CoglTextureFlags flags,
|
CoglTextureFlags flags,
|
||||||
CoglPixelFormat internal_format);
|
CoglPixelFormat internal_format);
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle,
|
|||||||
CoglPixelFormat format);
|
CoglPixelFormat format);
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_texture_2d_sliced_new_from_bitmap (CoglHandle bmp_handle,
|
_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
|
||||||
CoglTextureFlags flags,
|
CoglTextureFlags flags,
|
||||||
CoglPixelFormat internal_format);
|
CoglPixelFormat internal_format);
|
||||||
|
|
||||||
|
@ -230,11 +230,13 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
int bpp;
|
int bpp;
|
||||||
int x, y;
|
int x, y;
|
||||||
guint8 *waste_buf;
|
guint8 *waste_buf;
|
||||||
|
CoglPixelFormat bmp_format;
|
||||||
|
|
||||||
bpp = _cogl_get_format_bpp (bmp->format);
|
bmp_format = _cogl_bitmap_get_format (bmp);
|
||||||
|
bpp = _cogl_get_format_bpp (bmp_format);
|
||||||
|
|
||||||
waste_buf = _cogl_texture_2d_sliced_allocate_waste_buffer (tex_2ds,
|
waste_buf = _cogl_texture_2d_sliced_allocate_waste_buffer (tex_2ds,
|
||||||
bmp->format);
|
bmp_format);
|
||||||
|
|
||||||
/* Iterate vertical slices */
|
/* Iterate vertical slices */
|
||||||
for (y = 0; y < tex_2ds->slice_y_spans->len; ++y)
|
for (y = 0; y < tex_2ds->slice_y_spans->len; ++y)
|
||||||
@ -267,11 +269,18 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
|
|
||||||
/* Keep a copy of the first pixel if needed */
|
/* Keep a copy of the first pixel if needed */
|
||||||
if (tex_2ds->first_pixels)
|
if (tex_2ds->first_pixels)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
if ((data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
{
|
{
|
||||||
memcpy (tex_2ds->first_pixels[slice_num].data,
|
memcpy (tex_2ds->first_pixels[slice_num].data,
|
||||||
bmp->data + x_span->start * bpp
|
data + x_span->start * bpp
|
||||||
+ y_span->start * bmp->rowstride,
|
+ y_span->start * _cogl_bitmap_get_rowstride (bmp),
|
||||||
bpp);
|
bpp);
|
||||||
|
_cogl_bitmap_unmap (bmp);
|
||||||
|
}
|
||||||
|
|
||||||
tex_2ds->first_pixels[slice_num].gl_format = gl_format;
|
tex_2ds->first_pixels[slice_num].gl_format = gl_format;
|
||||||
tex_2ds->first_pixels[slice_num].gl_type = gl_type;
|
tex_2ds->first_pixels[slice_num].gl_type = gl_type;
|
||||||
}
|
}
|
||||||
@ -279,8 +288,14 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
/* Fill the waste with a copies of the rightmost pixels */
|
/* Fill the waste with a copies of the rightmost pixels */
|
||||||
if (x_span->waste > 0)
|
if (x_span->waste > 0)
|
||||||
{
|
{
|
||||||
const guint8 *src = bmp->data
|
int bmp_rowstride = _cogl_bitmap_get_rowstride (bmp);
|
||||||
+ y_span->start * bmp->rowstride
|
guint8 *bmp_data = _cogl_bitmap_map (bmp,
|
||||||
|
COGL_BUFFER_ACCESS_READ, 0);
|
||||||
|
|
||||||
|
if (bmp_data)
|
||||||
|
{
|
||||||
|
const guint8 *src = bmp_data
|
||||||
|
+ y_span->start * bmp_rowstride
|
||||||
+ (x_span->start + x_span->size - x_span->waste - 1) * bpp;
|
+ (x_span->start + x_span->size - x_span->waste - 1) * bpp;
|
||||||
guint8 *dst = waste_buf;
|
guint8 *dst = waste_buf;
|
||||||
unsigned int wx, wy;
|
unsigned int wx, wy;
|
||||||
@ -292,9 +307,11 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
memcpy (dst, src, bpp);
|
memcpy (dst, src, bpp);
|
||||||
dst += bpp;
|
dst += bpp;
|
||||||
}
|
}
|
||||||
src += bmp->rowstride;
|
src += bmp_rowstride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (bmp);
|
||||||
|
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
||||||
x_span->waste * bpp,
|
x_span->waste * bpp,
|
||||||
bpp);
|
bpp);
|
||||||
@ -307,12 +324,19 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
gl_format, gl_type,
|
gl_format, gl_type,
|
||||||
waste_buf) );
|
waste_buf) );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (y_span->waste > 0)
|
if (y_span->waste > 0)
|
||||||
{
|
{
|
||||||
const guint8 *src = bmp->data
|
int bmp_rowstride = _cogl_bitmap_get_rowstride (bmp);
|
||||||
|
guint8 *bmp_data = _cogl_bitmap_map (bmp,
|
||||||
|
COGL_BUFFER_ACCESS_READ, 0);
|
||||||
|
|
||||||
|
if (bmp_data)
|
||||||
|
{
|
||||||
|
const guint8 *src = bmp_data
|
||||||
+ ((y_span->start + y_span->size - y_span->waste - 1)
|
+ ((y_span->start + y_span->size - y_span->waste - 1)
|
||||||
* bmp->rowstride)
|
* bmp_rowstride)
|
||||||
+ x_span->start * bpp;
|
+ x_span->start * bpp;
|
||||||
guint8 *dst = waste_buf;
|
guint8 *dst = waste_buf;
|
||||||
unsigned int wy, wx;
|
unsigned int wy, wx;
|
||||||
@ -329,6 +353,8 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (bmp);
|
||||||
|
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
||||||
x_span->size * bpp,
|
x_span->size * bpp,
|
||||||
bpp);
|
bpp);
|
||||||
@ -343,6 +369,7 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (waste_buf)
|
if (waste_buf)
|
||||||
g_free (waste_buf);
|
g_free (waste_buf);
|
||||||
@ -374,11 +401,13 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
int inter_w = 0, inter_h = 0;
|
int inter_w = 0, inter_h = 0;
|
||||||
int local_x = 0, local_y = 0;
|
int local_x = 0, local_y = 0;
|
||||||
guint8 *waste_buf;
|
guint8 *waste_buf;
|
||||||
|
CoglPixelFormat source_format;
|
||||||
|
|
||||||
bpp = _cogl_get_format_bpp (source_bmp->format);
|
source_format = _cogl_bitmap_get_format (source_bmp);
|
||||||
|
bpp = _cogl_get_format_bpp (source_format);
|
||||||
|
|
||||||
waste_buf =
|
waste_buf =
|
||||||
_cogl_texture_2d_sliced_allocate_waste_buffer (tex_2ds, source_bmp->format);
|
_cogl_texture_2d_sliced_allocate_waste_buffer (tex_2ds, source_format);
|
||||||
|
|
||||||
/* Iterate vertical spans */
|
/* Iterate vertical spans */
|
||||||
for (source_y = src_y,
|
for (source_y = src_y,
|
||||||
@ -456,11 +485,19 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
|
|
||||||
/* Keep a copy of the first pixel if needed */
|
/* Keep a copy of the first pixel if needed */
|
||||||
if (tex_2ds->first_pixels && local_x == 0 && local_y == 0)
|
if (tex_2ds->first_pixels && local_x == 0 && local_y == 0)
|
||||||
|
{
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
|
if ((data = _cogl_bitmap_map (source_bmp,
|
||||||
|
COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
{
|
{
|
||||||
memcpy (tex_2ds->first_pixels[slice_num].data,
|
memcpy (tex_2ds->first_pixels[slice_num].data,
|
||||||
source_bmp->data + source_x * bpp
|
data + source_x * bpp
|
||||||
+ source_y * source_bmp->rowstride,
|
+ source_y * _cogl_bitmap_get_rowstride (source_bmp),
|
||||||
bpp);
|
bpp);
|
||||||
|
_cogl_bitmap_unmap (source_bmp);
|
||||||
|
}
|
||||||
|
|
||||||
tex_2ds->first_pixels[slice_num].gl_format = source_gl_format;
|
tex_2ds->first_pixels[slice_num].gl_format = source_gl_format;
|
||||||
tex_2ds->first_pixels[slice_num].gl_type = source_gl_type;
|
tex_2ds->first_pixels[slice_num].gl_type = source_gl_type;
|
||||||
}
|
}
|
||||||
@ -471,15 +508,21 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
if (x_span->waste > 0
|
if (x_span->waste > 0
|
||||||
&& local_x < x_span->size - x_span->waste
|
&& local_x < x_span->size - x_span->waste
|
||||||
&& local_x + inter_w >= x_span->size - x_span->waste)
|
&& local_x + inter_w >= x_span->size - x_span->waste)
|
||||||
|
{
|
||||||
|
int bmp_rowstride = _cogl_bitmap_get_rowstride (source_bmp);
|
||||||
|
guint8 *bmp_data = _cogl_bitmap_map (source_bmp,
|
||||||
|
COGL_BUFFER_ACCESS_READ, 0);
|
||||||
|
|
||||||
|
if (bmp_data)
|
||||||
{
|
{
|
||||||
const guint8 *src;
|
const guint8 *src;
|
||||||
guint8 *dst;
|
guint8 *dst;
|
||||||
unsigned int wx, wy;
|
unsigned int wx, wy;
|
||||||
|
|
||||||
src = source_bmp->data
|
src = bmp_data
|
||||||
+ (src_y + ((int)y_iter.intersect_start)
|
+ (src_y + ((int)y_iter.intersect_start)
|
||||||
- dst_y)
|
- dst_y)
|
||||||
* source_bmp->rowstride
|
* bmp_rowstride
|
||||||
+ (src_x + x_span->start + x_span->size - x_span->waste
|
+ (src_x + x_span->start + x_span->size - x_span->waste
|
||||||
- dst_x - 1)
|
- dst_x - 1)
|
||||||
* bpp;
|
* bpp;
|
||||||
@ -493,9 +536,11 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
memcpy (dst, src, bpp);
|
memcpy (dst, src, bpp);
|
||||||
dst += bpp;
|
dst += bpp;
|
||||||
}
|
}
|
||||||
src += source_bmp->rowstride;
|
src += bmp_rowstride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (source_bmp);
|
||||||
|
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
||||||
x_span->waste * bpp,
|
x_span->waste * bpp,
|
||||||
bpp);
|
bpp);
|
||||||
@ -509,24 +554,31 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
source_gl_type,
|
source_gl_type,
|
||||||
waste_buf) );
|
waste_buf) );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* same for the bottom-most pixels */
|
/* same for the bottom-most pixels */
|
||||||
if (y_span->waste > 0
|
if (y_span->waste > 0
|
||||||
&& local_y < y_span->size - y_span->waste
|
&& local_y < y_span->size - y_span->waste
|
||||||
&& local_y + inter_h >= y_span->size - y_span->waste)
|
&& local_y + inter_h >= y_span->size - y_span->waste)
|
||||||
|
{
|
||||||
|
int bmp_rowstride = _cogl_bitmap_get_rowstride (source_bmp);
|
||||||
|
guint8 *bmp_data = _cogl_bitmap_map (source_bmp,
|
||||||
|
COGL_BUFFER_ACCESS_READ, 0);
|
||||||
|
|
||||||
|
if (bmp_data)
|
||||||
{
|
{
|
||||||
const guint8 *src;
|
const guint8 *src;
|
||||||
guint8 *dst;
|
guint8 *dst;
|
||||||
unsigned int wy, wx;
|
unsigned int wy, wx;
|
||||||
unsigned int copy_width;
|
unsigned int copy_width;
|
||||||
|
|
||||||
src = source_bmp->data
|
src = bmp_data
|
||||||
+ (src_x + ((int)x_iter.intersect_start)
|
+ (src_x + ((int)x_iter.intersect_start)
|
||||||
- dst_x)
|
- dst_x)
|
||||||
* bpp
|
* bpp
|
||||||
+ (src_y + y_span->start + y_span->size - y_span->waste
|
+ (src_y + y_span->start + y_span->size - y_span->waste
|
||||||
- dst_y - 1)
|
- dst_y - 1)
|
||||||
* source_bmp->rowstride;
|
* bmp_rowstride;
|
||||||
|
|
||||||
dst = waste_buf;
|
dst = waste_buf;
|
||||||
|
|
||||||
@ -547,6 +599,8 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (source_bmp);
|
||||||
|
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
||||||
copy_width * bpp,
|
copy_width * bpp,
|
||||||
bpp);
|
bpp);
|
||||||
@ -562,6 +616,7 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (waste_buf)
|
if (waste_buf)
|
||||||
g_free (waste_buf);
|
g_free (waste_buf);
|
||||||
@ -914,15 +969,15 @@ _cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_cogl_texture_2d_sliced_upload_from_data
|
_cogl_texture_2d_sliced_init_base (CoglTexture2DSliced *tex_2ds,
|
||||||
(CoglTexture2DSliced *tex_2ds,
|
int width,
|
||||||
CoglBitmap *bmp,
|
int height,
|
||||||
|
GLenum gl_intformat,
|
||||||
|
GLenum gl_format,
|
||||||
|
GLenum gl_type,
|
||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format)
|
||||||
{
|
{
|
||||||
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
|
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
|
||||||
GLenum gl_intformat;
|
|
||||||
GLenum gl_format;
|
|
||||||
GLenum gl_type;
|
|
||||||
|
|
||||||
tex->vtable = &cogl_texture_2d_sliced_vtable;
|
tex->vtable = &cogl_texture_2d_sliced_vtable;
|
||||||
|
|
||||||
@ -939,71 +994,18 @@ _cogl_texture_2d_sliced_upload_from_data
|
|||||||
tex_2ds->min_filter = GL_LINEAR;
|
tex_2ds->min_filter = GL_LINEAR;
|
||||||
tex_2ds->mag_filter = GL_LINEAR;
|
tex_2ds->mag_filter = GL_LINEAR;
|
||||||
|
|
||||||
if (bmp->data)
|
|
||||||
{
|
|
||||||
CoglBitmap dst_bmp;
|
|
||||||
gboolean dst_bmp_owner;
|
|
||||||
|
|
||||||
if (!_cogl_texture_prepare_for_upload (bmp,
|
|
||||||
internal_format,
|
|
||||||
&internal_format,
|
|
||||||
&dst_bmp,
|
|
||||||
&dst_bmp_owner,
|
|
||||||
&gl_intformat,
|
|
||||||
&gl_format,
|
|
||||||
&gl_type))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Create slices for the given format and size */
|
/* Create slices for the given format and size */
|
||||||
if (!_cogl_texture_2d_sliced_slices_create (tex_2ds,
|
if (!_cogl_texture_2d_sliced_slices_create (tex_2ds,
|
||||||
dst_bmp.width,
|
width,
|
||||||
dst_bmp.height,
|
height,
|
||||||
gl_intformat,
|
|
||||||
gl_format,
|
|
||||||
gl_type))
|
|
||||||
{
|
|
||||||
if (dst_bmp_owner)
|
|
||||||
g_free (dst_bmp.data);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_cogl_texture_2d_sliced_upload_to_gl (tex_2ds,
|
|
||||||
&dst_bmp,
|
|
||||||
gl_intformat,
|
|
||||||
gl_format,
|
|
||||||
gl_type))
|
|
||||||
{
|
|
||||||
if (dst_bmp_owner)
|
|
||||||
g_free (dst_bmp.data);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dst_bmp_owner)
|
|
||||||
g_free (dst_bmp.data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Find closest GL format match */
|
|
||||||
internal_format = _cogl_pixel_format_to_gl (internal_format,
|
|
||||||
&gl_intformat,
|
|
||||||
&gl_format,
|
|
||||||
&gl_type);
|
|
||||||
|
|
||||||
/* Create slices for the given format and size */
|
|
||||||
if (!_cogl_texture_2d_sliced_slices_create (tex_2ds,
|
|
||||||
bmp->width,
|
|
||||||
bmp->height,
|
|
||||||
gl_intformat,
|
gl_intformat,
|
||||||
gl_format,
|
gl_format,
|
||||||
gl_type))
|
gl_type))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
tex_2ds->gl_format = gl_intformat;
|
tex_2ds->gl_format = gl_intformat;
|
||||||
tex_2ds->width = bmp->width;
|
tex_2ds->width = width;
|
||||||
tex_2ds->height = bmp->height;
|
tex_2ds->height = height;
|
||||||
tex_2ds->format = internal_format;
|
tex_2ds->format = internal_format;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -1016,7 +1018,9 @@ _cogl_texture_2d_sliced_new_with_size (unsigned int width,
|
|||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format)
|
||||||
{
|
{
|
||||||
CoglTexture2DSliced *tex_2ds;
|
CoglTexture2DSliced *tex_2ds;
|
||||||
CoglBitmap bmp;
|
GLenum gl_intformat;
|
||||||
|
GLenum gl_format;
|
||||||
|
GLenum gl_type;
|
||||||
|
|
||||||
/* Since no data, we need some internal format */
|
/* Since no data, we need some internal format */
|
||||||
if (internal_format == COGL_PIXEL_FORMAT_ANY)
|
if (internal_format == COGL_PIXEL_FORMAT_ANY)
|
||||||
@ -1025,36 +1029,60 @@ _cogl_texture_2d_sliced_new_with_size (unsigned int width,
|
|||||||
/* Init texture with empty bitmap */
|
/* Init texture with empty bitmap */
|
||||||
tex_2ds = g_new (CoglTexture2DSliced, 1);
|
tex_2ds = g_new (CoglTexture2DSliced, 1);
|
||||||
|
|
||||||
bmp.width = width;
|
|
||||||
bmp.height = height;
|
|
||||||
bmp.data = NULL;
|
|
||||||
|
|
||||||
if ((flags & COGL_TEXTURE_NO_SLICING))
|
if ((flags & COGL_TEXTURE_NO_SLICING))
|
||||||
tex_2ds->max_waste = -1;
|
tex_2ds->max_waste = -1;
|
||||||
else
|
else
|
||||||
tex_2ds->max_waste = COGL_TEXTURE_MAX_WASTE;
|
tex_2ds->max_waste = COGL_TEXTURE_MAX_WASTE;
|
||||||
|
|
||||||
if (!_cogl_texture_2d_sliced_upload_from_data (tex_2ds, &bmp,
|
/* Find closest GL format match */
|
||||||
|
internal_format = _cogl_pixel_format_to_gl (internal_format,
|
||||||
|
&gl_intformat,
|
||||||
|
&gl_format,
|
||||||
|
&gl_type);
|
||||||
|
|
||||||
|
if (!_cogl_texture_2d_sliced_init_base (tex_2ds,
|
||||||
|
width, height,
|
||||||
|
gl_intformat,
|
||||||
|
gl_format,
|
||||||
|
gl_type,
|
||||||
internal_format))
|
internal_format))
|
||||||
{
|
{
|
||||||
_cogl_texture_2d_sliced_free (tex_2ds);
|
_cogl_texture_2d_sliced_free (tex_2ds);
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_cogl_texture_2d_sliced_slices_create (tex_2ds,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
gl_intformat,
|
||||||
|
gl_format,
|
||||||
|
gl_type))
|
||||||
|
{
|
||||||
|
_cogl_texture_2d_sliced_free (tex_2ds);
|
||||||
|
return COGL_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
tex_2ds->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
tex_2ds->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
||||||
|
|
||||||
return _cogl_texture_2d_sliced_handle_new (tex_2ds);
|
return _cogl_texture_2d_sliced_handle_new (tex_2ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_texture_2d_sliced_new_from_bitmap (CoglHandle bmp_handle,
|
_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
|
||||||
CoglTextureFlags flags,
|
CoglTextureFlags flags,
|
||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format)
|
||||||
{
|
{
|
||||||
CoglTexture2DSliced *tex_2ds;
|
CoglTexture2DSliced *tex_2ds;
|
||||||
CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
|
CoglBitmap *dst_bmp;
|
||||||
|
GLenum gl_intformat;
|
||||||
|
GLenum gl_format;
|
||||||
|
GLenum gl_type;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
g_return_val_if_fail (bmp_handle != COGL_INVALID_HANDLE, COGL_INVALID_HANDLE);
|
g_return_val_if_fail (cogl_is_bitmap (bmp), COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
|
width = _cogl_bitmap_get_width (bmp);
|
||||||
|
height = _cogl_bitmap_get_height (bmp);
|
||||||
|
|
||||||
/* Create new texture and fill with loaded data */
|
/* Create new texture and fill with loaded data */
|
||||||
tex_2ds = g_new0 (CoglTexture2DSliced, 1);
|
tex_2ds = g_new0 (CoglTexture2DSliced, 1);
|
||||||
@ -1072,16 +1100,50 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
* CoglHandle is returned, it should also be destroyed
|
* CoglHandle is returned, it should also be destroyed
|
||||||
* with cogl_handle_unref at some point! */
|
* with cogl_handle_unref at some point! */
|
||||||
|
|
||||||
if (!_cogl_texture_2d_sliced_upload_from_data (tex_2ds, bmp,
|
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||||
internal_format))
|
internal_format,
|
||||||
|
&internal_format,
|
||||||
|
&gl_intformat,
|
||||||
|
&gl_format,
|
||||||
|
&gl_type);
|
||||||
|
if (dst_bmp == COGL_INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
_cogl_texture_2d_sliced_free (tex_2ds);
|
_cogl_texture_2d_sliced_free (tex_2ds);
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_cogl_texture_2d_sliced_init_base (tex_2ds,
|
||||||
|
width, height,
|
||||||
|
gl_intformat,
|
||||||
|
gl_format,
|
||||||
|
gl_type,
|
||||||
|
internal_format))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!_cogl_texture_2d_sliced_slices_create (tex_2ds,
|
||||||
|
width, height,
|
||||||
|
gl_intformat,
|
||||||
|
gl_format,
|
||||||
|
gl_type))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!_cogl_texture_2d_sliced_upload_to_gl (tex_2ds,
|
||||||
|
dst_bmp,
|
||||||
|
gl_intformat,
|
||||||
|
gl_format,
|
||||||
|
gl_type))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
cogl_object_unref (dst_bmp);
|
||||||
|
|
||||||
tex_2ds->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
tex_2ds->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
||||||
|
|
||||||
return _cogl_texture_2d_sliced_handle_new (tex_2ds);
|
return _cogl_texture_2d_sliced_handle_new (tex_2ds);
|
||||||
|
|
||||||
|
error:
|
||||||
|
cogl_object_unref (dst_bmp);
|
||||||
|
_cogl_texture_2d_sliced_free (tex_2ds);
|
||||||
|
return COGL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
@ -1467,7 +1529,7 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex,
|
|||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
|
||||||
_cogl_pixel_format_to_gl (bmp->format,
|
_cogl_pixel_format_to_gl (_cogl_bitmap_get_format (bmp),
|
||||||
NULL, /* internal format */
|
NULL, /* internal format */
|
||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type);
|
&gl_type);
|
||||||
@ -1496,9 +1558,10 @@ _cogl_texture_2d_sliced_download_from_gl (
|
|||||||
GLuint gl_handle;
|
GLuint gl_handle;
|
||||||
int bpp;
|
int bpp;
|
||||||
int x, y;
|
int x, y;
|
||||||
CoglBitmap slice_bmp;
|
CoglBitmap *slice_bmp;
|
||||||
|
CoglPixelFormat target_format = _cogl_bitmap_get_format (target_bmp);
|
||||||
|
|
||||||
bpp = _cogl_get_format_bpp (target_bmp->format);
|
bpp = _cogl_get_format_bpp (target_format);
|
||||||
|
|
||||||
/* Iterate vertical slices */
|
/* Iterate vertical slices */
|
||||||
for (y = 0; y < tex_2ds->slice_y_spans->len; ++y)
|
for (y = 0; y < tex_2ds->slice_y_spans->len; ++y)
|
||||||
@ -1520,18 +1583,21 @@ _cogl_texture_2d_sliced_download_from_gl (
|
|||||||
|
|
||||||
if (y_span->waste != 0 || x_span->waste != 0)
|
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 */
|
/* Setup temp bitmap for slice subregion */
|
||||||
slice_bmp.format = target_bmp->format;
|
slice_bmp = _cogl_bitmap_new_from_data (data,
|
||||||
slice_bmp.width = x_span->size;
|
target_format,
|
||||||
slice_bmp.height = y_span->size;
|
x_span->size,
|
||||||
slice_bmp.rowstride = bpp * slice_bmp.width;
|
y_span->size,
|
||||||
slice_bmp.data = g_malloc (slice_bmp.rowstride *
|
rowstride,
|
||||||
slice_bmp.height);
|
(CoglBitmapDestroyNotify)
|
||||||
|
g_free,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/* Setup gl alignment to 0,0 top-left corner */
|
/* Setup gl alignment to 0,0 top-left corner */
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_download (
|
_cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp);
|
||||||
slice_bmp.rowstride,
|
|
||||||
bpp);
|
|
||||||
|
|
||||||
/* Download slice image data into temp bmp */
|
/* Download slice image data into temp bmp */
|
||||||
_cogl_bind_gl_texture_transient (tex_2ds->gl_target,
|
_cogl_bind_gl_texture_transient (tex_2ds->gl_target,
|
||||||
@ -1541,15 +1607,15 @@ _cogl_texture_2d_sliced_download_from_gl (
|
|||||||
if (!_cogl_texture_driver_gl_get_tex_image (tex_2ds->gl_target,
|
if (!_cogl_texture_driver_gl_get_tex_image (tex_2ds->gl_target,
|
||||||
target_gl_format,
|
target_gl_format,
|
||||||
target_gl_type,
|
target_gl_type,
|
||||||
slice_bmp.data))
|
data))
|
||||||
{
|
{
|
||||||
/* Free temp bitmap */
|
/* Free temp bitmap */
|
||||||
g_free (slice_bmp.data);
|
cogl_object_unref (slice_bmp);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy portion of slice from temp to target bmp */
|
/* Copy portion of slice from temp to target bmp */
|
||||||
_cogl_bitmap_copy_subregion (&slice_bmp,
|
_cogl_bitmap_copy_subregion (slice_bmp,
|
||||||
target_bmp,
|
target_bmp,
|
||||||
0, 0,
|
0, 0,
|
||||||
x_span->start,
|
x_span->start,
|
||||||
@ -1557,30 +1623,39 @@ _cogl_texture_2d_sliced_download_from_gl (
|
|||||||
x_span->size - x_span->waste,
|
x_span->size - x_span->waste,
|
||||||
y_span->size - y_span->waste);
|
y_span->size - y_span->waste);
|
||||||
/* Free temp bitmap */
|
/* Free temp bitmap */
|
||||||
g_free (slice_bmp.data);
|
cogl_object_unref (slice_bmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GLvoid *dst = target_bmp->data
|
guint8 *data;
|
||||||
+ x_span->start * bpp
|
GLvoid *dst;
|
||||||
+ y_span->start * target_bmp->rowstride;
|
gboolean ret;
|
||||||
|
int rowstride = _cogl_bitmap_get_rowstride (target_bmp);
|
||||||
|
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_download (
|
data = _cogl_bitmap_map (target_bmp,
|
||||||
target_bmp->rowstride,
|
COGL_BUFFER_ACCESS_WRITE,
|
||||||
bpp);
|
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 */
|
/* Download slice image data */
|
||||||
_cogl_bind_gl_texture_transient (tex_2ds->gl_target,
|
_cogl_bind_gl_texture_transient (tex_2ds->gl_target,
|
||||||
gl_handle,
|
gl_handle,
|
||||||
tex_2ds->is_foreign);
|
tex_2ds->is_foreign);
|
||||||
|
|
||||||
if (!_cogl_texture_driver_gl_get_tex_image (tex_2ds->gl_target,
|
ret = _cogl_texture_driver_gl_get_tex_image (tex_2ds->gl_target,
|
||||||
target_gl_format,
|
target_gl_format,
|
||||||
target_gl_type,
|
target_gl_type,
|
||||||
dst))
|
dst);
|
||||||
{
|
|
||||||
return FALSE;
|
_cogl_bitmap_unmap (target_bmp);
|
||||||
}
|
|
||||||
|
if (!ret)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1588,7 +1663,7 @@ _cogl_texture_2d_sliced_download_from_gl (
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static gboolean
|
||||||
_cogl_texture_2d_sliced_get_data (CoglTexture *tex,
|
_cogl_texture_2d_sliced_get_data (CoglTexture *tex,
|
||||||
CoglPixelFormat format,
|
CoglPixelFormat format,
|
||||||
unsigned int rowstride,
|
unsigned int rowstride,
|
||||||
@ -1598,7 +1673,8 @@ _cogl_texture_2d_sliced_get_data (CoglTexture *tex,
|
|||||||
int bpp;
|
int bpp;
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
CoglBitmap target_bmp;
|
CoglBitmap *target_bmp;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
bpp = _cogl_get_format_bpp (format);
|
bpp = _cogl_get_format_bpp (format);
|
||||||
|
|
||||||
@ -1607,16 +1683,23 @@ _cogl_texture_2d_sliced_get_data (CoglTexture *tex,
|
|||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type);
|
&gl_type);
|
||||||
|
|
||||||
target_bmp.width = tex_2ds->width;
|
target_bmp = _cogl_bitmap_new_from_data (data,
|
||||||
target_bmp.height = tex_2ds->height;
|
format,
|
||||||
target_bmp.format = format;
|
tex_2ds->width,
|
||||||
target_bmp.rowstride = rowstride;
|
tex_2ds->height,
|
||||||
target_bmp.data = data;
|
rowstride,
|
||||||
|
NULL, /* destroy_fn */
|
||||||
|
NULL /* destroy_fn_data */);
|
||||||
|
|
||||||
/* Retrieve data from slices */
|
/* Retrieve data from slices */
|
||||||
return _cogl_texture_2d_sliced_download_from_gl (tex_2ds, &target_bmp,
|
ret = _cogl_texture_2d_sliced_download_from_gl (tex_2ds,
|
||||||
|
target_bmp,
|
||||||
gl_format,
|
gl_format,
|
||||||
gl_type);
|
gl_type);
|
||||||
|
|
||||||
|
cogl_object_unref (target_bmp);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglPixelFormat
|
static CoglPixelFormat
|
||||||
|
@ -254,61 +254,67 @@ _cogl_texture_2d_new_with_size (unsigned int width,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_texture_2d_new_from_bitmap (CoglHandle bmp_handle,
|
_cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
|
||||||
CoglTextureFlags flags,
|
CoglTextureFlags flags,
|
||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format)
|
||||||
{
|
{
|
||||||
CoglTexture2D *tex_2d;
|
CoglTexture2D *tex_2d;
|
||||||
CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
|
CoglBitmap *dst_bmp;
|
||||||
CoglBitmap dst_bmp;
|
|
||||||
gboolean dst_bmp_owner;
|
|
||||||
GLenum gl_intformat;
|
GLenum gl_intformat;
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
g_return_val_if_fail (bmp_handle != COGL_INVALID_HANDLE, COGL_INVALID_HANDLE);
|
g_return_val_if_fail (bmp != NULL, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
internal_format = _cogl_texture_determine_internal_format (bmp->format,
|
internal_format =
|
||||||
|
_cogl_texture_determine_internal_format (_cogl_bitmap_get_format (bmp),
|
||||||
internal_format);
|
internal_format);
|
||||||
|
|
||||||
if (!_cogl_texture_2d_can_create (bmp->width, bmp->height, internal_format))
|
if (!_cogl_texture_2d_can_create (_cogl_bitmap_get_width (bmp),
|
||||||
|
_cogl_bitmap_get_height (bmp),
|
||||||
|
internal_format))
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
if (!_cogl_texture_prepare_for_upload (bmp,
|
if ((dst_bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||||
internal_format,
|
internal_format,
|
||||||
&internal_format,
|
&internal_format,
|
||||||
&dst_bmp,
|
|
||||||
&dst_bmp_owner,
|
|
||||||
&gl_intformat,
|
&gl_intformat,
|
||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type))
|
&gl_type)) == NULL)
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
tex_2d = _cogl_texture_2d_create_base (bmp->width,
|
tex_2d = _cogl_texture_2d_create_base (_cogl_bitmap_get_width (bmp),
|
||||||
bmp->height,
|
_cogl_bitmap_get_height (bmp),
|
||||||
flags,
|
flags,
|
||||||
internal_format);
|
internal_format);
|
||||||
|
|
||||||
/* Keep a copy of the first pixel so that if glGenerateMipmap isn't
|
/* Keep a copy of the first pixel so that if glGenerateMipmap isn't
|
||||||
supported we can fallback to using GL_GENERATE_MIPMAP */
|
supported we can fallback to using GL_GENERATE_MIPMAP */
|
||||||
|
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
|
||||||
|
(data = _cogl_bitmap_map (dst_bmp,
|
||||||
|
COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
|
{
|
||||||
tex_2d->first_pixel.gl_format = gl_format;
|
tex_2d->first_pixel.gl_format = gl_format;
|
||||||
tex_2d->first_pixel.gl_type = gl_type;
|
tex_2d->first_pixel.gl_type = gl_type;
|
||||||
memcpy (tex_2d->first_pixel.data, dst_bmp.data,
|
memcpy (tex_2d->first_pixel.data, data,
|
||||||
_cogl_get_format_bpp (dst_bmp.format));
|
_cogl_get_format_bpp (_cogl_bitmap_get_format (dst_bmp)));
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (dst_bmp);
|
||||||
|
}
|
||||||
|
|
||||||
_cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
|
_cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
|
||||||
_cogl_texture_driver_upload_to_gl (GL_TEXTURE_2D,
|
_cogl_texture_driver_upload_to_gl (GL_TEXTURE_2D,
|
||||||
tex_2d->gl_texture,
|
tex_2d->gl_texture,
|
||||||
FALSE,
|
FALSE,
|
||||||
&dst_bmp,
|
dst_bmp,
|
||||||
gl_intformat,
|
gl_intformat,
|
||||||
gl_format,
|
gl_format,
|
||||||
gl_type);
|
gl_type);
|
||||||
|
|
||||||
tex_2d->gl_format = gl_intformat;
|
tex_2d->gl_format = gl_intformat;
|
||||||
|
|
||||||
if (dst_bmp_owner)
|
cogl_object_unref (dst_bmp);
|
||||||
g_free (dst_bmp.data);
|
|
||||||
|
|
||||||
return _cogl_texture_2d_handle_new (tex_2d);
|
return _cogl_texture_2d_handle_new (tex_2d);
|
||||||
}
|
}
|
||||||
@ -463,21 +469,27 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
|
|||||||
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
|
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
_cogl_pixel_format_to_gl (bmp->format,
|
_cogl_pixel_format_to_gl (_cogl_bitmap_get_format (bmp),
|
||||||
NULL, /* internal format */
|
NULL, /* internal format */
|
||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type);
|
&gl_type);
|
||||||
|
|
||||||
/* If this touches the first pixel then we'll update our copy */
|
/* If this touches the first pixel then we'll update our copy */
|
||||||
if (dst_x == 0 && dst_y == 0)
|
if (dst_x == 0 && dst_y == 0 &&
|
||||||
|
!cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
|
||||||
|
(data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
{
|
{
|
||||||
CoglPixelFormat bpp = _cogl_get_format_bpp (bmp->format);
|
CoglPixelFormat bpp =
|
||||||
|
_cogl_get_format_bpp (_cogl_bitmap_get_format (bmp));
|
||||||
tex_2d->first_pixel.gl_format = gl_format;
|
tex_2d->first_pixel.gl_format = gl_format;
|
||||||
tex_2d->first_pixel.gl_type = gl_type;
|
tex_2d->first_pixel.gl_type = gl_type;
|
||||||
memcpy (tex_2d->first_pixel.data,
|
memcpy (tex_2d->first_pixel.data,
|
||||||
bmp->data + bmp->rowstride * src_y + bpp * src_x,
|
data + _cogl_bitmap_get_rowstride (bmp) * src_y + bpp * src_x,
|
||||||
bpp);
|
bpp);
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send data to GL */
|
/* Send data to GL */
|
||||||
|
@ -88,7 +88,7 @@ _cogl_handle_texture_3d_get_type (void);
|
|||||||
* there was an error.
|
* there was an error.
|
||||||
*/
|
*/
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_texture_3d_new_from_bitmap (CoglHandle bmp_handle,
|
_cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
|
||||||
unsigned int height,
|
unsigned int height,
|
||||||
unsigned int depth,
|
unsigned int depth,
|
||||||
CoglTextureFlags flags,
|
CoglTextureFlags flags,
|
||||||
|
@ -303,7 +303,7 @@ cogl_texture_3d_new_with_size (unsigned int width,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_texture_3d_new_from_bitmap (CoglHandle bmp_handle,
|
_cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
|
||||||
unsigned int height,
|
unsigned int height,
|
||||||
unsigned int depth,
|
unsigned int depth,
|
||||||
CoglTextureFlags flags,
|
CoglTextureFlags flags,
|
||||||
@ -311,46 +311,57 @@ _cogl_texture_3d_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
CoglTexture3D *tex_3d;
|
CoglTexture3D *tex_3d;
|
||||||
CoglBitmap *bmp = (CoglBitmap *) bmp_handle;
|
CoglBitmap *dst_bmp;
|
||||||
CoglBitmap dst_bmp;
|
CoglPixelFormat bmp_format;
|
||||||
gboolean dst_bmp_owner;
|
unsigned int bmp_width;
|
||||||
GLenum gl_intformat;
|
GLenum gl_intformat;
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
internal_format = _cogl_texture_determine_internal_format (bmp->format,
|
bmp_width = _cogl_bitmap_get_width (bmp);
|
||||||
|
bmp_format = _cogl_bitmap_get_format (bmp);
|
||||||
|
|
||||||
|
internal_format = _cogl_texture_determine_internal_format (bmp_format,
|
||||||
internal_format);
|
internal_format);
|
||||||
|
|
||||||
if (!_cogl_texture_3d_can_create (bmp->width, height, depth,
|
if (!_cogl_texture_3d_can_create (bmp_width, height, depth,
|
||||||
flags, internal_format,
|
flags, internal_format,
|
||||||
error))
|
error))
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
if (!_cogl_texture_prepare_for_upload (bmp,
|
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||||
internal_format,
|
internal_format,
|
||||||
&internal_format,
|
&internal_format,
|
||||||
&dst_bmp,
|
|
||||||
&dst_bmp_owner,
|
|
||||||
&gl_intformat,
|
&gl_intformat,
|
||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type))
|
&gl_type);
|
||||||
|
|
||||||
|
if (dst_bmp == NULL)
|
||||||
{
|
{
|
||||||
g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_FAILED,
|
g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_FAILED,
|
||||||
"Bitmap conversion failed");
|
"Bitmap conversion failed");
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
tex_3d = _cogl_texture_3d_create_base (dst_bmp.width, height, depth,
|
tex_3d = _cogl_texture_3d_create_base (bmp_width, height, depth,
|
||||||
flags, internal_format);
|
flags, internal_format);
|
||||||
|
|
||||||
/* Keep a copy of the first pixel so that if glGenerateMipmap isn't
|
/* Keep a copy of the first pixel so that if glGenerateMipmap isn't
|
||||||
supported we can fallback to using GL_GENERATE_MIPMAP */
|
supported we can fallback to using GL_GENERATE_MIPMAP */
|
||||||
|
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
|
||||||
|
(data = _cogl_bitmap_map (dst_bmp,
|
||||||
|
COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
|
{
|
||||||
tex_3d->first_pixel.gl_format = gl_format;
|
tex_3d->first_pixel.gl_format = gl_format;
|
||||||
tex_3d->first_pixel.gl_type = gl_type;
|
tex_3d->first_pixel.gl_type = gl_type;
|
||||||
memcpy (tex_3d->first_pixel.data, dst_bmp.data,
|
memcpy (tex_3d->first_pixel.data, data,
|
||||||
_cogl_get_format_bpp (dst_bmp.format));
|
_cogl_get_format_bpp (_cogl_bitmap_get_format (dst_bmp)));
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (dst_bmp);
|
||||||
|
}
|
||||||
|
|
||||||
_cogl_texture_driver_gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture);
|
_cogl_texture_driver_gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture);
|
||||||
|
|
||||||
@ -359,15 +370,14 @@ _cogl_texture_3d_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
FALSE, /* is_foreign */
|
FALSE, /* is_foreign */
|
||||||
height,
|
height,
|
||||||
depth,
|
depth,
|
||||||
&dst_bmp,
|
dst_bmp,
|
||||||
gl_intformat,
|
gl_intformat,
|
||||||
gl_format,
|
gl_format,
|
||||||
gl_type);
|
gl_type);
|
||||||
|
|
||||||
tex_3d->gl_format = gl_intformat;
|
tex_3d->gl_format = gl_intformat;
|
||||||
|
|
||||||
if (dst_bmp_owner)
|
cogl_object_unref (dst_bmp);
|
||||||
g_free (dst_bmp.data);
|
|
||||||
|
|
||||||
return _cogl_texture_3d_handle_new (tex_3d);
|
return _cogl_texture_3d_handle_new (tex_3d);
|
||||||
}
|
}
|
||||||
@ -384,8 +394,7 @@ cogl_texture_3d_new_from_data (unsigned int width,
|
|||||||
const guint8 *data,
|
const guint8 *data,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
CoglBitmap bitmap;
|
CoglBitmap *bitmap;
|
||||||
gboolean bitmap_owned = FALSE;
|
|
||||||
CoglHandle ret;
|
CoglHandle ret;
|
||||||
|
|
||||||
/* These are considered a programmer errors so we won't set a
|
/* These are considered a programmer errors so we won't set a
|
||||||
@ -414,42 +423,42 @@ cogl_texture_3d_new_from_data (unsigned int width,
|
|||||||
if (image_stride % rowstride != 0)
|
if (image_stride % rowstride != 0)
|
||||||
{
|
{
|
||||||
int z, y;
|
int z, y;
|
||||||
|
int bmp_rowstride = _cogl_get_format_bpp (format) * width;
|
||||||
|
guint8 *bmp_data = g_malloc (bmp_rowstride * height * depth);
|
||||||
|
|
||||||
bitmap.width = width;
|
bitmap = _cogl_bitmap_new_from_data (bmp_data,
|
||||||
bitmap.height = depth * height;
|
format,
|
||||||
bitmap.rowstride = _cogl_get_format_bpp (format) * width;
|
width,
|
||||||
bitmap.data = g_malloc (bitmap.rowstride * height * depth);
|
depth * height,
|
||||||
bitmap.format = format;
|
bmp_rowstride,
|
||||||
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL /* destroy_fn_data */);
|
||||||
|
|
||||||
/* Copy all of the images in */
|
/* Copy all of the images in */
|
||||||
for (z = 0; z < depth; z++)
|
for (z = 0; z < depth; z++)
|
||||||
for (y = 0; y < height; y++)
|
for (y = 0; y < height; y++)
|
||||||
memcpy (bitmap.data + (z * bitmap.rowstride * height +
|
memcpy (bmp_data + (z * bmp_rowstride * height +
|
||||||
bitmap.rowstride * y),
|
bmp_rowstride * y),
|
||||||
data + z * image_stride + rowstride * y,
|
data + z * image_stride + rowstride * y,
|
||||||
bitmap.rowstride);
|
bmp_rowstride);
|
||||||
|
|
||||||
bitmap_owned = TRUE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
bitmap = _cogl_bitmap_new_from_data ((guint8 *) data,
|
||||||
/* Wrap the data into a bitmap */
|
format,
|
||||||
bitmap.width = width;
|
width,
|
||||||
bitmap.height = image_stride / rowstride * depth;
|
image_stride / rowstride * depth,
|
||||||
bitmap.data = (guint8 *) data;
|
rowstride,
|
||||||
bitmap.format = format;
|
NULL, /* destroy_fn */
|
||||||
bitmap.rowstride = rowstride;
|
NULL /* destroy_fn_data */);
|
||||||
}
|
|
||||||
|
|
||||||
ret = _cogl_texture_3d_new_from_bitmap (&bitmap,
|
ret = _cogl_texture_3d_new_from_bitmap (bitmap,
|
||||||
height,
|
height,
|
||||||
depth,
|
depth,
|
||||||
flags,
|
flags,
|
||||||
internal_format,
|
internal_format,
|
||||||
error);
|
error);
|
||||||
|
|
||||||
if (bitmap_owned)
|
cogl_object_unref (bitmap);
|
||||||
g_free (bitmap.data);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -240,12 +240,10 @@ _cogl_texture_determine_internal_format (CoglPixelFormat src_format,
|
|||||||
be set to TRUE. Otherwise dst_bmp will be set to a shallow copy of
|
be set to TRUE. Otherwise dst_bmp will be set to a shallow copy of
|
||||||
src_bmp. The GLenums needed for uploading are returned */
|
src_bmp. The GLenums needed for uploading are returned */
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
|
_cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
|
||||||
CoglPixelFormat dst_format,
|
CoglPixelFormat dst_format,
|
||||||
CoglPixelFormat *dst_format_out,
|
CoglPixelFormat *dst_format_out,
|
||||||
CoglBitmap *dst_bmp,
|
|
||||||
gboolean *copied_bitmap,
|
|
||||||
GLenum *out_glintformat,
|
GLenum *out_glintformat,
|
||||||
GLenum *out_glformat,
|
GLenum *out_glformat,
|
||||||
GLenum *out_gltype);
|
GLenum *out_gltype);
|
||||||
|
@ -61,7 +61,7 @@ _cogl_texture_rectangle_new_with_size (unsigned int width,
|
|||||||
CoglPixelFormat internal_format);
|
CoglPixelFormat internal_format);
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_texture_rectangle_new_from_bitmap (CoglHandle bmp_handle,
|
_cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
|
||||||
CoglTextureFlags flags,
|
CoglTextureFlags flags,
|
||||||
CoglPixelFormat internal_format);
|
CoglPixelFormat internal_format);
|
||||||
|
|
||||||
|
@ -278,39 +278,39 @@ _cogl_texture_rectangle_new_with_size (unsigned int width,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
_cogl_texture_rectangle_new_from_bitmap (CoglHandle bmp_handle,
|
_cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
|
||||||
CoglTextureFlags flags,
|
CoglTextureFlags flags,
|
||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format)
|
||||||
{
|
{
|
||||||
CoglTextureRectangle *tex_rect;
|
CoglTextureRectangle *tex_rect;
|
||||||
CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
|
CoglBitmap *dst_bmp;
|
||||||
CoglBitmap dst_bmp;
|
|
||||||
gboolean dst_bmp_owner;
|
|
||||||
GLenum gl_intformat;
|
GLenum gl_intformat;
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
|
||||||
g_return_val_if_fail (bmp_handle != COGL_INVALID_HANDLE, COGL_INVALID_HANDLE);
|
g_return_val_if_fail (cogl_is_bitmap (bmp), COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
internal_format = _cogl_texture_determine_internal_format (bmp->format,
|
internal_format =
|
||||||
|
_cogl_texture_determine_internal_format (_cogl_bitmap_get_format (bmp),
|
||||||
internal_format);
|
internal_format);
|
||||||
|
|
||||||
if (!_cogl_texture_rectangle_can_create (bmp->width, bmp->height,
|
if (!_cogl_texture_rectangle_can_create (_cogl_bitmap_get_width (bmp),
|
||||||
|
_cogl_bitmap_get_height (bmp),
|
||||||
internal_format))
|
internal_format))
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
if (!_cogl_texture_prepare_for_upload (bmp,
|
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||||
internal_format,
|
internal_format,
|
||||||
&internal_format,
|
&internal_format,
|
||||||
&dst_bmp,
|
|
||||||
&dst_bmp_owner,
|
|
||||||
&gl_intformat,
|
&gl_intformat,
|
||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type))
|
&gl_type);
|
||||||
|
|
||||||
|
if (dst_bmp == NULL)
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
tex_rect = _cogl_texture_rectangle_create_base (bmp->width,
|
tex_rect = _cogl_texture_rectangle_create_base (_cogl_bitmap_get_width (bmp),
|
||||||
bmp->height,
|
_cogl_bitmap_get_height (bmp),
|
||||||
flags,
|
flags,
|
||||||
internal_format);
|
internal_format);
|
||||||
|
|
||||||
@ -318,15 +318,14 @@ _cogl_texture_rectangle_new_from_bitmap (CoglHandle bmp_handle,
|
|||||||
_cogl_texture_driver_upload_to_gl (GL_TEXTURE_RECTANGLE_ARB,
|
_cogl_texture_driver_upload_to_gl (GL_TEXTURE_RECTANGLE_ARB,
|
||||||
tex_rect->gl_texture,
|
tex_rect->gl_texture,
|
||||||
FALSE,
|
FALSE,
|
||||||
&dst_bmp,
|
dst_bmp,
|
||||||
gl_intformat,
|
gl_intformat,
|
||||||
gl_format,
|
gl_format,
|
||||||
gl_type);
|
gl_type);
|
||||||
|
|
||||||
tex_rect->gl_format = gl_intformat;
|
tex_rect->gl_format = gl_intformat;
|
||||||
|
|
||||||
if (dst_bmp_owner)
|
cogl_object_unref (dst_bmp);
|
||||||
g_free (dst_bmp.data);
|
|
||||||
|
|
||||||
return _cogl_texture_rectangle_handle_new (tex_rect);
|
return _cogl_texture_rectangle_handle_new (tex_rect);
|
||||||
}
|
}
|
||||||
@ -453,7 +452,7 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex,
|
|||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
|
||||||
_cogl_pixel_format_to_gl (bmp->format,
|
_cogl_pixel_format_to_gl (_cogl_bitmap_get_format (bmp),
|
||||||
NULL, /* internal format */
|
NULL, /* internal format */
|
||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type);
|
&gl_type);
|
||||||
|
@ -152,21 +152,19 @@ _cogl_texture_determine_internal_format (CoglPixelFormat src_format,
|
|||||||
return dst_format;
|
return dst_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
CoglBitmap *
|
||||||
_cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
|
_cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
|
||||||
CoglPixelFormat dst_format,
|
CoglPixelFormat dst_format,
|
||||||
CoglPixelFormat *dst_format_out,
|
CoglPixelFormat *dst_format_out,
|
||||||
CoglBitmap *dst_bmp,
|
|
||||||
gboolean *copied_bitmap,
|
|
||||||
GLenum *out_glintformat,
|
GLenum *out_glintformat,
|
||||||
GLenum *out_glformat,
|
GLenum *out_glformat,
|
||||||
GLenum *out_gltype)
|
GLenum *out_gltype)
|
||||||
{
|
{
|
||||||
dst_format = _cogl_texture_determine_internal_format (src_bmp->format,
|
CoglPixelFormat src_format = _cogl_bitmap_get_format (src_bmp);
|
||||||
dst_format);
|
CoglBitmap *dst_bmp;
|
||||||
|
|
||||||
*copied_bitmap = FALSE;
|
dst_format = _cogl_texture_determine_internal_format (src_format,
|
||||||
*dst_bmp = *src_bmp;
|
dst_format);
|
||||||
|
|
||||||
/* OpenGL supports specifying a different format for the internal
|
/* OpenGL supports specifying a different format for the internal
|
||||||
format when uploading texture data. We should use this to convert
|
format when uploading texture data. We should use this to convert
|
||||||
@ -180,26 +178,46 @@ _cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
|
|||||||
|
|
||||||
/* If the source format does not have the same premult flag as the
|
/* If the source format does not have the same premult flag as the
|
||||||
dst format then we need to copy and convert it */
|
dst format then we need to copy and convert it */
|
||||||
if (_cogl_texture_needs_premult_conversion (src_bmp->format,
|
if (_cogl_texture_needs_premult_conversion (src_format,
|
||||||
dst_format))
|
dst_format))
|
||||||
{
|
{
|
||||||
dst_bmp->data = g_memdup (dst_bmp->data,
|
guint8 *src_data;
|
||||||
dst_bmp->height * dst_bmp->rowstride);
|
guint8 *dst_data;
|
||||||
*copied_bitmap = TRUE;
|
|
||||||
|
if ((src_data = _cogl_bitmap_map (src_bmp,
|
||||||
|
COGL_BUFFER_ACCESS_READ, 0)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dst_data = g_memdup (src_data,
|
||||||
|
_cogl_bitmap_get_height (src_bmp) *
|
||||||
|
_cogl_bitmap_get_rowstride (src_bmp));
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (src_bmp);
|
||||||
|
|
||||||
|
dst_bmp =
|
||||||
|
_cogl_bitmap_new_from_data (dst_data,
|
||||||
|
src_format,
|
||||||
|
_cogl_bitmap_get_width (src_bmp),
|
||||||
|
_cogl_bitmap_get_height (src_bmp),
|
||||||
|
_cogl_bitmap_get_rowstride (src_bmp),
|
||||||
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL);
|
||||||
|
|
||||||
if (!_cogl_bitmap_convert_premult_status (dst_bmp,
|
if (!_cogl_bitmap_convert_premult_status (dst_bmp,
|
||||||
src_bmp->format ^
|
src_format ^
|
||||||
COGL_PREMULT_BIT))
|
COGL_PREMULT_BIT))
|
||||||
{
|
{
|
||||||
g_free (dst_bmp->data);
|
cogl_object_unref (dst_bmp);
|
||||||
return FALSE;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
dst_bmp = cogl_object_ref (src_bmp);
|
||||||
|
|
||||||
/* Use the source format from the src bitmap type and the internal
|
/* Use the source format from the src bitmap type and the internal
|
||||||
format from the dst format type so that GL can do the
|
format from the dst format type so that GL can do the
|
||||||
conversion */
|
conversion */
|
||||||
_cogl_pixel_format_to_gl (src_bmp->format,
|
_cogl_pixel_format_to_gl (src_format,
|
||||||
NULL, /* internal format */
|
NULL, /* internal format */
|
||||||
out_glformat,
|
out_glformat,
|
||||||
out_gltype);
|
out_gltype);
|
||||||
@ -212,28 +230,23 @@ _cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
|
|||||||
{
|
{
|
||||||
CoglPixelFormat closest_format;
|
CoglPixelFormat closest_format;
|
||||||
|
|
||||||
closest_format = _cogl_pixel_format_to_gl (dst_bmp->format,
|
closest_format = _cogl_pixel_format_to_gl (dst_format,
|
||||||
out_glintformat,
|
out_glintformat,
|
||||||
out_glformat,
|
out_glformat,
|
||||||
out_gltype);
|
out_gltype);
|
||||||
|
|
||||||
|
if (closest_format != src_format)
|
||||||
if (closest_format != src_bmp->format)
|
dst_bmp = _cogl_bitmap_convert_format_and_premult (src_bmp,
|
||||||
{
|
closest_format);
|
||||||
if (!_cogl_bitmap_convert_format_and_premult (src_bmp,
|
else
|
||||||
dst_bmp,
|
dst_bmp = cogl_object_ref (src_bmp);
|
||||||
closest_format))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
*copied_bitmap = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* HAVE_COGL_GL */
|
#endif /* HAVE_COGL_GL */
|
||||||
|
|
||||||
if (dst_format_out)
|
if (dst_format_out)
|
||||||
*dst_format_out = dst_format;
|
*dst_format_out = dst_format;
|
||||||
|
|
||||||
return TRUE;
|
return dst_bmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -402,7 +415,8 @@ cogl_texture_new_from_data (unsigned int width,
|
|||||||
unsigned int rowstride,
|
unsigned int rowstride,
|
||||||
const guint8 *data)
|
const guint8 *data)
|
||||||
{
|
{
|
||||||
CoglBitmap bitmap;
|
CoglBitmap *bmp;
|
||||||
|
CoglHandle tex;
|
||||||
|
|
||||||
if (format == COGL_PIXEL_FORMAT_ANY)
|
if (format == COGL_PIXEL_FORMAT_ANY)
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
@ -415,13 +429,18 @@ cogl_texture_new_from_data (unsigned int width,
|
|||||||
rowstride = width * _cogl_get_format_bpp (format);
|
rowstride = width * _cogl_get_format_bpp (format);
|
||||||
|
|
||||||
/* Wrap the data into a bitmap */
|
/* Wrap the data into a bitmap */
|
||||||
bitmap.width = width;
|
bmp = _cogl_bitmap_new_from_data ((guint8 *) data,
|
||||||
bitmap.height = height;
|
format,
|
||||||
bitmap.data = (guint8 *) data;
|
width,
|
||||||
bitmap.format = format;
|
height,
|
||||||
bitmap.rowstride = rowstride;
|
rowstride,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
return cogl_texture_new_from_bitmap (&bitmap, flags, internal_format);
|
tex = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
|
||||||
|
|
||||||
|
cogl_object_unref (bmp);
|
||||||
|
|
||||||
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
@ -455,29 +474,29 @@ cogl_texture_new_from_file (const char *filename,
|
|||||||
CoglPixelFormat internal_format,
|
CoglPixelFormat internal_format,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
CoglHandle bmp_handle;
|
|
||||||
CoglBitmap *bmp;
|
CoglBitmap *bmp;
|
||||||
CoglHandle handle = COGL_INVALID_HANDLE;
|
CoglHandle handle = COGL_INVALID_HANDLE;
|
||||||
|
CoglPixelFormat src_format;
|
||||||
|
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
|
g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
bmp_handle = cogl_bitmap_new_from_file (filename, error);
|
bmp = cogl_bitmap_new_from_file (filename, error);
|
||||||
if (bmp_handle == COGL_INVALID_HANDLE)
|
if (bmp == NULL)
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
bmp = (CoglBitmap *) bmp_handle;
|
src_format = _cogl_bitmap_get_format (bmp);
|
||||||
|
|
||||||
/* We know that the bitmap data is solely owned by this function so
|
/* We know that the bitmap data is solely owned by this function so
|
||||||
we can do the premult conversion in place. This avoids having to
|
we can do the premult conversion in place. This avoids having to
|
||||||
copy the bitmap which will otherwise happen in
|
copy the bitmap which will otherwise happen in
|
||||||
_cogl_texture_prepare_for_upload */
|
_cogl_texture_prepare_for_upload */
|
||||||
internal_format = _cogl_texture_determine_internal_format (bmp->format,
|
internal_format =
|
||||||
internal_format);
|
_cogl_texture_determine_internal_format (src_format, internal_format);
|
||||||
if (!_cogl_texture_needs_premult_conversion (bmp->format, internal_format) ||
|
if (!_cogl_texture_needs_premult_conversion (src_format, internal_format) ||
|
||||||
_cogl_bitmap_convert_premult_status (bmp, bmp->format ^ COGL_PREMULT_BIT))
|
_cogl_bitmap_convert_premult_status (bmp, src_format ^ COGL_PREMULT_BIT))
|
||||||
handle = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
|
handle = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
|
||||||
|
|
||||||
cogl_handle_unref (bmp);
|
cogl_object_unref (bmp);
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
@ -572,19 +591,21 @@ cogl_texture_new_from_buffer_EXP (CoglHandle buffer,
|
|||||||
#if !defined (COGL_HAS_GLES)
|
#if !defined (COGL_HAS_GLES)
|
||||||
if (cogl_features_available (COGL_FEATURE_PBOS))
|
if (cogl_features_available (COGL_FEATURE_PBOS))
|
||||||
{
|
{
|
||||||
CoglBitmap bitmap;
|
CoglBitmap *bmp;
|
||||||
|
|
||||||
/* Wrap the data into a bitmap */
|
/* Wrap the data into a bitmap */
|
||||||
bitmap.width = width;
|
bmp = _cogl_bitmap_new_from_data (GUINT_TO_POINTER (offset),
|
||||||
bitmap.height = height;
|
format,
|
||||||
bitmap.data = GUINT_TO_POINTER (offset);
|
width, height,
|
||||||
bitmap.format = format;
|
rowstride,
|
||||||
bitmap.rowstride = rowstride;
|
NULL, NULL);
|
||||||
|
|
||||||
_cogl_buffer_bind (cogl_buffer,
|
_cogl_buffer_bind (cogl_buffer,
|
||||||
COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK);
|
COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK);
|
||||||
texture = cogl_texture_new_from_bitmap (&bitmap, flags, internal_format);
|
texture = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
|
||||||
_cogl_buffer_unbind (cogl_buffer);
|
_cogl_buffer_unbind (cogl_buffer);
|
||||||
|
|
||||||
|
cogl_object_unref (bmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -823,8 +844,6 @@ _cogl_texture_set_region_from_bitmap (CoglHandle handle,
|
|||||||
CoglBitmap *bmp)
|
CoglBitmap *bmp)
|
||||||
{
|
{
|
||||||
CoglTexture *tex = COGL_TEXTURE (handle);
|
CoglTexture *tex = COGL_TEXTURE (handle);
|
||||||
CoglBitmap tmp_bmp;
|
|
||||||
gboolean tmp_bmp_owner = FALSE;
|
|
||||||
GLenum closest_gl_format;
|
GLenum closest_gl_format;
|
||||||
GLenum closest_gl_type;
|
GLenum closest_gl_type;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
@ -835,11 +854,9 @@ _cogl_texture_set_region_from_bitmap (CoglHandle handle,
|
|||||||
|
|
||||||
/* Prepare the bitmap so that it will do the premultiplication
|
/* Prepare the bitmap so that it will do the premultiplication
|
||||||
conversion */
|
conversion */
|
||||||
_cogl_texture_prepare_for_upload (bmp,
|
bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||||
cogl_texture_get_format (handle),
|
cogl_texture_get_format (handle),
|
||||||
NULL,
|
NULL,
|
||||||
&tmp_bmp,
|
|
||||||
&tmp_bmp_owner,
|
|
||||||
NULL,
|
NULL,
|
||||||
&closest_gl_format,
|
&closest_gl_format,
|
||||||
&closest_gl_type);
|
&closest_gl_type);
|
||||||
@ -848,11 +865,9 @@ _cogl_texture_set_region_from_bitmap (CoglHandle handle,
|
|||||||
src_x, src_y,
|
src_x, src_y,
|
||||||
dst_x, dst_y,
|
dst_x, dst_y,
|
||||||
dst_width, dst_height,
|
dst_width, dst_height,
|
||||||
&tmp_bmp);
|
bmp);
|
||||||
|
|
||||||
/* Free data if owner */
|
cogl_object_unref (bmp);
|
||||||
if (tmp_bmp_owner)
|
|
||||||
g_free (tmp_bmp.data);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -871,28 +886,35 @@ cogl_texture_set_region (CoglHandle handle,
|
|||||||
unsigned int rowstride,
|
unsigned int rowstride,
|
||||||
const guint8 *data)
|
const guint8 *data)
|
||||||
{
|
{
|
||||||
int bpp;
|
CoglBitmap *source_bmp;
|
||||||
CoglBitmap source_bmp;
|
gboolean ret;
|
||||||
|
|
||||||
/* Check for valid format */
|
/* Check for valid format */
|
||||||
if (format == COGL_PIXEL_FORMAT_ANY)
|
if (format == COGL_PIXEL_FORMAT_ANY)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Init source bitmap */
|
|
||||||
source_bmp.width = width;
|
|
||||||
source_bmp.height = height;
|
|
||||||
source_bmp.format = format;
|
|
||||||
source_bmp.data = (guint8 *) data;
|
|
||||||
|
|
||||||
/* Rowstride from width if none specified */
|
/* Rowstride from width if none specified */
|
||||||
bpp = _cogl_get_format_bpp (format);
|
if (rowstride == 0)
|
||||||
source_bmp.rowstride = (rowstride == 0) ? width * bpp : rowstride;
|
rowstride = _cogl_get_format_bpp (format) * width;
|
||||||
|
|
||||||
return _cogl_texture_set_region_from_bitmap (handle,
|
/* Init source bitmap */
|
||||||
|
source_bmp = _cogl_bitmap_new_from_data ((guint8 *) data,
|
||||||
|
format,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
rowstride,
|
||||||
|
NULL, /* destroy_fn */
|
||||||
|
NULL); /* destroy_fn_data */
|
||||||
|
|
||||||
|
ret = _cogl_texture_set_region_from_bitmap (handle,
|
||||||
src_x, src_y,
|
src_x, src_y,
|
||||||
dst_x, dst_y,
|
dst_x, dst_y,
|
||||||
dst_width, dst_height,
|
dst_width, dst_height,
|
||||||
&source_bmp);
|
source_bmp);
|
||||||
|
|
||||||
|
cogl_object_unref (source_bmp);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reads back the contents of a texture by rendering it to the framebuffer
|
/* Reads back the contents of a texture by rendering it to the framebuffer
|
||||||
@ -919,7 +941,7 @@ do_texture_draw_and_read (CoglHandle handle,
|
|||||||
float tx1, ty1;
|
float tx1, ty1;
|
||||||
float tx2, ty2;
|
float tx2, ty2;
|
||||||
int bw, bh;
|
int bw, bh;
|
||||||
CoglBitmap rect_bmp;
|
CoglBitmap *rect_bmp;
|
||||||
unsigned int tex_width, tex_height;
|
unsigned int tex_width, tex_height;
|
||||||
|
|
||||||
bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);
|
bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);
|
||||||
@ -947,10 +969,19 @@ do_texture_draw_and_read (CoglHandle handle,
|
|||||||
/* Walk X axis until whole bitmap width consumed */
|
/* Walk X axis until whole bitmap width consumed */
|
||||||
for (bw = tex_width; bw > 0; bw-=viewport[2])
|
for (bw = tex_width; bw > 0; bw-=viewport[2])
|
||||||
{
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int rowstride;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
/* Rectangle X coords */
|
/* Rectangle X coords */
|
||||||
rx1 = rx2;
|
rx1 = rx2;
|
||||||
rx2 += (bw < viewport[2]) ? bw : viewport[2];
|
rx2 += (bw < viewport[2]) ? bw : viewport[2];
|
||||||
|
|
||||||
|
width = rx2 - rx1;
|
||||||
|
height = ry2 - ry1;
|
||||||
|
rowstride = width * bpp;
|
||||||
|
|
||||||
/* Normalized texture X coords */
|
/* Normalized texture X coords */
|
||||||
tx1 = tx2;
|
tx1 = tx2;
|
||||||
tx2 = (rx2 / (float) tex_width);
|
tx2 = (rx2 / (float) tex_width);
|
||||||
@ -962,31 +993,35 @@ do_texture_draw_and_read (CoglHandle handle,
|
|||||||
tx1, ty1,
|
tx1, ty1,
|
||||||
tx2, ty2);
|
tx2, ty2);
|
||||||
|
|
||||||
|
data = g_malloc (height * rowstride);
|
||||||
|
|
||||||
/* Read into a temporary bitmap */
|
/* Read into a temporary bitmap */
|
||||||
rect_bmp.format = COGL_PIXEL_FORMAT_RGBA_8888;
|
rect_bmp =
|
||||||
rect_bmp.width = rx2 - rx1;
|
_cogl_bitmap_new_from_data (data,
|
||||||
rect_bmp.height = ry2 - ry1;
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
rect_bmp.rowstride = bpp * rect_bmp.width;
|
width,
|
||||||
rect_bmp.data = g_malloc (rect_bmp.rowstride *
|
height,
|
||||||
rect_bmp.height);
|
rowstride,
|
||||||
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL);
|
||||||
|
|
||||||
cogl_read_pixels (viewport[0], viewport[1],
|
cogl_read_pixels (viewport[0], viewport[1],
|
||||||
rect_bmp.width,
|
width,
|
||||||
rect_bmp.height,
|
height,
|
||||||
COGL_READ_PIXELS_COLOR_BUFFER,
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
rect_bmp.data);
|
data);
|
||||||
|
|
||||||
/* Copy to target bitmap */
|
/* Copy to target bitmap */
|
||||||
_cogl_bitmap_copy_subregion (&rect_bmp,
|
_cogl_bitmap_copy_subregion (rect_bmp,
|
||||||
target_bmp,
|
target_bmp,
|
||||||
0,0,
|
0,0,
|
||||||
rx1,ry1,
|
rx1,ry1,
|
||||||
rect_bmp.width,
|
width,
|
||||||
rect_bmp.height);
|
height);
|
||||||
|
|
||||||
/* Free temp bitmap */
|
/* Free temp bitmap */
|
||||||
g_free (rect_bmp.data);
|
cogl_object_unref (rect_bmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1006,10 +1041,13 @@ _cogl_texture_draw_and_read (CoglHandle handle,
|
|||||||
int bpp;
|
int bpp;
|
||||||
CoglFramebuffer *framebuffer;
|
CoglFramebuffer *framebuffer;
|
||||||
int viewport[4];
|
int viewport[4];
|
||||||
CoglBitmap alpha_bmp;
|
CoglBitmap *alpha_bmp;
|
||||||
CoglHandle prev_source;
|
CoglHandle prev_source;
|
||||||
CoglMatrixStack *projection_stack;
|
CoglMatrixStack *projection_stack;
|
||||||
CoglMatrixStack *modelview_stack;
|
CoglMatrixStack *modelview_stack;
|
||||||
|
int target_width = _cogl_bitmap_get_width (target_bmp);
|
||||||
|
int target_height = _cogl_bitmap_get_height (target_bmp);
|
||||||
|
int target_rowstride = _cogl_bitmap_get_rowstride (target_bmp);
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||||
|
|
||||||
@ -1086,14 +1124,22 @@ _cogl_texture_draw_and_read (CoglHandle handle,
|
|||||||
guint8 *srcpixel;
|
guint8 *srcpixel;
|
||||||
guint8 *dstpixel;
|
guint8 *dstpixel;
|
||||||
int x,y;
|
int x,y;
|
||||||
|
int alpha_rowstride = bpp * target_width;
|
||||||
|
|
||||||
|
if ((dstdata = _cogl_bitmap_map (target_bmp,
|
||||||
|
COGL_BUFFER_ACCESS_WRITE,
|
||||||
|
COGL_BUFFER_MAP_HINT_DISCARD)) == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
srcdata = g_malloc (alpha_rowstride * target_height);
|
||||||
|
|
||||||
/* Create temp bitmap for alpha values */
|
/* Create temp bitmap for alpha values */
|
||||||
alpha_bmp.format = COGL_PIXEL_FORMAT_RGBA_8888;
|
alpha_bmp = _cogl_bitmap_new_from_data (srcdata,
|
||||||
alpha_bmp.width = target_bmp->width;
|
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||||
alpha_bmp.height = target_bmp->height;
|
target_width, target_height,
|
||||||
alpha_bmp.rowstride = bpp * alpha_bmp.width;
|
alpha_rowstride,
|
||||||
alpha_bmp.data = g_malloc (alpha_bmp.rowstride *
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
alpha_bmp.height);
|
NULL);
|
||||||
|
|
||||||
/* Draw alpha values into RGB channels */
|
/* Draw alpha values into RGB channels */
|
||||||
cogl_material_set_layer_combine (ctx->texture_download_material,
|
cogl_material_set_layer_combine (ctx->texture_download_material,
|
||||||
@ -1101,25 +1147,25 @@ _cogl_texture_draw_and_read (CoglHandle handle,
|
|||||||
"RGBA = REPLACE (TEXTURE[A])",
|
"RGBA = REPLACE (TEXTURE[A])",
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
do_texture_draw_and_read (handle, &alpha_bmp, viewport);
|
do_texture_draw_and_read (handle, alpha_bmp, viewport);
|
||||||
|
|
||||||
/* Copy temp R to target A */
|
/* Copy temp R to target A */
|
||||||
srcdata = alpha_bmp.data;
|
|
||||||
dstdata = target_bmp->data;
|
|
||||||
|
|
||||||
for (y=0; y<target_bmp->height; ++y)
|
for (y=0; y<target_height; ++y)
|
||||||
{
|
{
|
||||||
for (x=0; x<target_bmp->width; ++x)
|
for (x=0; x<target_width; ++x)
|
||||||
{
|
{
|
||||||
srcpixel = srcdata + x*bpp;
|
srcpixel = srcdata + x*bpp;
|
||||||
dstpixel = dstdata + x*bpp;
|
dstpixel = dstdata + x*bpp;
|
||||||
dstpixel[3] = srcpixel[0];
|
dstpixel[3] = srcpixel[0];
|
||||||
}
|
}
|
||||||
srcdata += alpha_bmp.rowstride;
|
srcdata += alpha_rowstride;
|
||||||
dstdata += target_bmp->rowstride;
|
dstdata += target_rowstride;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (alpha_bmp.data);
|
_cogl_bitmap_unmap (target_bmp);
|
||||||
|
|
||||||
|
cogl_object_unref (alpha_bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore old state */
|
/* Restore old state */
|
||||||
@ -1146,8 +1192,8 @@ cogl_texture_get_data (CoglHandle handle,
|
|||||||
int closest_bpp;
|
int closest_bpp;
|
||||||
GLenum closest_gl_format;
|
GLenum closest_gl_format;
|
||||||
GLenum closest_gl_type;
|
GLenum closest_gl_type;
|
||||||
CoglBitmap target_bmp;
|
CoglBitmap *target_bmp;
|
||||||
CoglBitmap new_bmp;
|
CoglBitmap *new_bmp;
|
||||||
gboolean success;
|
gboolean success;
|
||||||
guint8 *src;
|
guint8 *src;
|
||||||
guint8 *dst;
|
guint8 *dst;
|
||||||
@ -1156,7 +1202,7 @@ cogl_texture_get_data (CoglHandle handle,
|
|||||||
int tex_height;
|
int tex_height;
|
||||||
|
|
||||||
if (!cogl_is_texture (handle))
|
if (!cogl_is_texture (handle))
|
||||||
return FALSE;
|
return 0;
|
||||||
|
|
||||||
tex = COGL_TEXTURE (handle);
|
tex = COGL_TEXTURE (handle);
|
||||||
|
|
||||||
@ -1183,60 +1229,89 @@ cogl_texture_get_data (CoglHandle handle,
|
|||||||
&closest_gl_type);
|
&closest_gl_type);
|
||||||
closest_bpp = _cogl_get_format_bpp (closest_format);
|
closest_bpp = _cogl_get_format_bpp (closest_format);
|
||||||
|
|
||||||
target_bmp.width = tex_width;
|
|
||||||
target_bmp.height = tex_height;
|
|
||||||
|
|
||||||
/* Is the requested format supported? */
|
/* Is the requested format supported? */
|
||||||
if (closest_format == format)
|
if (closest_format == format)
|
||||||
{
|
|
||||||
/* Target user data directly */
|
/* Target user data directly */
|
||||||
target_bmp.format = format;
|
target_bmp = _cogl_bitmap_new_from_data (data,
|
||||||
target_bmp.rowstride = rowstride;
|
format,
|
||||||
target_bmp.data = data;
|
tex_width,
|
||||||
}
|
tex_height,
|
||||||
|
rowstride,
|
||||||
|
NULL, NULL);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Target intermediate buffer */
|
int target_rowstride = tex_width * closest_bpp;
|
||||||
target_bmp.format = closest_format;
|
guint8 *target_data = g_malloc (tex_height * target_rowstride);
|
||||||
target_bmp.rowstride = target_bmp.width * closest_bpp;
|
target_bmp = _cogl_bitmap_new_from_data (target_data,
|
||||||
target_bmp.data = g_malloc (target_bmp.height * target_bmp.rowstride);
|
closest_format,
|
||||||
|
tex_width,
|
||||||
|
tex_height,
|
||||||
|
target_rowstride,
|
||||||
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tex->vtable->get_data (tex,
|
if ((dst = _cogl_bitmap_map (target_bmp, COGL_BUFFER_ACCESS_WRITE,
|
||||||
target_bmp.format,
|
COGL_BUFFER_MAP_HINT_DISCARD)) == NULL)
|
||||||
target_bmp.rowstride,
|
{
|
||||||
target_bmp.data))
|
cogl_object_unref (target_bmp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
success = tex->vtable->get_data (tex,
|
||||||
|
closest_format,
|
||||||
|
rowstride,
|
||||||
|
dst);
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (target_bmp);
|
||||||
|
|
||||||
/* XXX: In some cases _cogl_texture_2d_download_from_gl may fail
|
/* 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
|
* 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. */
|
||||||
_cogl_texture_draw_and_read (tex, &target_bmp,
|
if (!success)
|
||||||
|
_cogl_texture_draw_and_read (tex, target_bmp,
|
||||||
closest_gl_format,
|
closest_gl_format,
|
||||||
closest_gl_type);
|
closest_gl_type);
|
||||||
|
|
||||||
/* Was intermediate used? */
|
/* Was intermediate used? */
|
||||||
if (closest_format != format)
|
if (closest_format != format)
|
||||||
{
|
{
|
||||||
|
guint8 *new_bmp_data;
|
||||||
|
int new_bmp_rowstride;
|
||||||
|
|
||||||
/* Convert to requested format */
|
/* Convert to requested format */
|
||||||
success = _cogl_bitmap_convert_format_and_premult (&target_bmp,
|
new_bmp = _cogl_bitmap_convert_format_and_premult (target_bmp,
|
||||||
&new_bmp,
|
|
||||||
format);
|
format);
|
||||||
|
|
||||||
/* Free intermediate data and return if failed */
|
/* Free intermediate data and return if failed */
|
||||||
g_free (target_bmp.data);
|
cogl_object_unref (target_bmp);
|
||||||
if (!success)
|
|
||||||
|
if (new_bmp == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Copy to user buffer */
|
new_bmp_rowstride = _cogl_bitmap_get_rowstride (new_bmp);
|
||||||
for (y = 0; y < new_bmp.height; ++y)
|
new_bmp_data = _cogl_bitmap_map (new_bmp, COGL_BUFFER_ACCESS_WRITE,
|
||||||
|
COGL_BUFFER_MAP_HINT_DISCARD);
|
||||||
|
|
||||||
|
if (new_bmp_data == NULL)
|
||||||
{
|
{
|
||||||
src = new_bmp.data + y * new_bmp.rowstride;
|
cogl_object_unref (new_bmp);
|
||||||
dst = data + y * rowstride;
|
return 0;
|
||||||
memcpy (dst, src, new_bmp.width * bpp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy to user buffer */
|
||||||
|
for (y = 0; y < tex_height; ++y)
|
||||||
|
{
|
||||||
|
src = new_bmp_data + y * new_bmp_rowstride;
|
||||||
|
dst = data + y * rowstride;
|
||||||
|
memcpy (dst, src, tex_width * bpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (new_bmp);
|
||||||
|
|
||||||
/* Free converted data */
|
/* Free converted data */
|
||||||
g_free (new_bmp.data);
|
cogl_object_unref (new_bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return byte_size;
|
return byte_size;
|
||||||
|
@ -619,10 +619,12 @@ cogl_read_pixels (int x,
|
|||||||
CoglFramebuffer *framebuffer;
|
CoglFramebuffer *framebuffer;
|
||||||
int framebuffer_height;
|
int framebuffer_height;
|
||||||
int bpp;
|
int bpp;
|
||||||
CoglBitmap bmp;
|
CoglBitmap *bmp;
|
||||||
GLenum gl_intformat;
|
GLenum gl_intformat;
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
CoglPixelFormat bmp_format;
|
||||||
|
int rowstride;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
@ -649,11 +651,8 @@ cogl_read_pixels (int x,
|
|||||||
|
|
||||||
/* Initialise the CoglBitmap */
|
/* Initialise the CoglBitmap */
|
||||||
bpp = _cogl_get_format_bpp (format);
|
bpp = _cogl_get_format_bpp (format);
|
||||||
bmp.format = format;
|
rowstride = bpp * width;
|
||||||
bmp.data = pixels;
|
bmp_format = format;
|
||||||
bmp.width = width;
|
|
||||||
bmp.height = height;
|
|
||||||
bmp.rowstride = bpp * width;
|
|
||||||
|
|
||||||
if ((format & COGL_A_BIT))
|
if ((format & COGL_A_BIT))
|
||||||
{
|
{
|
||||||
@ -667,9 +666,13 @@ cogl_read_pixels (int x,
|
|||||||
it. Eventually we may want to add a way for an application to
|
it. Eventually we may want to add a way for an application to
|
||||||
inform Cogl that the framebuffer is not premultiplied in case
|
inform Cogl that the framebuffer is not premultiplied in case
|
||||||
it is being used for some special purpose. */
|
it is being used for some special purpose. */
|
||||||
bmp.format |= COGL_PREMULT_BIT;
|
bmp_format |= COGL_PREMULT_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bmp = _cogl_bitmap_new_from_data (pixels,
|
||||||
|
bmp_format, width, height, rowstride,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
_cogl_pixel_format_to_gl (format, &gl_intformat, &gl_format, &gl_type);
|
_cogl_pixel_format_to_gl (format, &gl_intformat, &gl_format, &gl_type);
|
||||||
|
|
||||||
/* Under GLES only GL_RGBA with GL_UNSIGNED_BYTE as well as an
|
/* Under GLES only GL_RGBA with GL_UNSIGNED_BYTE as well as an
|
||||||
@ -683,33 +686,33 @@ cogl_read_pixels (int x,
|
|||||||
#ifndef COGL_HAS_GL
|
#ifndef COGL_HAS_GL
|
||||||
if (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE)
|
if (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE)
|
||||||
{
|
{
|
||||||
CoglBitmap tmp_bmp, dst_bmp;
|
CoglBitmap *tmp_bmp, *dst_bmp;
|
||||||
|
guint8 *tmp_data = g_malloc (width * height * 4);
|
||||||
|
|
||||||
tmp_bmp.format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
tmp_bmp = _cogl_bitmap_new_from_data (tmp_data,
|
||||||
tmp_bmp.data = g_malloc (width * height * 4);
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
tmp_bmp.width = width;
|
width, height, 4 * width,
|
||||||
tmp_bmp.height = height;
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
tmp_bmp.rowstride = 4 * width;
|
NULL);
|
||||||
|
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_download (tmp_bmp.rowstride, 4);
|
_cogl_texture_driver_prep_gl_for_pixels_download (4 * width, 4);
|
||||||
|
|
||||||
GE( glReadPixels (x, y, width, height,
|
GE( glReadPixels (x, y, width, height,
|
||||||
GL_RGBA, GL_UNSIGNED_BYTE,
|
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
tmp_bmp.data) );
|
tmp_data) );
|
||||||
|
|
||||||
/* CoglBitmap doesn't currently have a way to convert without
|
/* CoglBitmap doesn't currently have a way to convert without
|
||||||
allocating its own buffer so we have to copy the data
|
allocating its own buffer so we have to copy the data
|
||||||
again */
|
again */
|
||||||
if (_cogl_bitmap_convert_format_and_premult (&tmp_bmp,
|
if ((dst_bmp = _cogl_bitmap_convert_format_and_premult (tmp_bmp,
|
||||||
&dst_bmp,
|
bmp_format)))
|
||||||
bmp.format))
|
|
||||||
{
|
{
|
||||||
_cogl_bitmap_copy_subregion (&dst_bmp,
|
_cogl_bitmap_copy_subregion (dst_bmp,
|
||||||
&bmp,
|
bmp,
|
||||||
0, 0,
|
0, 0,
|
||||||
0, 0,
|
0, 0,
|
||||||
bmp.width, bmp.height);
|
width, height);
|
||||||
g_free (dst_bmp.data);
|
cogl_object_unref (dst_bmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -717,26 +720,26 @@ cogl_read_pixels (int x,
|
|||||||
just have to leave the data initialised */
|
just have to leave the data initialised */
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (tmp_bmp.data);
|
cogl_object_unref (tmp_bmp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_download (bmp.rowstride, bpp);
|
_cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp);
|
||||||
|
|
||||||
GE( glReadPixels (x, y, width, height, gl_format, gl_type, pixels) );
|
GE( glReadPixels (x, y, width, height, gl_format, gl_type, pixels) );
|
||||||
|
|
||||||
/* Convert to the premult format specified by the caller
|
/* Convert to the premult format specified by the caller
|
||||||
in-place. This will do nothing if the premult status is already
|
in-place. This will do nothing if the premult status is already
|
||||||
correct. */
|
correct. */
|
||||||
_cogl_bitmap_convert_premult_status (&bmp, format);
|
_cogl_bitmap_convert_premult_status (bmp, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NB: All offscreen rendering is done upside down so there is no need
|
/* NB: All offscreen rendering is done upside down so there is no need
|
||||||
* to flip in this case... */
|
* to flip in this case... */
|
||||||
if (!cogl_is_offscreen (framebuffer))
|
if (!cogl_is_offscreen (framebuffer))
|
||||||
{
|
{
|
||||||
guint8 *temprow = g_alloca (bmp.rowstride * sizeof (guint8));
|
guint8 *temprow = g_alloca (rowstride * sizeof (guint8));
|
||||||
|
|
||||||
/* TODO: consider using the GL_MESA_pack_invert extension in the future
|
/* TODO: consider using the GL_MESA_pack_invert extension in the future
|
||||||
* to avoid this flip... */
|
* to avoid this flip... */
|
||||||
@ -747,15 +750,17 @@ cogl_read_pixels (int x,
|
|||||||
if (y != height - y - 1) /* skip center row */
|
if (y != height - y - 1) /* skip center row */
|
||||||
{
|
{
|
||||||
memcpy (temprow,
|
memcpy (temprow,
|
||||||
pixels + y * bmp.rowstride, bmp.rowstride);
|
pixels + y * rowstride, rowstride);
|
||||||
memcpy (pixels + y * bmp.rowstride,
|
memcpy (pixels + y * rowstride,
|
||||||
pixels + (height - y - 1) * bmp.rowstride, bmp.rowstride);
|
pixels + (height - y - 1) * rowstride, rowstride);
|
||||||
memcpy (pixels + (height - y - 1) * bmp.rowstride,
|
memcpy (pixels + (height - y - 1) * rowstride,
|
||||||
temprow,
|
temprow,
|
||||||
bmp.rowstride);
|
rowstride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cogl_object_unref (bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -153,10 +153,14 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
|||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
GLuint source_gl_type)
|
GLuint source_gl_type)
|
||||||
{
|
{
|
||||||
int bpp = _cogl_get_format_bpp (source_bmp->format);
|
guint8 *data;
|
||||||
|
|
||||||
|
if ((data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
|
{
|
||||||
|
int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
|
||||||
|
|
||||||
/* Setup gl alignment to match rowstride and top-left corner */
|
/* Setup gl alignment to match rowstride and top-left corner */
|
||||||
prep_gl_for_pixels_upload_full (source_bmp->rowstride,
|
prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
|
||||||
0,
|
0,
|
||||||
src_x,
|
src_x,
|
||||||
src_y,
|
src_y,
|
||||||
@ -169,7 +173,10 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
|||||||
width, height,
|
width, height,
|
||||||
source_gl_format,
|
source_gl_format,
|
||||||
source_gl_type,
|
source_gl_type,
|
||||||
source_bmp->data) );
|
data) );
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (source_bmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -181,20 +188,29 @@ _cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
|||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
GLuint source_gl_type)
|
GLuint source_gl_type)
|
||||||
{
|
{
|
||||||
int bpp = _cogl_get_format_bpp (source_bmp->format);
|
guint8 *data;
|
||||||
|
|
||||||
|
if ((data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
|
{
|
||||||
|
int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
|
||||||
|
|
||||||
/* Setup gl alignment to match rowstride and top-left corner */
|
/* Setup gl alignment to match rowstride and top-left corner */
|
||||||
prep_gl_for_pixels_upload_full (source_bmp->rowstride, 0, 0, 0, bpp);
|
prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
|
||||||
|
0, 0, 0, bpp);
|
||||||
|
|
||||||
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||||
|
|
||||||
GE( glTexImage2D (gl_target, 0,
|
GE( glTexImage2D (gl_target, 0,
|
||||||
internal_gl_format,
|
internal_gl_format,
|
||||||
source_bmp->width, source_bmp->height,
|
_cogl_bitmap_get_width (source_bmp),
|
||||||
|
_cogl_bitmap_get_height (source_bmp),
|
||||||
0,
|
0,
|
||||||
source_gl_format,
|
source_gl_format,
|
||||||
source_gl_type,
|
source_gl_type,
|
||||||
source_bmp->data) );
|
data) );
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (source_bmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -208,13 +224,18 @@ _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
|
|||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
GLuint source_gl_type)
|
GLuint source_gl_type)
|
||||||
{
|
{
|
||||||
int bpp = _cogl_get_format_bpp (source_bmp->format);
|
guint8 *data;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
|
if ((data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
|
{
|
||||||
|
int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
|
||||||
|
|
||||||
/* Setup gl alignment to match rowstride and top-left corner */
|
/* Setup gl alignment to match rowstride and top-left corner */
|
||||||
prep_gl_for_pixels_upload_full (source_bmp->rowstride,
|
prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
|
||||||
source_bmp->height / depth,
|
(_cogl_bitmap_get_height (source_bmp) /
|
||||||
|
depth),
|
||||||
0, 0, bpp);
|
0, 0, bpp);
|
||||||
|
|
||||||
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||||
@ -222,13 +243,16 @@ _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
|
|||||||
GE( glTexImage3D (gl_target,
|
GE( glTexImage3D (gl_target,
|
||||||
0, /* level */
|
0, /* level */
|
||||||
internal_gl_format,
|
internal_gl_format,
|
||||||
source_bmp->width,
|
_cogl_bitmap_get_width (source_bmp),
|
||||||
height,
|
height,
|
||||||
depth,
|
depth,
|
||||||
0,
|
0,
|
||||||
source_gl_format,
|
source_gl_format,
|
||||||
source_gl_type,
|
source_gl_type,
|
||||||
source_bmp->data) );
|
data) );
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (source_bmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
@ -113,36 +113,45 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
|||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
GLuint source_gl_type)
|
GLuint source_gl_type)
|
||||||
{
|
{
|
||||||
int bpp = _cogl_get_format_bpp (source_bmp->format);
|
guint8 *data;
|
||||||
CoglBitmap slice_bmp;
|
CoglPixelFormat source_format = _cogl_bitmap_get_format (source_bmp);
|
||||||
|
int bpp = _cogl_get_format_bpp (source_format);
|
||||||
|
CoglBitmap *slice_bmp;
|
||||||
|
int rowstride;
|
||||||
|
|
||||||
/* NB: GLES doesn't support the GL_UNPACK_ROW_LENGTH, GL_UNPACK_SKIP_PIXELS
|
/* NB: GLES doesn't support the GL_UNPACK_ROW_LENGTH,
|
||||||
* or GL_UNPACK_SKIP_ROWS pixel store options so we can't directly source a
|
* GL_UNPACK_SKIP_PIXELS or GL_UNPACK_SKIP_ROWS pixel store options
|
||||||
* sub-region from source_bmp, we need to use a transient bitmap instead. */
|
* so we can't directly source a sub-region from source_bmp, we need
|
||||||
|
* to use a transient bitmap instead. */
|
||||||
|
|
||||||
/* FIXME: optimize by not copying to intermediate slice bitmap when source
|
/* FIXME: optimize by not copying to intermediate slice bitmap when
|
||||||
* rowstride = bpp * width and the texture image is not sliced */
|
* source rowstride = bpp * width and the texture image is not
|
||||||
|
* sliced */
|
||||||
|
|
||||||
/* Setup temp bitmap for slice subregion */
|
/* Setup temp bitmap for slice subregion */
|
||||||
slice_bmp.format = source_bmp->format;
|
rowstride = bpp * width;
|
||||||
slice_bmp.width = width;
|
slice_bmp = _cogl_bitmap_new_from_data (g_malloc (rowstride * height),
|
||||||
slice_bmp.height = height;
|
source_format,
|
||||||
slice_bmp.rowstride = bpp * slice_bmp.width;
|
width,
|
||||||
slice_bmp.data = g_malloc (slice_bmp.rowstride * slice_bmp.height);
|
height,
|
||||||
|
rowstride,
|
||||||
|
(CoglBitmapDestroyNotify)
|
||||||
|
g_free,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/* Setup gl alignment to match rowstride and top-left corner */
|
/* Setup gl alignment to match rowstride and top-left corner */
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_upload (slice_bmp.rowstride,
|
_cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
|
||||||
bpp);
|
|
||||||
|
|
||||||
/* Copy subregion data */
|
/* Copy subregion data */
|
||||||
_cogl_bitmap_copy_subregion (source_bmp,
|
_cogl_bitmap_copy_subregion (source_bmp,
|
||||||
&slice_bmp,
|
slice_bmp,
|
||||||
src_x,
|
src_x,
|
||||||
src_y,
|
src_y,
|
||||||
0, 0,
|
0, 0,
|
||||||
slice_bmp.width,
|
width, height);
|
||||||
slice_bmp.height);
|
|
||||||
|
|
||||||
|
if ((data = _cogl_bitmap_map (slice_bmp, COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
|
{
|
||||||
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||||
|
|
||||||
GE( glTexSubImage2D (gl_target, 0,
|
GE( glTexSubImage2D (gl_target, 0,
|
||||||
@ -150,10 +159,12 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
|
|||||||
width, height,
|
width, height,
|
||||||
source_gl_format,
|
source_gl_format,
|
||||||
source_gl_type,
|
source_gl_type,
|
||||||
slice_bmp.data) );
|
data) );
|
||||||
|
|
||||||
/* Free temp bitmap */
|
_cogl_bitmap_unmap (slice_bmp);
|
||||||
g_free (slice_bmp.data);
|
}
|
||||||
|
|
||||||
|
cogl_object_unref (slice_bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -165,41 +176,53 @@ _cogl_texture_driver_upload_to_gl (GLenum gl_target,
|
|||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
GLuint source_gl_type)
|
GLuint source_gl_type)
|
||||||
{
|
{
|
||||||
int bpp = _cogl_get_format_bpp (source_bmp->format);
|
int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
|
||||||
CoglBitmap bmp = *source_bmp;
|
int rowstride = _cogl_bitmap_get_rowstride (source_bmp);
|
||||||
gboolean bmp_owner = FALSE;
|
int bmp_width = _cogl_bitmap_get_width (source_bmp);
|
||||||
|
int bmp_height = _cogl_bitmap_get_height (source_bmp);
|
||||||
|
CoglBitmap *bmp;
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
/* If the rowstride can't be specified with just GL_ALIGNMENT alone
|
/* If the rowstride can't be specified with just GL_ALIGNMENT alone
|
||||||
then we need to copy the bitmap because there is no GL_ROW_LENGTH */
|
then we need to copy the bitmap because there is no GL_ROW_LENGTH */
|
||||||
if (source_bmp->rowstride / bpp != source_bmp->width)
|
if (rowstride / bpp != bmp_width)
|
||||||
{
|
{
|
||||||
bmp.rowstride = bpp * bmp.width;
|
bmp = _cogl_bitmap_new_from_data (g_malloc (rowstride * bmp_height),
|
||||||
bmp.data = g_malloc (bmp.rowstride * bmp.height);
|
_cogl_bitmap_get_format (source_bmp),
|
||||||
bmp_owner = TRUE;
|
bmp_width,
|
||||||
|
bmp_height,
|
||||||
|
rowstride,
|
||||||
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL);
|
||||||
|
|
||||||
_cogl_bitmap_copy_subregion (source_bmp,
|
_cogl_bitmap_copy_subregion (source_bmp,
|
||||||
&bmp,
|
bmp,
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
bmp.width,
|
bmp_width,
|
||||||
bmp.height);
|
bmp_height);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
bmp = cogl_object_ref (source_bmp);
|
||||||
|
|
||||||
/* Setup gl alignment to match rowstride and top-left corner */
|
/* Setup gl alignment to match rowstride and top-left corner */
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_upload (bmp.rowstride,
|
_cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
|
||||||
bpp);
|
|
||||||
|
|
||||||
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
_cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
|
||||||
|
|
||||||
|
if ((data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
|
{
|
||||||
GE( glTexImage2D (gl_target, 0,
|
GE( glTexImage2D (gl_target, 0,
|
||||||
internal_gl_format,
|
internal_gl_format,
|
||||||
bmp.width, bmp.height,
|
bmp_width, bmp_height,
|
||||||
0,
|
0,
|
||||||
source_gl_format,
|
source_gl_format,
|
||||||
source_gl_type,
|
source_gl_type,
|
||||||
bmp.data) );
|
data) );
|
||||||
|
|
||||||
if (bmp_owner)
|
_cogl_bitmap_unmap (bmp);
|
||||||
g_free (bmp.data);
|
}
|
||||||
|
|
||||||
|
cogl_object_unref (bmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -213,7 +236,11 @@ _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
|
|||||||
GLuint source_gl_format,
|
GLuint source_gl_format,
|
||||||
GLuint source_gl_type)
|
GLuint source_gl_type)
|
||||||
{
|
{
|
||||||
int bpp = _cogl_get_format_bpp (source_bmp->format);
|
int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
|
||||||
|
int rowstride = _cogl_bitmap_get_rowstride (source_bmp);
|
||||||
|
int bmp_width = _cogl_bitmap_get_width (source_bmp);
|
||||||
|
int bmp_height = _cogl_bitmap_get_height (source_bmp);
|
||||||
|
guint8 *data;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
@ -222,14 +249,14 @@ _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
|
|||||||
/* If the rowstride or image height can't be specified with just
|
/* If the rowstride or image height can't be specified with just
|
||||||
GL_ALIGNMENT alone then we need to copy the bitmap because there
|
GL_ALIGNMENT alone then we need to copy the bitmap because there
|
||||||
is no GL_ROW_LENGTH */
|
is no GL_ROW_LENGTH */
|
||||||
if (source_bmp->rowstride / bpp != source_bmp->width ||
|
if (rowstride / bpp != bmp_width ||
|
||||||
height != source_bmp->height / depth)
|
height != bmp_height / depth)
|
||||||
{
|
{
|
||||||
int image_height = source_bmp->height / depth;
|
CoglBitmap *bmp;
|
||||||
|
int image_height = bmp_height / depth;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_upload (source_bmp->width * bpp,
|
_cogl_texture_driver_prep_gl_for_pixels_upload (bmp_width * bpp, bpp);
|
||||||
bpp);
|
|
||||||
|
|
||||||
/* Initialize the texture with empty data and then upload each
|
/* Initialize the texture with empty data and then upload each
|
||||||
image with a sub-region update */
|
image with a sub-region update */
|
||||||
@ -237,7 +264,7 @@ _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
|
|||||||
GE( glTexImage3D (gl_target,
|
GE( glTexImage3D (gl_target,
|
||||||
0, /* level */
|
0, /* level */
|
||||||
internal_gl_format,
|
internal_gl_format,
|
||||||
source_bmp->width,
|
bmp_width,
|
||||||
height,
|
height,
|
||||||
depth,
|
depth,
|
||||||
0,
|
0,
|
||||||
@ -245,51 +272,60 @@ _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
|
|||||||
source_gl_type,
|
source_gl_type,
|
||||||
NULL) );
|
NULL) );
|
||||||
|
|
||||||
|
bmp = _cogl_bitmap_new_from_data (g_malloc (bpp * bmp_width * height),
|
||||||
|
_cogl_bitmap_get_format (source_bmp),
|
||||||
|
bmp_width,
|
||||||
|
height,
|
||||||
|
bpp * bmp_width,
|
||||||
|
(CoglBitmapDestroyNotify) g_free,
|
||||||
|
NULL);
|
||||||
|
|
||||||
for (i = 0; i < depth; i++)
|
for (i = 0; i < depth; i++)
|
||||||
{
|
{
|
||||||
CoglBitmap bmp = *source_bmp;
|
|
||||||
|
|
||||||
bmp.rowstride = bpp * bmp.width;
|
|
||||||
bmp.height = height;
|
|
||||||
bmp.data = g_malloc (bmp.rowstride * bmp.height);
|
|
||||||
|
|
||||||
_cogl_bitmap_copy_subregion (source_bmp,
|
_cogl_bitmap_copy_subregion (source_bmp,
|
||||||
&bmp,
|
bmp,
|
||||||
0, image_height * i,
|
0, image_height * i,
|
||||||
0, 0,
|
0, 0,
|
||||||
bmp.width,
|
bmp_width,
|
||||||
bmp.height);
|
bmp_height);
|
||||||
|
|
||||||
|
if ((data = _cogl_bitmap_map (bmp,
|
||||||
|
COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
|
{
|
||||||
GE( glTexSubImage3D (gl_target,
|
GE( glTexSubImage3D (gl_target,
|
||||||
0, /* level */
|
0, /* level */
|
||||||
0, /* xoffset */
|
0, /* xoffset */
|
||||||
0, /* yoffset */
|
0, /* yoffset */
|
||||||
i, /* zoffset */
|
i, /* zoffset */
|
||||||
bmp.width, /* width */
|
bmp_width, /* width */
|
||||||
height, /* height */
|
height, /* height */
|
||||||
1, /* depth */
|
1, /* depth */
|
||||||
source_gl_format,
|
source_gl_format,
|
||||||
source_gl_type,
|
source_gl_type,
|
||||||
bmp.data) );
|
data) );
|
||||||
|
|
||||||
g_free (bmp.data);
|
_cogl_bitmap_unmap (bmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
cogl_object_unref (bmp);
|
||||||
|
}
|
||||||
|
else if ((data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0)))
|
||||||
{
|
{
|
||||||
_cogl_texture_driver_prep_gl_for_pixels_upload (source_bmp->rowstride,
|
_cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
|
||||||
bpp);
|
|
||||||
|
|
||||||
GE( glTexImage3D (gl_target,
|
GE( glTexImage3D (gl_target,
|
||||||
0, /* level */
|
0, /* level */
|
||||||
internal_gl_format,
|
internal_gl_format,
|
||||||
source_bmp->width,
|
bmp_width,
|
||||||
height,
|
height,
|
||||||
depth,
|
depth,
|
||||||
0,
|
0,
|
||||||
source_gl_format,
|
source_gl_format,
|
||||||
source_gl_type,
|
source_gl_type,
|
||||||
source_bmp->data) );
|
data) );
|
||||||
|
|
||||||
|
_cogl_bitmap_unmap (source_bmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user