summaryrefslogtreecommitdiff
path: root/src/modules/evas/engines/gl_common
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@samsung.com>2014-03-27 13:12:12 +0900
committerCedric BAIL <cedric.bail@free.fr>2014-04-01 22:00:54 +0900
commit854dd14474444548965af8faa4e6d18ab9bce3ac (patch)
treef02ace7791af29221a256b8b71dc0be64ee7a343 /src/modules/evas/engines/gl_common
parent5140ef6bc499146a11ecb729ac129652f1d3f0ec (diff)
downloadefl-854dd14474444548965af8faa4e6d18ab9bce3ac.tar.gz
evas: add ETC1 texture format support to Evas.
Diffstat (limited to 'src/modules/evas/engines/gl_common')
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_common.h14
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_context.c7
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_image.c39
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_texture.c75
4 files changed, 120 insertions, 15 deletions
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 e5b46321f7..f35d9c94d0 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_common.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_common.h
@@ -111,6 +111,10 @@
#ifndef GL_LUMINANCE16_ALPHA16
# define GL_LUMINANCE16_ALPHA16 0x8048
#endif
+#ifndef GL_ETC1_RGB8_OES
+# define GL_ETC1_RGB8_OES 0x8D64
+#endif
+
#ifndef GL_UNPACK_ROW_LENGTH
# define GL_UNPACK_ROW_LENGTH 0x0cf2
@@ -358,6 +362,7 @@ struct _Evas_GL_Shared
Eina_Bool sec_image_map : 1;
Eina_Bool bin_program : 1;
Eina_Bool unpack_row_length : 1;
+ Eina_Bool etc1 : 1;
// tuning params - per gpu/cpu combo?
#define MAX_CUTOUT 512
#define DEF_CUTOUT 512
@@ -839,7 +844,14 @@ extern void (*glsym_glProgramParameteri) (GLuint a, GLuint b, GLint d);
extern void (*glsym_glReleaseShaderCompiler)(void);
extern void *(*glsym_glMapBuffer) (GLenum a, GLenum b);
extern GLboolean (*glsym_glUnmapBuffer) (GLenum a);
-
+extern void (*glsym_glCompressedTexImage2d) (GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const GLvoid * data);
#ifdef GL_GLES
extern void *(*secsym_eglCreateImage) (void *a, void *b, GLenum c, void *d, const int *e);
extern unsigned int (*secsym_eglDestroyImage) (void *a, void *b);
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 cb02c6e6df..7bee00cdd6 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_context.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_context.c
@@ -30,6 +30,10 @@ GLboolean (*glsym_glUnmapBuffer) (GLenum a) = NULL;
void (*glsym_glStartTiling) (GLuint a, GLuint b, GLuint c, GLuint d, GLuint e) = NULL;
void (*glsym_glEndTiling) (GLuint a) = NULL;
+void (*glsym_glCompressedTexImage2d) (GLenum target, GLint level, GLenum internalformat,
+ GLsizei width, GLsizei height, GLint border, GLsizei imageSize,
+ const GLvoid * data) = NULL;
+
#ifdef GL_GLES
// just used for finding symbols :)
typedef void (*_eng_fn) (void);
@@ -211,6 +215,7 @@ gl_symbols(void)
FINDSYM(secsym_eglGetImageAttribSEC, "eglGetImageAttribSEC", secsym_func_uint);
#endif
+ FINDSYM(glsym_glCompressedTexImage2d, "glCompressedTexImage2D", glsym_func_void);
}
static void shader_array_flush(Evas_Engine_GL_Context *gc);
@@ -623,6 +628,8 @@ evas_gl_common_context_new(void)
(strstr((char *)ext, "GL_EXT_texture_format_BGRA8888")))
shared->info.bgra = 1;
#endif
+ if (glsym_glCompressedTexImage2d && strstr((char *)ext, "OES_compressed_ETC1_RGB8_texture"))
+ shared->info.etc1 = 1;
#ifdef GL_GLES
// FIXME: there should be an extension name/string to check for
// not just symbols in the lib
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 a89d79deca..a74f45a396 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_image.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_image.c
@@ -128,6 +128,13 @@ static const Evas_Colorspace known_cspace[] = {
EVAS_COLORSPACE_ARGB8888
};
+static const Evas_Colorspace known_etc1_cspace[] = {
+ EVAS_COLORSPACE_ETC1,
+ EVAS_COLORSPACE_GRY8,
+ EVAS_COLORSPACE_AGRY88,
+ 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)
{
@@ -177,19 +184,25 @@ _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;
unsigned int i;
+ if (gc->shared->info.etc1)
+ cspaces = known_etc1_cspace;
+ else
+ cspaces = known_cspace;
+
for (i = 0; im_im->cache_entry.cspaces[i] != EVAS_COLORSPACE_ARGB8888; i++)
{
unsigned int j;
for (j = 0;
- known_cspace[j] != EVAS_COLORSPACE_ARGB8888;
+ cspaces[j] != EVAS_COLORSPACE_ARGB8888;
j++)
- if (known_cspace[j] == im_im->cache_entry.cspaces[i])
+ if (cspaces[j] == im_im->cache_entry.cspaces[i])
break;
- if (known_cspace[j] == im_im->cache_entry.cspaces[i])
+ if (cspaces[j] == im_im->cache_entry.cspaces[i])
break;
}
@@ -318,6 +331,10 @@ evas_gl_common_image_new_from_data(Evas_Engine_GL_Context *gc, unsigned int w, u
case EVAS_COLORSPACE_GRY8:
case EVAS_COLORSPACE_AGRY88:
break;
+ case EVAS_COLORSPACE_ETC1:
+ if (gc->shared->info.etc1) break;
+ ERR("We don't know what to do with ETC1 on this hardware. You need to add a software converter here.");
+ break;
case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL:
if (im->tex) evas_gl_common_texture_free(im->tex, EINA_TRUE);
@@ -362,6 +379,10 @@ evas_gl_common_image_new_from_copied_data(Evas_Engine_GL_Context *gc, unsigned i
case EVAS_COLORSPACE_GRY8:
case EVAS_COLORSPACE_AGRY88:
break;
+ case EVAS_COLORSPACE_ETC1:
+ if (gc->shared->info.etc1) break;
+ ERR("We don't know what to do with ETC1 on this hardware. You need to add a software converter here.");
+ break;
case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL:
if (im->tex) evas_gl_common_texture_free(im->tex, EINA_TRUE);
@@ -413,6 +434,10 @@ evas_gl_common_image_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned in
case EVAS_COLORSPACE_GRY8:
case EVAS_COLORSPACE_AGRY88:
break;
+ case EVAS_COLORSPACE_ETC1:
+ if (gc->shared->info.etc1) break;
+ ERR("We don't know what to do with ETC1 on this hardware. You need to add a software converter here.");
+ break;
case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL:
case EVAS_COLORSPACE_YCBCR422601_PL:
@@ -546,9 +571,10 @@ evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint)
if (!im->gc->shared->info.sec_image_map) return;
if (!im->gc->shared->info.bgra) return;
// does not handle yuv yet.
- if (im->cs.space != EVAS_COLORSPACE_ARGB8888 ||
- im->cs.space != EVAS_COLORSPACE_GRY8 ||
- im->cs.space != EVAS_COLORSPACE_AGRY88) return;
+ if (im->cs.space != EVAS_COLORSPACE_ARGB8888 &&
+ im->cs.space != EVAS_COLORSPACE_GRY8 &&
+ im->cs.space != EVAS_COLORSPACE_AGRY88 &&
+ im->cs.space != EVAS_COLORSPACE_ETC1) return;
if (im->content_hint == EVAS_IMAGE_CONTENT_HINT_DYNAMIC)
{
if (im->cs.data)
@@ -725,6 +751,7 @@ evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im)
case EVAS_COLORSPACE_ARGB8888:
case EVAS_COLORSPACE_GRY8:
case EVAS_COLORSPACE_AGRY88:
+ case EVAS_COLORSPACE_ETC1:
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 baa27a2686..c43a924173 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_texture.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c
@@ -32,6 +32,8 @@ static const GLenum lum_alpha_ifmt = GL_LUMINANCE_ALPHA;
static const GLenum rgba8_ifmt = GL_RGBA;
static const GLenum rgba8_fmt = GL_BGRA;
+static const GLenum etc1_fmt = GL_ETC1_RGB8_OES;
+
static struct {
struct {
int num, pix;
@@ -58,7 +60,9 @@ static const struct {
{ EINA_FALSE, EINA_FALSE, EVAS_COLORSPACE_GRY8, &lum_fmt, &lum_ifmt },
{ EINA_FALSE, EINA_TRUE, EVAS_COLORSPACE_GRY8, &lum_fmt, &lum_ifmt },
{ EINA_TRUE, EINA_FALSE, EVAS_COLORSPACE_AGRY88, &lum_alpha_fmt, &lum_alpha_ifmt },
- { EINA_TRUE, EINA_TRUE, EVAS_COLORSPACE_AGRY88, &lum_alpha_fmt, &lum_alpha_ifmt }
+ { EINA_TRUE, EINA_TRUE, EVAS_COLORSPACE_AGRY88, &lum_alpha_fmt, &lum_alpha_ifmt },
+ { EINA_FALSE, EINA_FALSE, EVAS_COLORSPACE_ETC1, &etc1_fmt, &etc1_fmt },
+ { EINA_FALSE, EINA_TRUE, EVAS_COLORSPACE_ETC1, &etc1_fmt, &etc1_fmt }
};
static const GLenum matching_rgba[] = { GL_RGBA4, GL_RGBA8, GL_RGBA12, GL_RGBA16, 0x0 };
@@ -380,7 +384,7 @@ _pool_tex_alloc(Evas_GL_Texture_Pool *pt, int w, int h EINA_UNUSED, int *u, int
static Evas_GL_Texture_Pool *
_pool_tex_find(Evas_Engine_GL_Context *gc, int w, int h,
- int intformat, int format, int *u, int *v,
+ GLenum intformat, GLenum format, int *u, int *v,
Evas_GL_Texture_Alloca **apt, int atlas_w)
{
Evas_GL_Texture_Pool *pt = NULL;
@@ -390,7 +394,8 @@ _pool_tex_find(Evas_Engine_GL_Context *gc, int w, int h,
if (atlas_w > gc->shared->info.max_texture_size)
atlas_w = gc->shared->info.max_texture_size;
if ((w > gc->shared->info.tune.atlas.max_w) ||
- (h > gc->shared->info.tune.atlas.max_h))
+ (h > gc->shared->info.tune.atlas.max_h) ||
+ (intformat == etc1_fmt))
{
pt = _pool_tex_new(gc, w, h, intformat, format);
if (!pt) return NULL;
@@ -432,6 +437,7 @@ Evas_GL_Texture *
evas_gl_common_texture_new(Evas_Engine_GL_Context *gc, RGBA_Image *im)
{
Evas_GL_Texture *tex;
+ GLsizei w, h;
int u = 0, v = 0;
int lformat;
@@ -442,9 +448,24 @@ evas_gl_common_texture_new(Evas_Engine_GL_Context *gc, RGBA_Image *im)
#define TEX_VREP 1
lformat = _evas_gl_texture_search_format(im->cache_entry.flags.alpha, gc->shared->info.bgra, im->cache_entry.space);
- tex->pt = _pool_tex_find(gc,
- im->cache_entry.w + TEX_HREP + 2,
- im->cache_entry.h + TEX_VREP,
+ if (im->cache_entry.space == EVAS_COLORSPACE_ETC1)
+ {
+ // Add border for avoiding artifact
+ w = im->cache_entry.w + 2;
+ h = im->cache_entry.h + 2;
+
+ // Adjust w and h for etc1 format (multiple of 4 pixels on both axis)
+ w = ((w >> 2) + (w & 0x3 ? 1 : 0)) << 2;
+ h = ((h >> 2) + (h & 0x3 ? 1 : 0)) << 2;
+ }
+ else
+ {
+ /* This need to be adjusted if we do something else than strip allocation */
+ w = im->cache_entry.w + TEX_HREP + 2; /* one pixel stop gap and two pixels for the border */
+ h = im->cache_entry.h + TEX_VREP; /* only one added border for security down */
+ }
+
+ tex->pt = _pool_tex_find(gc, w, h,
*matching_format[lformat].intformat,
*matching_format[lformat].format,
&u, &v, &tex->apt,
@@ -457,6 +478,10 @@ evas_gl_common_texture_new(Evas_Engine_GL_Context *gc, RGBA_Image *im)
tex->apt->tex = tex;
tex->x = u + 1;
tex->y = v;
+
+ if (im->cache_entry.space == EVAS_COLORSPACE_ETC1)
+ tex->y++;
+
tex->pt->references++;
evas_gl_common_texture_update(tex, im);
@@ -1032,7 +1057,7 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
tex->alpha = im->cache_entry.flags.alpha;
lformat = _evas_gl_texture_search_format(tex->alpha, tex->gc->shared->info.bgra, im->cache_entry.space);
- // FIXME: why a 'render' new here ???
+ // FIXME: why a 'render' new here ??? Should already have been allocated, quite a weird path.
tex->pt = _pool_tex_render_new(tex->gc, tex->w, tex->h,
*matching_format[lformat].intformat,
*matching_format[lformat].format);
@@ -1046,7 +1071,41 @@ 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;
- default: return;
+ case EVAS_COLORSPACE_ETC1:
+ {
+ /*
+ ETC1 can't be scaled down on the fly and interpolated, like it is
+ required for preloading, so we don't take that path. Also as the content
+ already have duplicated border and we use a specific function to
+ upload the compressed data, there is no need to use the normal path at
+ all.
+ */
+ GLsizei width, height;
+
+ width = im->cache_entry.w + 2;
+ height = im->cache_entry.h + 2;
+ width = ((width >> 2) + (width & 0x3 ? 1 : 0)) << 2;
+ height = ((height >> 2) + (height & 0x3 ? 1 : 0)) << 2;
+
+ glBindTexture(GL_TEXTURE_2D, tex->pt->texture);
+ GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, tex->pt->format,
+ width, height, 0,
+ ((width * height) >> 4) * 8, im->image.data);
+ GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+
+ if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex)
+ {
+ glBindTexture(GL_TEXTURE_2D, tex->gc->pipe[0].shader.cur_tex);
+ GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+ }
+
+ return;
+ }
+ default:
+ ERR("Don't know how to upload texture in colorspace %i.", im->cache_entry.space);
+ return;
}
// if preloaded, then async push it in after uploading a miniature of it