forked from enlightenment/efl
Evas gl: Enable texture atlasses with ETC1/2
We prefer ETC2 textures when ETC2 support has been detected. According to the spec, glCompressedTexSubImage2D should work for ETC2. Try even with ETC1. This may fail at runtime. The fallback path is very dubious right now but without a proper test case I'm not sure which approach to take. We can also imagine cases where the GPU supports TexSubImage for ETC1 but ETC2 is not supported at all. This will need testing, as this case is not handled. @feature
This commit is contained in:
parent
90985d2282
commit
dbd576b858
|
@ -378,6 +378,7 @@ struct _Evas_GL_Shared
|
|||
Eina_Bool unpack_row_length : 1;
|
||||
Eina_Bool etc1 : 1;
|
||||
Eina_Bool etc2 : 1;
|
||||
Eina_Bool etc1_subimage : 1;
|
||||
// tuning params - per gpu/cpu combo?
|
||||
#define MAX_CUTOUT 512
|
||||
#define DEF_CUTOUT 512
|
||||
|
@ -575,6 +576,7 @@ struct _Evas_GL_Texture_Pool
|
|||
Eina_Bool render : 1;
|
||||
Eina_Bool native : 1;
|
||||
Eina_Bool dynamic : 1;
|
||||
Eina_Bool comptex_ready : 1;
|
||||
};
|
||||
|
||||
struct _Evas_GL_Texture_Alloca
|
||||
|
|
|
@ -740,6 +740,10 @@ evas_gl_common_context_new(void)
|
|||
shared->info.etc2 = (cnt == 2);
|
||||
free(texFormats);
|
||||
|
||||
// Note: If we support ETC2 we'll try to always use ETC2 even when the
|
||||
// image has colorspace ETC1 (backwards compatibility).
|
||||
shared->info.etc1_subimage = shared->info.etc2;
|
||||
|
||||
// FIXME: My NVIDIA driver advertises ETC2 texture formats
|
||||
// but does not support them. Driver bug? Logic bug?
|
||||
// This is in #ifdef GL_GLES because Khronos recommends
|
||||
|
|
|
@ -218,6 +218,9 @@ _evas_gl_common_image(Evas_Engine_GL_Context *gc, RGBA_Image *im_im, Evas_Image_
|
|||
}
|
||||
|
||||
cspace = im_im->cache_entry.cspaces[i];
|
||||
// ETC2 is backwards compatible with ETC1 but we prefer ETC2
|
||||
if (cspace == EVAS_COLORSPACE_ETC1 && gc->shared->info.etc2)
|
||||
cspace = EVAS_COLORSPACE_RGB8_ETC2;
|
||||
im_im->cache_entry.space = cspace;
|
||||
}
|
||||
|
||||
|
|
|
@ -299,9 +299,7 @@ _pool_tex_new(Evas_Engine_GL_Context *gc, int w, int h, GLenum intformat, GLenum
|
|||
pt = calloc(1, sizeof(Evas_GL_Texture_Pool));
|
||||
if (!pt) return NULL;
|
||||
|
||||
if ((intformat == etc1_fmt) ||
|
||||
(intformat == etc2_rgb_fmt) ||
|
||||
(intformat == etc2_rgba_fmt))
|
||||
if (!gc->shared->info.etc1_subimage && (intformat == etc1_fmt))
|
||||
no_rounding = EINA_TRUE;
|
||||
|
||||
if (!no_rounding)
|
||||
|
@ -416,9 +414,7 @@ _pool_tex_find(Evas_Engine_GL_Context *gc, int w, int h,
|
|||
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) ||
|
||||
(intformat == etc1_fmt) ||
|
||||
(intformat == etc2_rgb_fmt) ||
|
||||
(intformat == etc2_rgba_fmt))
|
||||
(!gc->shared->info.etc1_subimage && (intformat == etc1_fmt)))
|
||||
{
|
||||
pt = _pool_tex_new(gc, w, h, intformat, format);
|
||||
if (!pt) return NULL;
|
||||
|
@ -1107,11 +1103,14 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
|
|||
all.
|
||||
*/
|
||||
GLsizei width, height;
|
||||
GLint x, y;
|
||||
int etc_block_size = 8;
|
||||
|
||||
if (im->cache_entry.space == EVAS_COLORSPACE_RGBA8_ETC2_EAC)
|
||||
etc_block_size = 16;
|
||||
|
||||
x = tex->x - 1;
|
||||
y = tex->y - 1;
|
||||
width = im->cache_entry.w + 2;
|
||||
height = im->cache_entry.h + 2;
|
||||
width = ((width >> 2) + (width & 0x3 ? 1 : 0)) << 2;
|
||||
|
@ -1120,11 +1119,52 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
|
|||
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) * etc_block_size,
|
||||
im->image.data);
|
||||
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
|
||||
if ((tex->gc->shared->info.etc1_subimage ||
|
||||
(im->cache_entry.space != EVAS_COLORSPACE_ETC1))
|
||||
&& (tex->pt->w != width || tex->pt->h != height))
|
||||
{
|
||||
int glerr;
|
||||
glerr = glGetError();
|
||||
|
||||
if (!tex->pt->comptex_ready)
|
||||
{
|
||||
GLsizei tw, th;
|
||||
tw = ((tex->pt->w >> 2) + (tex->pt->w & 0x3 ? 1 : 0)) << 2;
|
||||
th = ((tex->pt->h >> 2) + (tex->pt->h & 0x3 ? 1 : 0)) << 2;
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, tex->pt->format,
|
||||
tw, th, 0,
|
||||
((tw * th) >> 4) * etc_block_size,
|
||||
NULL);
|
||||
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
|
||||
tex->pt->comptex_ready = EINA_TRUE;
|
||||
}
|
||||
|
||||
glCompressedTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||
x, y, width, height,
|
||||
tex->pt->format,
|
||||
((width * height) >> 4) * etc_block_size,
|
||||
im->image.data);
|
||||
|
||||
glerr = glGetError();
|
||||
if (glerr != GL_NO_ERROR)
|
||||
{
|
||||
ERR("glCompressedTexSubImage2D failed with ETC1/2: %d", glerr);
|
||||
|
||||
// FIXME: Changing settings on the fly.
|
||||
// The first texture will be black.
|
||||
// How to fallback? We need a whole texture now.
|
||||
if (im->cache_entry.space == EVAS_COLORSPACE_ETC1)
|
||||
tex->gc->shared->info.etc1_subimage = EINA_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0, tex->pt->format,
|
||||
width, height, 0,
|
||||
((width * height) >> 4) * etc_block_size,
|
||||
im->image.data);
|
||||
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
|
||||
}
|
||||
|
||||
if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex)
|
||||
{
|
||||
|
|
|
@ -270,7 +270,7 @@ evas_image_load_file_data_tgv(void *loader_data,
|
|||
const char *m;
|
||||
unsigned int *p = pixels;
|
||||
unsigned char *p_etc = pixels;
|
||||
char *buffer;
|
||||
char *buffer = NULL;
|
||||
Eina_Rectangle master;
|
||||
unsigned int block_length;
|
||||
unsigned int length, offset;
|
||||
|
@ -326,12 +326,18 @@ evas_image_load_file_data_tgv(void *loader_data,
|
|||
default: abort();
|
||||
}
|
||||
|
||||
if (prop->cspace != EVAS_COLORSPACE_ARGB8888 && prop->cspace != loader->cspace)
|
||||
{
|
||||
if (!((prop->cspace == EVAS_COLORSPACE_RGB8_ETC2) &&
|
||||
(loader->cspace == EVAS_COLORSPACE_ETC1)))
|
||||
goto on_error;
|
||||
// else: ETC2 is compatible with ETC1 and is preferred
|
||||
}
|
||||
|
||||
// Allocate space for each ETC block (8 or 16 bytes per 4 * 4 pixels group)
|
||||
block_count = loader->block.width * loader->block.height / (4 * 4);
|
||||
if (loader->compress)
|
||||
buffer = alloca(etc_block_size * block_count);
|
||||
else
|
||||
buffer = NULL;
|
||||
|
||||
for (y = 0; y < loader->size.height + 2; y += loader->block.height)
|
||||
for (x = 0; x < loader->size.width + 2; x += loader->block.width)
|
||||
|
|
Loading…
Reference in New Issue