mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 01:50:42 -05:00
texture: Call _cogl_texture_prepare_for_upload in set_region impl
Instead of calling _cogl_texutre_prepare_for_upload in cogl_texture_set_region_from_bitmap the call is now deferred to the implementation of the virtual for set_region. This is needed if the texture backend is using a different format for the actual GL texture than what is reported by cogl_texture_get_format. This happens for example with atlas textures which report the original internal format specified when the texture was created but actually always store the data in an RGBA texture. Also when creating an atlas texture from a bitmap it was preparing the bitmap to be uploaded to the original format instead of the format of the actual texture used for the atlas. Then it was using cogl_texture_set_region_from_bitmap to upload the 5 pieces to make the copies of the edge pixels. This would end up converting the image to the actual format 5 times. The atlas textures have now been changed to prepare the bitmap for the right format. https://bugzilla.gnome.org/show_bug.cgi?id=657840 Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
parent
5ac563afdb
commit
503f138fb6
@ -488,6 +488,52 @@ _cogl_atlas_texture_set_region_with_border (CoglAtlasTexture *atlas_tex,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglBitmap *
|
||||
_cogl_atlas_texture_prepare_for_upload (CoglAtlasTexture *atlas_tex,
|
||||
CoglBitmap *bmp)
|
||||
{
|
||||
CoglPixelFormat internal_format;
|
||||
CoglBitmap *converted_bmp;
|
||||
CoglBitmap *override_bmp;
|
||||
|
||||
/* We'll prepare to upload using the format of the actual texture of
|
||||
the atlas texture instead of the format reported by
|
||||
cogl_texture_get_format which would be the original internal
|
||||
format specified when the texture was created. However we'll
|
||||
preserve the premult status of the internal format because the
|
||||
images are all stored in the original premult format of the
|
||||
orignal format so we do need to trigger the conversion */
|
||||
|
||||
internal_format = (COGL_PIXEL_FORMAT_RGBA_8888 |
|
||||
(atlas_tex->format & COGL_PREMULT_BIT));
|
||||
|
||||
converted_bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||
internal_format,
|
||||
NULL, /* dst_format_out */
|
||||
NULL, /* glintformat */
|
||||
NULL, /* glformat */
|
||||
NULL /* gltype */);
|
||||
|
||||
if (converted_bmp == NULL)
|
||||
return NULL;
|
||||
|
||||
/* We'll create another bitmap which uses the same data but
|
||||
overrides the format to remove the premult flag so that uploads
|
||||
to the atlas texture won't trigger the conversion again */
|
||||
|
||||
override_bmp =
|
||||
_cogl_bitmap_new_shared (converted_bmp,
|
||||
_cogl_bitmap_get_format (converted_bmp) &
|
||||
~COGL_PREMULT_BIT,
|
||||
_cogl_bitmap_get_width (converted_bmp),
|
||||
_cogl_bitmap_get_height (converted_bmp),
|
||||
_cogl_bitmap_get_rowstride (converted_bmp));
|
||||
|
||||
cogl_object_unref (converted_bmp);
|
||||
|
||||
return override_bmp;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_atlas_texture_set_region (CoglTexture *tex,
|
||||
int src_x,
|
||||
@ -506,12 +552,8 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
|
||||
{
|
||||
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));
|
||||
bmp = _cogl_atlas_texture_prepare_for_upload (atlas_tex,
|
||||
bmp);
|
||||
|
||||
/* Upload the data ignoring the premult bit */
|
||||
ret = _cogl_atlas_texture_set_region_with_border (atlas_tex,
|
||||
@ -684,10 +726,6 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
|
||||
CoglHandle atlas_tex_handle;
|
||||
CoglAtlasTexture *atlas_tex;
|
||||
CoglBitmap *dst_bmp;
|
||||
CoglBitmap *override_bmp;
|
||||
GLenum gl_intformat;
|
||||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
int bmp_width;
|
||||
int bmp_height;
|
||||
CoglPixelFormat bmp_format;
|
||||
@ -711,12 +749,8 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
|
||||
|
||||
atlas_tex = atlas_tex_handle;
|
||||
|
||||
dst_bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||
internal_format,
|
||||
&internal_format,
|
||||
&gl_intformat,
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
dst_bmp = _cogl_atlas_texture_prepare_for_upload (atlas_tex,
|
||||
bmp);
|
||||
|
||||
if (dst_bmp == NULL)
|
||||
{
|
||||
@ -724,19 +758,8 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
|
||||
return COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* 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
|
||||
edge pixels to the border. We don't want to pass the actual
|
||||
format of the converted texture because otherwise it will get
|
||||
unpremultiplied. */
|
||||
edge pixels to the border. */
|
||||
_cogl_atlas_texture_set_region_with_border (atlas_tex,
|
||||
0, /* src_x */
|
||||
0, /* src_y */
|
||||
@ -744,9 +767,9 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
|
||||
0, /* dst_y */
|
||||
bmp_width, /* dst_width */
|
||||
bmp_height, /* dst_height */
|
||||
override_bmp);
|
||||
dst_bmp);
|
||||
|
||||
cogl_object_unref (override_bmp);
|
||||
cogl_object_unref (dst_bmp);
|
||||
|
||||
return atlas_tex_handle;
|
||||
}
|
||||
|
@ -1325,10 +1325,12 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex,
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
ctx->texture_driver->pixel_format_to_gl (_cogl_bitmap_get_format (bmp),
|
||||
NULL, /* internal format */
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||
cogl_texture_get_format (tex),
|
||||
NULL,
|
||||
NULL,
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
/* Send data to GL */
|
||||
_cogl_texture_2d_sliced_upload_subregion_to_gl (tex_2ds,
|
||||
@ -1339,6 +1341,8 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex,
|
||||
gl_format,
|
||||
gl_type);
|
||||
|
||||
cogl_object_unref (bmp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -816,10 +816,12 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
ctx->texture_driver->pixel_format_to_gl (_cogl_bitmap_get_format (bmp),
|
||||
NULL, /* internal format */
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||
cogl_texture_get_format (tex),
|
||||
NULL,
|
||||
NULL,
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
/* If this touches the first pixel then we'll update our copy */
|
||||
if (dst_x == 0 && dst_y == 0 &&
|
||||
@ -850,6 +852,8 @@ _cogl_texture_2d_set_region (CoglTexture *tex,
|
||||
|
||||
tex_2d->mipmaps_dirty = TRUE;
|
||||
|
||||
cogl_object_unref (bmp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -67,8 +67,10 @@ struct _CoglTextureVtable
|
||||
backend */
|
||||
|
||||
/* This should update the specified sub region of the texture with a
|
||||
sub region of the given bitmap. The bitmap will have first been
|
||||
converted to a suitable format for uploading if neccessary. */
|
||||
sub region of the given bitmap. The bitmap is not converted
|
||||
before being passed so the implementation is expected to call
|
||||
_cogl_texture_prepare_for_upload with a suitable destination
|
||||
format before uploading */
|
||||
gboolean (* set_region) (CoglTexture *tex,
|
||||
int src_x,
|
||||
int src_y,
|
||||
|
@ -564,10 +564,12 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex,
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
ctx->texture_driver->pixel_format_to_gl (_cogl_bitmap_get_format (bmp),
|
||||
NULL, /* internal format */
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||
cogl_texture_get_format (tex),
|
||||
NULL,
|
||||
NULL,
|
||||
&gl_format,
|
||||
&gl_type);
|
||||
|
||||
/* Send data to GL */
|
||||
ctx->texture_driver->upload_subregion_to_gl (GL_TEXTURE_RECTANGLE_ARB,
|
||||
@ -580,6 +582,8 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex,
|
||||
gl_format,
|
||||
gl_type);
|
||||
|
||||
cogl_object_unref (bmp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -862,22 +862,18 @@ cogl_texture_set_region_from_bitmap (CoglHandle handle,
|
||||
CoglBitmap *bmp)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (handle);
|
||||
GLenum closest_gl_format;
|
||||
GLenum closest_gl_type;
|
||||
gboolean ret;
|
||||
|
||||
/* Shortcut out early if the image is empty */
|
||||
if (dst_width == 0 || dst_height == 0)
|
||||
return TRUE;
|
||||
|
||||
/* Prepare the bitmap so that it will do the premultiplication
|
||||
conversion */
|
||||
bmp = _cogl_texture_prepare_for_upload (bmp,
|
||||
cogl_texture_get_format (handle),
|
||||
NULL,
|
||||
NULL,
|
||||
&closest_gl_format,
|
||||
&closest_gl_type);
|
||||
/* Note that we don't prepare the bitmap for upload here because
|
||||
some backends may be internally using a different format for the
|
||||
actual GL texture than that reported by
|
||||
cogl_texture_get_format. For example the atlas textures are
|
||||
always stored in an RGBA texture even if the texture format is
|
||||
advertised as RGB. */
|
||||
|
||||
ret = tex->vtable->set_region (handle,
|
||||
src_x, src_y,
|
||||
@ -885,8 +881,6 @@ cogl_texture_set_region_from_bitmap (CoglHandle handle,
|
||||
dst_width, dst_height,
|
||||
bmp);
|
||||
|
||||
cogl_object_unref (bmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user