jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=86ce491a862296c92bbf377cc11faf93d7a7efe7

commit 86ce491a862296c92bbf377cc11faf93d7a7efe7
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Fri Apr 25 14:51:42 2014 +0900

    Evas gl_x11: Add ETC2 support to the GL/X11 engine
    
    This should allow texture upload with ETC2 RGB8 or RGBA8 formats.
    Untested for now...
    
    @feature
---
 src/lib/evas/Evas_GL.h                             |  5 +++
 src/lib/evas/common/evas_image_main.c              |  8 +++-
 .../evas/engines/gl_common/evas_gl_common.h        |  7 ++++
 .../evas/engines/gl_common/evas_gl_context.c       | 35 ++++++++++++++++
 src/modules/evas/engines/gl_common/evas_gl_image.c | 40 +++++++++++++++---
 .../evas/engines/gl_common/evas_gl_texture.c       | 49 +++++++++++++++-------
 src/modules/evas/engines/gl_x11/evas_engine.c      |  6 ++-
 7 files changed, 126 insertions(+), 24 deletions(-)

diff --git a/src/lib/evas/Evas_GL.h b/src/lib/evas/Evas_GL.h
index 75bdc8c..8f148d9 100644
--- a/src/lib/evas/Evas_GL.h
+++ b/src/lib/evas/Evas_GL.h
@@ -1056,6 +1056,11 @@ typedef signed long int  GLsizeiptr;   // Changed 
khronos_ssize_t
 /* 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
diff --git a/src/lib/evas/common/evas_image_main.c 
b/src/lib/evas/common/evas_image_main.c
index 46fdcb2..2ce8370 100644
--- a/src/lib/evas/common/evas_image_main.c
+++ b/src/lib/evas/common/evas_image_main.c
@@ -126,10 +126,14 @@ _evas_common_rgba_image_surface_size(unsigned int w, 
unsigned int h, Evas_Colors
       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;
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 d61186e..1ca0eec 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_common.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_common.h
@@ -114,6 +114,12 @@
 #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
@@ -363,6 +369,7 @@ struct _Evas_GL_Shared
       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
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 7a0b215..aaabc78 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_context.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_context.c
@@ -724,6 +724,39 @@ evas_gl_common_context_new(void)
              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"
@@ -732,6 +765,7 @@ evas_gl_common_context_new(void)
                    "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"
@@ -752,6 +786,7 @@ evas_gl_common_context_new(void)
                    (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,
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 70ff5e0..248eb30 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_image.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_image.c
@@ -135,6 +135,15 @@ static const Evas_Colorspace known_etc1_cspace[] = {
    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)
 {
@@ -187,7 +196,9 @@ _evas_gl_common_image(Evas_Engine_GL_Context *gc, 
RGBA_Image *im_im, Evas_Image_
         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;
@@ -332,9 +343,14 @@ evas_gl_common_image_new_from_data(Evas_Engine_GL_Context 
*gc, unsigned int w, u
       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);
@@ -380,9 +396,14 @@ 
evas_gl_common_image_new_from_copied_data(Evas_Engine_GL_Context *gc, unsigned i
       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);
@@ -435,9 +456,14 @@ evas_gl_common_image_new(Evas_Engine_GL_Context *gc, 
unsigned int w, unsigned in
       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:
@@ -574,7 +600,9 @@ evas_gl_common_image_content_hint_set(Evas_GL_Image *im, 
int hint)
    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)
@@ -752,6 +780,8 @@ evas_gl_common_image_update(Evas_Engine_GL_Context *gc, 
Evas_GL_Image *im)
       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)))
           {
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 2ff7be8..7cc501a 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_texture.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c
@@ -32,7 +32,12 @@ static const GLenum lum_alpha_ifmt = GL_LUMINANCE_ALPHA;
 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 {
@@ -62,7 +67,11 @@ static const 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 };
@@ -395,7 +404,9 @@ _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 == etc1_fmt) ||
+       (intformat == etc2_rgb_fmt) ||
+       (intformat == etc2_rgba_fmt))
      {
         pt = _pool_tex_new(gc, w, h, intformat, format);
         if (!pt) return NULL;
@@ -438,7 +449,7 @@ 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 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);
@@ -448,18 +459,22 @@ 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);
-   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 */
@@ -477,10 +492,7 @@ 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->y = v + yoffset;
 
    tex->pt->references++;
    evas_gl_common_texture_update(tex, im);
@@ -1072,15 +1084,21 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, 
RGBA_Image *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;
@@ -1092,7 +1110,8 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, 
RGBA_Image *im)
 
            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)
diff --git a/src/modules/evas/engines/gl_x11/evas_engine.c 
b/src/modules/evas/engines/gl_x11/evas_engine.c
index 9ee1ada..719e29e 100644
--- a/src/modules/evas/engines/gl_x11/evas_engine.c
+++ b/src/modules/evas/engines/gl_x11/evas_engine.c
@@ -2870,8 +2870,10 @@ eng_image_data_get(void *data, void *image, int 
to_write, DATA32 **image_data, i
          *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:

-- 


Reply via email to