cogl: Let GL do the format conversion when uploading texture data
Cogl accepts a pixel format for both the data in memory and the internal format to be used for the texture. If they do not match then it would convert them using the CoglBitmap functions before uploading the data. However, GL also lets you specify both formats so it makes more sense to let GL do the conversion. The driver may need the texture in a specific format so it may end up being converted anyway. The cogl_texture_upload_data functions have been removed and replaced with a single function to prepare the bitmap. This will only do the premultiplication conversion because that is the only part that GL can't do directly.
This commit is contained in:
parent
e83ffb1fa3
commit
abe91784c4
@ -508,11 +508,8 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
|
||||
{
|
||||
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 */
|
||||
@ -533,25 +530,14 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
|
||||
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 =
|
||||
@ -559,16 +545,16 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
|
||||
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;
|
||||
}
|
||||
@ -927,9 +913,13 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
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);
|
||||
|
||||
@ -956,18 +946,18 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_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)
|
||||
@ -975,7 +965,6 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
COGL_NOTE (ATLAS, "Texture can not be added because the "
|
||||
"format is unsupported");
|
||||
|
||||
_cogl_texture_upload_data_free (&upload_data);
|
||||
return COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
@ -984,8 +973,8 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_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,
|
||||
@ -993,15 +982,20 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1019,14 +1013,17 @@ _cogl_atlas_texture_new_from_bitmap (CoglHandle bmp_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);
|
||||
}
|
||||
|
@ -213,7 +213,10 @@ _cogl_texture_2d_sliced_allocate_waste_buffer (CoglTexture2DSliced *tex_2ds,
|
||||
|
||||
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;
|
||||
@ -222,11 +225,10 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
||||
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)
|
||||
@ -252,27 +254,26 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
||||
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;
|
||||
@ -284,7 +285,7 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
||||
memcpy (dst, src, bpp);
|
||||
dst += bpp;
|
||||
}
|
||||
src += upload_data->bitmap.rowstride;
|
||||
src += bmp->rowstride;
|
||||
}
|
||||
|
||||
_cogl_texture_driver_prep_gl_for_pixels_upload (
|
||||
@ -296,15 +297,15 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
||||
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;
|
||||
@ -330,7 +331,7 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
|
||||
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) );
|
||||
}
|
||||
}
|
||||
@ -685,7 +686,10 @@ _cogl_texture_2d_sliced_set_wrap_mode_parameter (CoglTexture *tex,
|
||||
|
||||
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;
|
||||
@ -703,15 +707,15 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds,
|
||||
/* 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;
|
||||
}
|
||||
@ -723,8 +727,8 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds,
|
||||
|
||||
/* 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))
|
||||
{
|
||||
@ -746,19 +750,19 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds,
|
||||
/* 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))
|
||||
{
|
||||
@ -773,11 +777,11 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds,
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
@ -791,11 +795,11 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds,
|
||||
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);
|
||||
}
|
||||
@ -845,15 +849,15 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds,
|
||||
/* 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) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -893,11 +897,14 @@ _cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds)
|
||||
|
||||
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;
|
||||
|
||||
@ -914,36 +921,72 @@ _cogl_texture_2d_sliced_upload_from_data
|
||||
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;
|
||||
}
|
||||
@ -956,7 +999,7 @@ _cogl_texture_2d_sliced_new_with_size (unsigned int width,
|
||||
{
|
||||
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)
|
||||
@ -967,28 +1010,24 @@ _cogl_texture_2d_sliced_new_with_size (unsigned int width,
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1000,7 +1039,6 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglHandle bmp_handle,
|
||||
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);
|
||||
|
||||
@ -1009,9 +1047,6 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglHandle bmp_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
|
||||
@ -1025,18 +1060,15 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglHandle bmp_handle,
|
||||
* 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);
|
||||
}
|
||||
|
||||
@ -1398,12 +1430,10 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex,
|
||||
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)
|
||||
@ -1423,38 +1453,30 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex,
|
||||
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;
|
||||
}
|
||||
|
@ -275,42 +275,43 @@ _cogl_texture_2d_new_from_bitmap (CoglHandle bmp_handle,
|
||||
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_prepare_for_upload (bmp,
|
||||
internal_format,
|
||||
&internal_format,
|
||||
&dst_bmp,
|
||||
&dst_bmp_owner,
|
||||
&gl_intformat,
|
||||
&gl_format,
|
||||
&gl_type))
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@ -431,12 +432,10 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
|
||||
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)
|
||||
@ -456,25 +455,16 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
|
||||
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,
|
||||
@ -482,13 +472,13 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
|
||||
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;
|
||||
}
|
||||
|
@ -32,7 +32,6 @@
|
||||
|
||||
typedef struct _CoglTexture CoglTexture;
|
||||
typedef struct _CoglTextureVtable CoglTextureVtable;
|
||||
typedef struct _CoglTextureUploadData CoglTextureUploadData;
|
||||
|
||||
typedef void (*CoglTextureSliceCallback) (CoglHandle handle,
|
||||
GLuint gl_handle,
|
||||
@ -107,17 +106,6 @@ struct _CoglTextureVtable
|
||||
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;
|
||||
@ -162,28 +150,20 @@ _cogl_texture_ensure_mipmaps (CoglHandle handle);
|
||||
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);
|
||||
/* 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_format
|
||||
(CoglTextureUploadData *data,
|
||||
CoglPixelFormat *internal_format);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_upload_data_convert (CoglTextureUploadData *data,
|
||||
CoglPixelFormat internal_format);
|
||||
|
||||
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);
|
||||
|
@ -100,25 +100,71 @@ cogl_texture_unref (CoglHandle handle)
|
||||
cogl_handle_unref (handle);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_upload_data_free (CoglTextureUploadData *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 (data->bitmap.data != NULL && data->bitmap_owner)
|
||||
g_free (data->bitmap.data);
|
||||
/* 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;
|
||||
|
||||
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 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;
|
||||
|
||||
data->bitmap = *new_bitmap;
|
||||
data->bitmap_owner = TRUE;
|
||||
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;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -157,64 +203,6 @@ _cogl_texture_set_wrap_mode_parameter (CoglHandle handle,
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user