From b0df3079276b542d2264af4413ff9cedfb098f89 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Mon, 30 Jun 2014 15:10:07 +0900 Subject: [PATCH] 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 --- src/lib/evas/common/evas_image_main.c | 6 ++ .../evas/engines/gl_common/evas_gl_common.h | 18 +++- .../evas/engines/gl_common/evas_gl_context.c | 6 ++ .../evas/engines/gl_common/evas_gl_image.c | 92 ++++++++++--------- .../evas/engines/gl_common/evas_gl_texture.c | 45 ++++++++- .../evas/loaders/dds/evas_image_load_dds.c | 6 +- 6 files changed, 123 insertions(+), 50 deletions(-) diff --git a/src/lib/evas/common/evas_image_main.c b/src/lib/evas/common/evas_image_main.c index faabda4a3e..c911d3f63f 100644 --- a/src/lib/evas/common/evas_image_main.c +++ b/src/lib/evas/common/evas_image_main.c @@ -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) { diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 4e9fe6386e..fb1281ebfa 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -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; diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index 6c2e9b07f7..e24d2bac5d 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -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); diff --git a/src/modules/evas/engines/gl_common/evas_gl_image.c b/src/modules/evas/engines/gl_common/evas_gl_image.c index 13b7598979..0a6d8c98e7 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_image.c +++ b/src/modules/evas/engines/gl_common/evas_gl_image.c @@ -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))) { diff --git a/src/modules/evas/engines/gl_common/evas_gl_texture.c b/src/modules/evas/engines/gl_common/evas_gl_texture.c index c76fcfe9c6..eaac74b118 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_texture.c +++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c @@ -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: { diff --git a/src/modules/evas/loaders/dds/evas_image_load_dds.c b/src/modules/evas/loaders/dds/evas_image_load_dds.c index cd3f87fb66..fb151ab407 100644 --- a/src/modules/evas/loaders/dds/evas_image_load_dds.c +++ b/src/modules/evas/loaders/dds/evas_image_load_dds.c @@ -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 };