This should allow texture upload with ETC2 RGB8 or RGBA8 formats.
Untested for now...
@feature
/* GL_OES_compressed_ETC1_RGB8_texture */
#define GL_ETC1_RGB8_OES 0x8D64
+/* The following are OpenGL ES 3.0 definitions for ETC2
+ * Note that RGB8_ETC2 is a superset of GL_OES_compressed_ETC1_RGB8_texture */
+#define GL_COMPRESSED_RGB8_ETC2 0x8D64
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x8D64
+
/* GL_OES_compressed_paletted_texture */
#define GL_PALETTE4_RGB8_OES 0x8B90
#define GL_PALETTE4_RGBA8_OES 0x8B91
case EVAS_COLORSPACE_GRY8: siz = w * h * sizeof(DATA8); break;
case EVAS_COLORSPACE_AGRY88: siz = w * h * sizeof(DATA16); break;
case EVAS_COLORSPACE_ETC1:
+ case EVAS_COLORSPACE_RGB8_ETC2:
// Need to round width and height independently
w += 2; h += 2; // We do duplicate border in ETC1 to have better rendering on GPU.
- siz = (w / 4 + (w % 4 ? 1 : 0)) *
- (h / 4 + (h % 4 ? 1 : 0)) * 8;
+ siz = (w / 4 + (w % 4 ? 1 : 0)) * (h / 4 + (h % 4 ? 1 : 0)) * 8;
+ break;
+ case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+ w += 2; h += 2;
+ siz = (w / 4 + (w % 4 ? 1 : 0)) * (h / 4 + (h % 4 ? 1 : 0)) * 16;
break;
default:
case EVAS_COLORSPACE_ARGB8888: siz = w * h * sizeof(DATA32); break;
#ifndef GL_ETC1_RGB8_OES
# define GL_ETC1_RGB8_OES 0x8D64
#endif
+#ifndef GL_COMPRESSED_RGB8_ETC2
+# define GL_COMPRESSED_RGB8_ETC2 0x9274
+#endif
+#ifndef GL_COMPRESSED_RGBA8_ETC2_EAC
+# define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#endif
#ifndef GL_UNPACK_ROW_LENGTH
Eina_Bool bin_program : 1;
Eina_Bool unpack_row_length : 1;
Eina_Bool etc1 : 1;
+ Eina_Bool etc2 : 1;
// tuning params - per gpu/cpu combo?
#define MAX_CUTOUT 512
#define DEF_CUTOUT 512
if (atoi(s) == 0) shared->info.bin_program = 0;
}
+#ifdef GL_GLES
+ // Detect ECT2 support. We need both RGB and RGBA formats.
+ if (glsym_glCompressedTexImage2d)
+ {
+ GLint texFormatCnt = 0;
+ glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &texFormatCnt);
+ if (texFormatCnt > 0)
+ {
+ GLenum *texFormats = malloc(texFormatCnt * sizeof(GLenum));
+ if (texFormats)
+ {
+ int k, cnt = 0;
+ glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, (GLint *) texFormats);
+ for (k = 0; k < texFormatCnt && cnt < 2; k++)
+ {
+ if (texFormats[k] == GL_COMPRESSED_RGB8_ETC2)
+ cnt++;
+ else if (texFormats[k] == GL_COMPRESSED_RGBA8_ETC2_EAC)
+ cnt++;
+ }
+ shared->info.etc2 = (cnt == 2);
+ free(texFormats);
+
+ // 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
+ // use of GL_COMPRESSED_TEXTURE_FORMATS but OpenGL 4.x
+ // does not.
+ }
+ }
+ }
+#endif
+
if (getenv("EVAS_GL_INFO"))
fprintf(stderr,
"max tex size %ix%i\n"
"rect tex %i\n"
"bgra : %i\n"
"etc1 : %i\n"
+ "etc2 : %i%s\n"
"max ansiotropic filtering: %3.3f\n"
"egl sec map image: %i\n"
"max vertex count: %i\n"
(int)shared->info.tex_rect,
(int)shared->info.bgra,
(int)shared->info.etc1,
+ (int)shared->info.etc2, shared->info.etc2 ? " (GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGBA8_ETC2_EAC)" : "",
(double)shared->info.anisotropic,
(int)shared->info.sec_image_map,
(int)shared->info.max_vertex_elements,
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 Evas_GL_Image *
_evas_gl_common_image(Evas_Engine_GL_Context *gc, RGBA_Image *im_im, Evas_Image_Load_Opts *lo, int *error)
{
const Evas_Colorspace *cspaces;
unsigned int i;
- if (gc->shared->info.etc1)
+ if (gc->shared->info.etc2)
+ cspaces = known_etc2_cspace;
+ else if (gc->shared->info.etc1)
cspaces = known_etc1_cspace;
else
cspaces = known_cspace;
case EVAS_COLORSPACE_AGRY88:
break;
case EVAS_COLORSPACE_ETC1:
- if (gc->shared->info.etc1) break;
+ if (gc->shared->info.etc1 && !gc->shared->info.etc2) 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_RGB8_ETC2:
+ case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+ if (gc->shared->info.etc2) break;
+ ERR("We don't know what to do with ETC2 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);
case EVAS_COLORSPACE_AGRY88:
break;
case EVAS_COLORSPACE_ETC1:
- if (gc->shared->info.etc1) break;
+ if (gc->shared->info.etc1 && !gc->shared->info.etc2) 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_RGB8_ETC2:
+ case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+ if (gc->shared->info.etc2) break;
+ ERR("We don't know what to do with ETC2 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);
case EVAS_COLORSPACE_AGRY88:
break;
case EVAS_COLORSPACE_ETC1:
- if (gc->shared->info.etc1) break;
+ if (gc->shared->info.etc1 && !gc->shared->info.etc2) 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_RGB8_ETC2:
+ case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+ if (gc->shared->info.etc2) break;
+ ERR("We don't know what to do with ETC2 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:
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;
+ im->cs.space != EVAS_COLORSPACE_ETC1 &&
+ im->cs.space != EVAS_COLORSPACE_RGB8_ETC2 &&
+ im->cs.space != EVAS_COLORSPACE_RGBA8_ETC2_EAC) return;
if (im->content_hint == EVAS_IMAGE_CONTENT_HINT_DYNAMIC)
{
if (im->cs.data)
case EVAS_COLORSPACE_GRY8:
case EVAS_COLORSPACE_AGRY88:
case EVAS_COLORSPACE_ETC1:
+ case EVAS_COLORSPACE_RGB8_ETC2:
+ case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
if ((im->tex) &&
((im->dirty) || (ie->animated.animated) || (ie->flags.updated_data)))
{
static const GLenum rgba8_ifmt = GL_RGBA;
static const GLenum rgba8_fmt = GL_BGRA;
+/* FIXME: RGB8_ETC2 is a superset of ETC1,
+ * but is GL_ETC1_RGB8_OES supported whenever GL_COMPRESSED_RGB8_ETC2 is?
+ */
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 struct {
struct {
{ 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_FALSE, EINA_FALSE, EVAS_COLORSPACE_ETC1, &etc1_fmt, &etc1_fmt },
- { EINA_FALSE, EINA_TRUE, EVAS_COLORSPACE_ETC1, &etc1_fmt, &etc1_fmt }
+ { EINA_FALSE, EINA_TRUE, EVAS_COLORSPACE_ETC1, &etc1_fmt, &etc1_fmt },
+ { EINA_FALSE, EINA_FALSE, EVAS_COLORSPACE_RGB8_ETC2, &etc2_rgb_fmt, &etc2_rgb_fmt },
+ { EINA_FALSE, EINA_TRUE, EVAS_COLORSPACE_RGB8_ETC2, &etc2_rgb_fmt, &etc2_rgb_fmt },
+ { 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 }
};
static const GLenum matching_rgba[] = { GL_RGBA4, GL_RGBA8, GL_RGBA12, GL_RGBA16, 0x0 };
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 == etc1_fmt) ||
+ (intformat == etc2_rgb_fmt) ||
+ (intformat == etc2_rgba_fmt))
{
pt = _pool_tex_new(gc, w, h, intformat, format);
if (!pt) return NULL;
{
Evas_GL_Texture *tex;
GLsizei w, h;
- int u = 0, v = 0;
+ int u = 0, v = 0, yoffset = 0;
int lformat;
tex = evas_gl_common_texture_alloc(gc, im->cache_entry.w, im->cache_entry.h, im->cache_entry.flags.alpha);
#define TEX_VREP 1
lformat = _evas_gl_texture_search_format(im->cache_entry.flags.alpha, gc->shared->info.bgra, im->cache_entry.space);
- if (im->cache_entry.space == EVAS_COLORSPACE_ETC1)
+ switch (im->cache_entry.space)
{
- // Add border for avoiding artifact
+ case EVAS_COLORSPACE_ETC1:
+ case EVAS_COLORSPACE_RGB8_ETC2:
+ case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+ // Add border to avoid artifacts
w = im->cache_entry.w + 2;
h = im->cache_entry.h + 2;
+ yoffset = 1;
- // Adjust w and h for etc1 format (multiple of 4 pixels on both axis)
+ // Adjust w and h for ETC1/2 formats (multiple of 4 pixels on both axes)
w = ((w >> 2) + (w & 0x3 ? 1 : 0)) << 2;
h = ((h >> 2) + (h & 0x3 ? 1 : 0)) << 2;
- }
- else
- {
+ break;
+
+ default:
/* 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->apt->tex = tex;
tex->x = u + 1;
- tex->y = v;
-
- if (im->cache_entry.space == EVAS_COLORSPACE_ETC1)
- tex->y++;
+ tex->y = v + yoffset;
tex->pt->references++;
evas_gl_common_texture_update(tex, im);
case EVAS_COLORSPACE_GRY8: bytes_count = 1; break;
case EVAS_COLORSPACE_AGRY88: bytes_count = 2; break;
case EVAS_COLORSPACE_ETC1:
+ case EVAS_COLORSPACE_RGB8_ETC2:
+ case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
{
/*
- ETC1 can't be scaled down on the fly and interpolated, like it is
+ ETC1/2 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;
+ int etc_block_size = 8;
+
+ if (im->cache_entry.space == EVAS_COLORSPACE_RGBA8_ETC2_EAC)
+ etc_block_size = 16;
width = im->cache_entry.w + 2;
height = im->cache_entry.h + 2;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, tex->pt->format,
width, height, 0,
- ((width * height) >> 4) * 8, im->image.data);
+ ((width * height) >> 4) * etc_block_size,
+ im->image.data);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex)
*image_data = im->cs.data;
break;
case EVAS_COLORSPACE_ETC1:
- ERR("This image is encoded in ETC1, not returning any data");
- *err = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+ case EVAS_COLORSPACE_RGB8_ETC2:
+ case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+ ERR("This image is encoded in ETC1 or ETC2, not returning any data");
+ error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
*image_data = NULL;
break;
default: