Evas gl: Add support for S3TC textures

Add support for DXT1, DXT3 and DXT5 textures (4 formats in total).

@feature Add support for S3TC textures if the GPU supports them
This commit is contained in:
Jean-Philippe Andre 2014-06-30 15:10:07 +09:00
parent 81929e3404
commit b0df307927
6 changed files with 123 additions and 50 deletions

View File

@ -130,10 +130,16 @@ _evas_common_rgba_image_surface_size(unsigned int w, unsigned int h,
case EVAS_COLORSPACE_GRY8: siz = w * h * sizeof(DATA8); break;
case EVAS_COLORSPACE_AGRY88: siz = w * h * sizeof(DATA16); break;
case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
case EVAS_COLORSPACE_RGBA_S3TC_DXT2:
case EVAS_COLORSPACE_RGBA_S3TC_DXT3:
case EVAS_COLORSPACE_RGBA_S3TC_DXT4:
case EVAS_COLORSPACE_RGBA_S3TC_DXT5:
block_size = 16;
// fallthrough
case EVAS_COLORSPACE_ETC1:
case EVAS_COLORSPACE_RGB8_ETC2:
case EVAS_COLORSPACE_RGB_S3TC_DXT1:
case EVAS_COLORSPACE_RGBA_S3TC_DXT1:
reset_borders = EINA_FALSE;
if (l && r && t && b)
{

View File

@ -120,7 +120,18 @@
#ifndef GL_COMPRESSED_RGBA8_ETC2_EAC
# define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
#endif
#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
# define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#endif
#ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
# define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#endif
#ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
# define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#endif
#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
# define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#endif
#ifndef GL_UNPACK_ROW_LENGTH
# define GL_UNPACK_ROW_LENGTH 0x0cf2
@ -379,6 +390,7 @@ struct _Evas_GL_Shared
Eina_Bool etc1 : 1;
Eina_Bool etc2 : 1;
Eina_Bool etc1_subimage : 1;
Eina_Bool s3tc : 1;
// tuning params - per gpu/cpu combo?
#define MAX_CUTOUT 512
#define DEF_CUTOUT 512
@ -403,6 +415,8 @@ struct _Evas_GL_Shared
#define MAX_ATLAS_H 512
#define DEF_ATLAS_H 512
Eina_List *cspaces; // depend on the values of etc1, etc2 and st3c
struct {
struct {
int max;
@ -421,7 +435,7 @@ struct _Evas_GL_Shared
struct {
Eina_List *whole;
Eina_List *atlas[6];
Eina_List *atlas[10];
} tex;
Eina_Hash *native_pm_hash;

View File

@ -625,6 +625,9 @@ evas_gl_common_context_new(void)
#endif
if (strstr((char *)ext, "OES_compressed_ETC1_RGB8_texture"))
shared->info.etc1 = 1;
if (strstr((char *)ext, "GL_EXT_texture_compression_s3tc") ||
strstr((char *)ext, "GL_S3_s3tc"))
shared->info.s3tc = 1;
#ifdef GL_GLES
// FIXME: there should be an extension name/string to check for
// not just symbols in the lib
@ -761,6 +764,7 @@ evas_gl_common_context_new(void)
"bgra : %i\n"
"etc1 : %i\n"
"etc2 : %i%s\n"
"s3tc : %i\n"
"max ansiotropic filtering: %3.3f\n"
"egl sec map image: %i\n"
"max vertex count: %i\n"
@ -781,6 +785,7 @@ evas_gl_common_context_new(void)
(int)shared->info.bgra,
(int)shared->info.etc1,
(int)shared->info.etc2, shared->info.etc2 ? " (GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGBA8_ETC2_EAC)" : "",
(int)shared->info.s3tc,
(double)shared->info.anisotropic,
(int)shared->info.sec_image_map,
(int)shared->info.max_vertex_elements,
@ -943,6 +948,7 @@ evas_gl_common_context_free(Evas_Engine_GL_Context *gc)
}
EINA_LIST_FOREACH(gc->shared->tex.whole, l, pt)
evas_gl_texture_pool_empty(pt);
eina_list_free(gc->shared->info.cspaces);
eina_list_free(gc->shared->tex.whole);
eina_hash_free(gc->shared->native_pm_hash);
eina_hash_free(gc->shared->native_tex_hash);

View File

@ -122,30 +122,36 @@ evas_gl_common_image_unref(Evas_GL_Image *im)
}
}
static const Evas_Colorspace known_cspace[] = {
EVAS_COLORSPACE_GRY8,
EVAS_COLORSPACE_AGRY88,
EVAS_COLORSPACE_ARGB8888
};
static const Evas_Colorspace known_etc1_cspace[] = {
EVAS_COLORSPACE_ETC1,
EVAS_COLORSPACE_GRY8,
EVAS_COLORSPACE_AGRY88,
EVAS_COLORSPACE_ARGB8888
};
static const Evas_Colorspace known_etc2_cspace[] = {
EVAS_COLORSPACE_RGBA8_ETC2_EAC,
EVAS_COLORSPACE_RGB8_ETC2,
EVAS_COLORSPACE_ETC1,
EVAS_COLORSPACE_GRY8,
EVAS_COLORSPACE_AGRY88,
EVAS_COLORSPACE_ARGB8888
};
static void
_evas_gl_cspace_list_fill(Evas_Engine_GL_Context *gc)
{
#define CS_APPEND(cs) gc->shared->info.cspaces = eina_list_append \
(gc->shared->info.cspaces, (void *) (intptr_t) cs)
if (gc->shared->info.etc2)
{
CS_APPEND(EVAS_COLORSPACE_RGBA8_ETC2_EAC);
CS_APPEND(EVAS_COLORSPACE_RGB8_ETC2);
CS_APPEND(EVAS_COLORSPACE_ETC1);
}
else if (gc->shared->info.etc1)
CS_APPEND(EVAS_COLORSPACE_ETC1);
if (gc->shared->info.s3tc)
{
CS_APPEND(EVAS_COLORSPACE_RGB_S3TC_DXT1);
CS_APPEND(EVAS_COLORSPACE_RGBA_S3TC_DXT1);
CS_APPEND(EVAS_COLORSPACE_RGBA_S3TC_DXT2);
CS_APPEND(EVAS_COLORSPACE_RGBA_S3TC_DXT3);
CS_APPEND(EVAS_COLORSPACE_RGBA_S3TC_DXT4);
CS_APPEND(EVAS_COLORSPACE_RGBA_S3TC_DXT5);
}
CS_APPEND(EVAS_COLORSPACE_GRY8);
CS_APPEND(EVAS_COLORSPACE_AGRY88);
CS_APPEND(EVAS_COLORSPACE_ARGB8888);
}
static Evas_GL_Image *
_evas_gl_common_image(Evas_Engine_GL_Context *gc, RGBA_Image *im_im, Evas_Image_Load_Opts *lo, int *error)
_evas_gl_common_image(Evas_Engine_GL_Context *gc, RGBA_Image *im_im,
Evas_Image_Load_Opts *lo, int *error)
{
Evas_GL_Image *im;
Eina_List *l;
@ -193,31 +199,27 @@ _evas_gl_common_image(Evas_Engine_GL_Context *gc, RGBA_Image *im_im, Evas_Image_
}
if (im_im->cache_entry.cspaces)
{
const Evas_Colorspace *cspaces;
Evas_Colorspace cs;
unsigned int i;
Eina_List *l2;
void *ldata;
if (gc->shared->info.etc2)
cspaces = known_etc2_cspace;
else if (gc->shared->info.etc1)
cspaces = known_etc1_cspace;
else
cspaces = known_cspace;
if (!gc->shared->info.cspaces)
_evas_gl_cspace_list_fill(gc);
cspace = EVAS_COLORSPACE_ARGB8888;
for (i = 0; im_im->cache_entry.cspaces[i] != EVAS_COLORSPACE_ARGB8888; i++)
{
unsigned int j;
EINA_LIST_FOREACH(gc->shared->info.cspaces, l2, ldata)
{
cs = (Evas_Colorspace) (intptr_t) ldata;
if (cs == im_im->cache_entry.cspaces[i])
{
cspace = cs;
goto found_cspace;
}
}
for (j = 0;
cspaces[j] != EVAS_COLORSPACE_ARGB8888;
j++)
if (cspaces[j] == im_im->cache_entry.cspaces[i])
break;
if (cspaces[j] == im_im->cache_entry.cspaces[i])
break;
}
cspace = im_im->cache_entry.cspaces[i];
found_cspace:
// ETC2 is backwards compatible with ETC1 but we prefer ETC2
if (cspace == EVAS_COLORSPACE_ETC1 && gc->shared->info.etc2)
cspace = EVAS_COLORSPACE_RGB8_ETC2;
@ -786,6 +788,12 @@ evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im)
case EVAS_COLORSPACE_ETC1:
case EVAS_COLORSPACE_RGB8_ETC2:
case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
case EVAS_COLORSPACE_RGB_S3TC_DXT1:
case EVAS_COLORSPACE_RGBA_S3TC_DXT1:
case EVAS_COLORSPACE_RGBA_S3TC_DXT2:
case EVAS_COLORSPACE_RGBA_S3TC_DXT3:
case EVAS_COLORSPACE_RGBA_S3TC_DXT4:
case EVAS_COLORSPACE_RGBA_S3TC_DXT5:
if ((im->tex) &&
((im->dirty) || (ie->animated.animated) || (ie->flags.updated_data)))
{

View File

@ -39,6 +39,11 @@ static const GLenum etc1_fmt = GL_ETC1_RGB8_OES;
static const GLenum etc2_rgb_fmt = GL_COMPRESSED_RGB8_ETC2;
static const GLenum etc2_rgba_fmt = GL_COMPRESSED_RGBA8_ETC2_EAC;
static const GLenum s3tc_rgb_dxt1_fmt = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
static const GLenum s3tc_rgba_dxt1_fmt = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
static const GLenum s3tc_rgba_dxt23_fmt = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
static const GLenum s3tc_rgba_dxt45_fmt = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
static struct {
struct {
int num, pix;
@ -74,7 +79,20 @@ static const struct {
{ EINA_TRUE, EINA_TRUE, EVAS_COLORSPACE_RGBA8_ETC2_EAC, &etc2_rgba_fmt, &etc2_rgba_fmt },
// images marked as no alpha but format supports it (RGBA8_ETC2_EAC):
{ EINA_FALSE, EINA_FALSE, EVAS_COLORSPACE_RGBA8_ETC2_EAC, &etc2_rgba_fmt, &etc2_rgba_fmt },
{ EINA_FALSE, EINA_TRUE, EVAS_COLORSPACE_RGBA8_ETC2_EAC, &etc2_rgba_fmt, &etc2_rgba_fmt }
{ EINA_FALSE, EINA_TRUE, EVAS_COLORSPACE_RGBA8_ETC2_EAC, &etc2_rgba_fmt, &etc2_rgba_fmt },
// S3TC support
{ EINA_FALSE, EINA_FALSE, EVAS_COLORSPACE_RGB_S3TC_DXT1, &s3tc_rgb_dxt1_fmt, &s3tc_rgb_dxt1_fmt },
{ EINA_FALSE, EINA_TRUE, EVAS_COLORSPACE_RGB_S3TC_DXT1, &s3tc_rgb_dxt1_fmt, &s3tc_rgb_dxt1_fmt },
{ EINA_TRUE, EINA_FALSE, EVAS_COLORSPACE_RGBA_S3TC_DXT1, &s3tc_rgba_dxt1_fmt, &s3tc_rgba_dxt1_fmt },
{ EINA_TRUE, EINA_TRUE, EVAS_COLORSPACE_RGBA_S3TC_DXT1, &s3tc_rgba_dxt1_fmt, &s3tc_rgba_dxt1_fmt },
{ EINA_TRUE, EINA_FALSE, EVAS_COLORSPACE_RGBA_S3TC_DXT2, &s3tc_rgba_dxt23_fmt, &s3tc_rgba_dxt23_fmt },
{ EINA_TRUE, EINA_TRUE, EVAS_COLORSPACE_RGBA_S3TC_DXT2, &s3tc_rgba_dxt23_fmt, &s3tc_rgba_dxt23_fmt },
{ EINA_TRUE, EINA_FALSE, EVAS_COLORSPACE_RGBA_S3TC_DXT3, &s3tc_rgba_dxt23_fmt, &s3tc_rgba_dxt23_fmt },
{ EINA_TRUE, EINA_TRUE, EVAS_COLORSPACE_RGBA_S3TC_DXT3, &s3tc_rgba_dxt23_fmt, &s3tc_rgba_dxt23_fmt },
{ EINA_TRUE, EINA_FALSE, EVAS_COLORSPACE_RGBA_S3TC_DXT4, &s3tc_rgba_dxt45_fmt, &s3tc_rgba_dxt45_fmt },
{ EINA_TRUE, EINA_TRUE, EVAS_COLORSPACE_RGBA_S3TC_DXT4, &s3tc_rgba_dxt45_fmt, &s3tc_rgba_dxt45_fmt },
{ EINA_TRUE, EINA_FALSE, EVAS_COLORSPACE_RGBA_S3TC_DXT5, &s3tc_rgba_dxt45_fmt, &s3tc_rgba_dxt45_fmt },
{ EINA_TRUE, EINA_TRUE, EVAS_COLORSPACE_RGBA_S3TC_DXT5, &s3tc_rgba_dxt45_fmt, &s3tc_rgba_dxt45_fmt }
};
static const GLenum matching_rgb[] = { GL_RGB4, GL_RGB8, GL_RGB12, GL_RGB16, 0x0 };
@ -206,17 +224,25 @@ _tex_format_index(GLuint format)
return 4;
case GL_COMPRESSED_RGBA8_ETC2_EAC:
return 5;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
return 6;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return 7;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: // dxt2 as well
return 8;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: // dxt4 as well
return 9;
case GL_LUMINANCE: // never used in atlas
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
return 6;
return 10;
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
return 7;
return 11;
default:
// abort?
return 0;
@ -490,6 +516,12 @@ evas_gl_common_texture_new(Evas_Engine_GL_Context *gc, RGBA_Image *im)
case EVAS_COLORSPACE_ETC1:
case EVAS_COLORSPACE_RGB8_ETC2:
case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
case EVAS_COLORSPACE_RGB_S3TC_DXT1:
case EVAS_COLORSPACE_RGBA_S3TC_DXT1:
case EVAS_COLORSPACE_RGBA_S3TC_DXT2:
case EVAS_COLORSPACE_RGBA_S3TC_DXT3:
case EVAS_COLORSPACE_RGBA_S3TC_DXT4:
case EVAS_COLORSPACE_RGBA_S3TC_DXT5:
// Add border to avoid artifacts
w = im->cache_entry.w + im->cache_entry.borders.l + im->cache_entry.borders.r;
h = im->cache_entry.h + im->cache_entry.borders.t + im->cache_entry.borders.b;
@ -1140,9 +1172,16 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
case EVAS_COLORSPACE_ARGB8888: bytes_count = 4; break;
case EVAS_COLORSPACE_GRY8: bytes_count = 1; break;
case EVAS_COLORSPACE_AGRY88: bytes_count = 2; break;
// Compressed texture formats: S3TC and ETC1/2
case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
case EVAS_COLORSPACE_RGBA_S3TC_DXT2:
case EVAS_COLORSPACE_RGBA_S3TC_DXT3:
case EVAS_COLORSPACE_RGBA_S3TC_DXT4:
case EVAS_COLORSPACE_RGBA_S3TC_DXT5:
bsize = 16;
// fallthrough
case EVAS_COLORSPACE_RGB_S3TC_DXT1:
case EVAS_COLORSPACE_RGBA_S3TC_DXT1:
case EVAS_COLORSPACE_ETC1:
case EVAS_COLORSPACE_RGB8_ETC2:
{

View File

@ -78,7 +78,7 @@ enum DDSCaps {
#endif
static const Evas_Colorspace cspaces_s3tc_dxt1_rgb[] = {
//EVAS_COLORSPACE_RGB_S3TC_DXT1,
EVAS_COLORSPACE_RGB_S3TC_DXT1,
EVAS_COLORSPACE_ARGB8888
};
@ -88,7 +88,7 @@ static const Evas_Colorspace cspaces_s3tc_dxt1_rgba[] = {
};
static const Evas_Colorspace cspaces_s3tc_dxt2[] = {
//EVAS_COLORSPACE_RGBA_S3TC_DXT2,
EVAS_COLORSPACE_RGBA_S3TC_DXT2,
EVAS_COLORSPACE_ARGB8888
};
@ -98,7 +98,7 @@ static const Evas_Colorspace cspaces_s3tc_dxt3[] = {
};
static const Evas_Colorspace cspaces_s3tc_dxt4[] = {
//EVAS_COLORSPACE_RGBA_S3TC_DXT4,
EVAS_COLORSPACE_RGBA_S3TC_DXT4,
EVAS_COLORSPACE_ARGB8888
};