{
gint bpp;
CoglBitmap source_bmp;
- CoglBitmap temp_bmp;
- gboolean source_bmp_owner = FALSE;
- CoglPixelFormat closest_format;
- GLenum closest_gl_format;
- GLenum closest_gl_type;
+ CoglBitmap tmp_bmp;
+ gboolean tmp_bmp_owner = FALSE;
gboolean success;
/* Check for valid format */
bpp = _cogl_get_format_bpp (format);
source_bmp.rowstride = (rowstride == 0) ? width * bpp : rowstride;
- /* Find closest format to internal that's supported by GL */
- closest_format = _cogl_pixel_format_to_gl (atlas_tex->format,
- NULL, /* don't need */
- &closest_gl_format,
- &closest_gl_type);
-
- /* If no direct match, convert */
- if (closest_format != format)
- {
- /* Convert to required format */
- success = _cogl_bitmap_convert_format_and_premult (&source_bmp,
- &temp_bmp,
- closest_format);
-
- /* Swap bitmaps if succeeded */
- if (!success) return FALSE;
- source_bmp = temp_bmp;
- source_bmp_owner = TRUE;
- }
+ /* Prepare the bitmap so that it will do the premultiplication
+ conversion */
+ _cogl_texture_prepare_for_upload (&source_bmp,
+ atlas_tex->format,
+ NULL,
+ &tmp_bmp,
+ &tmp_bmp_owner,
+ NULL, NULL, NULL);
/* Upload the data ignoring the premult bit */
success =
src_x, src_y,
dst_x, dst_y,
dst_width, dst_height,
- source_bmp.width,
- source_bmp.height,
- source_bmp.format &
+ tmp_bmp.width,
+ tmp_bmp.height,
+ tmp_bmp.format &
~COGL_PREMULT_BIT,
- source_bmp.rowstride,
- source_bmp.data);
+ tmp_bmp.rowstride,
+ tmp_bmp.data);
/* Free data if owner */
- if (source_bmp_owner)
- g_free (source_bmp.data);
+ if (tmp_bmp_owner)
+ g_free (tmp_bmp.data);
return success;
}
CoglTextureFlags flags,
CoglPixelFormat internal_format)
{
- CoglAtlasTexture *atlas_tex;
- CoglBitmap *bmp = (CoglBitmap *) bmp_handle;
- CoglTextureUploadData upload_data;
+ CoglAtlasTexture *atlas_tex;
+ CoglBitmap *bmp = (CoglBitmap *) bmp_handle;
+ CoglBitmap dst_bmp;
+ gboolean dst_bmp_owner;
+ GLenum gl_intformat;
+ GLenum gl_format;
+ GLenum gl_type;
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
if (!cogl_features_available (COGL_FEATURE_TEXTURE_READ_PIXELS))
return COGL_INVALID_HANDLE;
- upload_data.bitmap = *bmp;
- upload_data.bitmap_owner = FALSE;
-
- if (!_cogl_texture_upload_data_prepare_format (&upload_data,
- &internal_format))
- {
- _cogl_texture_upload_data_free (&upload_data);
- return COGL_INVALID_HANDLE;
- }
-
COGL_NOTE (ATLAS, "Adding texture of size %ix%i", bmp->width, bmp->height);
+ if (!_cogl_texture_prepare_for_upload (bmp,
+ internal_format,
+ &internal_format,
+ NULL,
+ NULL,
+ &gl_intformat,
+ &gl_format,
+ &gl_type))
+ return COGL_INVALID_HANDLE;
+
/* If the texture is in a strange format then we can't use it */
if (internal_format != COGL_PIXEL_FORMAT_RGB_888 &&
(internal_format & ~COGL_PREMULT_BIT) != COGL_PIXEL_FORMAT_RGBA_8888)
COGL_NOTE (ATLAS, "Texture can not be added because the "
"format is unsupported");
- _cogl_texture_upload_data_free (&upload_data);
return COGL_INVALID_HANDLE;
}
atlas_tex = g_new (CoglAtlasTexture, 1);
/* 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 */
- atlas_tex->rectangle.width = upload_data.bitmap.width + 2;
- atlas_tex->rectangle.height = upload_data.bitmap.height + 2;
+ atlas_tex->rectangle.width = bmp->width + 2;
+ atlas_tex->rectangle.height = bmp->height + 2;
/* Try to make some space in the atlas for the texture */
if (!_cogl_atlas_texture_reserve_space (atlas_tex,
atlas_tex->rectangle.height))
{
g_free (atlas_tex);
- _cogl_texture_upload_data_free (&upload_data);
return COGL_INVALID_HANDLE;
}
- if (!_cogl_texture_upload_data_convert (&upload_data, internal_format))
+ if (!_cogl_texture_prepare_for_upload (bmp,
+ internal_format,
+ &internal_format,
+ &dst_bmp,
+ &dst_bmp_owner,
+ &gl_intformat,
+ &gl_format,
+ &gl_type))
{
cogl_atlas_remove_rectangle (ctx->atlas, &atlas_tex->rectangle);
g_free (atlas_tex);
- _cogl_texture_upload_data_free (&upload_data);
return COGL_INVALID_HANDLE;
}
_cogl_atlas_texture_set_region_with_border (atlas_tex,
0, 0,
0, 0,
- upload_data.bitmap.width,
- upload_data.bitmap.height,
- upload_data.bitmap.width,
- upload_data.bitmap.height,
- upload_data.bitmap.format &
+ dst_bmp.width,
+ dst_bmp.height,
+ dst_bmp.width,
+ dst_bmp.height,
+ dst_bmp.format &
~COGL_PREMULT_BIT,
- upload_data.bitmap.rowstride,
- upload_data.bitmap.data);
+ dst_bmp.rowstride,
+ dst_bmp.data);
+
+ if (dst_bmp_owner)
+ g_free (dst_bmp.data);
return _cogl_atlas_texture_handle_new (atlas_tex);
}
static gboolean
_cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
- CoglTextureUploadData *upload_data)
+ CoglBitmap *bmp,
+ GLenum gl_intformat,
+ GLenum gl_format,
+ GLenum gl_type)
{
CoglSpan *x_span;
CoglSpan *y_span;
gint x,y;
guchar *waste_buf;
- bpp = _cogl_get_format_bpp (upload_data->bitmap.format);
+ bpp = _cogl_get_format_bpp (bmp->format);
- waste_buf =
- _cogl_texture_2d_sliced_allocate_waste_buffer (tex_2ds,
- upload_data->bitmap.format);
+ waste_buf = _cogl_texture_2d_sliced_allocate_waste_buffer (tex_2ds,
+ bmp->format);
/* Iterate vertical slices */
for (y = 0; y < tex_2ds->slice_y_spans->len; ++y)
0, /* dst y */
x_span->size - x_span->waste, /* width */
y_span->size - y_span->waste, /* height */
- &upload_data->bitmap,
- upload_data->gl_format,
- upload_data->gl_type);
+ bmp,
+ gl_format,
+ gl_type);
/* Keep a copy of the first pixel if needed */
if (tex_2ds->first_pixels)
{
memcpy (tex_2ds->first_pixels[slice_num].data,
- upload_data->bitmap.data + x_span->start * bpp
- + y_span->start * upload_data->bitmap.rowstride,
+ bmp->data + x_span->start * bpp
+ + y_span->start * bmp->rowstride,
bpp);
- tex_2ds->first_pixels[slice_num].gl_format =
- upload_data->gl_format;
- tex_2ds->first_pixels[slice_num].gl_type = upload_data->gl_type;
+ tex_2ds->first_pixels[slice_num].gl_format = gl_format;
+ tex_2ds->first_pixels[slice_num].gl_type = gl_type;
}
/* Fill the waste with a copies of the rightmost pixels */
if (x_span->waste > 0)
{
- const guchar *src = upload_data->bitmap.data
- + y_span->start * upload_data->bitmap.rowstride
+ const guchar *src = bmp->data
+ + y_span->start * bmp->rowstride
+ (x_span->start + x_span->size - x_span->waste - 1) * bpp;
guchar *dst = waste_buf;
guint wx, wy;
memcpy (dst, src, bpp);
dst += bpp;
}
- src += upload_data->bitmap.rowstride;
+ src += bmp->rowstride;
}
_cogl_texture_driver_prep_gl_for_pixels_upload (
0,
x_span->waste,
y_span->size - y_span->waste,
- upload_data->gl_format, upload_data->gl_type,
+ gl_format, gl_type,
waste_buf) );
}
if (y_span->waste > 0)
{
- const guchar *src = upload_data->bitmap.data
+ const guchar *src = bmp->data
+ ((y_span->start + y_span->size - y_span->waste - 1)
- * upload_data->bitmap.rowstride)
+ * bmp->rowstride)
+ x_span->start * bpp;
guchar *dst = waste_buf;
guint wy, wx;
y_span->size - y_span->waste,
x_span->size,
y_span->waste,
- upload_data->gl_format, upload_data->gl_type,
+ gl_format, gl_type,
waste_buf) );
}
}
static gboolean
_cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds,
- const CoglTextureUploadData *upload_data)
+ gint width, gint height,
+ GLenum gl_intformat,
+ GLenum gl_format,
+ GLenum gl_type)
{
gint max_width;
gint max_height;
/* Initialize size of largest slice according to supported features */
if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT))
{
- max_width = upload_data->bitmap.width;
- max_height = upload_data->bitmap.height;
+ max_width = width;
+ max_height = height;
tex_2ds->gl_target = GL_TEXTURE_2D;
slices_for_size = _cogl_rect_slices_for_size;
}
else
{
- max_width = cogl_util_next_p2 (upload_data->bitmap.width);
- max_height = cogl_util_next_p2 (upload_data->bitmap.height);
+ max_width = cogl_util_next_p2 (width);
+ max_height = cogl_util_next_p2 (height);
tex_2ds->gl_target = GL_TEXTURE_2D;
slices_for_size = _cogl_pot_slices_for_size;
}
/* Check if size supported else bail out */
if (!_cogl_texture_driver_size_supported (tex_2ds->gl_target,
- upload_data->gl_intformat,
- upload_data->gl_type,
+ gl_intformat,
+ gl_type,
max_width,
max_height))
{
/* Add a single span for width and height */
span.start = 0;
span.size = max_width;
- span.waste = max_width - upload_data->bitmap.width;
+ span.waste = max_width - width;
g_array_append_val (tex_2ds->slice_x_spans, span);
span.size = max_height;
- span.waste = max_height - upload_data->bitmap.height;
+ span.waste = max_height - height;
g_array_append_val (tex_2ds->slice_y_spans, span);
}
else
{
/* Decrease the size of largest slice until supported by GL */
while (!_cogl_texture_driver_size_supported (tex_2ds->gl_target,
- upload_data->gl_intformat,
- upload_data->gl_type,
+ gl_intformat,
+ gl_type,
max_width,
max_height))
{
}
/* Determine the slices required to cover the bitmap area */
- n_x_slices = slices_for_size (upload_data->bitmap.width,
+ n_x_slices = slices_for_size (width,
max_width, tex_2ds->max_waste,
NULL);
- n_y_slices = slices_for_size (upload_data->bitmap.height,
+ n_y_slices = slices_for_size (height,
max_height, tex_2ds->max_waste,
NULL);
n_y_slices);
/* Fill span arrays with info */
- slices_for_size (upload_data->bitmap.width,
+ slices_for_size (width,
max_width, tex_2ds->max_waste,
tex_2ds->slice_x_spans);
- slices_for_size (upload_data->bitmap.height,
+ slices_for_size (height,
max_height, tex_2ds->max_waste,
tex_2ds->slice_y_spans);
}
/* Setup texture parameters */
GE( _cogl_texture_driver_bind (tex_2ds->gl_target,
gl_handles[y * n_x_slices + x],
- upload_data->gl_intformat) );
+ gl_intformat) );
_cogl_texture_driver_try_setting_gl_border_color (tex_2ds->gl_target,
transparent_color);
/* Pass NULL data to init size and internal format */
- GE( glTexImage2D (tex_2ds->gl_target, 0, upload_data->gl_intformat,
+ GE( glTexImage2D (tex_2ds->gl_target, 0, gl_intformat,
x_span->size, y_span->size, 0,
- upload_data->gl_format, upload_data->gl_type, 0) );
+ gl_format, gl_type, 0) );
}
}
static gboolean
_cogl_texture_2d_sliced_upload_from_data
- (CoglTexture2DSliced *tex_2ds,
- CoglTextureUploadData *upload_data,
- CoglPixelFormat internal_format)
+ (CoglTexture2DSliced *tex_2ds,
+ CoglBitmap *bmp,
+ CoglPixelFormat internal_format)
{
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
+ GLenum gl_intformat;
+ GLenum gl_format;
+ GLenum gl_type;
tex->vtable = &cogl_texture_2d_sliced_vtable;
tex_2ds->min_filter = GL_FALSE;
tex_2ds->mag_filter = GL_FALSE;
- if (upload_data->bitmap.data)
+ if (bmp->data)
{
- if (!_cogl_texture_upload_data_prepare (upload_data, internal_format))
+ 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 */
- if (!_cogl_texture_2d_sliced_slices_create (tex_2ds, upload_data))
- return FALSE;
+ if (!_cogl_texture_2d_sliced_slices_create (tex_2ds,
+ bmp->width,
+ bmp->height,
+ gl_intformat,
+ gl_format,
+ gl_type))
+ {
+ if (dst_bmp_owner)
+ g_free (dst_bmp.data);
- if (!_cogl_texture_2d_sliced_upload_to_gl (tex_2ds, upload_data))
- return FALSE;
+ return FALSE;
+ }
+
+ if (!_cogl_texture_2d_sliced_upload_to_gl (tex_2ds,
+ 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 */
- upload_data->bitmap.format =
- _cogl_pixel_format_to_gl (internal_format,
- &upload_data->gl_intformat,
- &upload_data->gl_format,
- &upload_data->gl_type);
+ _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, upload_data))
+ if (!_cogl_texture_2d_sliced_slices_create (tex_2ds,
+ bmp->width,
+ bmp->height,
+ gl_intformat,
+ gl_format,
+ gl_type))
return FALSE;
}
- tex_2ds->gl_format = upload_data->gl_intformat;
- tex_2ds->width = upload_data->bitmap.width;
- tex_2ds->height = upload_data->bitmap.height;
- tex_2ds->format = upload_data->bitmap.format;
+ tex_2ds->gl_format = gl_intformat;
+ tex_2ds->width = bmp->width;
+ tex_2ds->height = bmp->height;
+ tex_2ds->format = bmp->format;
return TRUE;
}
{
CoglTexture2DSliced *tex_2ds;
CoglTexture *tex;
- CoglTextureUploadData upload_data;
+ CoglBitmap bmp;
/* Since no data, we need some internal format */
if (internal_format == COGL_PIXEL_FORMAT_ANY)
tex = COGL_TEXTURE (tex_2ds);
- upload_data.bitmap.width = width;
- upload_data.bitmap.height = height;
- upload_data.bitmap.data = NULL;
- upload_data.bitmap_owner = FALSE;
+ bmp.width = width;
+ bmp.height = height;
+ bmp.data = NULL;
if ((flags & COGL_TEXTURE_NO_SLICING))
tex_2ds->max_waste = -1;
else
tex_2ds->max_waste = COGL_TEXTURE_MAX_WASTE;
- if (!_cogl_texture_2d_sliced_upload_from_data (tex_2ds, &upload_data,
+ if (!_cogl_texture_2d_sliced_upload_from_data (tex_2ds, &bmp,
internal_format))
{
_cogl_texture_2d_sliced_free (tex_2ds);
- _cogl_texture_upload_data_free (&upload_data);
return COGL_INVALID_HANDLE;
}
tex_2ds->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
- _cogl_texture_upload_data_free (&upload_data);
-
return _cogl_texture_2d_sliced_handle_new (tex_2ds);
}
CoglTexture2DSliced *tex_2ds;
CoglTexture *tex;
CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
- CoglTextureUploadData upload_data;
g_return_val_if_fail (bmp_handle != COGL_INVALID_HANDLE, COGL_INVALID_HANDLE);
tex = COGL_TEXTURE (tex_2ds);
- upload_data.bitmap = *bmp;
- upload_data.bitmap_owner = FALSE;
-
if (flags & COGL_TEXTURE_NO_SLICING)
tex_2ds->max_waste = -1;
else
* CoglHandle is returned, it should also be destroyed
* with cogl_handle_unref at some point! */
- if (!_cogl_texture_2d_sliced_upload_from_data (tex_2ds, &upload_data,
+ if (!_cogl_texture_2d_sliced_upload_from_data (tex_2ds, bmp,
internal_format))
{
_cogl_texture_2d_sliced_free (tex_2ds);
- _cogl_texture_upload_data_free (&upload_data);
return COGL_INVALID_HANDLE;
}
tex_2ds->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
- _cogl_texture_upload_data_free (&upload_data);
-
return _cogl_texture_2d_sliced_handle_new (tex_2ds);
}
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
gint bpp;
CoglBitmap source_bmp;
- CoglBitmap temp_bmp;
- gboolean source_bmp_owner = FALSE;
- CoglPixelFormat closest_format;
+ CoglBitmap tmp_bmp;
+ gboolean tmp_bmp_owner = FALSE;
GLenum closest_gl_format;
GLenum closest_gl_type;
- gboolean success;
/* Check for valid format */
if (format == COGL_PIXEL_FORMAT_ANY)
bpp = _cogl_get_format_bpp (format);
source_bmp.rowstride = (rowstride == 0) ? width * bpp : rowstride;
- /* Find closest format to internal that's supported by GL */
- closest_format = _cogl_pixel_format_to_gl (tex_2ds->format,
- NULL, /* don't need */
- &closest_gl_format,
- &closest_gl_type);
+ /* Prepare the bitmap so that it will do the premultiplication
+ conversion */
+ _cogl_texture_prepare_for_upload (&source_bmp,
+ tex_2ds->format,
+ NULL,
+ &tmp_bmp,
+ &tmp_bmp_owner,
+ NULL,
+ &closest_gl_format,
+ &closest_gl_type);
- /* If no direct match, convert */
- if (closest_format != format)
- {
- /* Convert to required format */
- success = _cogl_bitmap_convert_format_and_premult (&source_bmp,
- &temp_bmp,
- closest_format);
-
- /* Swap bitmaps if succeeded */
- if (!success) return FALSE;
- source_bmp = temp_bmp;
- source_bmp_owner = TRUE;
- }
/* Send data to GL */
_cogl_texture_2d_sliced_upload_subregion_to_gl (tex_2ds,
src_x, src_y,
dst_x, dst_y,
dst_width, dst_height,
- &source_bmp,
+ &tmp_bmp,
closest_gl_format,
closest_gl_type);
/* Free data if owner */
- if (source_bmp_owner)
- g_free (source_bmp.data);
+ if (tmp_bmp_owner)
+ g_free (tmp_bmp.data);
return TRUE;
}
CoglTextureFlags flags,
CoglPixelFormat internal_format)
{
- CoglTexture2D *tex_2d;
- CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
- CoglTextureUploadData upload_data;
+ CoglTexture2D *tex_2d;
+ CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
+ CoglBitmap dst_bmp;
+ gboolean dst_bmp_owner;
+ GLenum gl_intformat;
+ GLenum gl_format;
+ GLenum gl_type;
g_return_val_if_fail (bmp_handle != COGL_INVALID_HANDLE, COGL_INVALID_HANDLE);
- upload_data.bitmap = *bmp;
- upload_data.bitmap_owner = FALSE;
-
- if (!_cogl_texture_upload_data_prepare_format (&upload_data,
- &internal_format) ||
- !_cogl_texture_2d_can_create (upload_data.bitmap.width,
- upload_data.bitmap.height,
- internal_format) ||
- !_cogl_texture_upload_data_convert (&upload_data, internal_format))
- {
- _cogl_texture_upload_data_free (&upload_data);
- return COGL_INVALID_HANDLE;
- }
+ if (!_cogl_texture_prepare_for_upload (bmp,
+ internal_format,
+ &internal_format,
+ &dst_bmp,
+ &dst_bmp_owner,
+ &gl_intformat,
+ &gl_format,
+ &gl_type))
+ return COGL_INVALID_HANDLE;
- tex_2d = _cogl_texture_2d_create_base (upload_data.bitmap.width,
- upload_data.bitmap.height,
+ tex_2d = _cogl_texture_2d_create_base (bmp->width,
+ bmp->height,
flags,
- upload_data.bitmap.format);
+ internal_format);
GE( glGenTextures (1, &tex_2d->gl_texture) );
_cogl_texture_driver_upload_to_gl (GL_TEXTURE_2D,
tex_2d->gl_texture,
- &upload_data.bitmap,
- upload_data.gl_intformat,
- upload_data.gl_format,
- upload_data.gl_type);
+ &dst_bmp,
+ gl_intformat,
+ gl_format,
+ gl_type);
- tex_2d->gl_format = upload_data.gl_intformat;
+ tex_2d->gl_format = gl_intformat;
- _cogl_texture_upload_data_free (&upload_data);
+ if (dst_bmp_owner)
+ g_free (dst_bmp.data);
return _cogl_texture_2d_handle_new (tex_2d);
}
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
gint bpp;
CoglBitmap source_bmp;
- CoglBitmap temp_bmp;
- gboolean source_bmp_owner = FALSE;
- CoglPixelFormat closest_format;
+ CoglBitmap tmp_bmp;
+ gboolean tmp_bmp_owner = FALSE;
GLenum closest_gl_format;
GLenum closest_gl_type;
- gboolean success;
/* Check for valid format */
if (format == COGL_PIXEL_FORMAT_ANY)
bpp = _cogl_get_format_bpp (format);
source_bmp.rowstride = (rowstride == 0) ? width * bpp : rowstride;
- /* Find closest format to internal that's supported by GL */
- closest_format = _cogl_pixel_format_to_gl (tex_2d->format,
- NULL, /* don't need */
- &closest_gl_format,
- &closest_gl_type);
-
- /* If no direct match, convert */
- if (closest_format != format)
- {
- /* Convert to required format */
- success = _cogl_bitmap_convert_format_and_premult (&source_bmp,
- &temp_bmp,
- closest_format);
-
- /* Swap bitmaps if succeeded */
- if (!success) return FALSE;
- source_bmp = temp_bmp;
- source_bmp_owner = TRUE;
- }
+ /* Prepare the bitmap so that it will do the premultiplication
+ conversion */
+ _cogl_texture_prepare_for_upload (&source_bmp,
+ tex_2d->format,
+ NULL,
+ &tmp_bmp,
+ &tmp_bmp_owner,
+ NULL,
+ &closest_gl_format,
+ &closest_gl_type);
/* Send data to GL */
_cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_2D,
src_x, src_y,
dst_x, dst_y,
dst_width, dst_height,
- &source_bmp,
+ &tmp_bmp,
closest_gl_format,
closest_gl_type);
/* Free data if owner */
- if (source_bmp_owner)
- g_free (source_bmp.data);
+ if (tmp_bmp_owner)
+ g_free (tmp_bmp.data);
return TRUE;
}
typedef struct _CoglTexture CoglTexture;
typedef struct _CoglTextureVtable CoglTextureVtable;
-typedef struct _CoglTextureUploadData CoglTextureUploadData;
typedef void (*CoglTextureSliceCallback) (CoglHandle handle,
GLuint gl_handle,
gint (* get_height) (CoglTexture *tex);
};
-/* This represents the state needed to upload texture data. There are
- utility functions in cogl-texture which use this state */
-struct _CoglTextureUploadData
-{
- CoglBitmap bitmap;
- gboolean bitmap_owner;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
-};
-
struct _CoglTexture
{
CoglHandleObject _parent;
void
_cogl_texture_ensure_non_quad_rendering (CoglHandle handle);
-/* Utility functions to help uploading a bitmap. These are intended to
- * be used by CoglTexture implementations or drivers... */
-
-void
-_cogl_texture_upload_data_free (CoglTextureUploadData *data);
-
-void
-_cogl_texture_upload_data_swap_bitmap (CoglTextureUploadData *data,
- CoglBitmap *new_bitmap);
-
-gboolean
-_cogl_texture_upload_data_prepare_format
- (CoglTextureUploadData *data,
- CoglPixelFormat *internal_format);
-
-gboolean
-_cogl_texture_upload_data_convert (CoglTextureUploadData *data,
- CoglPixelFormat internal_format);
+/* Utility function to help uploading a bitmap. If the bitmap needs
+ premult conversion then it will be copied and *copied_bitmap will
+ be set to TRUE. Otherwise dst_bmp will be set to a shallow copy of
+ src_bmp. The GLenums needed for uploading are returned */
gboolean
-_cogl_texture_upload_data_prepare (CoglTextureUploadData *data,
- CoglPixelFormat internal_format);
+_cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
+ CoglPixelFormat dst_format,
+ CoglPixelFormat *dst_format_out,
+ CoglBitmap *dst_bmp,
+ gboolean *copied_bitmap,
+ GLenum *out_glintformat,
+ GLenum *out_glformat,
+ GLenum *out_gltype);
void
_cogl_texture_prep_gl_alignment_for_pixels_upload (int pixels_rowstride);
cogl_handle_unref (handle);
}
-void
-_cogl_texture_upload_data_free (CoglTextureUploadData *data)
-{
- if (data->bitmap.data != NULL && data->bitmap_owner)
- g_free (data->bitmap.data);
+gboolean
+_cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
+ CoglPixelFormat dst_format,
+ CoglPixelFormat *dst_format_out,
+ CoglBitmap *dst_bmp,
+ gboolean *copied_bitmap,
+ GLenum *out_glintformat,
+ GLenum *out_glformat,
+ GLenum *out_gltype)
+{
+ /* If the application hasn't specified a specific format then we'll
+ * pick the most appropriate. By default Cogl will use a
+ * premultiplied internal format. Later we will add control over
+ * this. */
+ if (dst_format == COGL_PIXEL_FORMAT_ANY)
+ {
+ if ((src_bmp->format & COGL_A_BIT) &&
+ src_bmp->format != COGL_PIXEL_FORMAT_A_8)
+ dst_format = src_bmp->format | COGL_PREMULT_BIT;
+ else
+ dst_format = src_bmp->format;
+ }
- data->bitmap.data = NULL;
- data->bitmap_owner = FALSE;
-}
+ if (dst_bmp)
+ {
+ *copied_bitmap = FALSE;
+ *dst_bmp = *src_bmp;
+
+ /* If the source format does not have the same premult flag as the
+ dst format then we need to copy and convert it */
+ if ((src_bmp->format & COGL_A_BIT) &&
+ src_bmp->format != COGL_PIXEL_FORMAT_A_8 &&
+ (src_bmp->format & COGL_PREMULT_BIT) !=
+ (dst_format & COGL_PREMULT_BIT))
+ {
+ dst_bmp->data = g_memdup (dst_bmp->data,
+ dst_bmp->height * dst_bmp->rowstride);
+ *copied_bitmap = TRUE;
-void
-_cogl_texture_upload_data_swap_bitmap (CoglTextureUploadData *data,
- CoglBitmap *new_bitmap)
-{
- if (data->bitmap.data != NULL && data->bitmap_owner)
- g_free (data->bitmap.data);
+ if (!_cogl_bitmap_convert_premult_status (dst_bmp,
+ src_bmp->format ^
+ COGL_PREMULT_BIT))
+ {
+ g_free (dst_bmp->data);
+ return FALSE;
+ }
+ }
+ }
+
+ /* Use the source format from the src bitmap type and the internal
+ format from the dst format type so that GL can do the
+ conversion */
+ _cogl_pixel_format_to_gl (src_bmp->format,
+ NULL, /* internal format */
+ out_glformat,
+ out_gltype);
+ _cogl_pixel_format_to_gl (dst_format,
+ out_glintformat,
+ NULL,
+ NULL);
+
+ if (dst_format_out)
+ *dst_format_out = dst_format;
- data->bitmap = *new_bitmap;
- data->bitmap_owner = TRUE;
+ return TRUE;
}
void
tex->vtable->set_wrap_mode_parameter (tex, wrap_mode);
}
-gboolean
-_cogl_texture_upload_data_prepare_format
- (CoglTextureUploadData *data,
- CoglPixelFormat *internal_format)
-{
- /* Was there any internal conversion requested?
- * By default Cogl will use a premultiplied internal format. Later we will
- * add control over this. */
- if (*internal_format == COGL_PIXEL_FORMAT_ANY)
- {
- if ((data->bitmap.format & COGL_A_BIT) &&
- data->bitmap.format != COGL_PIXEL_FORMAT_A_8)
- *internal_format = data->bitmap.format | COGL_PREMULT_BIT;
- else
- *internal_format = data->bitmap.format;
- }
-
- /* Find closest format accepted by GL */
- *internal_format = _cogl_pixel_format_to_gl (*internal_format,
- &data->gl_intformat,
- &data->gl_format,
- &data->gl_type);
-
- return TRUE;
-}
-
-gboolean
-_cogl_texture_upload_data_convert (CoglTextureUploadData *data,
- CoglPixelFormat internal_format)
-{
- CoglBitmap new_bitmap;
- gboolean success;
-
- /* Convert to internal format */
- if (internal_format != data->bitmap.format)
- {
- success = _cogl_bitmap_convert_format_and_premult (&data->bitmap,
- &new_bitmap,
- internal_format);
-
- if (!success)
- return FALSE;
-
- /* Update texture with new data */
- _cogl_texture_upload_data_swap_bitmap (data, &new_bitmap);
- }
-
- return TRUE;
-}
-
-gboolean
-_cogl_texture_upload_data_prepare (CoglTextureUploadData *data,
- CoglPixelFormat internal_format)
-{
- return (_cogl_texture_upload_data_prepare_format (data, &internal_format) &&
- _cogl_texture_upload_data_convert (data, internal_format));
-}
-
/* This is like CoglSpanIter except it deals with floats and it
effectively assumes there is only one span from 0.0 to 1.0 */
typedef struct _CoglTextureIter