forked from enlightenment/efl
evas: add ETC1 texture format support to Evas.
This commit is contained in:
parent
5140ef6bc4
commit
854dd14474
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue