introduce texture loaders to make allocations lazy
This introduces the internal idea of texture loaders that track the state for loading and allocating a texture. This defers a lot more work until the texture is allocated. There are several intentions to this change: - provides a means for extending how textures are allocated without requiring all the parameters to be supplied in a single _texture_new() function call. - allow us to remove the internal_format argument from all _texture_new() apis since using CoglPixelFormat is bad way of expressing the internal format constraints because it is too specific. For now the internal_format arguments haven't actually been removed but this patch does introduce replacement apis for controlling the internal format: cogl_texture_set_components() lets you specify what components your texture needs when it is allocated. cogl_texture_set_premultiplied() lets you specify whether a texture data should be interpreted as premultiplied or not. - Enable us to support asynchronous texture loading + allocation in the future. Of note, the _new_from_data() texture constructors all continue to allocate textures immediately so that existing code doesn't need to be adapted to manage the lifetime of the data being uploaded. Reviewed-by: Neil Roberts <neil@linux.intel.com> (cherry picked from commit 6a83de9ef4210f380a31f410797447b365a8d02c) Note: Compared to the original patch, the ->premultipled state for textures isn't forced to be %TRUE in _cogl_texture_init since that effectively ignores the users explicitly given internal_format which was a mistake and on master that change should have been made in the patch that followed. The gtk-doc comments for cogl_texture_set_premultiplied() and cogl_texture_set_components() have also been updated in-line with this fix.
This commit is contained in:
parent
3f780e2f3f
commit
cbd6951134
@ -37,7 +37,7 @@ struct _CoglAtlasTexture
|
|||||||
/* The format that the texture is in. This isn't necessarily the
|
/* The format that the texture is in. This isn't necessarily the
|
||||||
same format as the atlas texture because we can store
|
same format as the atlas texture because we can store
|
||||||
pre-multiplied and non-pre-multiplied textures together */
|
pre-multiplied and non-pre-multiplied textures together */
|
||||||
CoglPixelFormat format;
|
CoglPixelFormat internal_format;
|
||||||
|
|
||||||
/* The rectangle that was used to add this texture to the
|
/* The rectangle that was used to add this texture to the
|
||||||
atlas. This includes the 1-pixel border */
|
atlas. This includes the 1-pixel border */
|
||||||
|
@ -384,7 +384,7 @@ _cogl_atlas_texture_migrate_out_of_atlas (CoglAtlasTexture *atlas_tex)
|
|||||||
atlas_tex->rectangle.y + 1,
|
atlas_tex->rectangle.y + 1,
|
||||||
atlas_tex->rectangle.width - 2,
|
atlas_tex->rectangle.width - 2,
|
||||||
atlas_tex->rectangle.height - 2,
|
atlas_tex->rectangle.height - 2,
|
||||||
atlas_tex->format);
|
atlas_tex->internal_format);
|
||||||
/* Note: we simply silently ignore failures to migrate a texture
|
/* Note: we simply silently ignore failures to migrate a texture
|
||||||
* out (most likely due to lack of memory) and hope for the
|
* out (most likely due to lack of memory) and hope for the
|
||||||
* best.
|
* best.
|
||||||
@ -515,10 +515,10 @@ _cogl_atlas_texture_set_region_with_border (CoglAtlasTexture *atlas_tex,
|
|||||||
static CoglBitmap *
|
static CoglBitmap *
|
||||||
_cogl_atlas_texture_convert_bitmap_for_upload (CoglAtlasTexture *atlas_tex,
|
_cogl_atlas_texture_convert_bitmap_for_upload (CoglAtlasTexture *atlas_tex,
|
||||||
CoglBitmap *bmp,
|
CoglBitmap *bmp,
|
||||||
|
CoglPixelFormat internal_format,
|
||||||
CoglBool can_convert_in_place,
|
CoglBool can_convert_in_place,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglPixelFormat internal_format;
|
|
||||||
CoglBitmap *upload_bmp;
|
CoglBitmap *upload_bmp;
|
||||||
CoglBitmap *override_bmp;
|
CoglBitmap *override_bmp;
|
||||||
|
|
||||||
@ -531,7 +531,7 @@ _cogl_atlas_texture_convert_bitmap_for_upload (CoglAtlasTexture *atlas_tex,
|
|||||||
orignal format so we do need to trigger the conversion */
|
orignal format so we do need to trigger the conversion */
|
||||||
|
|
||||||
internal_format = (COGL_PIXEL_FORMAT_RGBA_8888 |
|
internal_format = (COGL_PIXEL_FORMAT_RGBA_8888 |
|
||||||
(atlas_tex->format & COGL_PREMULT_BIT));
|
(internal_format & COGL_PREMULT_BIT));
|
||||||
|
|
||||||
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
|
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
|
||||||
internal_format,
|
internal_format,
|
||||||
@ -582,6 +582,7 @@ _cogl_atlas_texture_set_region (CoglTexture *tex,
|
|||||||
CoglBitmap *upload_bmp =
|
CoglBitmap *upload_bmp =
|
||||||
_cogl_atlas_texture_convert_bitmap_for_upload (atlas_tex,
|
_cogl_atlas_texture_convert_bitmap_for_upload (atlas_tex,
|
||||||
bmp,
|
bmp,
|
||||||
|
atlas_tex->internal_format,
|
||||||
FALSE, /* can't convert
|
FALSE, /* can't convert
|
||||||
in place */
|
in place */
|
||||||
error);
|
error);
|
||||||
@ -619,7 +620,7 @@ _cogl_atlas_texture_get_format (CoglTexture *tex)
|
|||||||
/* We don't want to forward this on the sub-texture because it isn't
|
/* We don't want to forward this on the sub-texture because it isn't
|
||||||
the necessarily the same format. This will happen if the texture
|
the necessarily the same format. This will happen if the texture
|
||||||
isn't pre-multiplied */
|
isn't pre-multiplied */
|
||||||
return atlas_tex->format;
|
return atlas_tex->internal_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLenum
|
static GLenum
|
||||||
@ -645,24 +646,20 @@ _cogl_atlas_texture_can_use_format (CoglPixelFormat format)
|
|||||||
format == COGL_PIXEL_FORMAT_RGBA_8888);
|
format == COGL_PIXEL_FORMAT_RGBA_8888);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglAtlasTexture *
|
static CoglAtlasTexture *
|
||||||
cogl_atlas_texture_new_with_size (CoglContext *ctx,
|
_cogl_atlas_texture_create_base (CoglContext *ctx,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
CoglPixelFormat internal_format,
|
CoglPixelFormat internal_format,
|
||||||
CoglError **error)
|
CoglTextureLoader *loader)
|
||||||
{
|
{
|
||||||
CoglAtlasTexture *atlas_tex;
|
CoglAtlasTexture *atlas_tex;
|
||||||
|
|
||||||
/* We can't atlas zero-sized textures because it breaks the atlas
|
|
||||||
* data structure */
|
|
||||||
_COGL_RETURN_VAL_IF_FAIL (width > 0 && height > 0, NULL);
|
|
||||||
|
|
||||||
COGL_NOTE (ATLAS, "Adding texture of size %ix%i", width, height);
|
COGL_NOTE (ATLAS, "Adding texture of size %ix%i", width, height);
|
||||||
|
|
||||||
/* We need to allocate the texture now because we need the pointer
|
/* We need to allocate the texture now because we need the pointer
|
||||||
to set as the data for the rectangle in the atlas */
|
to set as the data for the rectangle in the atlas */
|
||||||
atlas_tex = g_new (CoglAtlasTexture, 1);
|
atlas_tex = g_new0 (CoglAtlasTexture, 1);
|
||||||
/* Mark it as having no atlas so we don't try to unref it in
|
/* Mark it as having no atlas so we don't try to unref it in
|
||||||
_cogl_atlas_texture_post_reorganize_cb */
|
_cogl_atlas_texture_post_reorganize_cb */
|
||||||
atlas_tex->atlas = NULL;
|
atlas_tex->atlas = NULL;
|
||||||
@ -670,27 +667,53 @@ cogl_atlas_texture_new_with_size (CoglContext *ctx,
|
|||||||
_cogl_texture_init (COGL_TEXTURE (atlas_tex),
|
_cogl_texture_init (COGL_TEXTURE (atlas_tex),
|
||||||
ctx,
|
ctx,
|
||||||
width, height,
|
width, height,
|
||||||
|
internal_format,
|
||||||
|
loader,
|
||||||
&cogl_atlas_texture_vtable);
|
&cogl_atlas_texture_vtable);
|
||||||
|
|
||||||
atlas_tex->sub_texture = NULL;
|
atlas_tex->sub_texture = NULL;
|
||||||
|
|
||||||
atlas_tex->format = internal_format;
|
|
||||||
atlas_tex->atlas = NULL;
|
atlas_tex->atlas = NULL;
|
||||||
|
|
||||||
return _cogl_atlas_texture_object_new (atlas_tex);
|
return _cogl_atlas_texture_object_new (atlas_tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglBool
|
CoglAtlasTexture *
|
||||||
_cogl_atlas_texture_allocate (CoglTexture *tex,
|
cogl_atlas_texture_new_with_size (CoglContext *ctx,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
CoglPixelFormat internal_format,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
|
/* We can't atlas zero-sized textures because it breaks the atlas
|
||||||
|
* data structure */
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (width > 0 && height > 0, NULL);
|
||||||
|
|
||||||
|
loader = _cogl_texture_create_loader ();
|
||||||
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED;
|
||||||
|
loader->src.sized.width = width;
|
||||||
|
loader->src.sized.height = height;
|
||||||
|
|
||||||
|
return _cogl_atlas_texture_create_base (ctx, width, height,
|
||||||
|
internal_format, loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
allocate_space (CoglAtlasTexture *atlas_tex,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
CoglPixelFormat internal_format,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (atlas_tex);
|
||||||
CoglContext *ctx = tex->context;
|
CoglContext *ctx = tex->context;
|
||||||
CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
|
|
||||||
CoglAtlas *atlas;
|
CoglAtlas *atlas;
|
||||||
GSList *l;
|
GSList *l;
|
||||||
|
|
||||||
/* If the texture is in a strange format then we won't use it */
|
/* If the texture is in a strange format then we won't use it */
|
||||||
if (!_cogl_atlas_texture_can_use_format (atlas_tex->format))
|
if (!_cogl_atlas_texture_can_use_format (internal_format))
|
||||||
{
|
{
|
||||||
COGL_NOTE (ATLAS, "Texture can not be added because the "
|
COGL_NOTE (ATLAS, "Texture can not be added because the "
|
||||||
"format is unsupported");
|
"format is unsupported");
|
||||||
@ -718,7 +741,7 @@ _cogl_atlas_texture_allocate (CoglTexture *tex,
|
|||||||
/* 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_reserve_space (atlas = l->data,
|
if (_cogl_atlas_reserve_space (atlas = l->data,
|
||||||
/* Add two pixels for the border */
|
/* Add two pixels for the border */
|
||||||
tex->width + 2, tex->height + 2,
|
width + 2, height + 2,
|
||||||
atlas_tex))
|
atlas_tex))
|
||||||
{
|
{
|
||||||
cogl_object_ref (atlas);
|
cogl_object_ref (atlas);
|
||||||
@ -732,7 +755,7 @@ _cogl_atlas_texture_allocate (CoglTexture *tex,
|
|||||||
COGL_NOTE (ATLAS, "Created new atlas for textures: %p", atlas);
|
COGL_NOTE (ATLAS, "Created new atlas for textures: %p", atlas);
|
||||||
if (!_cogl_atlas_reserve_space (atlas,
|
if (!_cogl_atlas_reserve_space (atlas,
|
||||||
/* Add two pixels for the border */
|
/* Add two pixels for the border */
|
||||||
tex->width + 2, tex->height + 2,
|
width + 2, height + 2,
|
||||||
atlas_tex))
|
atlas_tex))
|
||||||
{
|
{
|
||||||
/* Ok, this means we really can't add it to the atlas */
|
/* Ok, this means we really can't add it to the atlas */
|
||||||
@ -746,55 +769,73 @@ _cogl_atlas_texture_allocate (CoglTexture *tex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atlas_tex->internal_format = internal_format;
|
||||||
|
|
||||||
atlas_tex->atlas = atlas;
|
atlas_tex->atlas = atlas;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglAtlasTexture *
|
static CoglBool
|
||||||
_cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
|
allocate_with_size (CoglAtlasTexture *atlas_tex,
|
||||||
CoglPixelFormat internal_format,
|
CoglTextureLoader *loader,
|
||||||
CoglBool can_convert_in_place,
|
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglContext *ctx = _cogl_bitmap_get_context (bmp);
|
CoglTexture *tex = COGL_TEXTURE (atlas_tex);
|
||||||
CoglAtlasTexture *atlas_tex;
|
CoglPixelFormat internal_format =
|
||||||
CoglBitmap *upload_bmp;
|
_cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY);
|
||||||
int bmp_width;
|
|
||||||
int bmp_height;
|
|
||||||
CoglPixelFormat bmp_format;
|
|
||||||
|
|
||||||
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
|
if (allocate_space (atlas_tex,
|
||||||
|
loader->src.sized.width,
|
||||||
bmp_width = cogl_bitmap_get_width (bmp);
|
loader->src.sized.height,
|
||||||
bmp_height = cogl_bitmap_get_height (bmp);
|
|
||||||
bmp_format = cogl_bitmap_get_format (bmp);
|
|
||||||
|
|
||||||
internal_format = _cogl_texture_determine_internal_format (bmp_format,
|
|
||||||
internal_format);
|
|
||||||
|
|
||||||
atlas_tex = cogl_atlas_texture_new_with_size (ctx,
|
|
||||||
bmp_width, bmp_height,
|
|
||||||
internal_format,
|
internal_format,
|
||||||
error);
|
error))
|
||||||
if (!atlas_tex)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!cogl_texture_allocate (COGL_TEXTURE (atlas_tex), error))
|
|
||||||
{
|
{
|
||||||
cogl_object_unref (atlas_tex);
|
_cogl_texture_set_allocated (COGL_TEXTURE (atlas_tex),
|
||||||
return NULL;
|
internal_format,
|
||||||
|
loader->src.sized.width,
|
||||||
|
loader->src.sized.height);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
allocate_from_bitmap (CoglAtlasTexture *atlas_tex,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (atlas_tex);
|
||||||
|
CoglBitmap *bmp = loader->src.bitmap.bitmap;
|
||||||
|
CoglPixelFormat bmp_format = cogl_bitmap_get_format (bmp);
|
||||||
|
int width = cogl_bitmap_get_width (bmp);
|
||||||
|
int height = cogl_bitmap_get_height (bmp);
|
||||||
|
CoglBool can_convert_in_place = loader->src.bitmap.can_convert_in_place;
|
||||||
|
CoglPixelFormat internal_format;
|
||||||
|
CoglBitmap *upload_bmp;
|
||||||
|
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (atlas_tex->atlas == NULL, FALSE);
|
||||||
|
|
||||||
|
internal_format = _cogl_texture_determine_internal_format (tex, bmp_format);
|
||||||
|
|
||||||
upload_bmp =
|
upload_bmp =
|
||||||
_cogl_atlas_texture_convert_bitmap_for_upload (atlas_tex,
|
_cogl_atlas_texture_convert_bitmap_for_upload (atlas_tex,
|
||||||
bmp,
|
bmp,
|
||||||
|
internal_format,
|
||||||
can_convert_in_place,
|
can_convert_in_place,
|
||||||
error);
|
error);
|
||||||
if (upload_bmp == NULL)
|
if (upload_bmp == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!allocate_space (atlas_tex,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
internal_format,
|
||||||
|
error))
|
||||||
{
|
{
|
||||||
cogl_object_unref (atlas_tex);
|
cogl_object_unref (upload_bmp);
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
@ -804,19 +845,65 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
|
|||||||
0, /* src_y */
|
0, /* src_y */
|
||||||
0, /* dst_x */
|
0, /* dst_x */
|
||||||
0, /* dst_y */
|
0, /* dst_y */
|
||||||
bmp_width, /* dst_width */
|
width, /* dst_width */
|
||||||
bmp_height, /* dst_height */
|
height, /* dst_height */
|
||||||
upload_bmp,
|
upload_bmp,
|
||||||
error))
|
error))
|
||||||
{
|
{
|
||||||
|
_cogl_atlas_texture_remove_from_atlas (atlas_tex);
|
||||||
cogl_object_unref (upload_bmp);
|
cogl_object_unref (upload_bmp);
|
||||||
cogl_object_unref (atlas_tex);
|
return FALSE;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_object_unref (upload_bmp);
|
cogl_object_unref (upload_bmp);
|
||||||
|
|
||||||
return atlas_tex;
|
_cogl_texture_set_allocated (tex, internal_format, width, height);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
_cogl_atlas_texture_allocate (CoglTexture *tex,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
|
||||||
|
CoglTextureLoader *loader = tex->loader;
|
||||||
|
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (loader, FALSE);
|
||||||
|
|
||||||
|
switch (loader->src_type)
|
||||||
|
{
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_SIZED:
|
||||||
|
return allocate_with_size (atlas_tex, loader, error);
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_BITMAP:
|
||||||
|
return allocate_from_bitmap (atlas_tex, loader, error);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglAtlasTexture *
|
||||||
|
_cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
|
||||||
|
CoglPixelFormat internal_format,
|
||||||
|
CoglBool can_convert_in_place,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
|
||||||
|
|
||||||
|
loader = _cogl_texture_create_loader ();
|
||||||
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_BITMAP;
|
||||||
|
loader->src.bitmap.bitmap = cogl_object_ref (bmp);
|
||||||
|
loader->src.bitmap.can_convert_in_place = can_convert_in_place;
|
||||||
|
|
||||||
|
return _cogl_atlas_texture_create_base (_cogl_bitmap_get_context (bmp),
|
||||||
|
cogl_bitmap_get_width (bmp),
|
||||||
|
cogl_bitmap_get_height (bmp),
|
||||||
|
internal_format,
|
||||||
|
loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglAtlasTexture *
|
CoglAtlasTexture *
|
||||||
@ -859,6 +946,13 @@ cogl_atlas_texture_new_from_data (CoglContext *ctx,
|
|||||||
|
|
||||||
cogl_object_unref (bmp);
|
cogl_object_unref (bmp);
|
||||||
|
|
||||||
|
if (atlas_tex &&
|
||||||
|
!cogl_texture_allocate (COGL_TEXTURE (atlas_tex), error))
|
||||||
|
{
|
||||||
|
cogl_object_unref (atlas_tex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return atlas_tex;
|
return atlas_tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +78,11 @@ typedef struct _CoglAtlasTexture CoglAtlasTexture;
|
|||||||
* allocate the underlying storage or let Cogl automatically allocate
|
* allocate the underlying storage or let Cogl automatically allocate
|
||||||
* storage lazily.
|
* storage lazily.
|
||||||
*
|
*
|
||||||
|
* The texture is still configurable until it has been allocated so
|
||||||
|
* for example you can influence the internal format of the texture
|
||||||
|
* using cogl_texture_set_components() and
|
||||||
|
* cogl_texture_set_premultiplied().
|
||||||
|
*
|
||||||
* <note>This call can fail if Cogl considers the given
|
* <note>This call can fail if Cogl considers the given
|
||||||
* @internal_format incompatible with the format of its internal
|
* @internal_format incompatible with the format of its internal
|
||||||
* atlases.</note>
|
* atlases.</note>
|
||||||
@ -109,7 +114,17 @@ cogl_atlas_texture_new_with_size (CoglContext *ctx,
|
|||||||
* represents a sub-region within one of Cogl's shared texture
|
* represents a sub-region within one of Cogl's shared texture
|
||||||
* atlases.
|
* atlases.
|
||||||
*
|
*
|
||||||
* <note>This call can fail if Cogl considers the given
|
* The storage for the texture is not allocated before this function
|
||||||
|
* returns. You can call cogl_texture_allocate() to explicitly
|
||||||
|
* allocate the underlying storage or let Cogl automatically allocate
|
||||||
|
* storage lazily.
|
||||||
|
*
|
||||||
|
* The texture is still configurable until it has been allocated so
|
||||||
|
* for example you can influence the internal format of the texture
|
||||||
|
* using cogl_texture_set_components() and
|
||||||
|
* cogl_texture_set_premultiplied().
|
||||||
|
*
|
||||||
|
* <note>Allocation can fail later if Cogl considers the given
|
||||||
* @internal_format incompatible with the format of its internal
|
* @internal_format incompatible with the format of its internal
|
||||||
* atlases.</note>
|
* atlases.</note>
|
||||||
*
|
*
|
||||||
@ -152,7 +167,18 @@ cogl_atlas_texture_new_from_file (CoglContext *ctx,
|
|||||||
* memory. A #CoglAtlasTexture represents a sub-region within one of
|
* memory. A #CoglAtlasTexture represents a sub-region within one of
|
||||||
* Cogl's shared texture atlases.
|
* Cogl's shared texture atlases.
|
||||||
*
|
*
|
||||||
* <note>This call can fail if Cogl considers the given
|
* <note>This api will always immediately allocate GPU memory for the
|
||||||
|
* texture and upload the given data so that the @data pointer does
|
||||||
|
* not need to remain valid once this function returns. This means it
|
||||||
|
* is not possible to configure the texture before it is allocated. If
|
||||||
|
* you do need to configure the texture before allocation (to specify
|
||||||
|
* constraints on the internal format for example) then you can
|
||||||
|
* instead create a #CoglBitmap for your data and use
|
||||||
|
* cogl_atlas_texture_new_from_bitmap() or use
|
||||||
|
* cogl_atlas_texture_new_with_size() and then upload data using
|
||||||
|
* cogl_texture_set_data()</note>
|
||||||
|
*
|
||||||
|
* <note>Allocation can fail if Cogl considers the given
|
||||||
* @internal_format incompatible with the format of its internal
|
* @internal_format incompatible with the format of its internal
|
||||||
* atlases.</note>
|
* atlases.</note>
|
||||||
*
|
*
|
||||||
@ -192,7 +218,18 @@ cogl_atlas_texture_new_from_data (CoglContext *ctx,
|
|||||||
* @bitmap. A #CoglAtlasTexture represents a sub-region within one of
|
* @bitmap. A #CoglAtlasTexture represents a sub-region within one of
|
||||||
* Cogl's shared texture atlases.
|
* Cogl's shared texture atlases.
|
||||||
*
|
*
|
||||||
* <note>This call can fail if Cogl considers the given
|
* The storage for the texture is not allocated before this function
|
||||||
|
* returns. You can call cogl_texture_allocate() to explicitly
|
||||||
|
* allocate the underlying storage or preferably let Cogl
|
||||||
|
* automatically allocate storage lazily when it may know more about
|
||||||
|
* how the texture is being used and can optimize how it is allocated.
|
||||||
|
*
|
||||||
|
* The texture is still configurable until it has been allocated so
|
||||||
|
* for example you can influence the internal format of the texture
|
||||||
|
* using cogl_texture_set_components() and
|
||||||
|
* cogl_texture_set_premultiplied().
|
||||||
|
*
|
||||||
|
* <note>Allocation can fail if Cogl considers the given
|
||||||
* @internal_format incompatible with the format of its internal
|
* @internal_format incompatible with the format of its internal
|
||||||
* atlases.</note>
|
* atlases.</note>
|
||||||
*
|
*
|
||||||
|
@ -135,8 +135,8 @@ cogl_context_new (CoglDisplay *display,
|
|||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglContext *context;
|
CoglContext *context;
|
||||||
uint8_t default_texture_data[] = { 0xff, 0xff, 0xff, 0xff };
|
uint8_t white_pixel[] = { 0xff, 0xff, 0xff, 0xff };
|
||||||
CoglBitmap *default_texture_bitmap;
|
CoglBitmap *white_pixel_bitmap;
|
||||||
const CoglWinsysVtable *winsys;
|
const CoglWinsysVtable *winsys;
|
||||||
int i;
|
int i;
|
||||||
CoglError *internal_error = NULL;
|
CoglError *internal_error = NULL;
|
||||||
@ -429,41 +429,53 @@ cogl_context_new (CoglDisplay *display,
|
|||||||
_cogl_matrix_entry_cache_init (&context->builtin_flushed_projection);
|
_cogl_matrix_entry_cache_init (&context->builtin_flushed_projection);
|
||||||
_cogl_matrix_entry_cache_init (&context->builtin_flushed_modelview);
|
_cogl_matrix_entry_cache_init (&context->builtin_flushed_modelview);
|
||||||
|
|
||||||
default_texture_bitmap =
|
|
||||||
cogl_bitmap_new_for_data (context,
|
|
||||||
1, 1, /* width/height */
|
|
||||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
|
||||||
4, /* rowstride */
|
|
||||||
default_texture_data);
|
|
||||||
|
|
||||||
/* Create default textures used for fall backs */
|
/* Create default textures used for fall backs */
|
||||||
context->default_gl_texture_2d_tex =
|
context->default_gl_texture_2d_tex =
|
||||||
cogl_texture_2d_new_from_bitmap (default_texture_bitmap,
|
cogl_texture_2d_new_from_data (context,
|
||||||
/* internal format */
|
1, 1,
|
||||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
NULL);
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
|
0, /* rowstride */
|
||||||
|
white_pixel,
|
||||||
|
NULL); /* abort on error */
|
||||||
|
|
||||||
/* If 3D or rectangle textures aren't supported then these will
|
/* If 3D or rectangle textures aren't supported then these will
|
||||||
* return errors that we can simply ignore. */
|
* return errors that we can simply ignore. */
|
||||||
internal_error = NULL;
|
internal_error = NULL;
|
||||||
context->default_gl_texture_3d_tex =
|
context->default_gl_texture_3d_tex =
|
||||||
cogl_texture_3d_new_from_bitmap (default_texture_bitmap,
|
cogl_texture_3d_new_from_data (context,
|
||||||
1, /* height */
|
1, 1, 1, /* width, height, depth */
|
||||||
1, /* depth */
|
|
||||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
|
0, /* rowstride */
|
||||||
|
0, /* image stride */
|
||||||
|
white_pixel,
|
||||||
&internal_error);
|
&internal_error);
|
||||||
if (internal_error)
|
if (internal_error)
|
||||||
cogl_error_free (internal_error);
|
cogl_error_free (internal_error);
|
||||||
|
|
||||||
|
/* TODO: add cogl_texture_rectangle_new_from_data() */
|
||||||
|
white_pixel_bitmap =
|
||||||
|
cogl_bitmap_new_for_data (context,
|
||||||
|
1, 1, /* width/height */
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
|
4, /* rowstride */
|
||||||
|
white_pixel);
|
||||||
|
|
||||||
internal_error = NULL;
|
internal_error = NULL;
|
||||||
context->default_gl_texture_rect_tex =
|
context->default_gl_texture_rect_tex =
|
||||||
cogl_texture_rectangle_new_from_bitmap (default_texture_bitmap,
|
cogl_texture_rectangle_new_from_bitmap (white_pixel_bitmap,
|
||||||
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
|
NULL); /* legacy error argument */
|
||||||
|
|
||||||
|
/* XXX: we need to allocate the texture now because the white_pixel
|
||||||
|
* data is on the stack */
|
||||||
|
cogl_texture_allocate (COGL_TEXTURE (context->default_gl_texture_rect_tex),
|
||||||
&internal_error);
|
&internal_error);
|
||||||
if (internal_error)
|
if (internal_error)
|
||||||
cogl_error_free (internal_error);
|
cogl_error_free (internal_error);
|
||||||
|
|
||||||
cogl_object_unref (default_texture_bitmap);
|
cogl_object_unref (white_pixel_bitmap);
|
||||||
|
|
||||||
cogl_push_source (context->opaque_color_pipeline);
|
cogl_push_source (context->opaque_color_pipeline);
|
||||||
|
|
||||||
|
@ -141,31 +141,6 @@ struct _CoglDriverVtable
|
|||||||
(* texture_2d_allocate) (CoglTexture *tex,
|
(* texture_2d_allocate) (CoglTexture *tex,
|
||||||
CoglError **error);
|
CoglError **error);
|
||||||
|
|
||||||
/* Instantiates a new CoglTexture2D object with storage initialized
|
|
||||||
* with the contents of the given bitmap, using the specified
|
|
||||||
* internal format.
|
|
||||||
*/
|
|
||||||
CoglTexture2D *
|
|
||||||
(* texture_2d_new_from_bitmap) (CoglBitmap *bmp,
|
|
||||||
CoglPixelFormat internal_format,
|
|
||||||
CoglBool can_convert_in_place,
|
|
||||||
CoglError **error);
|
|
||||||
|
|
||||||
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
|
||||||
/* Instantiates a new CoglTexture2D object with storage initialized
|
|
||||||
* with the contents of the given EGL image.
|
|
||||||
*
|
|
||||||
* This is optional for drivers to support
|
|
||||||
*/
|
|
||||||
CoglTexture2D *
|
|
||||||
(* egl_texture_2d_new_from_image) (CoglContext *ctx,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
CoglPixelFormat format,
|
|
||||||
EGLImageKHR image,
|
|
||||||
CoglError **error);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Initialize the specified region of storage of the given texture
|
/* Initialize the specified region of storage of the given texture
|
||||||
* with the contents of the specified framebuffer region
|
* with the contents of the specified framebuffer region
|
||||||
*/
|
*/
|
||||||
|
@ -235,6 +235,8 @@ cogl_sub_texture_new (CoglContext *ctx,
|
|||||||
tex = COGL_TEXTURE (sub_tex);
|
tex = COGL_TEXTURE (sub_tex);
|
||||||
|
|
||||||
_cogl_texture_init (tex, ctx, sub_width, sub_height,
|
_cogl_texture_init (tex, ctx, sub_width, sub_height,
|
||||||
|
_cogl_texture_get_format (next_texture),
|
||||||
|
NULL, /* no loader */
|
||||||
&cogl_sub_texture_vtable);
|
&cogl_sub_texture_vtable);
|
||||||
|
|
||||||
/* If the next texture is also a sub texture we can avoid one level
|
/* If the next texture is also a sub texture we can avoid one level
|
||||||
@ -264,8 +266,13 @@ _cogl_sub_texture_allocate (CoglTexture *tex,
|
|||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
|
CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
|
||||||
|
CoglBool status = cogl_texture_allocate (sub_tex->full_texture, error);
|
||||||
|
|
||||||
return cogl_texture_allocate (sub_tex->full_texture, error);
|
_cogl_texture_set_allocated (tex,
|
||||||
|
_cogl_texture_get_format (sub_tex->full_texture),
|
||||||
|
tex->width, tex->height);
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTexture *
|
CoglTexture *
|
||||||
|
@ -49,6 +49,10 @@ COGL_BEGIN_DECLS
|
|||||||
* This can be used for integrating Cogl with software using OpenGL
|
* This can be used for integrating Cogl with software using OpenGL
|
||||||
* directly.
|
* directly.
|
||||||
*
|
*
|
||||||
|
* The texture is still configurable until it has been allocated so
|
||||||
|
* for example you can declare whether the texture is premultiplied
|
||||||
|
* with cogl_texture_set_premultiplied().
|
||||||
|
*
|
||||||
* <note>The results are undefined for passing an invalid @gl_handle
|
* <note>The results are undefined for passing an invalid @gl_handle
|
||||||
* or if @width or @height don't have the correct texture
|
* or if @width or @height don't have the correct texture
|
||||||
* geometry.</note>
|
* geometry.</note>
|
||||||
|
@ -82,7 +82,8 @@ CoglTexture2D *
|
|||||||
_cogl_texture_2d_create_base (CoglContext *ctx,
|
_cogl_texture_2d_create_base (CoglContext *ctx,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
CoglPixelFormat internal_format);
|
CoglPixelFormat internal_format,
|
||||||
|
CoglTextureLoader *loader);
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_2d_set_auto_mipmap (CoglTexture *tex,
|
_cogl_texture_2d_set_auto_mipmap (CoglTexture *tex,
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
struct _CoglTexture2DSliced
|
struct _CoglTexture2DSliced
|
||||||
{
|
{
|
||||||
CoglTexture _parent;
|
CoglTexture _parent;
|
||||||
|
|
||||||
GArray *slice_x_spans;
|
GArray *slice_x_spans;
|
||||||
GArray *slice_y_spans;
|
GArray *slice_y_spans;
|
||||||
GArray *slice_textures;
|
GArray *slice_textures;
|
||||||
|
@ -659,8 +659,24 @@ _cogl_texture_2d_sliced_gl_flush_legacy_texobj_wrap_modes (CoglTexture *tex,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_spans (CoglTexture2DSliced *tex_2ds)
|
||||||
|
{
|
||||||
|
if (tex_2ds->slice_x_spans != NULL)
|
||||||
|
{
|
||||||
|
g_array_free (tex_2ds->slice_x_spans, TRUE);
|
||||||
|
tex_2ds->slice_x_spans = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tex_2ds->slice_y_spans != NULL)
|
||||||
|
{
|
||||||
|
g_array_free (tex_2ds->slice_y_spans, TRUE);
|
||||||
|
tex_2ds->slice_y_spans = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
_cogl_texture_2d_sliced_setup_spans (CoglContext *ctx,
|
setup_spans (CoglContext *ctx,
|
||||||
CoglTexture2DSliced *tex_2ds,
|
CoglTexture2DSliced *tex_2ds,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
@ -754,8 +770,8 @@ _cogl_texture_2d_sliced_setup_spans (CoglContext *ctx,
|
|||||||
COGL_TEXTURE_ERROR,
|
COGL_TEXTURE_ERROR,
|
||||||
COGL_TEXTURE_ERROR_SIZE,
|
COGL_TEXTURE_ERROR_SIZE,
|
||||||
"No suitable slice geometry found");
|
"No suitable slice geometry found");
|
||||||
|
free_spans (tex_2ds);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -791,7 +807,7 @@ _cogl_texture_2d_sliced_setup_spans (CoglContext *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_texture_2d_sliced_slices_free (CoglTexture2DSliced *tex_2ds)
|
free_slices (CoglTexture2DSliced *tex_2ds)
|
||||||
{
|
{
|
||||||
if (tex_2ds->slice_textures != NULL)
|
if (tex_2ds->slice_textures != NULL)
|
||||||
{
|
{
|
||||||
@ -806,26 +822,12 @@ _cogl_texture_2d_sliced_slices_free (CoglTexture2DSliced *tex_2ds)
|
|||||||
|
|
||||||
g_array_free (tex_2ds->slice_textures, TRUE);
|
g_array_free (tex_2ds->slice_textures, TRUE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
free_spans (tex_2ds);
|
||||||
_cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds)
|
|
||||||
{
|
|
||||||
_cogl_texture_2d_sliced_slices_free (tex_2ds);
|
|
||||||
|
|
||||||
if (tex_2ds->slice_x_spans != NULL)
|
|
||||||
g_array_free (tex_2ds->slice_x_spans, TRUE);
|
|
||||||
|
|
||||||
if (tex_2ds->slice_y_spans != NULL)
|
|
||||||
g_array_free (tex_2ds->slice_y_spans, TRUE);
|
|
||||||
|
|
||||||
/* Chain up */
|
|
||||||
_cogl_texture_free (COGL_TEXTURE (tex_2ds));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
_cogl_texture_2d_sliced_init_base (CoglContext *ctx,
|
allocate_slices (CoglTexture2DSliced *tex_2ds,
|
||||||
CoglTexture2DSliced *tex_2ds,
|
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
int max_waste,
|
int max_waste,
|
||||||
@ -833,84 +835,23 @@ _cogl_texture_2d_sliced_init_base (CoglContext *ctx,
|
|||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
|
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
|
||||||
|
|
||||||
_cogl_texture_init (tex, ctx, width, height, &cogl_texture_2d_sliced_vtable);
|
|
||||||
|
|
||||||
tex_2ds->max_waste = max_waste;
|
|
||||||
tex_2ds->internal_format = internal_format;
|
|
||||||
|
|
||||||
return _cogl_texture_2d_sliced_setup_spans (ctx, tex_2ds,
|
|
||||||
width, height,
|
|
||||||
max_waste,
|
|
||||||
internal_format,
|
|
||||||
error);
|
|
||||||
}
|
|
||||||
|
|
||||||
CoglTexture2DSliced *
|
|
||||||
cogl_texture_2d_sliced_new_with_size (CoglContext *ctx,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int max_waste,
|
|
||||||
CoglPixelFormat internal_format)
|
|
||||||
{
|
|
||||||
CoglTexture2DSliced *tex_2ds;
|
|
||||||
CoglError *ignore_error = NULL;
|
|
||||||
|
|
||||||
/* Since no data, we need some internal format */
|
|
||||||
if (internal_format == COGL_PIXEL_FORMAT_ANY)
|
|
||||||
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
|
||||||
|
|
||||||
/* Init texture with empty bitmap */
|
|
||||||
tex_2ds = g_new0 (CoglTexture2DSliced, 1);
|
|
||||||
|
|
||||||
if (!_cogl_texture_2d_sliced_init_base (ctx,
|
|
||||||
tex_2ds,
|
|
||||||
width, height,
|
|
||||||
max_waste,
|
|
||||||
internal_format,
|
|
||||||
&ignore_error))
|
|
||||||
{
|
|
||||||
/* In this case we failed to find any suitable slicing geometry
|
|
||||||
* for the given texture size.
|
|
||||||
*
|
|
||||||
* We don't need to do anything with the error here since it
|
|
||||||
* will be picked up on later when trying to allocate the
|
|
||||||
* texture.
|
|
||||||
*/
|
|
||||||
cogl_error_free (ignore_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NB: We need to be sure that cogl_texture_is_sliced() will work
|
|
||||||
* correctly before returning since
|
|
||||||
* cogl_framebuffer_allocate() uses this api to determine
|
|
||||||
* if a texture can be rendered to which may be before the
|
|
||||||
* slices have been allocated.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return _cogl_texture_2d_sliced_object_new (tex_2ds);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CoglBool
|
|
||||||
_cogl_texture_2d_sliced_allocate (CoglTexture *tex,
|
|
||||||
CoglError **error)
|
|
||||||
{
|
|
||||||
CoglContext *ctx = tex->context;
|
CoglContext *ctx = tex->context;
|
||||||
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
|
|
||||||
int n_x_slices;
|
int n_x_slices;
|
||||||
int n_y_slices;
|
int n_y_slices;
|
||||||
int n_slices;
|
int n_slices;
|
||||||
int x, y;
|
int x, y;
|
||||||
CoglPixelFormat format = tex_2ds->internal_format;
|
|
||||||
CoglSpan *x_span;
|
CoglSpan *x_span;
|
||||||
CoglSpan *y_span;
|
CoglSpan *y_span;
|
||||||
|
|
||||||
if (!tex_2ds->slice_x_spans || !tex_2ds->slice_y_spans)
|
tex_2ds->internal_format = internal_format;
|
||||||
|
|
||||||
|
if (!setup_spans (ctx, tex_2ds,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
max_waste,
|
||||||
|
internal_format,
|
||||||
|
error))
|
||||||
{
|
{
|
||||||
_cogl_set_error (error,
|
|
||||||
COGL_TEXTURE_ERROR,
|
|
||||||
COGL_TEXTURE_ERROR_SIZE,
|
|
||||||
"Couldn't find suitable slicing geometry "
|
|
||||||
"for given size");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -941,11 +882,11 @@ _cogl_texture_2d_sliced_allocate (CoglTexture *tex,
|
|||||||
slice = COGL_TEXTURE (
|
slice = COGL_TEXTURE (
|
||||||
cogl_texture_2d_new_with_size (ctx,
|
cogl_texture_2d_new_with_size (ctx,
|
||||||
x_span->size, y_span->size,
|
x_span->size, y_span->size,
|
||||||
format));
|
internal_format));
|
||||||
g_array_append_val (tex_2ds->slice_textures, slice);
|
g_array_append_val (tex_2ds->slice_textures, slice);
|
||||||
if (!cogl_texture_allocate (slice, error))
|
if (!cogl_texture_allocate (slice, error))
|
||||||
{
|
{
|
||||||
_cogl_texture_2d_sliced_slices_free (tex_2ds);
|
free_slices (tex_2ds);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -954,6 +895,60 @@ _cogl_texture_2d_sliced_allocate (CoglTexture *tex,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds)
|
||||||
|
{
|
||||||
|
free_slices (tex_2ds);
|
||||||
|
|
||||||
|
/* Chain up */
|
||||||
|
_cogl_texture_free (COGL_TEXTURE (tex_2ds));
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglTexture2DSliced *
|
||||||
|
_cogl_texture_2d_sliced_create_base (CoglContext *ctx,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int max_waste,
|
||||||
|
CoglPixelFormat internal_format,
|
||||||
|
CoglTextureLoader *loader)
|
||||||
|
{
|
||||||
|
CoglTexture2DSliced *tex_2ds = g_new0 (CoglTexture2DSliced, 1);
|
||||||
|
|
||||||
|
_cogl_texture_init (COGL_TEXTURE (tex_2ds), ctx, width, height,
|
||||||
|
internal_format, loader,
|
||||||
|
&cogl_texture_2d_sliced_vtable);
|
||||||
|
|
||||||
|
tex_2ds->max_waste = max_waste;
|
||||||
|
|
||||||
|
return _cogl_texture_2d_sliced_object_new (tex_2ds);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglTexture2DSliced *
|
||||||
|
cogl_texture_2d_sliced_new_with_size (CoglContext *ctx,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int max_waste,
|
||||||
|
CoglPixelFormat internal_format)
|
||||||
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
|
/* Since no data, we need some internal format */
|
||||||
|
if (internal_format == COGL_PIXEL_FORMAT_ANY)
|
||||||
|
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||||
|
|
||||||
|
loader = _cogl_texture_create_loader ();
|
||||||
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED;
|
||||||
|
loader->src.sized.width = width;
|
||||||
|
loader->src.sized.height = height;
|
||||||
|
|
||||||
|
return _cogl_texture_2d_sliced_create_base (ctx,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
max_waste,
|
||||||
|
internal_format,
|
||||||
|
loader);
|
||||||
|
}
|
||||||
|
|
||||||
CoglTexture2DSliced *
|
CoglTexture2DSliced *
|
||||||
_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
|
_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
|
||||||
int max_waste,
|
int max_waste,
|
||||||
@ -961,61 +956,21 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
|
|||||||
CoglBool can_convert_in_place,
|
CoglBool can_convert_in_place,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglContext *ctx;
|
CoglTextureLoader *loader;
|
||||||
CoglTexture2DSliced *tex_2ds;
|
|
||||||
CoglBitmap *upload_bmp;
|
|
||||||
int width, height;
|
|
||||||
|
|
||||||
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
|
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
|
||||||
|
|
||||||
ctx = _cogl_bitmap_get_context (bmp);
|
loader = _cogl_texture_create_loader ();
|
||||||
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_BITMAP;
|
||||||
|
loader->src.bitmap.bitmap = cogl_object_ref (bmp);
|
||||||
|
loader->src.bitmap.can_convert_in_place = can_convert_in_place;
|
||||||
|
|
||||||
width = cogl_bitmap_get_width (bmp);
|
return _cogl_texture_2d_sliced_create_base (_cogl_bitmap_get_context (bmp),
|
||||||
height = cogl_bitmap_get_height (bmp);
|
cogl_bitmap_get_width (bmp),
|
||||||
|
cogl_bitmap_get_height (bmp),
|
||||||
/* Create new texture and fill with loaded data */
|
|
||||||
tex_2ds = g_new0 (CoglTexture2DSliced, 1);
|
|
||||||
|
|
||||||
internal_format =
|
|
||||||
_cogl_texture_determine_internal_format (cogl_bitmap_get_format (bmp),
|
|
||||||
internal_format);
|
|
||||||
|
|
||||||
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
|
|
||||||
internal_format,
|
|
||||||
can_convert_in_place,
|
|
||||||
error);
|
|
||||||
if (upload_bmp == NULL)
|
|
||||||
{
|
|
||||||
_cogl_texture_2d_sliced_free (tex_2ds);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NB: we may fail to find any suitable slicing geometry for the
|
|
||||||
* given texture size. */
|
|
||||||
if (!_cogl_texture_2d_sliced_init_base (ctx,
|
|
||||||
tex_2ds,
|
|
||||||
width, height,
|
|
||||||
max_waste,
|
max_waste,
|
||||||
internal_format,
|
internal_format,
|
||||||
error))
|
loader);
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (!cogl_texture_allocate (COGL_TEXTURE (tex_2ds), error))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (!_cogl_texture_2d_sliced_upload_bitmap (tex_2ds,
|
|
||||||
upload_bmp,
|
|
||||||
error))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
cogl_object_unref (upload_bmp);
|
|
||||||
|
|
||||||
return _cogl_texture_2d_sliced_object_new (tex_2ds);
|
|
||||||
|
|
||||||
error:
|
|
||||||
cogl_object_unref (upload_bmp);
|
|
||||||
_cogl_texture_2d_sliced_free (tex_2ds);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTexture2DSliced *
|
CoglTexture2DSliced *
|
||||||
@ -1042,85 +997,40 @@ _cogl_texture_2d_sliced_new_from_foreign (CoglContext *ctx,
|
|||||||
CoglPixelFormat format,
|
CoglPixelFormat format,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
/* NOTE: width, height and internal format are not queriable
|
/* NOTE: width, height and internal format are not queriable
|
||||||
* in GLES, hence such a function prototype.
|
* in GLES, hence such a function prototype.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int gl_width = 0;
|
|
||||||
int gl_height = 0;
|
|
||||||
CoglTexture2DSliced *tex_2ds;
|
|
||||||
CoglTexture *tex;
|
|
||||||
CoglSpan x_span;
|
|
||||||
CoglSpan y_span;
|
|
||||||
CoglTexture2D *tex_2d;
|
|
||||||
|
|
||||||
/* This should only be called when the texture target is 2D. If a
|
/* This should only be called when the texture target is 2D. If a
|
||||||
rectangle texture is used then _cogl_texture_new_from_foreign
|
rectangle texture is used then _cogl_texture_new_from_foreign
|
||||||
will create a cogl_texture_rectangle instead */
|
will create a cogl_texture_rectangle instead */
|
||||||
_COGL_RETURN_VAL_IF_FAIL (gl_target == GL_TEXTURE_2D, NULL);
|
_COGL_RETURN_VAL_IF_FAIL (gl_target == GL_TEXTURE_2D, NULL);
|
||||||
|
|
||||||
gl_width = width + x_pot_waste;
|
/* Assert it is a valid GL texture object */
|
||||||
gl_height = height + y_pot_waste;
|
_COGL_RETURN_VAL_IF_FAIL (ctx->glIsTexture (gl_handle), FALSE);
|
||||||
|
|
||||||
|
/* Validate width and height */
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (width > 0 && height > 0, NULL);
|
||||||
|
|
||||||
/* Validate pot waste */
|
/* Validate pot waste */
|
||||||
if (x_pot_waste < 0 || x_pot_waste >= width ||
|
_COGL_RETURN_VAL_IF_FAIL (x_pot_waste >= 0 && x_pot_waste < width &&
|
||||||
y_pot_waste < 0 || y_pot_waste >= height)
|
y_pot_waste >= 0 && y_pot_waste < height,
|
||||||
return NULL;
|
NULL);
|
||||||
|
|
||||||
tex_2d = cogl_texture_2d_new_from_foreign (ctx,
|
loader = _cogl_texture_create_loader ();
|
||||||
gl_target,
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN;
|
||||||
gl_width,
|
loader->src.gl_foreign.gl_handle = gl_handle;
|
||||||
gl_height,
|
loader->src.gl_foreign.width = width + x_pot_waste;
|
||||||
format,
|
loader->src.gl_foreign.height = height + y_pot_waste;
|
||||||
error);
|
loader->src.gl_foreign.format = format;
|
||||||
|
|
||||||
if (!tex_2d)
|
return _cogl_texture_2d_sliced_create_base (ctx,
|
||||||
return NULL;
|
width,
|
||||||
|
height,
|
||||||
/* The texture 2d backend may use a different pixel format if it
|
0, /* max waste */
|
||||||
queries the actual texture so we'll refetch the format it
|
format, loader);
|
||||||
actually used */
|
|
||||||
format = _cogl_texture_get_format (COGL_TEXTURE (tex_2d));
|
|
||||||
|
|
||||||
/* Create new texture */
|
|
||||||
tex_2ds = g_new0 (CoglTexture2DSliced, 1);
|
|
||||||
|
|
||||||
tex = COGL_TEXTURE (tex_2ds);
|
|
||||||
_cogl_texture_init (tex, ctx, gl_width, gl_height,
|
|
||||||
&cogl_texture_2d_sliced_vtable);
|
|
||||||
|
|
||||||
tex_2ds->max_waste = 0;
|
|
||||||
tex_2ds->internal_format = format;
|
|
||||||
|
|
||||||
/* Create slice arrays */
|
|
||||||
tex_2ds->slice_x_spans =
|
|
||||||
g_array_sized_new (FALSE, FALSE,
|
|
||||||
sizeof (CoglSpan), 1);
|
|
||||||
|
|
||||||
tex_2ds->slice_y_spans =
|
|
||||||
g_array_sized_new (FALSE, FALSE,
|
|
||||||
sizeof (CoglSpan), 1);
|
|
||||||
|
|
||||||
tex_2ds->slice_textures =
|
|
||||||
g_array_sized_new (FALSE, FALSE,
|
|
||||||
sizeof (CoglTexture2D *), 1);
|
|
||||||
|
|
||||||
/* Store info for a single slice */
|
|
||||||
x_span.start = 0;
|
|
||||||
x_span.size = gl_width;
|
|
||||||
x_span.waste = x_pot_waste;
|
|
||||||
g_array_append_val (tex_2ds->slice_x_spans, x_span);
|
|
||||||
|
|
||||||
y_span.start = 0;
|
|
||||||
y_span.size = gl_height;
|
|
||||||
y_span.waste = y_pot_waste;
|
|
||||||
g_array_append_val (tex_2ds->slice_y_spans, y_span);
|
|
||||||
|
|
||||||
g_array_append_val (tex_2ds->slice_textures, tex_2d);
|
|
||||||
|
|
||||||
_cogl_texture_set_allocated (COGL_TEXTURE (tex_2ds), TRUE);
|
|
||||||
|
|
||||||
return _cogl_texture_2d_sliced_object_new (tex_2ds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTexture2DSliced *
|
CoglTexture2DSliced *
|
||||||
@ -1157,6 +1067,13 @@ cogl_texture_2d_sliced_new_from_data (CoglContext *ctx,
|
|||||||
|
|
||||||
cogl_object_unref (bmp);
|
cogl_object_unref (bmp);
|
||||||
|
|
||||||
|
if (tex_2ds &&
|
||||||
|
!cogl_texture_allocate (COGL_TEXTURE (tex_2ds), error))
|
||||||
|
{
|
||||||
|
cogl_object_unref (tex_2ds);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return tex_2ds;
|
return tex_2ds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1187,6 +1104,175 @@ cogl_texture_2d_sliced_new_from_file (CoglContext *ctx,
|
|||||||
return tex_2ds;
|
return tex_2ds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
allocate_with_size (CoglTexture2DSliced *tex_2ds,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
|
||||||
|
CoglPixelFormat internal_format =
|
||||||
|
_cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY);
|
||||||
|
|
||||||
|
if (allocate_slices (tex_2ds,
|
||||||
|
loader->src.sized.width,
|
||||||
|
loader->src.sized.height,
|
||||||
|
tex_2ds->max_waste,
|
||||||
|
internal_format,
|
||||||
|
error))
|
||||||
|
{
|
||||||
|
_cogl_texture_set_allocated (COGL_TEXTURE (tex_2ds),
|
||||||
|
internal_format,
|
||||||
|
loader->src.sized.width,
|
||||||
|
loader->src.sized.height);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
allocate_from_bitmap (CoglTexture2DSliced *tex_2ds,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
|
||||||
|
CoglBitmap *bmp = loader->src.bitmap.bitmap;
|
||||||
|
int width = cogl_bitmap_get_width (bmp);
|
||||||
|
int height = cogl_bitmap_get_height (bmp);
|
||||||
|
CoglBool can_convert_in_place = loader->src.bitmap.can_convert_in_place;
|
||||||
|
CoglPixelFormat internal_format;
|
||||||
|
CoglBitmap *upload_bmp;
|
||||||
|
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (tex_2ds->slice_textures == NULL, FALSE);
|
||||||
|
|
||||||
|
internal_format =
|
||||||
|
_cogl_texture_determine_internal_format (tex,
|
||||||
|
cogl_bitmap_get_format (bmp));
|
||||||
|
|
||||||
|
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
|
||||||
|
internal_format,
|
||||||
|
can_convert_in_place,
|
||||||
|
error);
|
||||||
|
if (upload_bmp == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!allocate_slices (tex_2ds,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
tex_2ds->max_waste,
|
||||||
|
internal_format,
|
||||||
|
error))
|
||||||
|
{
|
||||||
|
cogl_object_unref (upload_bmp);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_cogl_texture_2d_sliced_upload_bitmap (tex_2ds,
|
||||||
|
upload_bmp,
|
||||||
|
error))
|
||||||
|
{
|
||||||
|
free_slices (tex_2ds);
|
||||||
|
cogl_object_unref (upload_bmp);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cogl_object_unref (upload_bmp);
|
||||||
|
|
||||||
|
_cogl_texture_set_allocated (tex, internal_format, width, height);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
allocate_from_gl_foreign (CoglTexture2DSliced *tex_2ds,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (tex_2ds);
|
||||||
|
CoglContext *ctx = tex->context;
|
||||||
|
CoglPixelFormat format = loader->src.gl_foreign.format;
|
||||||
|
int gl_width = loader->src.gl_foreign.width;
|
||||||
|
int gl_height = loader->src.gl_foreign.height;
|
||||||
|
int x_pot_waste = gl_width - tex->width;
|
||||||
|
int y_pot_waste = gl_height - tex->height;
|
||||||
|
CoglSpan x_span;
|
||||||
|
CoglSpan y_span;
|
||||||
|
CoglTexture2D *tex_2d =
|
||||||
|
cogl_texture_2d_new_from_foreign (ctx,
|
||||||
|
loader->src.gl_foreign.gl_handle,
|
||||||
|
gl_width,
|
||||||
|
gl_height,
|
||||||
|
format,
|
||||||
|
error);
|
||||||
|
|
||||||
|
if (!tex_2d)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!cogl_texture_allocate (COGL_TEXTURE (tex_2d), error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* The texture 2d backend may use a different pixel format if it
|
||||||
|
queries the actual texture so we'll refetch the format it
|
||||||
|
actually used */
|
||||||
|
format = _cogl_texture_get_format (tex);
|
||||||
|
|
||||||
|
tex_2ds->internal_format = format;
|
||||||
|
|
||||||
|
/* Create slice arrays */
|
||||||
|
tex_2ds->slice_x_spans =
|
||||||
|
g_array_sized_new (FALSE, FALSE, sizeof (CoglSpan), 1);
|
||||||
|
|
||||||
|
tex_2ds->slice_y_spans =
|
||||||
|
g_array_sized_new (FALSE, FALSE, sizeof (CoglSpan), 1);
|
||||||
|
|
||||||
|
tex_2ds->slice_textures =
|
||||||
|
g_array_sized_new (FALSE, FALSE, sizeof (CoglTexture2D *), 1);
|
||||||
|
|
||||||
|
/* Store info for a single slice */
|
||||||
|
x_span.start = 0;
|
||||||
|
x_span.size = gl_width;
|
||||||
|
x_span.waste = x_pot_waste;
|
||||||
|
g_array_append_val (tex_2ds->slice_x_spans, x_span);
|
||||||
|
|
||||||
|
y_span.start = 0;
|
||||||
|
y_span.size = gl_height;
|
||||||
|
y_span.waste = y_pot_waste;
|
||||||
|
g_array_append_val (tex_2ds->slice_y_spans, y_span);
|
||||||
|
|
||||||
|
g_array_append_val (tex_2ds->slice_textures, tex_2d);
|
||||||
|
|
||||||
|
_cogl_texture_set_allocated (tex,
|
||||||
|
format,
|
||||||
|
tex->width,
|
||||||
|
tex->height);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
_cogl_texture_2d_sliced_allocate (CoglTexture *tex,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
|
||||||
|
CoglTextureLoader *loader = tex->loader;
|
||||||
|
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (loader, FALSE);
|
||||||
|
|
||||||
|
switch (loader->src_type)
|
||||||
|
{
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_SIZED:
|
||||||
|
return allocate_with_size (tex_2ds, loader, error);
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_BITMAP:
|
||||||
|
return allocate_from_bitmap (tex_2ds, loader, error);
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN:
|
||||||
|
return allocate_from_gl_foreign (tex_2ds, loader, error);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
_cogl_texture_2d_sliced_is_foreign (CoglTexture *tex)
|
_cogl_texture_2d_sliced_is_foreign (CoglTexture *tex)
|
||||||
{
|
{
|
||||||
@ -1215,17 +1301,10 @@ _cogl_texture_2d_sliced_is_sliced (CoglTexture *tex)
|
|||||||
{
|
{
|
||||||
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
|
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
|
||||||
|
|
||||||
/* It's possible that we failed to calculate valid slicing geometry
|
/* It's only after allocating a sliced texture that we will know
|
||||||
* when initializing the texture due to the max_waste size and in
|
* whether it really needed to be sliced... */
|
||||||
* this case we report that the texture is not sliced.
|
if (!tex->allocated)
|
||||||
*
|
cogl_texture_allocate (tex, NULL);
|
||||||
* In this case though we know that we will be throwing an error
|
|
||||||
* when this texture is later allocated so it shouldn't really
|
|
||||||
* matter what we report here since the texture won't be used in the
|
|
||||||
* end.
|
|
||||||
*/
|
|
||||||
if (!tex_2ds->slice_x_spans || !tex_2ds->slice_y_spans)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (tex_2ds->slice_x_spans->len != 1 ||
|
if (tex_2ds->slice_x_spans->len != 1 ||
|
||||||
tex_2ds->slice_y_spans->len != 1)
|
tex_2ds->slice_y_spans->len != 1)
|
||||||
|
@ -147,6 +147,11 @@ cogl_texture_2d_sliced_new_with_size (CoglContext *ctx,
|
|||||||
* wasted padding at the bottom and right of the textures is less than
|
* wasted padding at the bottom and right of the textures is less than
|
||||||
* specified. A negative @max_waste will disable slicing.
|
* specified. A negative @max_waste will disable slicing.
|
||||||
*
|
*
|
||||||
|
* The storage for the texture is not allocated before this function
|
||||||
|
* returns. You can call cogl_texture_allocate() to explicitly
|
||||||
|
* allocate the underlying storage or let Cogl automatically allocate
|
||||||
|
* storage lazily.
|
||||||
|
*
|
||||||
* <note>It's possible for the allocation of a sliced texture to fail
|
* <note>It's possible for the allocation of a sliced texture to fail
|
||||||
* later due to impossible slicing constraints if a negative
|
* later due to impossible slicing constraints if a negative
|
||||||
* @max_waste value is given. If the given virtual texture size is
|
* @max_waste value is given. If the given virtual texture size is
|
||||||
@ -206,11 +211,22 @@ cogl_texture_2d_sliced_new_from_file (CoglContext *ctx,
|
|||||||
* wasted padding at the bottom and right of the textures is less than
|
* wasted padding at the bottom and right of the textures is less than
|
||||||
* specified. A negative @max_waste will disable slicing.
|
* specified. A negative @max_waste will disable slicing.
|
||||||
*
|
*
|
||||||
|
* <note>This api will always immediately allocate GPU memory for all
|
||||||
|
* the required texture slices and upload the given data so that the
|
||||||
|
* @data pointer does not need to remain valid once this function
|
||||||
|
* returns. This means it is not possible to configure the texture
|
||||||
|
* before it is allocated. If you do need to configure the texture
|
||||||
|
* before allocation (to specify constraints on the internal format
|
||||||
|
* for example) then you can instead create a #CoglBitmap for your
|
||||||
|
* data and use cogl_texture_2d_sliced_new_from_bitmap() or use
|
||||||
|
* cogl_texture_2d_sliced_new_with_size() and then upload data using
|
||||||
|
* cogl_texture_set_data()</note>
|
||||||
|
*
|
||||||
* <note>It's possible for the allocation of a sliced texture to fail
|
* <note>It's possible for the allocation of a sliced texture to fail
|
||||||
* later due to impossible slicing constraints if a negative
|
* due to impossible slicing constraints if a negative @max_waste
|
||||||
* @max_waste value is given. If the given virtual texture size is
|
* value is given. If the given virtual texture size is larger than is
|
||||||
* larger than is supported by the hardware but slicing is disabled
|
* supported by the hardware but slicing is disabled the texture size
|
||||||
* the texture size would be too large to handle.</note>
|
* would be too large to handle.</note>
|
||||||
*
|
*
|
||||||
* Return value: (transfer full): A newly created #CoglTexture2DSliced
|
* Return value: (transfer full): A newly created #CoglTexture2DSliced
|
||||||
* or %NULL on failure and @error will be updated.
|
* or %NULL on failure and @error will be updated.
|
||||||
@ -262,6 +278,11 @@ cogl_texture_2d_sliced_new_from_data (CoglContext *ctx,
|
|||||||
* wasted padding at the bottom and right of the textures is less than
|
* wasted padding at the bottom and right of the textures is less than
|
||||||
* specified. A negative @max_waste will disable slicing.
|
* specified. A negative @max_waste will disable slicing.
|
||||||
*
|
*
|
||||||
|
* The storage for the texture is not allocated before this function
|
||||||
|
* returns. You can call cogl_texture_allocate() to explicitly
|
||||||
|
* allocate the underlying storage or let Cogl automatically allocate
|
||||||
|
* storage lazily.
|
||||||
|
*
|
||||||
* <note>It's possible for the allocation of a sliced texture to fail
|
* <note>It's possible for the allocation of a sliced texture to fail
|
||||||
* later due to impossible slicing constraints if a negative
|
* later due to impossible slicing constraints if a negative
|
||||||
* @max_waste value is given. If the given virtual texture size is
|
* @max_waste value is given. If the given virtual texture size is
|
||||||
|
@ -75,25 +75,6 @@ _cogl_texture_2d_free (CoglTexture2D *tex_2d)
|
|||||||
_cogl_texture_free (COGL_TEXTURE (tex_2d));
|
_cogl_texture_free (COGL_TEXTURE (tex_2d));
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglBool
|
|
||||||
_cogl_texture_2d_can_create (CoglContext *ctx,
|
|
||||||
unsigned int width,
|
|
||||||
unsigned int height,
|
|
||||||
CoglPixelFormat internal_format)
|
|
||||||
{
|
|
||||||
/* If NPOT textures aren't supported then the size must be a power
|
|
||||||
of two */
|
|
||||||
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
|
|
||||||
(!_cogl_util_is_pot (width) ||
|
|
||||||
!_cogl_util_is_pot (height)))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return ctx->driver_vtable->texture_2d_can_create (ctx,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
internal_format);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_2d_set_auto_mipmap (CoglTexture *tex,
|
_cogl_texture_2d_set_auto_mipmap (CoglTexture *tex,
|
||||||
CoglBool value)
|
CoglBool value)
|
||||||
@ -107,20 +88,20 @@ CoglTexture2D *
|
|||||||
_cogl_texture_2d_create_base (CoglContext *ctx,
|
_cogl_texture_2d_create_base (CoglContext *ctx,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format,
|
||||||
|
CoglTextureLoader *loader)
|
||||||
{
|
{
|
||||||
CoglTexture2D *tex_2d = g_new (CoglTexture2D, 1);
|
CoglTexture2D *tex_2d = g_new (CoglTexture2D, 1);
|
||||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||||
|
|
||||||
_cogl_texture_init (tex, ctx, width, height, &cogl_texture_2d_vtable);
|
_cogl_texture_init (tex, ctx, width, height, internal_format, loader,
|
||||||
|
&cogl_texture_2d_vtable);
|
||||||
|
|
||||||
tex_2d->mipmaps_dirty = TRUE;
|
tex_2d->mipmaps_dirty = TRUE;
|
||||||
tex_2d->auto_mipmap = TRUE;
|
tex_2d->auto_mipmap = TRUE;
|
||||||
|
|
||||||
tex_2d->is_foreign = FALSE;
|
tex_2d->is_foreign = FALSE;
|
||||||
|
|
||||||
tex_2d->internal_format = internal_format;
|
|
||||||
|
|
||||||
ctx->driver_vtable->texture_2d_init (tex_2d);
|
ctx->driver_vtable->texture_2d_init (tex_2d);
|
||||||
|
|
||||||
return _cogl_texture_2d_object_new (tex_2d);
|
return _cogl_texture_2d_object_new (tex_2d);
|
||||||
@ -132,13 +113,19 @@ cogl_texture_2d_new_with_size (CoglContext *ctx,
|
|||||||
int height,
|
int height,
|
||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format)
|
||||||
{
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
/* 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)
|
||||||
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||||
|
|
||||||
return _cogl_texture_2d_create_base (ctx,
|
loader = _cogl_texture_create_loader ();
|
||||||
width, height,
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED;
|
||||||
internal_format);
|
loader->src.sized.width = width;
|
||||||
|
loader->src.sized.height = height;
|
||||||
|
|
||||||
|
return _cogl_texture_2d_create_base (ctx, width, height,
|
||||||
|
internal_format, loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
@ -146,6 +133,7 @@ _cogl_texture_2d_allocate (CoglTexture *tex,
|
|||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglContext *ctx = tex->context;
|
CoglContext *ctx = tex->context;
|
||||||
|
|
||||||
return ctx->driver_vtable->texture_2d_allocate (tex, error);
|
return ctx->driver_vtable->texture_2d_allocate (tex, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,32 +143,20 @@ _cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
|
|||||||
CoglBool can_convert_in_place,
|
CoglBool can_convert_in_place,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglContext *ctx;
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
_COGL_RETURN_VAL_IF_FAIL (bmp != NULL, NULL);
|
_COGL_RETURN_VAL_IF_FAIL (bmp != NULL, NULL);
|
||||||
|
|
||||||
ctx = _cogl_bitmap_get_context (bmp);
|
loader = _cogl_texture_create_loader ();
|
||||||
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_BITMAP;
|
||||||
|
loader->src.bitmap.bitmap = cogl_object_ref (bmp);
|
||||||
|
loader->src.bitmap.can_convert_in_place = can_convert_in_place;
|
||||||
|
|
||||||
internal_format =
|
return _cogl_texture_2d_create_base (_cogl_bitmap_get_context (bmp),
|
||||||
_cogl_texture_determine_internal_format (cogl_bitmap_get_format (bmp),
|
|
||||||
internal_format);
|
|
||||||
|
|
||||||
if (!_cogl_texture_2d_can_create (ctx,
|
|
||||||
cogl_bitmap_get_width (bmp),
|
cogl_bitmap_get_width (bmp),
|
||||||
cogl_bitmap_get_height (bmp),
|
cogl_bitmap_get_height (bmp),
|
||||||
internal_format))
|
|
||||||
{
|
|
||||||
_cogl_set_error (error, COGL_TEXTURE_ERROR,
|
|
||||||
COGL_TEXTURE_ERROR_SIZE,
|
|
||||||
"Failed to create texture 2d due to size/format"
|
|
||||||
" constraints");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx->driver_vtable->texture_2d_new_from_bitmap (bmp,
|
|
||||||
internal_format,
|
internal_format,
|
||||||
can_convert_in_place,
|
loader);
|
||||||
error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTexture2D *
|
CoglTexture2D *
|
||||||
@ -249,6 +225,13 @@ cogl_texture_2d_new_from_data (CoglContext *ctx,
|
|||||||
|
|
||||||
cogl_object_unref (bmp);
|
cogl_object_unref (bmp);
|
||||||
|
|
||||||
|
if (tex_2d &&
|
||||||
|
!cogl_texture_allocate (COGL_TEXTURE (tex_2d), error))
|
||||||
|
{
|
||||||
|
cogl_object_unref (tex_2d);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return tex_2d;
|
return tex_2d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,6 +247,8 @@ _cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
|
|||||||
EGLImageKHR image,
|
EGLImageKHR image,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
_COGL_RETURN_VAL_IF_FAIL (_cogl_context_get_winsys (ctx)->constraints &
|
_COGL_RETURN_VAL_IF_FAIL (_cogl_context_get_winsys (ctx)->constraints &
|
||||||
COGL_RENDERER_CONSTRAINT_USES_EGL,
|
COGL_RENDERER_CONSTRAINT_USES_EGL,
|
||||||
NULL);
|
NULL);
|
||||||
@ -273,22 +258,14 @@ _cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
|
|||||||
COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE),
|
COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (ctx->driver_vtable->egl_texture_2d_new_from_image)
|
loader = _cogl_texture_create_loader ();
|
||||||
return ctx->driver_vtable->egl_texture_2d_new_from_image (ctx,
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE;
|
||||||
width,
|
loader->src.egl_image.image = image;
|
||||||
height,
|
loader->src.egl_image.width = width;
|
||||||
format,
|
loader->src.egl_image.height = height;
|
||||||
image,
|
loader->src.egl_image.format = format;
|
||||||
error);
|
|
||||||
else
|
return _cogl_texture_2d_create_base (ctx, width, height, format, loader);
|
||||||
{
|
|
||||||
_cogl_set_error (error,
|
|
||||||
COGL_SYSTEM_ERROR,
|
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
|
||||||
"Creating 2D textures from EGL images is not "
|
|
||||||
"supported by the current driver");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) */
|
#endif /* defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) */
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Intel Corporation.
|
* Copyright (C) 2011,2013 Intel Corporation.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -75,11 +75,8 @@ cogl_is_texture_2d (void *object);
|
|||||||
* @height: Height of the texture to allocate
|
* @height: Height of the texture to allocate
|
||||||
* @internal_format: The format of the texture
|
* @internal_format: The format of the texture
|
||||||
*
|
*
|
||||||
* Allocates a low-level #CoglTexture2D texture that your GPU can
|
* Creates a low-level #CoglTexture2D texture with a given @width and
|
||||||
* texture from directly. This is unlike sliced textures for example
|
* @height that your GPU can texture from directly.
|
||||||
* which may be comprised of multiple internal textures, or atlas
|
|
||||||
* textures where Cogl has to modify texture coordinates before they
|
|
||||||
* may be used by the GPU.
|
|
||||||
*
|
*
|
||||||
* The storage for the texture is not allocated before this function
|
* The storage for the texture is not allocated before this function
|
||||||
* returns. You can call cogl_texture_allocate() to explicitly
|
* returns. You can call cogl_texture_allocate() to explicitly
|
||||||
@ -87,6 +84,11 @@ cogl_is_texture_2d (void *object);
|
|||||||
* automatically allocate storage lazily when it may know more about
|
* automatically allocate storage lazily when it may know more about
|
||||||
* how the texture is being used and can optimize how it is allocated.
|
* how the texture is being used and can optimize how it is allocated.
|
||||||
*
|
*
|
||||||
|
* The texture is still configurable until it has been allocated so
|
||||||
|
* for example you can influence the internal format of the texture
|
||||||
|
* using cogl_texture_set_components() and
|
||||||
|
* cogl_texture_set_premultiplied().
|
||||||
|
*
|
||||||
* <note>Many GPUs only support power of two sizes for #CoglTexture2D
|
* <note>Many GPUs only support power of two sizes for #CoglTexture2D
|
||||||
* textures. You can check support for non power of two textures by
|
* textures. You can check support for non power of two textures by
|
||||||
* checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature via
|
* checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature via
|
||||||
@ -116,7 +118,23 @@ cogl_texture_2d_new_with_size (CoglContext *ctx,
|
|||||||
* other than straight blending.
|
* other than straight blending.
|
||||||
* @error: A #CoglError to catch exceptional errors or %NULL
|
* @error: A #CoglError to catch exceptional errors or %NULL
|
||||||
*
|
*
|
||||||
* Creates a #CoglTexture2D from an image file.
|
* Creates a low-level #CoglTexture2D texture from an image file.
|
||||||
|
*
|
||||||
|
* The storage for the texture is not allocated before this function
|
||||||
|
* returns. You can call cogl_texture_allocate() to explicitly
|
||||||
|
* allocate the underlying storage or preferably let Cogl
|
||||||
|
* automatically allocate storage lazily when it may know more about
|
||||||
|
* how the texture is being used and can optimize how it is allocated.
|
||||||
|
*
|
||||||
|
* The texture is still configurable until it has been allocated so
|
||||||
|
* for example you can influence the internal format of the texture
|
||||||
|
* using cogl_texture_set_components() and
|
||||||
|
* cogl_texture_set_premultiplied().
|
||||||
|
*
|
||||||
|
* <note>Many GPUs only support power of two sizes for #CoglTexture2D
|
||||||
|
* textures. You can check support for non power of two textures by
|
||||||
|
* checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature via
|
||||||
|
* cogl_has_feature().</note>
|
||||||
*
|
*
|
||||||
* Return value: (transfer full): A newly created #CoglTexture2D or %NULL on failure
|
* Return value: (transfer full): A newly created #CoglTexture2D or %NULL on failure
|
||||||
* and @error will be updated.
|
* and @error will be updated.
|
||||||
@ -149,10 +167,19 @@ cogl_texture_2d_new_from_file (CoglContext *ctx,
|
|||||||
* @data: pointer the memory region where the source buffer resides
|
* @data: pointer the memory region where the source buffer resides
|
||||||
* @error: A #CoglError for exceptions
|
* @error: A #CoglError for exceptions
|
||||||
*
|
*
|
||||||
* Creates a new #CoglTexture2D texture based on data residing in memory.
|
* Creates a low-level #CoglTexture2D texture based on data residing
|
||||||
* These are unlike sliced textures for example which may be comprised
|
* in memory.
|
||||||
* of multiple internal textures, or atlas textures where Cogl has to
|
*
|
||||||
* modify texture coordinates before they may be used by the GPU.
|
* <note>This api will always immediately allocate GPU memory for the
|
||||||
|
* texture and upload the given data so that the @data pointer does
|
||||||
|
* not need to remain valid once this function returns. This means it
|
||||||
|
* is not possible to configure the texture before it is allocated. If
|
||||||
|
* you do need to configure the texture before allocation (to specify
|
||||||
|
* constraints on the internal format for example) then you can
|
||||||
|
* instead create a #CoglBitmap for your data and use
|
||||||
|
* cogl_texture_2d_new_from_bitmap() or use
|
||||||
|
* cogl_texture_2d_new_with_size() and then upload data using
|
||||||
|
* cogl_texture_set_data()</note>
|
||||||
*
|
*
|
||||||
* <note>Many GPUs only support power of two sizes for #CoglTexture2D
|
* <note>Many GPUs only support power of two sizes for #CoglTexture2D
|
||||||
* textures. You can check support for non power of two textures by
|
* textures. You can check support for non power of two textures by
|
||||||
@ -189,11 +216,19 @@ cogl_texture_2d_new_from_data (CoglContext *ctx,
|
|||||||
* something other than straight blending.
|
* something other than straight blending.
|
||||||
* @error: A #CoglError for exceptions
|
* @error: A #CoglError for exceptions
|
||||||
*
|
*
|
||||||
* Creates a new #CoglTexture2D texture based on data residing in a
|
* Creates a low-level #CoglTexture2D texture based on data residing
|
||||||
* bitmap. These are unlike sliced textures for example which may be
|
* in a #CoglBitmap.
|
||||||
* comprised of multiple internal textures, or atlas textures where
|
*
|
||||||
* Cogl has to modify texture coordinates before they may be used by
|
* The storage for the texture is not allocated before this function
|
||||||
* the GPU.
|
* returns. You can call cogl_texture_allocate() to explicitly
|
||||||
|
* allocate the underlying storage or preferably let Cogl
|
||||||
|
* automatically allocate storage lazily when it may know more about
|
||||||
|
* how the texture is being used and can optimize how it is allocated.
|
||||||
|
*
|
||||||
|
* The texture is still configurable until it has been allocated so
|
||||||
|
* for example you can influence the internal format of the texture
|
||||||
|
* using cogl_texture_set_components() and
|
||||||
|
* cogl_texture_set_premultiplied().
|
||||||
*
|
*
|
||||||
* <note>Many GPUs only support power of two sizes for #CoglTexture2D
|
* <note>Many GPUs only support power of two sizes for #CoglTexture2D
|
||||||
* textures. You can check support for non power of two textures by
|
* textures. You can check support for non power of two textures by
|
||||||
|
@ -116,12 +116,14 @@ _cogl_texture_3d_create_base (CoglContext *ctx,
|
|||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
int depth,
|
int depth,
|
||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format,
|
||||||
|
CoglTextureLoader *loader)
|
||||||
{
|
{
|
||||||
CoglTexture3D *tex_3d = g_new (CoglTexture3D, 1);
|
CoglTexture3D *tex_3d = g_new (CoglTexture3D, 1);
|
||||||
CoglTexture *tex = COGL_TEXTURE (tex_3d);
|
CoglTexture *tex = COGL_TEXTURE (tex_3d);
|
||||||
|
|
||||||
_cogl_texture_init (tex, ctx, width, height, &cogl_texture_3d_vtable);
|
_cogl_texture_init (tex, ctx, width, height,
|
||||||
|
internal_format, loader, &cogl_texture_3d_vtable);
|
||||||
|
|
||||||
tex_3d->gl_texture = 0;
|
tex_3d->gl_texture = 0;
|
||||||
|
|
||||||
@ -138,72 +140,9 @@ _cogl_texture_3d_create_base (CoglContext *ctx,
|
|||||||
tex_3d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
|
tex_3d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
|
||||||
tex_3d->gl_legacy_texobj_wrap_mode_p = GL_FALSE;
|
tex_3d->gl_legacy_texobj_wrap_mode_p = GL_FALSE;
|
||||||
|
|
||||||
tex_3d->internal_format = internal_format;
|
|
||||||
|
|
||||||
return _cogl_texture_3d_object_new (tex_3d);
|
return _cogl_texture_3d_object_new (tex_3d);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglBool
|
|
||||||
_cogl_texture_3d_can_create (CoglContext *ctx,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int depth,
|
|
||||||
CoglPixelFormat internal_format,
|
|
||||||
CoglError **error)
|
|
||||||
{
|
|
||||||
GLenum gl_intformat;
|
|
||||||
GLenum gl_type;
|
|
||||||
|
|
||||||
/* This should only happen on GLES */
|
|
||||||
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D))
|
|
||||||
{
|
|
||||||
_cogl_set_error (error,
|
|
||||||
COGL_SYSTEM_ERROR,
|
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
|
||||||
"3D textures are not supported by the GPU");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If NPOT textures aren't supported then the size must be a power
|
|
||||||
of two */
|
|
||||||
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT) &&
|
|
||||||
(!_cogl_util_is_pot (width) ||
|
|
||||||
!_cogl_util_is_pot (height) ||
|
|
||||||
!_cogl_util_is_pot (depth)))
|
|
||||||
{
|
|
||||||
_cogl_set_error (error,
|
|
||||||
COGL_SYSTEM_ERROR,
|
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
|
||||||
"A non-power-of-two size was requested but this is not "
|
|
||||||
"supported by the GPU");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
|
||||||
internal_format,
|
|
||||||
&gl_intformat,
|
|
||||||
NULL,
|
|
||||||
&gl_type);
|
|
||||||
|
|
||||||
/* Check that the driver can create a texture with that size */
|
|
||||||
if (!ctx->texture_driver->size_supported_3d (ctx,
|
|
||||||
GL_TEXTURE_3D,
|
|
||||||
gl_intformat,
|
|
||||||
gl_type,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
depth))
|
|
||||||
{
|
|
||||||
_cogl_set_error (error,
|
|
||||||
COGL_SYSTEM_ERROR,
|
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
|
||||||
"The requested dimensions are not supported by the GPU");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoglTexture3D *
|
CoglTexture3D *
|
||||||
cogl_texture_3d_new_with_size (CoglContext *ctx,
|
cogl_texture_3d_new_with_size (CoglContext *ctx,
|
||||||
int width,
|
int width,
|
||||||
@ -211,177 +150,46 @@ cogl_texture_3d_new_with_size (CoglContext *ctx,
|
|||||||
int depth,
|
int depth,
|
||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format)
|
||||||
{
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
/* 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)
|
||||||
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||||
|
|
||||||
return _cogl_texture_3d_create_base (ctx,
|
loader = _cogl_texture_create_loader ();
|
||||||
width, height, depth,
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED;
|
||||||
internal_format);
|
loader->src.sized.width = width;
|
||||||
}
|
loader->src.sized.height = height;
|
||||||
|
loader->src.sized.depth = depth;
|
||||||
|
|
||||||
static CoglBool
|
return _cogl_texture_3d_create_base (ctx, width, height, depth,
|
||||||
_cogl_texture_3d_allocate (CoglTexture *tex,
|
internal_format, loader);
|
||||||
CoglError **error)
|
|
||||||
{
|
|
||||||
CoglContext *ctx = tex->context;
|
|
||||||
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
|
|
||||||
GLenum gl_intformat;
|
|
||||||
GLenum gl_format;
|
|
||||||
GLenum gl_type;
|
|
||||||
GLenum gl_error;
|
|
||||||
GLenum gl_texture;
|
|
||||||
|
|
||||||
if (!_cogl_texture_3d_can_create (ctx,
|
|
||||||
tex->width,
|
|
||||||
tex->height,
|
|
||||||
tex_3d->depth,
|
|
||||||
tex_3d->internal_format,
|
|
||||||
error))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
|
||||||
tex_3d->internal_format,
|
|
||||||
&gl_intformat,
|
|
||||||
&gl_format,
|
|
||||||
&gl_type);
|
|
||||||
|
|
||||||
gl_texture =
|
|
||||||
ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, tex_3d->internal_format);
|
|
||||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
|
|
||||||
gl_texture,
|
|
||||||
FALSE);
|
|
||||||
/* Clear any GL errors */
|
|
||||||
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
|
|
||||||
;
|
|
||||||
|
|
||||||
ctx->glTexImage3D (GL_TEXTURE_3D, 0, gl_intformat,
|
|
||||||
tex->width, tex->height, tex_3d->depth,
|
|
||||||
0, gl_format, gl_type, NULL);
|
|
||||||
|
|
||||||
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
|
|
||||||
{
|
|
||||||
GE( ctx, glDeleteTextures (1, &gl_texture) );
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
tex_3d->gl_texture = gl_texture;
|
|
||||||
tex_3d->gl_format = gl_intformat;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTexture3D *
|
CoglTexture3D *
|
||||||
cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
|
cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
|
||||||
unsigned int height,
|
int height,
|
||||||
unsigned int depth,
|
int depth,
|
||||||
CoglPixelFormat internal_format,
|
CoglPixelFormat internal_format,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglTexture3D *tex_3d;
|
CoglTextureLoader *loader;
|
||||||
CoglBitmap *upload_bmp;
|
|
||||||
CoglPixelFormat bmp_format;
|
|
||||||
CoglPixelFormat upload_format;
|
|
||||||
unsigned int bmp_width;
|
|
||||||
GLenum gl_intformat;
|
|
||||||
GLenum gl_format;
|
|
||||||
GLenum gl_type;
|
|
||||||
CoglContext *ctx;
|
|
||||||
|
|
||||||
ctx = _cogl_bitmap_get_context (bmp);
|
_COGL_RETURN_VAL_IF_FAIL (bmp, NULL);
|
||||||
|
|
||||||
bmp_width = cogl_bitmap_get_width (bmp);
|
loader = _cogl_texture_create_loader ();
|
||||||
bmp_format = cogl_bitmap_get_format (bmp);
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_BITMAP;
|
||||||
|
loader->src.bitmap.bitmap = cogl_object_ref (bmp);
|
||||||
|
loader->src.bitmap.height = height;
|
||||||
|
loader->src.bitmap.depth = depth;
|
||||||
|
loader->src.bitmap.can_convert_in_place = FALSE; /* TODO add api for this */
|
||||||
|
|
||||||
internal_format = _cogl_texture_determine_internal_format (bmp_format,
|
return _cogl_texture_3d_create_base (_cogl_bitmap_get_context (bmp),
|
||||||
internal_format);
|
cogl_bitmap_get_width (bmp),
|
||||||
|
|
||||||
if (!_cogl_texture_3d_can_create (ctx,
|
|
||||||
bmp_width, height, depth,
|
|
||||||
internal_format,
|
|
||||||
error))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
upload_bmp =
|
|
||||||
_cogl_bitmap_convert_for_upload (bmp,
|
|
||||||
internal_format,
|
|
||||||
FALSE, /* can't convert in place */
|
|
||||||
error);
|
|
||||||
if (upload_bmp == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
upload_format = cogl_bitmap_get_format (upload_bmp);
|
|
||||||
|
|
||||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
|
||||||
upload_format,
|
|
||||||
NULL, /* internal format */
|
|
||||||
&gl_format,
|
|
||||||
&gl_type);
|
|
||||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
|
||||||
internal_format,
|
|
||||||
&gl_intformat,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
tex_3d = _cogl_texture_3d_create_base (ctx,
|
|
||||||
bmp_width, height, depth,
|
|
||||||
internal_format);
|
|
||||||
|
|
||||||
/* Keep a copy of the first pixel so that if glGenerateMipmap isn't
|
|
||||||
supported we can fallback to using GL_GENERATE_MIPMAP */
|
|
||||||
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
|
|
||||||
{
|
|
||||||
CoglError *ignore = NULL;
|
|
||||||
uint8_t *data = _cogl_bitmap_map (upload_bmp,
|
|
||||||
COGL_BUFFER_ACCESS_READ, 0,
|
|
||||||
&ignore);
|
|
||||||
|
|
||||||
tex_3d->first_pixel.gl_format = gl_format;
|
|
||||||
tex_3d->first_pixel.gl_type = gl_type;
|
|
||||||
|
|
||||||
if (data)
|
|
||||||
{
|
|
||||||
memcpy (tex_3d->first_pixel.data, data,
|
|
||||||
_cogl_pixel_format_get_bytes_per_pixel (upload_format));
|
|
||||||
_cogl_bitmap_unmap (upload_bmp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_warning ("Failed to read first pixel of bitmap for "
|
|
||||||
"glGenerateMipmap fallback");
|
|
||||||
cogl_error_free (ignore);
|
|
||||||
memset (tex_3d->first_pixel.data, 0,
|
|
||||||
_cogl_pixel_format_get_bytes_per_pixel (upload_format));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tex_3d->gl_texture =
|
|
||||||
ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, internal_format);
|
|
||||||
|
|
||||||
if (!ctx->texture_driver->upload_to_gl_3d (ctx,
|
|
||||||
GL_TEXTURE_3D,
|
|
||||||
tex_3d->gl_texture,
|
|
||||||
FALSE, /* is_foreign */
|
|
||||||
height,
|
height,
|
||||||
depth,
|
depth,
|
||||||
upload_bmp,
|
internal_format,
|
||||||
gl_intformat,
|
loader);
|
||||||
gl_format,
|
|
||||||
gl_type,
|
|
||||||
error))
|
|
||||||
{
|
|
||||||
cogl_object_unref (upload_bmp);
|
|
||||||
cogl_object_unref (tex_3d);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tex_3d->gl_format = gl_intformat;
|
|
||||||
|
|
||||||
cogl_object_unref (upload_bmp);
|
|
||||||
|
|
||||||
_cogl_texture_set_allocated (COGL_TEXTURE (tex_3d), TRUE);
|
|
||||||
|
|
||||||
return tex_3d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTexture3D *
|
CoglTexture3D *
|
||||||
@ -399,14 +207,8 @@ cogl_texture_3d_new_from_data (CoglContext *context,
|
|||||||
CoglBitmap *bitmap;
|
CoglBitmap *bitmap;
|
||||||
CoglTexture3D *ret;
|
CoglTexture3D *ret;
|
||||||
|
|
||||||
/* These are considered a programmer errors so we won't set a
|
_COGL_RETURN_VAL_IF_FAIL (data, NULL);
|
||||||
CoglError. It would be nice if this was a _COGL_RETURN_IF_FAIL but the
|
_COGL_RETURN_VAL_IF_FAIL (format != COGL_PIXEL_FORMAT_ANY, NULL);
|
||||||
rest of Cogl isn't using that */
|
|
||||||
if (format == COGL_PIXEL_FORMAT_ANY)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (data == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Rowstride from width if not given */
|
/* Rowstride from width if not given */
|
||||||
if (rowstride == 0)
|
if (rowstride == 0)
|
||||||
@ -475,9 +277,273 @@ cogl_texture_3d_new_from_data (CoglContext *context,
|
|||||||
|
|
||||||
cogl_object_unref (bitmap);
|
cogl_object_unref (bitmap);
|
||||||
|
|
||||||
|
if (ret &&
|
||||||
|
!cogl_texture_allocate (COGL_TEXTURE (ret), error))
|
||||||
|
{
|
||||||
|
cogl_object_unref (ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
_cogl_texture_3d_can_create (CoglContext *ctx,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int depth,
|
||||||
|
CoglPixelFormat internal_format,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
GLenum gl_intformat;
|
||||||
|
GLenum gl_type;
|
||||||
|
|
||||||
|
/* This should only happen on GLES */
|
||||||
|
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D))
|
||||||
|
{
|
||||||
|
_cogl_set_error (error,
|
||||||
|
COGL_SYSTEM_ERROR,
|
||||||
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
|
"3D textures are not supported by the GPU");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If NPOT textures aren't supported then the size must be a power
|
||||||
|
of two */
|
||||||
|
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT) &&
|
||||||
|
(!_cogl_util_is_pot (width) ||
|
||||||
|
!_cogl_util_is_pot (height) ||
|
||||||
|
!_cogl_util_is_pot (depth)))
|
||||||
|
{
|
||||||
|
_cogl_set_error (error,
|
||||||
|
COGL_SYSTEM_ERROR,
|
||||||
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
|
"A non-power-of-two size was requested but this is not "
|
||||||
|
"supported by the GPU");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||||
|
internal_format,
|
||||||
|
&gl_intformat,
|
||||||
|
NULL,
|
||||||
|
&gl_type);
|
||||||
|
|
||||||
|
/* Check that the driver can create a texture with that size */
|
||||||
|
if (!ctx->texture_driver->size_supported_3d (ctx,
|
||||||
|
GL_TEXTURE_3D,
|
||||||
|
gl_intformat,
|
||||||
|
gl_type,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
depth))
|
||||||
|
{
|
||||||
|
_cogl_set_error (error,
|
||||||
|
COGL_SYSTEM_ERROR,
|
||||||
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
|
"The requested dimensions are not supported by the GPU");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
allocate_with_size (CoglTexture3D *tex_3d,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (tex_3d);
|
||||||
|
CoglContext *ctx = tex->context;
|
||||||
|
CoglPixelFormat internal_format;
|
||||||
|
int width = loader->src.sized.width;
|
||||||
|
int height = loader->src.sized.height;
|
||||||
|
int depth = loader->src.sized.depth;
|
||||||
|
GLenum gl_intformat;
|
||||||
|
GLenum gl_format;
|
||||||
|
GLenum gl_type;
|
||||||
|
GLenum gl_error;
|
||||||
|
GLenum gl_texture;
|
||||||
|
|
||||||
|
internal_format =
|
||||||
|
_cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY);
|
||||||
|
|
||||||
|
if (!_cogl_texture_3d_can_create (ctx,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
depth,
|
||||||
|
internal_format,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||||
|
internal_format,
|
||||||
|
&gl_intformat,
|
||||||
|
&gl_format,
|
||||||
|
&gl_type);
|
||||||
|
|
||||||
|
gl_texture =
|
||||||
|
ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, internal_format);
|
||||||
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
|
||||||
|
gl_texture,
|
||||||
|
FALSE);
|
||||||
|
/* Clear any GL errors */
|
||||||
|
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
|
||||||
|
;
|
||||||
|
|
||||||
|
ctx->glTexImage3D (GL_TEXTURE_3D, 0, gl_intformat,
|
||||||
|
width, height, depth,
|
||||||
|
0, gl_format, gl_type, NULL);
|
||||||
|
|
||||||
|
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
|
||||||
|
{
|
||||||
|
GE( ctx, glDeleteTextures (1, &gl_texture) );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tex_3d->gl_texture = gl_texture;
|
||||||
|
tex_3d->gl_format = gl_intformat;
|
||||||
|
|
||||||
|
tex_3d->depth = depth;
|
||||||
|
|
||||||
|
tex_3d->internal_format = internal_format;
|
||||||
|
|
||||||
|
_cogl_texture_set_allocated (tex, internal_format, width, height);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
allocate_from_bitmap (CoglTexture3D *tex_3d,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (tex_3d);
|
||||||
|
CoglContext *ctx = tex->context;
|
||||||
|
CoglPixelFormat internal_format;
|
||||||
|
CoglBitmap *bmp = loader->src.bitmap.bitmap;
|
||||||
|
int bmp_width = cogl_bitmap_get_width (bmp);
|
||||||
|
int height = loader->src.bitmap.height;
|
||||||
|
int depth = loader->src.bitmap.depth;
|
||||||
|
CoglPixelFormat bmp_format = cogl_bitmap_get_format (bmp);
|
||||||
|
CoglBool can_convert_in_place = loader->src.bitmap.can_convert_in_place;
|
||||||
|
CoglBitmap *upload_bmp;
|
||||||
|
CoglPixelFormat upload_format;
|
||||||
|
GLenum gl_intformat;
|
||||||
|
GLenum gl_format;
|
||||||
|
GLenum gl_type;
|
||||||
|
|
||||||
|
internal_format = _cogl_texture_determine_internal_format (tex, bmp_format);
|
||||||
|
|
||||||
|
if (!_cogl_texture_3d_can_create (ctx,
|
||||||
|
bmp_width, height, depth,
|
||||||
|
internal_format,
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
|
||||||
|
internal_format,
|
||||||
|
can_convert_in_place,
|
||||||
|
error);
|
||||||
|
if (upload_bmp == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
upload_format = cogl_bitmap_get_format (upload_bmp);
|
||||||
|
|
||||||
|
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||||
|
upload_format,
|
||||||
|
NULL, /* internal format */
|
||||||
|
&gl_format,
|
||||||
|
&gl_type);
|
||||||
|
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||||
|
internal_format,
|
||||||
|
&gl_intformat,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Keep a copy of the first pixel so that if glGenerateMipmap isn't
|
||||||
|
supported we can fallback to using GL_GENERATE_MIPMAP */
|
||||||
|
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
|
||||||
|
{
|
||||||
|
CoglError *ignore = NULL;
|
||||||
|
uint8_t *data = _cogl_bitmap_map (upload_bmp,
|
||||||
|
COGL_BUFFER_ACCESS_READ, 0,
|
||||||
|
&ignore);
|
||||||
|
|
||||||
|
tex_3d->first_pixel.gl_format = gl_format;
|
||||||
|
tex_3d->first_pixel.gl_type = gl_type;
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
memcpy (tex_3d->first_pixel.data, data,
|
||||||
|
_cogl_pixel_format_get_bytes_per_pixel (upload_format));
|
||||||
|
_cogl_bitmap_unmap (upload_bmp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning ("Failed to read first pixel of bitmap for "
|
||||||
|
"glGenerateMipmap fallback");
|
||||||
|
cogl_error_free (ignore);
|
||||||
|
memset (tex_3d->first_pixel.data, 0,
|
||||||
|
_cogl_pixel_format_get_bytes_per_pixel (upload_format));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tex_3d->gl_texture =
|
||||||
|
ctx->texture_driver->gen (ctx, GL_TEXTURE_3D, internal_format);
|
||||||
|
|
||||||
|
if (!ctx->texture_driver->upload_to_gl_3d (ctx,
|
||||||
|
GL_TEXTURE_3D,
|
||||||
|
tex_3d->gl_texture,
|
||||||
|
FALSE, /* is_foreign */
|
||||||
|
height,
|
||||||
|
depth,
|
||||||
|
upload_bmp,
|
||||||
|
gl_intformat,
|
||||||
|
gl_format,
|
||||||
|
gl_type,
|
||||||
|
error))
|
||||||
|
{
|
||||||
|
cogl_object_unref (upload_bmp);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tex_3d->gl_format = gl_intformat;
|
||||||
|
|
||||||
|
cogl_object_unref (upload_bmp);
|
||||||
|
|
||||||
|
tex_3d->depth = loader->src.bitmap.depth;
|
||||||
|
|
||||||
|
tex_3d->internal_format = internal_format;
|
||||||
|
|
||||||
|
_cogl_texture_set_allocated (tex, internal_format,
|
||||||
|
bmp_width, loader->src.bitmap.height);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
_cogl_texture_3d_allocate (CoglTexture *tex,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
|
||||||
|
CoglTextureLoader *loader = tex->loader;
|
||||||
|
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (loader, FALSE);
|
||||||
|
|
||||||
|
switch (loader->src_type)
|
||||||
|
{
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_SIZED:
|
||||||
|
return allocate_with_size (tex_3d, loader, error);
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_BITMAP:
|
||||||
|
return allocate_from_bitmap (tex_3d, loader, error);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_cogl_texture_3d_get_max_waste (CoglTexture *tex)
|
_cogl_texture_3d_get_max_waste (CoglTexture *tex)
|
||||||
{
|
{
|
||||||
|
@ -56,8 +56,8 @@ typedef struct _CoglTexture3D CoglTexture3D;
|
|||||||
* @internal_format: the #CoglPixelFormat to use for the GPU
|
* @internal_format: the #CoglPixelFormat to use for the GPU
|
||||||
* storage of the texture.
|
* storage of the texture.
|
||||||
*
|
*
|
||||||
* Creates a new #CoglTexture3D texture with the specified dimensions
|
* Creates a low-level #CoglTexture3D texture with the specified
|
||||||
* and pixel format.
|
* dimensions and pixel format.
|
||||||
*
|
*
|
||||||
* The storage for the texture is not allocated before this function
|
* The storage for the texture is not allocated before this function
|
||||||
* returns. You can call cogl_texture_allocate() to explicitly
|
* returns. You can call cogl_texture_allocate() to explicitly
|
||||||
@ -66,6 +66,11 @@ typedef struct _CoglTexture3D CoglTexture3D;
|
|||||||
* how the texture is going to be used and can optimize how it is
|
* how the texture is going to be used and can optimize how it is
|
||||||
* allocated.
|
* allocated.
|
||||||
*
|
*
|
||||||
|
* The texture is still configurable until it has been allocated so
|
||||||
|
* for example you can influence the internal format of the texture
|
||||||
|
* using cogl_texture_set_components() and
|
||||||
|
* cogl_texture_set_premultiplied().
|
||||||
|
*
|
||||||
* <note>This texture will fail to allocate later if
|
* <note>This texture will fail to allocate later if
|
||||||
* %COGL_FEATURE_ID_TEXTURE_3D is not advertised. Allocation can also
|
* %COGL_FEATURE_ID_TEXTURE_3D is not advertised. Allocation can also
|
||||||
* fail if the requested dimensions are not supported by the
|
* fail if the requested dimensions are not supported by the
|
||||||
@ -107,16 +112,21 @@ cogl_texture_3d_new_with_size (CoglContext *context,
|
|||||||
* @data: pointer the memory region where the source buffer resides
|
* @data: pointer the memory region where the source buffer resides
|
||||||
* @error: A CoglError return location.
|
* @error: A CoglError return location.
|
||||||
*
|
*
|
||||||
* Creates a new 3D texture and initializes it with @data. The data is
|
* Creates a low-level 3D texture and initializes it with @data. The
|
||||||
* assumed to be packed array of @depth images. There can be padding
|
* data is assumed to be packed array of @depth images. There can be
|
||||||
* between the images using @image_stride.
|
* padding between the images using @image_stride.
|
||||||
*
|
*
|
||||||
* Note that this function will throw a #CoglError if
|
* <note>This api will always immediately allocate GPU memory for the
|
||||||
* %COGL_FEATURE_ID_TEXTURE_3D is not advertised. It can also fail if the
|
* texture and upload the given data so that the @data pointer does
|
||||||
* requested dimensions are not supported by the GPU.
|
* not need to remain valid once this function returns. This means it
|
||||||
|
* is not possible to configure the texture before it is allocated. If
|
||||||
|
* you do need to configure the texture before allocation (to specify
|
||||||
|
* constraints on the internal format for example) then you can
|
||||||
|
* instead create a #CoglBitmap for your data and use
|
||||||
|
* cogl_texture_3d_new_from_bitmap().</note>
|
||||||
*
|
*
|
||||||
* Return value: (transfer full): the newly created #CoglTexture3D or
|
* Return value: (transfer full): the newly created #CoglTexture3D or
|
||||||
* %NULL if there was an error an an exception will be
|
* %NULL if there was an error and an exception will be
|
||||||
* returned through @error.
|
* returned through @error.
|
||||||
* Since: 1.10
|
* Since: 1.10
|
||||||
* Stability: Unstable
|
* Stability: Unstable
|
||||||
@ -148,13 +158,30 @@ cogl_texture_3d_new_from_data (CoglContext *context,
|
|||||||
* something other than straight blending.
|
* something other than straight blending.
|
||||||
* @error: A CoglError return location.
|
* @error: A CoglError return location.
|
||||||
*
|
*
|
||||||
* Creates a new 3D texture and initializes it with the images in
|
* Creates a low-level 3D texture and initializes it with the images
|
||||||
* @bitmap. The images are assumed to be packed together after one
|
* in @bitmap. The images are assumed to be packed together after one
|
||||||
* another in the increasing y axis. The height of individual image is
|
* another in the increasing y axis. The height of individual image is
|
||||||
* given as @height and the number of images is given in @depth. The
|
* given as @height and the number of images is given in @depth. The
|
||||||
* actual height of the bitmap can be larger than @height × @depth. In
|
* actual height of the bitmap can be larger than @height × @depth. In
|
||||||
* this case it assumes there is padding between the images.
|
* this case it assumes there is padding between the images.
|
||||||
*
|
*
|
||||||
|
* The storage for the texture is not allocated before this function
|
||||||
|
* returns. You can call cogl_texture_allocate() to explicitly
|
||||||
|
* allocate the underlying storage or preferably let Cogl
|
||||||
|
* automatically allocate storage lazily when it may know more about
|
||||||
|
* how the texture is going to be used and can optimize how it is
|
||||||
|
* allocated.
|
||||||
|
*
|
||||||
|
* The texture is still configurable until it has been allocated so
|
||||||
|
* for example you can influence the internal format of the texture
|
||||||
|
* using cogl_texture_set_components() and
|
||||||
|
* cogl_texture_set_premultiplied().
|
||||||
|
*
|
||||||
|
* <note>This texture will fail to allocate later if
|
||||||
|
* %COGL_FEATURE_ID_TEXTURE_3D is not advertised. Allocation can also
|
||||||
|
* fail if the requested dimensions are not supported by the
|
||||||
|
* GPU.</note>
|
||||||
|
*
|
||||||
* Return value: (transfer full): the newly created texture or %NULL
|
* Return value: (transfer full): the newly created texture or %NULL
|
||||||
* if there was an error.
|
* if there was an error.
|
||||||
* Since: 2.0
|
* Since: 2.0
|
||||||
@ -162,8 +189,8 @@ cogl_texture_3d_new_from_data (CoglContext *context,
|
|||||||
*/
|
*/
|
||||||
CoglTexture3D *
|
CoglTexture3D *
|
||||||
cogl_texture_3d_new_from_bitmap (CoglBitmap *bitmap,
|
cogl_texture_3d_new_from_bitmap (CoglBitmap *bitmap,
|
||||||
unsigned int height,
|
int height,
|
||||||
unsigned int depth,
|
int depth,
|
||||||
CoglPixelFormat internal_format,
|
CoglPixelFormat internal_format,
|
||||||
CoglError **error);
|
CoglError **error);
|
||||||
|
|
||||||
|
@ -31,6 +31,10 @@
|
|||||||
#include "cogl-meta-texture.h"
|
#include "cogl-meta-texture.h"
|
||||||
#include "cogl-framebuffer.h"
|
#include "cogl-framebuffer.h"
|
||||||
|
|
||||||
|
#ifdef COGL_HAS_EGL_SUPPORT
|
||||||
|
#include "cogl-egl-defines.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct _CoglTextureVtable CoglTextureVtable;
|
typedef struct _CoglTextureVtable CoglTextureVtable;
|
||||||
|
|
||||||
/* Encodes three possibiloities result of transforming a quad */
|
/* Encodes three possibiloities result of transforming a quad */
|
||||||
@ -139,15 +143,62 @@ struct _CoglTextureVtable
|
|||||||
CoglBool value);
|
CoglBool value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum _CoglTextureSoureType {
|
||||||
|
COGL_TEXTURE_SOURCE_TYPE_SIZED = 1,
|
||||||
|
COGL_TEXTURE_SOURCE_TYPE_BITMAP,
|
||||||
|
COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE,
|
||||||
|
COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN
|
||||||
|
} CoglTextureSourceType;
|
||||||
|
|
||||||
|
typedef struct _CoglTextureLoader
|
||||||
|
{
|
||||||
|
CoglTextureSourceType src_type;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int depth; /* for 3d textures */
|
||||||
|
} sized;
|
||||||
|
struct {
|
||||||
|
CoglBitmap *bitmap;
|
||||||
|
int height; /* for 3d textures */
|
||||||
|
int depth; /* for 3d textures */
|
||||||
|
CoglBool can_convert_in_place;
|
||||||
|
} bitmap;
|
||||||
|
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
||||||
|
struct {
|
||||||
|
EGLImageKHR image;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
CoglPixelFormat format;
|
||||||
|
} egl_image;
|
||||||
|
#endif
|
||||||
|
struct {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
unsigned int gl_handle;
|
||||||
|
CoglPixelFormat format;
|
||||||
|
} gl_foreign;
|
||||||
|
} src;
|
||||||
|
} CoglTextureLoader;
|
||||||
|
|
||||||
struct _CoglTexture
|
struct _CoglTexture
|
||||||
{
|
{
|
||||||
CoglObject _parent;
|
CoglObject _parent;
|
||||||
CoglContext *context;
|
CoglContext *context;
|
||||||
|
CoglTextureLoader *loader;
|
||||||
GList *framebuffers;
|
GList *framebuffers;
|
||||||
int max_level;
|
int max_level;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
CoglBool allocated;
|
CoglBool allocated;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal format
|
||||||
|
*/
|
||||||
|
CoglTextureComponents components;
|
||||||
|
unsigned int premultiplied:1;
|
||||||
|
|
||||||
const CoglTextureVtable *vtable;
|
const CoglTextureVtable *vtable;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,6 +234,8 @@ _cogl_texture_init (CoglTexture *texture,
|
|||||||
CoglContext *ctx,
|
CoglContext *ctx,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
CoglPixelFormat internal_format,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
const CoglTextureVtable *vtable);
|
const CoglTextureVtable *vtable);
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -220,12 +273,38 @@ _cogl_texture_pre_paint (CoglTexture *texture, CoglTexturePrePaintFlags flags);
|
|||||||
void
|
void
|
||||||
_cogl_texture_ensure_non_quad_rendering (CoglTexture *texture);
|
_cogl_texture_ensure_non_quad_rendering (CoglTexture *texture);
|
||||||
|
|
||||||
/* Utility function to determine which pixel format to use when
|
/*
|
||||||
dst_format is COGL_PIXEL_FORMAT_ANY. If dst_format is not ANY then
|
* This determines a CoglPixelFormat according to texture::components
|
||||||
it will just be returned directly */
|
* and texture::premultiplied (i.e. the user required components and
|
||||||
|
* whether the texture should be considered premultiplied)
|
||||||
|
*
|
||||||
|
* A reference/source format can be given (or COGL_PIXEL_FORMAT_ANY)
|
||||||
|
* and wherever possible this function tries to simply return the
|
||||||
|
* given source format if its compatible with the required components.
|
||||||
|
*
|
||||||
|
* Texture backends can call this when allocating a texture to know
|
||||||
|
* how to convert a source image in preparation for uploading.
|
||||||
|
*/
|
||||||
CoglPixelFormat
|
CoglPixelFormat
|
||||||
_cogl_texture_determine_internal_format (CoglPixelFormat src_format,
|
_cogl_texture_determine_internal_format (CoglTexture *texture,
|
||||||
CoglPixelFormat dst_format);
|
CoglPixelFormat src_format);
|
||||||
|
|
||||||
|
/* This is called by texture backends when they have successfully
|
||||||
|
* allocated a texture.
|
||||||
|
*
|
||||||
|
* Most texture backends currently track the internal layout of
|
||||||
|
* textures using a CoglPixelFormat which will be finalized when a
|
||||||
|
* texture is allocated. At this point we need to update
|
||||||
|
* texture::components and texture::premultiplied according to the
|
||||||
|
* determined layout.
|
||||||
|
*
|
||||||
|
* XXX: Going forward we should probably aim to stop using
|
||||||
|
* CoglPixelFormat at all for tracking the internal layout of
|
||||||
|
* textures.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_cogl_texture_set_internal_format (CoglTexture *texture,
|
||||||
|
CoglPixelFormat internal_format);
|
||||||
|
|
||||||
CoglBool
|
CoglBool
|
||||||
_cogl_texture_is_foreign (CoglTexture *texture);
|
_cogl_texture_is_foreign (CoglTexture *texture);
|
||||||
@ -306,9 +385,14 @@ _cogl_texture_get_level_size (CoglTexture *texture,
|
|||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_set_allocated (CoglTexture *texture,
|
_cogl_texture_set_allocated (CoglTexture *texture,
|
||||||
CoglBool allocated);
|
CoglPixelFormat internal_format,
|
||||||
|
int width,
|
||||||
|
int height);
|
||||||
|
|
||||||
CoglPixelFormat
|
CoglPixelFormat
|
||||||
_cogl_texture_get_format (CoglTexture *texture);
|
_cogl_texture_get_format (CoglTexture *texture);
|
||||||
|
|
||||||
|
CoglTextureLoader *
|
||||||
|
_cogl_texture_create_loader (void);
|
||||||
|
|
||||||
#endif /* __COGL_TEXTURE_PRIVATE_H */
|
#endif /* __COGL_TEXTURE_PRIVATE_H */
|
||||||
|
@ -166,12 +166,15 @@ static CoglTextureRectangle *
|
|||||||
_cogl_texture_rectangle_create_base (CoglContext *ctx,
|
_cogl_texture_rectangle_create_base (CoglContext *ctx,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
CoglPixelFormat internal_format)
|
CoglPixelFormat internal_format,
|
||||||
|
CoglTextureLoader *loader)
|
||||||
{
|
{
|
||||||
CoglTextureRectangle *tex_rect = g_new (CoglTextureRectangle, 1);
|
CoglTextureRectangle *tex_rect = g_new (CoglTextureRectangle, 1);
|
||||||
CoglTexture *tex = COGL_TEXTURE (tex_rect);
|
CoglTexture *tex = COGL_TEXTURE (tex_rect);
|
||||||
|
|
||||||
_cogl_texture_init (tex, ctx, width, height, &cogl_texture_rectangle_vtable);
|
_cogl_texture_init (tex, ctx, width, height,
|
||||||
|
internal_format, loader,
|
||||||
|
&cogl_texture_rectangle_vtable);
|
||||||
|
|
||||||
tex_rect->gl_texture = 0;
|
tex_rect->gl_texture = 0;
|
||||||
tex_rect->is_foreign = FALSE;
|
tex_rect->is_foreign = FALSE;
|
||||||
@ -184,8 +187,6 @@ _cogl_texture_rectangle_create_base (CoglContext *ctx,
|
|||||||
tex_rect->gl_legacy_texobj_wrap_mode_s = GL_FALSE;
|
tex_rect->gl_legacy_texobj_wrap_mode_s = GL_FALSE;
|
||||||
tex_rect->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
|
tex_rect->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
|
||||||
|
|
||||||
tex_rect->internal_format = internal_format;
|
|
||||||
|
|
||||||
return _cogl_texture_rectangle_object_new (tex_rect);
|
return _cogl_texture_rectangle_object_new (tex_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,16 +197,20 @@ cogl_texture_rectangle_new_with_size (CoglContext *ctx,
|
|||||||
CoglPixelFormat internal_format,
|
CoglPixelFormat internal_format,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
CoglTextureRectangle *tex_rect;
|
CoglTextureRectangle *tex_rect;
|
||||||
|
|
||||||
/* 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)
|
||||||
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||||
|
|
||||||
tex_rect =_cogl_texture_rectangle_create_base (ctx,
|
loader = _cogl_texture_create_loader ();
|
||||||
width, height,
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED;
|
||||||
internal_format);
|
loader->src.sized.width = width;
|
||||||
|
loader->src.sized.height = height;
|
||||||
|
|
||||||
|
tex_rect = _cogl_texture_rectangle_create_base (ctx, width, height,
|
||||||
|
internal_format, loader);
|
||||||
/* XXX: This api has been changed for Cogl 2.0 on the master branch
|
/* XXX: This api has been changed for Cogl 2.0 on the master branch
|
||||||
* to not take a CoglError to allow the storage to be allocated
|
* to not take a CoglError to allow the storage to be allocated
|
||||||
* lazily but since Mutter uses this api we are currently
|
* lazily but since Mutter uses this api we are currently
|
||||||
@ -216,30 +221,38 @@ cogl_texture_rectangle_new_with_size (CoglContext *ctx,
|
|||||||
cogl_object_unref (tex_rect);
|
cogl_object_unref (tex_rect);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tex_rect;
|
return tex_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
_cogl_texture_rectangle_allocate (CoglTexture *tex,
|
allocate_with_size (CoglTextureRectangle *tex_rect,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (tex_rect);
|
||||||
CoglContext *ctx = tex->context;
|
CoglContext *ctx = tex->context;
|
||||||
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
CoglPixelFormat internal_format;
|
||||||
|
int width = loader->src.sized.width;
|
||||||
|
int height = loader->src.sized.height;
|
||||||
GLenum gl_intformat;
|
GLenum gl_intformat;
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
GLenum gl_error;
|
GLenum gl_error;
|
||||||
GLenum gl_texture;
|
GLenum gl_texture;
|
||||||
|
|
||||||
|
internal_format =
|
||||||
|
_cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY);
|
||||||
|
|
||||||
if (!_cogl_texture_rectangle_can_create (ctx,
|
if (!_cogl_texture_rectangle_can_create (ctx,
|
||||||
tex->width,
|
width,
|
||||||
tex->height,
|
height,
|
||||||
tex_rect->internal_format,
|
internal_format,
|
||||||
error))
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||||
tex_rect->internal_format,
|
internal_format,
|
||||||
&gl_intformat,
|
&gl_intformat,
|
||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type);
|
&gl_type);
|
||||||
@ -247,7 +260,7 @@ _cogl_texture_rectangle_allocate (CoglTexture *tex,
|
|||||||
gl_texture =
|
gl_texture =
|
||||||
ctx->texture_driver->gen (ctx,
|
ctx->texture_driver->gen (ctx,
|
||||||
GL_TEXTURE_RECTANGLE_ARB,
|
GL_TEXTURE_RECTANGLE_ARB,
|
||||||
tex_rect->internal_format);
|
internal_format);
|
||||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
|
||||||
gl_texture,
|
gl_texture,
|
||||||
tex_rect->is_foreign);
|
tex_rect->is_foreign);
|
||||||
@ -257,7 +270,7 @@ _cogl_texture_rectangle_allocate (CoglTexture *tex,
|
|||||||
;
|
;
|
||||||
|
|
||||||
ctx->glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_intformat,
|
ctx->glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_intformat,
|
||||||
tex->width, tex->height, 0, gl_format, gl_type, NULL);
|
width, height, 0, gl_format, gl_type, NULL);
|
||||||
|
|
||||||
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
|
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
|
||||||
{
|
{
|
||||||
@ -265,46 +278,50 @@ _cogl_texture_rectangle_allocate (CoglTexture *tex,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tex_rect->internal_format = internal_format;
|
||||||
|
|
||||||
tex_rect->gl_texture = gl_texture;
|
tex_rect->gl_texture = gl_texture;
|
||||||
tex_rect->gl_format = gl_intformat;
|
tex_rect->gl_format = gl_intformat;
|
||||||
|
|
||||||
|
_cogl_texture_set_allocated (COGL_TEXTURE (tex_rect),
|
||||||
|
internal_format, width, height);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTextureRectangle *
|
static CoglBool
|
||||||
cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
|
allocate_from_bitmap (CoglTextureRectangle *tex_rect,
|
||||||
CoglPixelFormat internal_format,
|
CoglTextureLoader *loader,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglTextureRectangle *tex_rect;
|
CoglTexture *tex = COGL_TEXTURE (tex_rect);
|
||||||
|
CoglContext *ctx = tex->context;
|
||||||
|
CoglPixelFormat internal_format;
|
||||||
|
CoglBitmap *bmp = loader->src.bitmap.bitmap;
|
||||||
|
int width = cogl_bitmap_get_width (bmp);
|
||||||
|
int height = cogl_bitmap_get_height (bmp);
|
||||||
|
CoglBool can_convert_in_place = loader->src.bitmap.can_convert_in_place;
|
||||||
CoglBitmap *upload_bmp;
|
CoglBitmap *upload_bmp;
|
||||||
GLenum gl_intformat;
|
GLenum gl_intformat;
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
CoglContext *ctx;
|
|
||||||
|
|
||||||
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
|
|
||||||
|
|
||||||
ctx = _cogl_bitmap_get_context (bmp);
|
|
||||||
|
|
||||||
internal_format =
|
internal_format =
|
||||||
_cogl_texture_determine_internal_format (cogl_bitmap_get_format (bmp),
|
_cogl_texture_determine_internal_format (tex, cogl_bitmap_get_format (bmp));
|
||||||
internal_format);
|
|
||||||
|
|
||||||
if (!_cogl_texture_rectangle_can_create (ctx,
|
if (!_cogl_texture_rectangle_can_create (ctx,
|
||||||
cogl_bitmap_get_width (bmp),
|
width,
|
||||||
cogl_bitmap_get_height (bmp),
|
height,
|
||||||
internal_format,
|
internal_format,
|
||||||
error))
|
error))
|
||||||
return NULL;
|
return FALSE;
|
||||||
|
|
||||||
upload_bmp =
|
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
|
||||||
_cogl_bitmap_convert_for_upload (bmp,
|
|
||||||
internal_format,
|
internal_format,
|
||||||
FALSE, /* can't convert in place */
|
can_convert_in_place,
|
||||||
error);
|
error);
|
||||||
if (upload_bmp == NULL)
|
if (upload_bmp == NULL)
|
||||||
return NULL;
|
return FALSE;
|
||||||
|
|
||||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||||
cogl_bitmap_get_format (upload_bmp),
|
cogl_bitmap_get_format (upload_bmp),
|
||||||
@ -317,11 +334,6 @@ cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
|
|||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
tex_rect = _cogl_texture_rectangle_create_base (ctx,
|
|
||||||
cogl_bitmap_get_width (bmp),
|
|
||||||
cogl_bitmap_get_height (bmp),
|
|
||||||
internal_format);
|
|
||||||
|
|
||||||
tex_rect->gl_texture =
|
tex_rect->gl_texture =
|
||||||
ctx->texture_driver->gen (ctx,
|
ctx->texture_driver->gen (ctx,
|
||||||
GL_TEXTURE_RECTANGLE_ARB,
|
GL_TEXTURE_RECTANGLE_ARB,
|
||||||
@ -337,38 +349,31 @@ cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
|
|||||||
error))
|
error))
|
||||||
{
|
{
|
||||||
cogl_object_unref (upload_bmp);
|
cogl_object_unref (upload_bmp);
|
||||||
cogl_object_unref (tex_rect);
|
return FALSE;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tex_rect->gl_format = gl_intformat;
|
tex_rect->gl_format = gl_intformat;
|
||||||
|
tex_rect->internal_format = internal_format;
|
||||||
|
|
||||||
cogl_object_unref (upload_bmp);
|
cogl_object_unref (upload_bmp);
|
||||||
|
|
||||||
_cogl_texture_set_allocated (COGL_TEXTURE (tex_rect), TRUE);
|
_cogl_texture_set_allocated (COGL_TEXTURE (tex_rect),
|
||||||
|
internal_format, width, height);
|
||||||
|
|
||||||
return tex_rect;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTextureRectangle *
|
static CoglBool
|
||||||
cogl_texture_rectangle_new_from_foreign (CoglContext *ctx,
|
allocate_from_gl_foreign (CoglTextureRectangle *tex_rect,
|
||||||
unsigned int gl_handle,
|
CoglTextureLoader *loader,
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
CoglPixelFormat format,
|
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
/* NOTE: width, height and internal format are not queriable
|
CoglTexture *tex = COGL_TEXTURE (tex_rect);
|
||||||
* in GLES, hence such a function prototype.
|
CoglContext *ctx = tex->context;
|
||||||
*/
|
CoglPixelFormat format = loader->src.gl_foreign.format;
|
||||||
|
|
||||||
GLenum gl_error = 0;
|
GLenum gl_error = 0;
|
||||||
GLint gl_compressed = GL_FALSE;
|
GLint gl_compressed = GL_FALSE;
|
||||||
GLenum gl_int_format = 0;
|
GLenum gl_int_format = 0;
|
||||||
CoglTextureRectangle *tex_rect;
|
|
||||||
|
|
||||||
/* Assert that it is a valid GL texture object */
|
|
||||||
g_return_val_if_fail (ctx->glIsTexture (gl_handle), NULL);
|
|
||||||
|
|
||||||
if (!ctx->texture_driver->allows_foreign_gl_target (ctx,
|
if (!ctx->texture_driver->allows_foreign_gl_target (ctx,
|
||||||
GL_TEXTURE_RECTANGLE_ARB))
|
GL_TEXTURE_RECTANGLE_ARB))
|
||||||
@ -378,21 +383,22 @@ cogl_texture_rectangle_new_from_foreign (CoglContext *ctx,
|
|||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
"Foreign GL_TEXTURE_RECTANGLE textures are not "
|
"Foreign GL_TEXTURE_RECTANGLE textures are not "
|
||||||
"supported by your system");
|
"supported by your system");
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure binding succeeds */
|
/* Make sure binding succeeds */
|
||||||
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
|
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
|
||||||
;
|
;
|
||||||
|
|
||||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, gl_handle, TRUE);
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
|
||||||
|
loader->src.gl_foreign.gl_handle, TRUE);
|
||||||
if (ctx->glGetError () != GL_NO_ERROR)
|
if (ctx->glGetError () != GL_NO_ERROR)
|
||||||
{
|
{
|
||||||
_cogl_set_error (error,
|
_cogl_set_error (error,
|
||||||
COGL_SYSTEM_ERROR,
|
COGL_SYSTEM_ERROR,
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
"Failed to bind foreign GL_TEXTURE_RECTANGLE texture");
|
"Failed to bind foreign GL_TEXTURE_RECTANGLE texture");
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Obtain texture parameters */
|
/* Obtain texture parameters */
|
||||||
@ -423,7 +429,7 @@ cogl_texture_rectangle_new_from_foreign (CoglContext *ctx,
|
|||||||
COGL_SYSTEM_ERROR,
|
COGL_SYSTEM_ERROR,
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
"Unsupported internal format for foreign texture");
|
"Unsupported internal format for foreign texture");
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -438,16 +444,6 @@ cogl_texture_rectangle_new_from_foreign (CoglContext *ctx,
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: We always trust the given width and height without querying
|
|
||||||
* the texture object because the user may be creating a Cogl
|
|
||||||
* texture for a texture_from_pixmap object where glTexImage2D may
|
|
||||||
* not have been called and the texture_from_pixmap spec doesn't
|
|
||||||
* clarify that it is reliable to query back the size from OpenGL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Validate width and height */
|
|
||||||
g_return_val_if_fail (width > 0 && height > 0, NULL);
|
|
||||||
|
|
||||||
/* Compressed texture images not supported */
|
/* Compressed texture images not supported */
|
||||||
if (gl_compressed == GL_TRUE)
|
if (gl_compressed == GL_TRUE)
|
||||||
{
|
{
|
||||||
@ -455,27 +451,107 @@ cogl_texture_rectangle_new_from_foreign (CoglContext *ctx,
|
|||||||
COGL_SYSTEM_ERROR,
|
COGL_SYSTEM_ERROR,
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
"Compressed foreign textures aren't currently supported");
|
"Compressed foreign textures aren't currently supported");
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create new texture */
|
|
||||||
tex_rect = _cogl_texture_rectangle_create_base (ctx, width, height, format);
|
|
||||||
|
|
||||||
/* Setup bitmap info */
|
/* Setup bitmap info */
|
||||||
tex_rect->is_foreign = TRUE;
|
tex_rect->is_foreign = TRUE;
|
||||||
|
|
||||||
tex_rect->internal_format = format;
|
tex_rect->gl_texture = loader->src.gl_foreign.gl_handle;
|
||||||
|
|
||||||
tex_rect->gl_texture = gl_handle;
|
|
||||||
tex_rect->gl_format = gl_int_format;
|
tex_rect->gl_format = gl_int_format;
|
||||||
|
|
||||||
/* Unknown filter */
|
/* Unknown filter */
|
||||||
tex_rect->gl_legacy_texobj_min_filter = GL_FALSE;
|
tex_rect->gl_legacy_texobj_min_filter = GL_FALSE;
|
||||||
tex_rect->gl_legacy_texobj_mag_filter = GL_FALSE;
|
tex_rect->gl_legacy_texobj_mag_filter = GL_FALSE;
|
||||||
|
|
||||||
_cogl_texture_set_allocated (COGL_TEXTURE (tex_rect), TRUE);
|
tex_rect->internal_format = format;
|
||||||
|
|
||||||
return tex_rect;
|
_cogl_texture_set_allocated (COGL_TEXTURE (tex_rect),
|
||||||
|
format,
|
||||||
|
loader->src.gl_foreign.width,
|
||||||
|
loader->src.gl_foreign.height);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
_cogl_texture_rectangle_allocate (CoglTexture *tex,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
||||||
|
CoglTextureLoader *loader = tex->loader;
|
||||||
|
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (loader, FALSE);
|
||||||
|
|
||||||
|
switch (loader->src_type)
|
||||||
|
{
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_SIZED:
|
||||||
|
return allocate_with_size (tex_rect, loader, error);
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_BITMAP:
|
||||||
|
return allocate_from_bitmap (tex_rect, loader, error);
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN:
|
||||||
|
return allocate_from_gl_foreign (tex_rect, loader, error);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglTextureRectangle *
|
||||||
|
cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
|
||||||
|
CoglPixelFormat internal_format,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
|
||||||
|
|
||||||
|
loader = _cogl_texture_create_loader ();
|
||||||
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_BITMAP;
|
||||||
|
loader->src.bitmap.bitmap = cogl_object_ref (bmp);
|
||||||
|
loader->src.bitmap.can_convert_in_place = FALSE; /* TODO add api for this */
|
||||||
|
|
||||||
|
return _cogl_texture_rectangle_create_base (_cogl_bitmap_get_context (bmp),
|
||||||
|
cogl_bitmap_get_width (bmp),
|
||||||
|
cogl_bitmap_get_height (bmp),
|
||||||
|
internal_format,
|
||||||
|
loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglTextureRectangle *
|
||||||
|
cogl_texture_rectangle_new_from_foreign (CoglContext *ctx,
|
||||||
|
unsigned int gl_handle,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
CoglPixelFormat format,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
|
/* NOTE: width, height and internal format are not queriable in
|
||||||
|
* GLES, hence such a function prototype. Also in the case of full
|
||||||
|
* opengl the user may be creating a Cogl texture for a
|
||||||
|
* texture_from_pixmap object where glTexImage2D may not have been
|
||||||
|
* called and the texture_from_pixmap spec doesn't clarify that it
|
||||||
|
* is reliable to query back the size from OpenGL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Assert that it is a valid GL texture object */
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (ctx->glIsTexture (gl_handle), NULL);
|
||||||
|
|
||||||
|
/* Validate width and height */
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (width > 0 && height > 0, NULL);
|
||||||
|
|
||||||
|
loader = _cogl_texture_create_loader ();
|
||||||
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN;
|
||||||
|
loader->src.gl_foreign.gl_handle = gl_handle;
|
||||||
|
loader->src.gl_foreign.width = width;
|
||||||
|
loader->src.gl_foreign.height = height;
|
||||||
|
loader->src.gl_foreign.format = format;
|
||||||
|
|
||||||
|
return _cogl_texture_rectangle_create_base (ctx, width, height,
|
||||||
|
format, loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -102,6 +102,11 @@ cogl_is_texture_rectangle (void *object);
|
|||||||
* first check for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature
|
* first check for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature
|
||||||
* using cogl_has_feature().</note>
|
* using cogl_has_feature().</note>
|
||||||
*
|
*
|
||||||
|
* <note>For compatibility, unlike other texture constructors, this
|
||||||
|
* api allocates texture storage synchronously and returns %NULL on
|
||||||
|
* failure so it is not possible to configure rectangle textures
|
||||||
|
* created with this api before allocation.</note>
|
||||||
|
*
|
||||||
* Return value: (transfer full): A pointer to a newly allocated
|
* Return value: (transfer full): A pointer to a newly allocated
|
||||||
* #CoglTextureRectangle texture or if the size was too large
|
* #CoglTextureRectangle texture or if the size was too large
|
||||||
* or there wasn't enough memory %NULL is returned and @error
|
* or there wasn't enough memory %NULL is returned and @error
|
||||||
@ -144,10 +149,18 @@ cogl_texture_rectangle_new_with_size (CoglContext *ctx,
|
|||||||
* first check for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature
|
* first check for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature
|
||||||
* using cogl_has_feature().</note>
|
* using cogl_has_feature().</note>
|
||||||
*
|
*
|
||||||
|
* The storage for the texture is not allocated before this function
|
||||||
|
* returns. You can call cogl_texture_allocate() to explicitly
|
||||||
|
* allocate the underlying storage or preferably let Cogl
|
||||||
|
* automatically allocate storage lazily when it may know more about
|
||||||
|
* how the texture is going to be used and can optimize how it is
|
||||||
|
* allocated.
|
||||||
|
*
|
||||||
* Return value: (transfer full): A pointer to a newly allocated
|
* Return value: (transfer full): A pointer to a newly allocated
|
||||||
* #CoglTextureRectangle texture or if the size was too large
|
* #CoglTextureRectangle texture or if the size was too large
|
||||||
* or there wasn't enough memory %NULL is returned and @error
|
* or there wasn't enough memory %NULL is returned and @error
|
||||||
* set.
|
* set.
|
||||||
|
*
|
||||||
* Since: 2.0
|
* Since: 2.0
|
||||||
* Stability: unstable
|
* Stability: unstable
|
||||||
*/
|
*/
|
||||||
@ -185,12 +198,15 @@ cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bitmap,
|
|||||||
* <note>Applications wanting to use #CoglTextureRectangle should
|
* <note>Applications wanting to use #CoglTextureRectangle should
|
||||||
* first check for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature
|
* first check for the %COGL_FEATURE_ID_TEXTURE_RECTANGLE feature
|
||||||
* using cogl_has_feature().</note>
|
* using cogl_has_feature().</note>
|
||||||
|
*
|
||||||
|
* The texture is still configurable until it has been allocated so
|
||||||
|
* for example you can declare whether the texture is premultiplied
|
||||||
|
* with cogl_texture_set_premultiplied().
|
||||||
|
*
|
||||||
* Return value: (transfer full): A newly allocated
|
* Return value: (transfer full): A newly allocated
|
||||||
* #CoglTextureRectangle, or if Cogl could not validate the
|
* #CoglTextureRectangle, or if Cogl could not validate the
|
||||||
* @gl_handle in some way (perhaps because of an unsupported
|
* @gl_handle in some way (perhaps because of an unsupported
|
||||||
* format) it will return %NULL and set @error.
|
* format) it will return %NULL and set @error.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
CoglTextureRectangle *
|
CoglTextureRectangle *
|
||||||
cogl_texture_rectangle_new_from_foreign (CoglContext *ctx,
|
cogl_texture_rectangle_new_from_foreign (CoglContext *ctx,
|
||||||
|
@ -107,6 +107,8 @@ _cogl_texture_init (CoglTexture *texture,
|
|||||||
CoglContext *context,
|
CoglContext *context,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
CoglPixelFormat internal_format,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
const CoglTextureVtable *vtable)
|
const CoglTextureVtable *vtable)
|
||||||
{
|
{
|
||||||
texture->context = context;
|
texture->context = context;
|
||||||
@ -116,11 +118,44 @@ _cogl_texture_init (CoglTexture *texture,
|
|||||||
texture->allocated = FALSE;
|
texture->allocated = FALSE;
|
||||||
texture->vtable = vtable;
|
texture->vtable = vtable;
|
||||||
texture->framebuffers = NULL;
|
texture->framebuffers = NULL;
|
||||||
|
|
||||||
|
texture->loader = loader;
|
||||||
|
|
||||||
|
_cogl_texture_set_internal_format (texture, internal_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_texture_free_loader (CoglTexture *texture)
|
||||||
|
{
|
||||||
|
if (texture->loader)
|
||||||
|
{
|
||||||
|
CoglTextureLoader *loader = texture->loader;
|
||||||
|
switch (loader->src_type)
|
||||||
|
{
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_SIZED:
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE:
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN:
|
||||||
|
break;
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_BITMAP:
|
||||||
|
cogl_object_unref (loader->src.bitmap.bitmap);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_slice_free (CoglTextureLoader, loader);
|
||||||
|
texture->loader = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglTextureLoader *
|
||||||
|
_cogl_texture_create_loader (void)
|
||||||
|
{
|
||||||
|
return g_slice_new0 (CoglTextureLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_free (CoglTexture *texture)
|
_cogl_texture_free (CoglTexture *texture)
|
||||||
{
|
{
|
||||||
|
_cogl_texture_free_loader (texture);
|
||||||
|
|
||||||
g_free (texture);
|
g_free (texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,34 +170,6 @@ _cogl_texture_needs_premult_conversion (CoglPixelFormat src_format,
|
|||||||
(dst_format & COGL_PREMULT_BIT));
|
(dst_format & COGL_PREMULT_BIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglPixelFormat
|
|
||||||
_cogl_texture_determine_internal_format (CoglPixelFormat src_format,
|
|
||||||
CoglPixelFormat dst_format)
|
|
||||||
{
|
|
||||||
/* 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 (COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (src_format))
|
|
||||||
return src_format | COGL_PREMULT_BIT;
|
|
||||||
else
|
|
||||||
return src_format;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* XXX: It might be nice to make this match the component ordering
|
|
||||||
of the source format when the formats are otherwise the same
|
|
||||||
because on GL there is no way to specify the ordering of the
|
|
||||||
internal format. However when using GLES with the
|
|
||||||
GL_EXT_texture_format_BGRA8888 the order of the internal format
|
|
||||||
becomes important because it must exactly match the format of
|
|
||||||
the uploaded data. That means that if someone creates a texture
|
|
||||||
with some RGBA data and then later tries to upload BGRA data we
|
|
||||||
do actually have to swizzle the components */
|
|
||||||
return dst_format;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoglBool
|
CoglBool
|
||||||
_cogl_texture_is_foreign (CoglTexture *texture)
|
_cogl_texture_is_foreign (CoglTexture *texture)
|
||||||
{
|
{
|
||||||
@ -1348,9 +1355,17 @@ _cogl_texture_spans_foreach_in_region (CoglSpan *x_spans,
|
|||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_set_allocated (CoglTexture *texture,
|
_cogl_texture_set_allocated (CoglTexture *texture,
|
||||||
CoglBool allocated)
|
CoglPixelFormat internal_format,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
{
|
{
|
||||||
texture->allocated = allocated;
|
_cogl_texture_set_internal_format (texture, internal_format);
|
||||||
|
|
||||||
|
texture->width = width;
|
||||||
|
texture->height = height;
|
||||||
|
texture->allocated = TRUE;
|
||||||
|
|
||||||
|
_cogl_texture_free_loader (texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglBool
|
CoglBool
|
||||||
@ -1364,3 +1379,127 @@ cogl_texture_allocate (CoglTexture *texture,
|
|||||||
|
|
||||||
return texture->allocated;
|
return texture->allocated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_texture_set_internal_format (CoglTexture *texture,
|
||||||
|
CoglPixelFormat internal_format)
|
||||||
|
{
|
||||||
|
texture->premultiplied = FALSE;
|
||||||
|
|
||||||
|
if (internal_format == COGL_PIXEL_FORMAT_ANY)
|
||||||
|
internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||||
|
|
||||||
|
if (internal_format == COGL_PIXEL_FORMAT_A_8)
|
||||||
|
{
|
||||||
|
texture->components = COGL_TEXTURE_COMPONENTS_A;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (internal_format & COGL_DEPTH_BIT)
|
||||||
|
{
|
||||||
|
texture->components = COGL_TEXTURE_COMPONENTS_DEPTH;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (internal_format & COGL_A_BIT)
|
||||||
|
{
|
||||||
|
texture->components = COGL_TEXTURE_COMPONENTS_RGBA;
|
||||||
|
if (internal_format & COGL_PREMULT_BIT)
|
||||||
|
texture->premultiplied = TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
texture->components = COGL_TEXTURE_COMPONENTS_RGB;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglPixelFormat
|
||||||
|
_cogl_texture_determine_internal_format (CoglTexture *texture,
|
||||||
|
CoglPixelFormat src_format)
|
||||||
|
{
|
||||||
|
switch (texture->components)
|
||||||
|
{
|
||||||
|
case COGL_TEXTURE_COMPONENTS_DEPTH:
|
||||||
|
if (src_format & COGL_DEPTH_BIT)
|
||||||
|
return src_format;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CoglContext *ctx = texture->context;
|
||||||
|
|
||||||
|
if (_cogl_has_private_feature (ctx,
|
||||||
|
COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL) ||
|
||||||
|
_cogl_has_private_feature (ctx,
|
||||||
|
COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL))
|
||||||
|
{
|
||||||
|
return COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return COGL_PIXEL_FORMAT_DEPTH_16;
|
||||||
|
}
|
||||||
|
case COGL_TEXTURE_COMPONENTS_A:
|
||||||
|
return COGL_PIXEL_FORMAT_A_8;
|
||||||
|
case COGL_TEXTURE_COMPONENTS_RGB:
|
||||||
|
if (src_format != COGL_PIXEL_FORMAT_ANY &&
|
||||||
|
!(src_format & COGL_A_BIT) && !(src_format & COGL_DEPTH_BIT))
|
||||||
|
return src_format;
|
||||||
|
else
|
||||||
|
return COGL_PIXEL_FORMAT_RGB_888;
|
||||||
|
case COGL_TEXTURE_COMPONENTS_RGBA:
|
||||||
|
{
|
||||||
|
CoglPixelFormat format;
|
||||||
|
|
||||||
|
if (src_format != COGL_PIXEL_FORMAT_ANY &&
|
||||||
|
(src_format & COGL_A_BIT) && src_format != COGL_PIXEL_FORMAT_A_8)
|
||||||
|
format = src_format;
|
||||||
|
else
|
||||||
|
format = COGL_PIXEL_FORMAT_RGBA_8888;
|
||||||
|
|
||||||
|
if (texture->premultiplied)
|
||||||
|
{
|
||||||
|
if (COGL_PIXEL_FORMAT_CAN_HAVE_PREMULT (format))
|
||||||
|
return format |= COGL_PREMULT_BIT;
|
||||||
|
else
|
||||||
|
return COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return format & ~COGL_PREMULT_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_reached (COGL_PIXEL_FORMAT_RGBA_8888_PRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_texture_set_components (CoglTexture *texture,
|
||||||
|
CoglTextureComponents components)
|
||||||
|
{
|
||||||
|
_COGL_RETURN_IF_FAIL (!texture->allocated);
|
||||||
|
|
||||||
|
if (texture->components == components)
|
||||||
|
return;
|
||||||
|
|
||||||
|
texture->components = components;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglBool
|
||||||
|
cogl_texture_get_components (CoglTexture *texture)
|
||||||
|
{
|
||||||
|
return texture->components;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cogl_texture_set_premultiplied (CoglTexture *texture,
|
||||||
|
CoglBool premultiplied)
|
||||||
|
{
|
||||||
|
_COGL_RETURN_IF_FAIL (!texture->allocated);
|
||||||
|
|
||||||
|
premultiplied = !!premultiplied;
|
||||||
|
|
||||||
|
if (texture->premultiplied == premultiplied)
|
||||||
|
return;
|
||||||
|
|
||||||
|
texture->premultiplied = premultiplied;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglBool
|
||||||
|
cogl_texture_get_premultiplied (CoglTexture *texture)
|
||||||
|
{
|
||||||
|
return texture->premultiplied;
|
||||||
|
}
|
||||||
|
@ -256,6 +256,96 @@ cogl_texture_new_from_bitmap (CoglBitmap *bitmap,
|
|||||||
CoglBool
|
CoglBool
|
||||||
cogl_is_texture (void *object);
|
cogl_is_texture (void *object);
|
||||||
|
|
||||||
|
typedef enum _CoglTextureComponents
|
||||||
|
{
|
||||||
|
COGL_TEXTURE_COMPONENTS_A = 1,
|
||||||
|
COGL_TEXTURE_COMPONENTS_RGB,
|
||||||
|
COGL_TEXTURE_COMPONENTS_RGBA,
|
||||||
|
COGL_TEXTURE_COMPONENTS_DEPTH
|
||||||
|
} CoglTextureComponents;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cogl_texture_set_components:
|
||||||
|
* @texture: a #CoglTexture pointer.
|
||||||
|
*
|
||||||
|
* Affects the internal storage format for this texture by
|
||||||
|
* determinging what components will be required for sampling later.
|
||||||
|
*
|
||||||
|
* This api affects how data is uploaded to the GPU since unused
|
||||||
|
* components can potentially be discarded from source data.
|
||||||
|
*
|
||||||
|
* By default the required components are automatically determined
|
||||||
|
* using the format of the source data that is first uploaded to
|
||||||
|
* the given @texture.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
cogl_texture_set_components (CoglTexture *texture,
|
||||||
|
CoglTextureComponents components);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cogl_texture_get_components:
|
||||||
|
* @texture: a #CoglTexture pointer.
|
||||||
|
*
|
||||||
|
* Queries what components the given @texture stores internally as set
|
||||||
|
* via cogl_texture_set_components().
|
||||||
|
*
|
||||||
|
* By default the required components are automatically determined
|
||||||
|
* using the format of the source data that is first uploaded to
|
||||||
|
* the given @texture.
|
||||||
|
*/
|
||||||
|
CoglBool
|
||||||
|
cogl_texture_get_components (CoglTexture *texture);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cogl_texture_set_premultiplied:
|
||||||
|
* @texture: a #CoglTexture pointer.
|
||||||
|
* @premultiplied: Whether any internally stored red, green or blue
|
||||||
|
* components are pre-multiplied by an alpha
|
||||||
|
* component.
|
||||||
|
*
|
||||||
|
* Affects the internal storage format for this texture by determining
|
||||||
|
* whether red, green and blue color components should be stored as
|
||||||
|
* pre-multiplied alpha values.
|
||||||
|
*
|
||||||
|
* This api affects how data is uploaded to the GPU since Cogl will
|
||||||
|
* convert source data to have premultiplied or unpremultiplied
|
||||||
|
* components according to this state.
|
||||||
|
*
|
||||||
|
* For example if you create a texture via
|
||||||
|
* cogl_texture_2d_new_with_size() and then upload data via
|
||||||
|
* cogl_texture_set_data() passing a source format of
|
||||||
|
* %COGL_PIXEL_FORMAT_RGBA_8888 then Cogl will internally multiply the
|
||||||
|
* red, green and blue components of the source data by the alpha
|
||||||
|
* component, for each pixel so that the internally stored data has
|
||||||
|
* pre-multiplied alpha components. If you instead upload data that
|
||||||
|
* already has pre-multiplied components by passing
|
||||||
|
* %COGL_PIXEL_FORMAT_RGBA_8888_PRE as the source format to
|
||||||
|
* cogl_texture_set_data() then the data can be uploaded without being
|
||||||
|
* converted.
|
||||||
|
*
|
||||||
|
* By default the @premultipled state is @TRUE.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
cogl_texture_set_premultiplied (CoglTexture *texture,
|
||||||
|
CoglBool premultiplied);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cogl_texture_get_premultiplied:
|
||||||
|
* @texture: a #CoglTexture pointer.
|
||||||
|
*
|
||||||
|
* Queries the pre-multiplied alpha status for internally stored red,
|
||||||
|
* green and blue components for the given @texture as set by
|
||||||
|
* cogl_texture_set_premultiplied().
|
||||||
|
*
|
||||||
|
* By default the pre-multipled state is @TRUE.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if red, green and blue components are
|
||||||
|
* internally stored pre-multiplied by the alpha
|
||||||
|
* value or %FALSE if not.
|
||||||
|
*/
|
||||||
|
CoglBool
|
||||||
|
cogl_texture_get_premultiplied (CoglTexture *texture);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cogl_texture_get_width:
|
* cogl_texture_get_width:
|
||||||
* @texture: a #CoglTexture pointer.
|
* @texture: a #CoglTexture pointer.
|
||||||
|
@ -25,13 +25,12 @@
|
|||||||
* Robert Bragg <robert@linux.intel.com>
|
* Robert Bragg <robert@linux.intel.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#include <config.h>
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "cogl-private.h"
|
#include "cogl-private.h"
|
||||||
|
#include "cogl-texture-private.h"
|
||||||
#include "cogl-texture-2d-gl.h"
|
#include "cogl-texture-2d-gl.h"
|
||||||
#include "cogl-texture-2d-gl-private.h"
|
#include "cogl-texture-2d-gl-private.h"
|
||||||
#include "cogl-texture-2d-private.h"
|
#include "cogl-texture-2d-private.h"
|
||||||
@ -57,6 +56,13 @@ _cogl_texture_2d_gl_can_create (CoglContext *ctx,
|
|||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
|
||||||
|
/* If NPOT textures aren't supported then the size must be a power
|
||||||
|
of two */
|
||||||
|
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
|
||||||
|
(!_cogl_util_is_pot (width) ||
|
||||||
|
!_cogl_util_is_pot (height)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||||
internal_format,
|
internal_format,
|
||||||
&gl_intformat,
|
&gl_intformat,
|
||||||
@ -90,22 +96,29 @@ _cogl_texture_2d_gl_init (CoglTexture2D *tex_2d)
|
|||||||
tex_2d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
|
tex_2d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglBool
|
static CoglBool
|
||||||
_cogl_texture_2d_gl_allocate (CoglTexture *tex,
|
allocate_with_size (CoglTexture2D *tex_2d,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||||
|
CoglPixelFormat internal_format;
|
||||||
|
int width = loader->src.sized.width;
|
||||||
|
int height = loader->src.sized.height;
|
||||||
CoglContext *ctx = tex->context;
|
CoglContext *ctx = tex->context;
|
||||||
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
|
|
||||||
GLenum gl_intformat;
|
GLenum gl_intformat;
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
GLenum gl_error;
|
GLenum gl_error;
|
||||||
GLenum gl_texture;
|
GLenum gl_texture;
|
||||||
|
|
||||||
|
internal_format =
|
||||||
|
_cogl_texture_determine_internal_format (tex, COGL_PIXEL_FORMAT_ANY);
|
||||||
|
|
||||||
if (!_cogl_texture_2d_gl_can_create (ctx,
|
if (!_cogl_texture_2d_gl_can_create (ctx,
|
||||||
tex->width,
|
width,
|
||||||
tex->height,
|
height,
|
||||||
tex_2d->internal_format))
|
internal_format))
|
||||||
{
|
{
|
||||||
_cogl_set_error (error, COGL_TEXTURE_ERROR,
|
_cogl_set_error (error, COGL_TEXTURE_ERROR,
|
||||||
COGL_TEXTURE_ERROR_SIZE,
|
COGL_TEXTURE_ERROR_SIZE,
|
||||||
@ -115,13 +128,12 @@ _cogl_texture_2d_gl_allocate (CoglTexture *tex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||||
tex_2d->internal_format,
|
internal_format,
|
||||||
&gl_intformat,
|
&gl_intformat,
|
||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type);
|
&gl_type);
|
||||||
|
|
||||||
gl_texture =
|
gl_texture = ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, internal_format);
|
||||||
ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, tex_2d->internal_format);
|
|
||||||
|
|
||||||
tex_2d->gl_internal_format = gl_intformat;
|
tex_2d->gl_internal_format = gl_intformat;
|
||||||
|
|
||||||
@ -134,7 +146,7 @@ _cogl_texture_2d_gl_allocate (CoglTexture *tex,
|
|||||||
;
|
;
|
||||||
|
|
||||||
ctx->glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
|
ctx->glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
|
||||||
tex->width, tex->height, 0, gl_format, gl_type, NULL);
|
width, height, 0, gl_format, gl_type, NULL);
|
||||||
|
|
||||||
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
|
if (_cogl_gl_util_catch_out_of_memory (ctx, error))
|
||||||
{
|
{
|
||||||
@ -145,28 +157,51 @@ _cogl_texture_2d_gl_allocate (CoglTexture *tex,
|
|||||||
tex_2d->gl_texture = gl_texture;
|
tex_2d->gl_texture = gl_texture;
|
||||||
tex_2d->gl_internal_format = gl_intformat;
|
tex_2d->gl_internal_format = gl_intformat;
|
||||||
|
|
||||||
|
tex_2d->internal_format = internal_format;
|
||||||
|
|
||||||
|
_cogl_texture_set_allocated (tex, internal_format, width, height);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTexture2D *
|
static CoglBool
|
||||||
_cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
|
allocate_from_bitmap (CoglTexture2D *tex_2d,
|
||||||
CoglPixelFormat internal_format,
|
CoglTextureLoader *loader,
|
||||||
CoglBool can_convert_in_place,
|
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||||
|
CoglBitmap *bmp = loader->src.bitmap.bitmap;
|
||||||
CoglContext *ctx = _cogl_bitmap_get_context (bmp);
|
CoglContext *ctx = _cogl_bitmap_get_context (bmp);
|
||||||
CoglTexture2D *tex_2d;
|
CoglPixelFormat internal_format;
|
||||||
|
int width = cogl_bitmap_get_width (bmp);
|
||||||
|
int height = cogl_bitmap_get_height (bmp);
|
||||||
|
CoglBool can_convert_in_place = loader->src.bitmap.can_convert_in_place;
|
||||||
CoglBitmap *upload_bmp;
|
CoglBitmap *upload_bmp;
|
||||||
GLenum gl_intformat;
|
GLenum gl_intformat;
|
||||||
GLenum gl_format;
|
GLenum gl_format;
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
|
|
||||||
|
internal_format =
|
||||||
|
_cogl_texture_determine_internal_format (tex, cogl_bitmap_get_format (bmp));
|
||||||
|
|
||||||
|
if (!_cogl_texture_2d_gl_can_create (ctx,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
internal_format))
|
||||||
|
{
|
||||||
|
_cogl_set_error (error, COGL_TEXTURE_ERROR,
|
||||||
|
COGL_TEXTURE_ERROR_SIZE,
|
||||||
|
"Failed to create texture 2d due to size/format"
|
||||||
|
" constraints");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
|
upload_bmp = _cogl_bitmap_convert_for_upload (bmp,
|
||||||
internal_format,
|
internal_format,
|
||||||
can_convert_in_place,
|
can_convert_in_place,
|
||||||
error);
|
error);
|
||||||
if (upload_bmp == NULL)
|
if (upload_bmp == NULL)
|
||||||
return NULL;
|
return FALSE;
|
||||||
|
|
||||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||||
cogl_bitmap_get_format (upload_bmp),
|
cogl_bitmap_get_format (upload_bmp),
|
||||||
@ -179,11 +214,6 @@ _cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
|
|||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
tex_2d = _cogl_texture_2d_create_base (ctx,
|
|
||||||
cogl_bitmap_get_width (bmp),
|
|
||||||
cogl_bitmap_get_height (bmp),
|
|
||||||
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_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
|
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
|
||||||
@ -226,44 +256,40 @@ _cogl_texture_2d_gl_new_from_bitmap (CoglBitmap *bmp,
|
|||||||
error))
|
error))
|
||||||
{
|
{
|
||||||
cogl_object_unref (upload_bmp);
|
cogl_object_unref (upload_bmp);
|
||||||
cogl_object_unref (tex_2d);
|
return FALSE;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tex_2d->gl_internal_format = gl_intformat;
|
tex_2d->gl_internal_format = gl_intformat;
|
||||||
|
|
||||||
cogl_object_unref (upload_bmp);
|
cogl_object_unref (upload_bmp);
|
||||||
|
|
||||||
_cogl_texture_set_allocated (COGL_TEXTURE (tex_2d), TRUE);
|
tex_2d->internal_format = internal_format;
|
||||||
|
|
||||||
return tex_2d;
|
_cogl_texture_set_allocated (tex, internal_format, width, height);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
||||||
CoglTexture2D *
|
static CoglBool
|
||||||
_cogl_egl_texture_2d_gl_new_from_image (CoglContext *ctx,
|
allocate_from_egl_image (CoglTexture2D *tex_2d,
|
||||||
int width,
|
CoglTextureLoader *loader,
|
||||||
int height,
|
|
||||||
CoglPixelFormat format,
|
|
||||||
EGLImageKHR image,
|
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
CoglTexture2D *tex_2d;
|
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||||
|
CoglContext *ctx = tex->context;
|
||||||
|
CoglPixelFormat internal_format = loader->src.egl_image.format;
|
||||||
GLenum gl_error;
|
GLenum gl_error;
|
||||||
|
|
||||||
tex_2d = _cogl_texture_2d_create_base (ctx,
|
|
||||||
width, height,
|
|
||||||
format);
|
|
||||||
|
|
||||||
tex_2d->gl_texture =
|
tex_2d->gl_texture =
|
||||||
ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, format);
|
ctx->texture_driver->gen (ctx, GL_TEXTURE_2D, internal_format);
|
||||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
||||||
tex_2d->gl_texture,
|
tex_2d->gl_texture,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
|
||||||
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
|
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
|
||||||
;
|
;
|
||||||
ctx->glEGLImageTargetTexture2D (GL_TEXTURE_2D, image);
|
ctx->glEGLImageTargetTexture2D (GL_TEXTURE_2D, loader->src.egl_image.image);
|
||||||
if (ctx->glGetError () != GL_NO_ERROR)
|
if (ctx->glGetError () != GL_NO_ERROR)
|
||||||
{
|
{
|
||||||
_cogl_set_error (error,
|
_cogl_set_error (error,
|
||||||
@ -271,16 +297,175 @@ _cogl_egl_texture_2d_gl_new_from_image (CoglContext *ctx,
|
|||||||
COGL_TEXTURE_ERROR_BAD_PARAMETER,
|
COGL_TEXTURE_ERROR_BAD_PARAMETER,
|
||||||
"Could not create a CoglTexture2D from a given "
|
"Could not create a CoglTexture2D from a given "
|
||||||
"EGLImage");
|
"EGLImage");
|
||||||
cogl_object_unref (tex_2d);
|
GE( ctx, glDeleteTextures (1, &tex_2d->gl_texture) );
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cogl_texture_set_allocated (COGL_TEXTURE (tex_2d), TRUE);
|
tex_2d->internal_format = internal_format;
|
||||||
|
|
||||||
return tex_2d;
|
_cogl_texture_set_allocated (tex,
|
||||||
|
internal_format,
|
||||||
|
loader->src.egl_image.width,
|
||||||
|
loader->src.egl_image.height);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
allocate_from_gl_foreign (CoglTexture2D *tex_2d,
|
||||||
|
CoglTextureLoader *loader,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||||
|
CoglContext *ctx = tex->context;
|
||||||
|
CoglPixelFormat format = loader->src.gl_foreign.format;
|
||||||
|
GLenum gl_error = 0;
|
||||||
|
GLint gl_compressed = GL_FALSE;
|
||||||
|
GLenum gl_int_format = 0;
|
||||||
|
|
||||||
|
if (!ctx->texture_driver->allows_foreign_gl_target (ctx, GL_TEXTURE_2D))
|
||||||
|
{
|
||||||
|
_cogl_set_error (error,
|
||||||
|
COGL_SYSTEM_ERROR,
|
||||||
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
|
"Foreign GL_TEXTURE_2D textures are not "
|
||||||
|
"supported by your system");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure binding succeeds */
|
||||||
|
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
|
||||||
|
;
|
||||||
|
|
||||||
|
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
||||||
|
loader->src.gl_foreign.gl_handle, TRUE);
|
||||||
|
if (ctx->glGetError () != GL_NO_ERROR)
|
||||||
|
{
|
||||||
|
_cogl_set_error (error,
|
||||||
|
COGL_SYSTEM_ERROR,
|
||||||
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
|
"Failed to bind foreign GL_TEXTURE_2D texture");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Obtain texture parameters
|
||||||
|
(only level 0 we are interested in) */
|
||||||
|
|
||||||
|
#ifdef HAVE_COGL_GL
|
||||||
|
if (_cogl_has_private_feature
|
||||||
|
(ctx, COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS))
|
||||||
|
{
|
||||||
|
GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
|
||||||
|
GL_TEXTURE_COMPRESSED,
|
||||||
|
&gl_compressed) );
|
||||||
|
|
||||||
|
{
|
||||||
|
GLint val;
|
||||||
|
|
||||||
|
GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
|
||||||
|
GL_TEXTURE_INTERNAL_FORMAT,
|
||||||
|
&val) );
|
||||||
|
|
||||||
|
gl_int_format = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we can query GL for the actual pixel format then we'll ignore
|
||||||
|
the passed in format and use that. */
|
||||||
|
if (!ctx->driver_vtable->pixel_format_from_gl_internal (ctx,
|
||||||
|
gl_int_format,
|
||||||
|
&format))
|
||||||
|
{
|
||||||
|
_cogl_set_error (error,
|
||||||
|
COGL_SYSTEM_ERROR,
|
||||||
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
|
"Unsupported internal format for foreign texture");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Otherwise we'll assume we can derive the GL format from the
|
||||||
|
passed in format */
|
||||||
|
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
||||||
|
format,
|
||||||
|
&gl_int_format,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compressed texture images not supported */
|
||||||
|
if (gl_compressed == GL_TRUE)
|
||||||
|
{
|
||||||
|
_cogl_set_error (error,
|
||||||
|
COGL_SYSTEM_ERROR,
|
||||||
|
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
||||||
|
"Compressed foreign textures aren't currently supported");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: previously this code would query the texture object for
|
||||||
|
whether it has GL_GENERATE_MIPMAP enabled to determine whether to
|
||||||
|
auto-generate the mipmap. This doesn't make much sense any more
|
||||||
|
since Cogl switch to using glGenerateMipmap. Ideally I think
|
||||||
|
cogl_texture_2d_new_from_foreign should take a flags parameter so
|
||||||
|
that the application can decide whether it wants
|
||||||
|
auto-mipmapping. To be compatible with existing code, Cogl now
|
||||||
|
disables its own auto-mipmapping but leaves the value of
|
||||||
|
GL_GENERATE_MIPMAP alone so that it would still work but without
|
||||||
|
the dirtiness tracking that Cogl would do. */
|
||||||
|
|
||||||
|
_cogl_texture_2d_set_auto_mipmap (COGL_TEXTURE (tex_2d), FALSE);
|
||||||
|
|
||||||
|
/* Setup bitmap info */
|
||||||
|
tex_2d->is_foreign = TRUE;
|
||||||
|
tex_2d->mipmaps_dirty = TRUE;
|
||||||
|
|
||||||
|
tex_2d->gl_texture = loader->src.gl_foreign.gl_handle;
|
||||||
|
tex_2d->gl_internal_format = gl_int_format;
|
||||||
|
|
||||||
|
/* Unknown filter */
|
||||||
|
tex_2d->gl_legacy_texobj_min_filter = GL_FALSE;
|
||||||
|
tex_2d->gl_legacy_texobj_mag_filter = GL_FALSE;
|
||||||
|
|
||||||
|
tex_2d->internal_format = format;
|
||||||
|
|
||||||
|
_cogl_texture_set_allocated (tex,
|
||||||
|
format,
|
||||||
|
loader->src.gl_foreign.width,
|
||||||
|
loader->src.gl_foreign.height);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoglBool
|
||||||
|
_cogl_texture_2d_gl_allocate (CoglTexture *tex,
|
||||||
|
CoglError **error)
|
||||||
|
{
|
||||||
|
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
|
||||||
|
CoglTextureLoader *loader = tex->loader;
|
||||||
|
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (loader, FALSE);
|
||||||
|
|
||||||
|
switch (loader->src_type)
|
||||||
|
{
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_SIZED:
|
||||||
|
return allocate_with_size (tex_2d, loader, error);
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_BITMAP:
|
||||||
|
return allocate_from_bitmap (tex_2d, loader, error);
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE:
|
||||||
|
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
||||||
|
return allocate_from_egl_image (tex_2d, loader, error);
|
||||||
|
#else
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
|
#endif
|
||||||
|
case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN:
|
||||||
|
return allocate_from_gl_foreign (tex_2d, loader, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_2d_gl_flush_legacy_texobj_filters (CoglTexture *tex,
|
_cogl_texture_2d_gl_flush_legacy_texobj_filters (CoglTexture *tex,
|
||||||
GLenum min_filter,
|
GLenum min_filter,
|
||||||
@ -343,89 +528,12 @@ cogl_texture_2d_new_from_foreign (CoglContext *ctx,
|
|||||||
CoglPixelFormat format,
|
CoglPixelFormat format,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
{
|
{
|
||||||
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
/* NOTE: width, height and internal format are not queriable
|
/* NOTE: width, height and internal format are not queriable
|
||||||
* in GLES, hence such a function prototype.
|
* in GLES, hence such a function prototype.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
GLenum gl_error = 0;
|
|
||||||
GLint gl_compressed = GL_FALSE;
|
|
||||||
GLenum gl_int_format = 0;
|
|
||||||
CoglTexture2D *tex_2d;
|
|
||||||
|
|
||||||
/* Assert it is a valid GL texture object */
|
|
||||||
g_return_val_if_fail (ctx->glIsTexture (gl_handle), NULL);
|
|
||||||
|
|
||||||
if (!ctx->texture_driver->allows_foreign_gl_target (ctx, GL_TEXTURE_2D))
|
|
||||||
{
|
|
||||||
_cogl_set_error (error,
|
|
||||||
COGL_SYSTEM_ERROR,
|
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
|
||||||
"Foreign GL_TEXTURE_2D textures are not "
|
|
||||||
"supported by your system");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Make sure binding succeeds */
|
|
||||||
while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
|
|
||||||
;
|
|
||||||
|
|
||||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D, gl_handle, TRUE);
|
|
||||||
if (ctx->glGetError () != GL_NO_ERROR)
|
|
||||||
{
|
|
||||||
_cogl_set_error (error,
|
|
||||||
COGL_SYSTEM_ERROR,
|
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
|
||||||
"Failed to bind foreign GL_TEXTURE_2D texture");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Obtain texture parameters
|
|
||||||
(only level 0 we are interested in) */
|
|
||||||
|
|
||||||
#ifdef HAVE_COGL_GL
|
|
||||||
if (_cogl_has_private_feature
|
|
||||||
(ctx, COGL_PRIVATE_FEATURE_QUERY_TEXTURE_PARAMETERS))
|
|
||||||
{
|
|
||||||
GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
|
|
||||||
GL_TEXTURE_COMPRESSED,
|
|
||||||
&gl_compressed) );
|
|
||||||
|
|
||||||
{
|
|
||||||
GLint val;
|
|
||||||
|
|
||||||
GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
|
|
||||||
GL_TEXTURE_INTERNAL_FORMAT,
|
|
||||||
&val) );
|
|
||||||
|
|
||||||
gl_int_format = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we can query GL for the actual pixel format then we'll ignore
|
|
||||||
the passed in format and use that. */
|
|
||||||
if (!ctx->driver_vtable->pixel_format_from_gl_internal (ctx,
|
|
||||||
gl_int_format,
|
|
||||||
&format))
|
|
||||||
{
|
|
||||||
_cogl_set_error (error,
|
|
||||||
COGL_SYSTEM_ERROR,
|
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
|
||||||
"Unsupported internal format for foreign texture");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
/* Otherwise we'll assume we can derive the GL format from the
|
|
||||||
passed in format */
|
|
||||||
ctx->driver_vtable->pixel_format_to_gl (ctx,
|
|
||||||
format,
|
|
||||||
&gl_int_format,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: We always trust the given width and height without querying
|
/* Note: We always trust the given width and height without querying
|
||||||
* the texture object because the user may be creating a Cogl
|
* the texture object because the user may be creating a Cogl
|
||||||
* texture for a texture_from_pixmap object where glTexImage2D may
|
* texture for a texture_from_pixmap object where glTexImage2D may
|
||||||
@ -433,50 +541,20 @@ cogl_texture_2d_new_from_foreign (CoglContext *ctx,
|
|||||||
* clarify that it is reliable to query back the size from OpenGL.
|
* clarify that it is reliable to query back the size from OpenGL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Assert it is a valid GL texture object */
|
||||||
|
_COGL_RETURN_VAL_IF_FAIL (ctx->glIsTexture (gl_handle), FALSE);
|
||||||
|
|
||||||
/* Validate width and height */
|
/* Validate width and height */
|
||||||
g_return_val_if_fail (width > 0 && height > 0, NULL);
|
_COGL_RETURN_VAL_IF_FAIL (width > 0 && height > 0, NULL);
|
||||||
|
|
||||||
/* Compressed texture images not supported */
|
loader = _cogl_texture_create_loader ();
|
||||||
if (gl_compressed == GL_TRUE)
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN;
|
||||||
{
|
loader->src.gl_foreign.gl_handle = gl_handle;
|
||||||
_cogl_set_error (error,
|
loader->src.gl_foreign.width = width;
|
||||||
COGL_SYSTEM_ERROR,
|
loader->src.gl_foreign.height = height;
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
loader->src.gl_foreign.format = format;
|
||||||
"Compressed foreign textures aren't currently supported");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: previously this code would query the texture object for
|
return _cogl_texture_2d_create_base (ctx, width, height, format, loader);
|
||||||
whether it has GL_GENERATE_MIPMAP enabled to determine whether to
|
|
||||||
auto-generate the mipmap. This doesn't make much sense any more
|
|
||||||
since Cogl switch to using glGenerateMipmap. Ideally I think
|
|
||||||
cogl_texture_2d_new_from_foreign should take a flags parameter so
|
|
||||||
that the application can decide whether it wants
|
|
||||||
auto-mipmapping. To be compatible with existing code, Cogl now
|
|
||||||
disables its own auto-mipmapping but leaves the value of
|
|
||||||
GL_GENERATE_MIPMAP alone so that it would still work but without
|
|
||||||
the dirtiness tracking that Cogl would do. */
|
|
||||||
|
|
||||||
/* Create new texture */
|
|
||||||
tex_2d = _cogl_texture_2d_create_base (ctx,
|
|
||||||
width, height,
|
|
||||||
format);
|
|
||||||
_cogl_texture_2d_set_auto_mipmap (COGL_TEXTURE (tex_2d), FALSE);
|
|
||||||
|
|
||||||
/* Setup bitmap info */
|
|
||||||
tex_2d->is_foreign = TRUE;
|
|
||||||
tex_2d->mipmaps_dirty = TRUE;
|
|
||||||
|
|
||||||
tex_2d->gl_texture = gl_handle;
|
|
||||||
tex_2d->gl_internal_format = gl_int_format;
|
|
||||||
|
|
||||||
/* Unknown filter */
|
|
||||||
tex_2d->gl_legacy_texobj_min_filter = GL_FALSE;
|
|
||||||
tex_2d->gl_legacy_texobj_mag_filter = GL_FALSE;
|
|
||||||
|
|
||||||
_cogl_texture_set_allocated (COGL_TEXTURE (tex_2d), TRUE);
|
|
||||||
|
|
||||||
return tex_2d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -678,10 +678,6 @@ _cogl_driver_gl =
|
|||||||
_cogl_texture_2d_gl_can_create,
|
_cogl_texture_2d_gl_can_create,
|
||||||
_cogl_texture_2d_gl_init,
|
_cogl_texture_2d_gl_init,
|
||||||
_cogl_texture_2d_gl_allocate,
|
_cogl_texture_2d_gl_allocate,
|
||||||
_cogl_texture_2d_gl_new_from_bitmap,
|
|
||||||
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
|
||||||
_cogl_egl_texture_2d_gl_new_from_image,
|
|
||||||
#endif
|
|
||||||
_cogl_texture_2d_gl_copy_from_framebuffer,
|
_cogl_texture_2d_gl_copy_from_framebuffer,
|
||||||
_cogl_texture_2d_gl_get_gl_handle,
|
_cogl_texture_2d_gl_get_gl_handle,
|
||||||
_cogl_texture_2d_gl_generate_mipmap,
|
_cogl_texture_2d_gl_generate_mipmap,
|
||||||
|
@ -397,10 +397,6 @@ _cogl_driver_gles =
|
|||||||
_cogl_texture_2d_gl_can_create,
|
_cogl_texture_2d_gl_can_create,
|
||||||
_cogl_texture_2d_gl_init,
|
_cogl_texture_2d_gl_init,
|
||||||
_cogl_texture_2d_gl_allocate,
|
_cogl_texture_2d_gl_allocate,
|
||||||
_cogl_texture_2d_gl_new_from_bitmap,
|
|
||||||
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
|
||||||
_cogl_egl_texture_2d_gl_new_from_image,
|
|
||||||
#endif
|
|
||||||
_cogl_texture_2d_gl_copy_from_framebuffer,
|
_cogl_texture_2d_gl_copy_from_framebuffer,
|
||||||
_cogl_texture_2d_gl_get_gl_handle,
|
_cogl_texture_2d_gl_get_gl_handle,
|
||||||
_cogl_texture_2d_gl_generate_mipmap,
|
_cogl_texture_2d_gl_generate_mipmap,
|
||||||
|
@ -69,10 +69,6 @@ _cogl_driver_nop =
|
|||||||
_cogl_texture_2d_nop_can_create,
|
_cogl_texture_2d_nop_can_create,
|
||||||
_cogl_texture_2d_nop_init,
|
_cogl_texture_2d_nop_init,
|
||||||
_cogl_texture_2d_nop_allocate,
|
_cogl_texture_2d_nop_allocate,
|
||||||
_cogl_texture_2d_nop_new_from_bitmap,
|
|
||||||
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
|
||||||
_cogl_egl_texture_2d_nop_new_from_image,
|
|
||||||
#endif
|
|
||||||
_cogl_texture_2d_nop_copy_from_framebuffer,
|
_cogl_texture_2d_nop_copy_from_framebuffer,
|
||||||
_cogl_texture_2d_nop_get_gl_handle,
|
_cogl_texture_2d_nop_get_gl_handle,
|
||||||
_cogl_texture_2d_nop_generate_mipmap,
|
_cogl_texture_2d_nop_generate_mipmap,
|
||||||
|
@ -48,22 +48,6 @@ CoglBool
|
|||||||
_cogl_texture_2d_nop_allocate (CoglTexture *tex,
|
_cogl_texture_2d_nop_allocate (CoglTexture *tex,
|
||||||
CoglError **error);
|
CoglError **error);
|
||||||
|
|
||||||
CoglTexture2D *
|
|
||||||
_cogl_texture_2d_nop_new_from_bitmap (CoglBitmap *bmp,
|
|
||||||
CoglPixelFormat internal_format,
|
|
||||||
CoglBool can_convert_in_place,
|
|
||||||
CoglError **error);
|
|
||||||
|
|
||||||
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
|
||||||
CoglTexture2D *
|
|
||||||
_cogl_egl_texture_2d_nop_new_from_image (CoglContext *ctx,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
CoglPixelFormat format,
|
|
||||||
EGLImageKHR image,
|
|
||||||
CoglError **error);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_2d_nop_flush_legacy_texobj_filters (CoglTexture *tex,
|
_cogl_texture_2d_nop_flush_legacy_texobj_filters (CoglTexture *tex,
|
||||||
GLenum min_filter,
|
GLenum min_filter,
|
||||||
|
@ -62,36 +62,6 @@ _cogl_texture_2d_nop_allocate (CoglTexture *tex,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTexture2D *
|
|
||||||
_cogl_texture_2d_nop_new_from_bitmap (CoglBitmap *bmp,
|
|
||||||
CoglPixelFormat internal_format,
|
|
||||||
CoglBool can_convert_in_place,
|
|
||||||
CoglError **error)
|
|
||||||
{
|
|
||||||
return _cogl_texture_2d_create_base (_cogl_bitmap_get_context (bmp),
|
|
||||||
cogl_bitmap_get_width (bmp),
|
|
||||||
cogl_bitmap_get_height (bmp),
|
|
||||||
internal_format);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
|
||||||
CoglTexture2D *
|
|
||||||
_cogl_egl_texture_2d_nop_new_from_image (CoglContext *ctx,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
CoglPixelFormat format,
|
|
||||||
EGLImageKHR image,
|
|
||||||
CoglError **error)
|
|
||||||
{
|
|
||||||
_cogl_set_error (error,
|
|
||||||
COGL_SYSTEM_ERROR,
|
|
||||||
COGL_SYSTEM_ERROR_UNSUPPORTED,
|
|
||||||
"Creating 2D textures from an EGLImage isn't "
|
|
||||||
"supported by the NOP backend");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_texture_2d_nop_flush_legacy_texobj_filters (CoglTexture *tex,
|
_cogl_texture_2d_nop_flush_legacy_texobj_filters (CoglTexture *tex,
|
||||||
GLenum min_filter,
|
GLenum min_filter,
|
||||||
|
@ -287,6 +287,7 @@ cogl_texture_pixmap_x11_new (CoglContext *ctxt,
|
|||||||
int pixmap_x, pixmap_y;
|
int pixmap_x, pixmap_y;
|
||||||
unsigned int pixmap_width, pixmap_height;
|
unsigned int pixmap_width, pixmap_height;
|
||||||
unsigned int pixmap_border_width;
|
unsigned int pixmap_border_width;
|
||||||
|
CoglPixelFormat internal_format;
|
||||||
CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
|
CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
|
||||||
XWindowAttributes window_attributes;
|
XWindowAttributes window_attributes;
|
||||||
int damage_base;
|
int damage_base;
|
||||||
@ -305,7 +306,15 @@ cogl_texture_pixmap_x11_new (CoglContext *ctxt,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note: the detailed pixel layout doesn't matter here, we are just
|
||||||
|
* interested in RGB vs RGBA... */
|
||||||
|
internal_format = (tex_pixmap->depth >= 32
|
||||||
|
? COGL_PIXEL_FORMAT_RGBA_8888_PRE
|
||||||
|
: COGL_PIXEL_FORMAT_RGB_888);
|
||||||
|
|
||||||
_cogl_texture_init (tex, ctxt, pixmap_width, pixmap_height,
|
_cogl_texture_init (tex, ctxt, pixmap_width, pixmap_height,
|
||||||
|
internal_format,
|
||||||
|
NULL, /* no loader */
|
||||||
&cogl_texture_pixmap_x11_vtable);
|
&cogl_texture_pixmap_x11_vtable);
|
||||||
|
|
||||||
tex_pixmap->pixmap = pixmap;
|
tex_pixmap->pixmap = pixmap;
|
||||||
@ -326,6 +335,7 @@ cogl_texture_pixmap_x11_new (CoglContext *ctxt,
|
|||||||
"Unable to query root window attributes");
|
"Unable to query root window attributes");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tex_pixmap->visual = window_attributes.visual;
|
tex_pixmap->visual = window_attributes.visual;
|
||||||
|
|
||||||
/* If automatic updates are requested and the Xlib connection
|
/* If automatic updates are requested and the Xlib connection
|
||||||
@ -346,9 +356,9 @@ cogl_texture_pixmap_x11_new (CoglContext *ctxt,
|
|||||||
|
|
||||||
/* Assume the entire pixmap is damaged to begin with */
|
/* Assume the entire pixmap is damaged to begin with */
|
||||||
tex_pixmap->damage_rect.x1 = 0;
|
tex_pixmap->damage_rect.x1 = 0;
|
||||||
tex_pixmap->damage_rect.x2 = tex->width;
|
tex_pixmap->damage_rect.x2 = pixmap_width;
|
||||||
tex_pixmap->damage_rect.y1 = 0;
|
tex_pixmap->damage_rect.y1 = 0;
|
||||||
tex_pixmap->damage_rect.y2 = tex->height;
|
tex_pixmap->damage_rect.y2 = pixmap_height;
|
||||||
|
|
||||||
winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
|
winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
|
||||||
if (winsys->texture_pixmap_x11_create)
|
if (winsys->texture_pixmap_x11_create)
|
||||||
@ -362,7 +372,8 @@ cogl_texture_pixmap_x11_new (CoglContext *ctxt,
|
|||||||
if (!tex_pixmap->use_winsys_texture)
|
if (!tex_pixmap->use_winsys_texture)
|
||||||
tex_pixmap->winsys = NULL;
|
tex_pixmap->winsys = NULL;
|
||||||
|
|
||||||
_cogl_texture_set_allocated (tex, TRUE);
|
_cogl_texture_set_allocated (tex, internal_format,
|
||||||
|
pixmap_width, pixmap_height);
|
||||||
|
|
||||||
return _cogl_texture_pixmap_x11_object_new (tex_pixmap);
|
return _cogl_texture_pixmap_x11_object_new (tex_pixmap);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <cogl/cogl.h>
|
#include <cogl/cogl.h>
|
||||||
#include <cogl-gst/cogl-gst.h>
|
#include <cogl-gst/cogl-gst.h>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user