Evas gl: Add support for ETC1+Alpha textures
authorJean-Philippe Andre <jp.andre@samsung.com>
Mon, 7 Jul 2014 11:14:02 +0000 (20:14 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Wed, 9 Jul 2014 00:04:55 +0000 (09:04 +0900)
Compile-in the required shaders, add support for the
new EVAS_COLORSPACE_ETC1_ALPHA, and upload textures as RGB+A
pairs.

@feature

src/lib/evas/common/evas_image_main.c
src/modules/evas/engines/gl_common/evas_gl_common.h
src/modules/evas/engines/gl_common/evas_gl_context.c
src/modules/evas/engines/gl_common/evas_gl_image.c
src/modules/evas/engines/gl_common/evas_gl_shader.c
src/modules/evas/engines/gl_common/evas_gl_texture.c
src/modules/evas/engines/gl_x11/evas_engine.c

index c911d3f..89d46a2 100644 (file)
@@ -134,6 +134,7 @@ _evas_common_rgba_image_surface_size(unsigned int w, unsigned int h,
       case EVAS_COLORSPACE_RGBA_S3TC_DXT3:
       case EVAS_COLORSPACE_RGBA_S3TC_DXT4:
       case EVAS_COLORSPACE_RGBA_S3TC_DXT5:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
         block_size = 16;
         // fallthrough
       case EVAS_COLORSPACE_ETC1:
index 94e8ce4..8a1071e 100644 (file)
@@ -332,6 +332,9 @@ typedef enum {
   SHADER_YUY2_NOMUL,
   SHADER_NV12,
   SHADER_NV12_NOMUL,
+
+  SHADER_RGB_A_PAIR,
+  SHADER_RGB_A_PAIR_NOMUL,
 /*   
   SHADER_FILTER_INVERT,
   SHADER_FILTER_INVERT_NOMUL,
@@ -413,6 +416,8 @@ struct _Evas_GL_Shared
 #define MAX_ATLAS_H            512
 #define DEF_ATLAS_H                 512
 
+#define ATLAS_FORMATS_COUNT    11
+
       Eina_List *cspaces; // depend on the values of etc1, etc2 and st3c
 
       struct {
@@ -433,7 +438,7 @@ struct _Evas_GL_Shared
 
    struct {
       Eina_List       *whole;
-      Eina_List       *atlas[10];
+      Eina_List       *atlas[ATLAS_FORMATS_COUNT];
    } tex;
 
    Eina_Hash          *native_pm_hash;
@@ -595,7 +600,11 @@ struct _Evas_GL_Texture
 {
    Evas_Engine_GL_Context *gc;
    Evas_GL_Image   *im;
-   Evas_GL_Texture_Pool *pt, *ptu, *ptv, *ptuv, *ptt;
+   Evas_GL_Texture_Pool *pt, *ptu, *ptv, *ptt;
+   union {
+      Evas_GL_Texture_Pool *ptuv;
+      Evas_GL_Texture_Pool *pta;
+   };
    RGBA_Font_Glyph *fglyph;
    int              x, y, w, h;
    int              tx, ty;
@@ -777,6 +786,12 @@ void             evas_gl_common_context_nv12_push(Evas_Engine_GL_Context *gc,
                                                   int x, int y, int w, int h,
                                                   int r, int g, int b, int a,
                                                   Eina_Bool smooth);
+void             evas_gl_common_context_rgb_a_pair_push(Evas_Engine_GL_Context *gc,
+                                                        Evas_GL_Texture *tex,
+                                                        double sx, double sy, double sw, double sh,
+                                                        int x, int y, int w, int h,
+                                                        int r, int g, int b, int a,
+                                                        Eina_Bool smooth);
 void             evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
                                                        Evas_GL_Texture *tex,
                                                        int npoints,
@@ -821,6 +836,8 @@ Evas_GL_Texture  *evas_gl_common_texture_nv12_new(Evas_Engine_GL_Context *gc, DA
 void              evas_gl_common_texture_nv12_update(Evas_GL_Texture *tex, DATA8 **row, unsigned int w, unsigned int h);
 Evas_GL_Texture  *evas_gl_common_texture_nv12tiled_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsigned int w, unsigned int h);
 void              evas_gl_common_texture_nv12tiled_update(Evas_GL_Texture *tex, DATA8 **row, unsigned int w, unsigned int h);
+Evas_GL_Texture  *evas_gl_common_texture_rgb_a_pair_new(Evas_Engine_GL_Context *gc, RGBA_Image *im);
+void              evas_gl_common_texture_rgb_a_pair_update(Evas_GL_Texture *tex, RGBA_Image *im);
 
 void              evas_gl_common_image_alloc_ensure(Evas_GL_Image *im);
 void              evas_gl_common_image_all_unload(Evas_Engine_GL_Context *gc);
@@ -900,6 +917,7 @@ void pt_unref(Evas_GL_Texture_Pool *pt);
 #else
 # define GLERR(fn, fl, ln, op)
 #endif
+#define GLERRLOG() GLERR(__FUNCTION__, __FILE__, __LINE__, "")
 
 Eina_Bool evas_gl_common_module_open(void);
 void      evas_gl_common_module_close(void);
@@ -913,6 +931,15 @@ _tex_sub_2d(Evas_Engine_GL_Context *gc, int x, int y, int w, int h, int fmt, int
    GLERR(__FUNCTION__, __FILE__, __LINE__, "");
 }
 
+static inline void
+_comp_tex_sub_2d(Evas_Engine_GL_Context *gc, int x, int y, int w, int h, int fmt, int imgsize, const void *pix)
+{
+   if ((w > gc->shared->info.max_texture_size) ||
+       (h > gc->shared->info.max_texture_size)) return;
+   glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, fmt, imgsize, pix);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "glCompressedTexSubImage2D");
+}
+
 #include "evas_gl_3d_common.h"
 
 #endif
index 22bb159..a2513a2 100644 (file)
@@ -861,6 +861,11 @@ evas_gl_common_context_new(void)
         SHADER_TEXTURE_ADD(shared, NV12_NOMUL, tex);
         SHADER_TEXTURE_ADD(shared, NV12_NOMUL, texuv);
 
+        SHADER_TEXTURE_ADD(shared, RGB_A_PAIR, tex);
+        SHADER_TEXTURE_ADD(shared, RGB_A_PAIR, texm);
+        SHADER_TEXTURE_ADD(shared, RGB_A_PAIR_NOMUL, tex);
+        SHADER_TEXTURE_ADD(shared, RGB_A_PAIR_NOMUL, texm);
+
         if (gc->state.current.cur_prog == PRG_INVALID)
            glUseProgram(shared->shader[0].prog);
         else glUseProgram(gc->state.current.cur_prog);
@@ -2294,6 +2299,108 @@ evas_gl_common_context_nv12_push(Evas_Engine_GL_Context *gc,
 }
 
 void
+evas_gl_common_context_rgb_a_pair_push(Evas_Engine_GL_Context *gc,
+                                       Evas_GL_Texture *tex,
+                                       double sx, double sy,
+                                       double sw, double sh,
+                                       int x, int y, int w, int h,
+                                       int r, int g, int b, int a,
+                                       Eina_Bool smooth)
+
+{
+   /* This RGB+Alpha mode is used for ETC1+Alpha textures, where the shader
+    * will multiply RGB by alpha. Two textures are created: tex->{pt,pta}.
+    * Since the exact encoding doesn't matter here (decoding is transparent
+    * from the shader point of view), this method could be used for other
+    * colorspaces as well (eg. RGB565+Alpha4, ...).
+    */
+
+   int pnum, nv, nc, nu, nm, i;
+   GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
+   GLuint prog;
+   int pn;
+
+   prog = gc->shared->shader[evas_gl_common_shader_choice
+     (0, NULL, r, g, b, a, SHADER_RGB_A_PAIR_NOMUL, SHADER_RGB_A_PAIR)].prog;
+
+   pn = _evas_gl_common_context_push(RTYPE_IMAGE,
+                                     gc, tex, NULL,
+                                     prog,
+                                     x, y, w, h,
+                                     EINA_TRUE,
+                                     smooth,
+                                     EINA_FALSE, 0, 0, 0, 0);
+
+   gc->pipe[pn].region.type = RTYPE_IMAGE;
+   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+   gc->pipe[pn].shader.cur_texm = tex->pta->texture;
+   gc->pipe[pn].shader.cur_prog = prog;
+   gc->pipe[pn].shader.smooth = smooth;
+   gc->pipe[pn].shader.blend = EINA_TRUE;
+   gc->pipe[pn].shader.render_op = gc->dc->render_op;
+   gc->pipe[pn].shader.clip = 0;
+   gc->pipe[pn].shader.cx = 0;
+   gc->pipe[pn].shader.cy = 0;
+   gc->pipe[pn].shader.cw = 0;
+   gc->pipe[pn].shader.ch = 0;
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = EINA_TRUE;
+   // if nomul... dont need this
+   gc->pipe[pn].array.use_color = EINA_TRUE;
+   gc->pipe[pn].array.use_texuv = EINA_TRUE;
+   gc->pipe[pn].array.use_texuv2 = 0;
+   gc->pipe[pn].array.use_texuv3 = 0;
+   gc->pipe[pn].array.use_texm = EINA_TRUE;
+   gc->pipe[pn].array.use_texsam = 0;
+
+   pipe_region_expand(gc, pn, x, y, w, h);
+
+   pnum = gc->pipe[pn].array.num;
+   nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; nm = pnum * 2;
+   gc->pipe[pn].array.num += 6;
+   array_alloc(gc, pn);
+
+   tx1 = (sx) / (double)tex->pt->w;
+   ty1 = (sy) / (double)tex->pt->h;
+   tx2 = (sx + sw) / (double)tex->pt->w;
+   ty2 = (sy + sh) / (double)tex->pt->h;
+
+   t2x1 = sx / (double)tex->pta->w;
+   t2y1 = sy / (double)tex->pta->h;
+   t2x2 = (sx + sw) / (double)tex->pta->w;
+   t2y2 = (sy + sh) / (double)tex->pta->h;
+
+   PUSH_VERTEX(pn, x    , y    , 0);
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
+
+   PUSH_TEXUV(pn, tx1, ty1);
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx1, ty2);
+
+   PUSH_TEXM(pn, t2x1, t2y1);
+   PUSH_TEXM(pn, t2x2, t2y1);
+   PUSH_TEXM(pn, t2x1, t2y2);
+
+   PUSH_VERTEX(pn, x + w, y    , 0);
+   PUSH_VERTEX(pn, x + w, y + h, 0);
+   PUSH_VERTEX(pn, x    , y + h, 0);
+
+   PUSH_TEXUV(pn, tx2, ty1);
+   PUSH_TEXUV(pn, tx2, ty2);
+   PUSH_TEXUV(pn, tx1, ty2);
+
+   PUSH_TEXM(pn, t2x2, t2y1);
+   PUSH_TEXM(pn, t2x2, t2y2);
+   PUSH_TEXM(pn, t2x1, t2y2);
+
+   for (i = 0; i < 6; i++)
+     {
+        PUSH_COLOR(pn, r, g, b, a);
+     }
+}
+
+void
 evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
                                       Evas_GL_Texture *tex,
                                       int npoints,
index 4f95a93..8070da4 100644 (file)
@@ -132,9 +132,13 @@ _evas_gl_cspace_list_fill(Evas_Engine_GL_Context *gc)
         CS_APPEND(EVAS_COLORSPACE_RGBA8_ETC2_EAC);
         CS_APPEND(EVAS_COLORSPACE_RGB8_ETC2);
         CS_APPEND(EVAS_COLORSPACE_ETC1);
+        CS_APPEND(EVAS_COLORSPACE_ETC1_ALPHA);
      }
    else if (gc->shared->info.etc1)
-     CS_APPEND(EVAS_COLORSPACE_ETC1);
+     {
+        CS_APPEND(EVAS_COLORSPACE_ETC1);
+        CS_APPEND(EVAS_COLORSPACE_ETC1_ALPHA);
+     }
    if (gc->shared->info.s3tc)
      {
         CS_APPEND(EVAS_COLORSPACE_RGB_S3TC_DXT1);
@@ -347,6 +351,7 @@ 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:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
         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;
@@ -400,6 +405,7 @@ evas_gl_common_image_new_from_copied_data(Evas_Engine_GL_Context *gc, unsigned i
       case EVAS_COLORSPACE_AGRY88:
         break;
       case EVAS_COLORSPACE_ETC1:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
         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;
@@ -460,6 +466,7 @@ evas_gl_common_image_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned in
       case EVAS_COLORSPACE_AGRY88:
          break;
       case EVAS_COLORSPACE_ETC1:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
         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;
@@ -601,12 +608,19 @@ 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 &&
-       im->cs.space != EVAS_COLORSPACE_ETC1 &&
-       im->cs.space != EVAS_COLORSPACE_RGB8_ETC2 &&
-       im->cs.space != EVAS_COLORSPACE_RGBA8_ETC2_EAC) return;
+   // TODO: Check this list of cspaces
+   switch (im->cs.space)
+     {
+      case EVAS_COLORSPACE_YCBCR422P601_PL:
+      case EVAS_COLORSPACE_YCBCR422P709_PL:
+      case EVAS_COLORSPACE_RGB565_A5P:
+      case EVAS_COLORSPACE_YCBCR422601_PL:
+      case EVAS_COLORSPACE_YCBCR420NV12601_PL:
+      case EVAS_COLORSPACE_YCBCR420TM12601_PL:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
+        return;
+      default: break;
+     }
    if (im->content_hint == EVAS_IMAGE_CONTENT_HINT_DYNAMIC)
      {
         if (im->cs.data)
@@ -831,6 +845,22 @@ evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im)
         im->dirty = 0;
         if (!im->tex) return;
        break;
+      case EVAS_COLORSPACE_ETC1_ALPHA:
+        if ((im->tex) && (im->dirty))
+          {
+             evas_cache_image_load_data(&im->im->cache_entry);
+             evas_gl_common_texture_rgb_a_pair_update(im->tex, im->im);
+             evas_cache_image_unload_data(&im->im->cache_entry);
+          }
+        else if ((!im->tex))
+          {
+             evas_cache_image_load_data(&im->im->cache_entry);
+             im->tex = evas_gl_common_texture_rgb_a_pair_new(gc, im->im);
+             evas_cache_image_unload_data(&im->im->cache_entry);
+          }
+        im->dirty = 0;
+        if (!im->tex) return;
+        break;
       case EVAS_COLORSPACE_YCBCR422P601_PL:
       case EVAS_COLORSPACE_YCBCR422P709_PL:
         if ((im->tex) && (im->dirty))
@@ -942,13 +972,14 @@ evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
                                          im->cs.space);
 }
 
-void
-evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
-                         int dx, int dy, int dw, int dh,
-                          int sx, int sy, int sw, int sh,
-                          int cx, int cy, int cw, int ch,
-                          int r, int g, int b, int a, int smooth,
-                          int yuv, int yuy2, int nv12)
+static void
+_evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
+                           int dx, int dy, int dw, int dh,
+                           int sx, int sy, int sw, int sh,
+                           int cx, int cy, int cw, int ch,
+                           int r, int g, int b, int a, Eina_Bool smooth,
+                           Eina_Bool yuv, Eina_Bool yuy2, Eina_Bool nv12,
+                           Eina_Bool rgb_a_pair)
 {
    double ssx, ssy, ssw, ssh;
    int nx, ny, nw, nh;
@@ -981,6 +1012,13 @@ evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
                                            dx, dy, dw, dh,
                                            r, g, b, a,
                                            smooth);
+        else if (rgb_a_pair)
+          evas_gl_common_context_rgb_a_pair_push(gc,
+                                                 im->tex,
+                                                 sx, sy, sw, sh,
+                                                 dx, dy, dw, dh,
+                                                 r, g, b, a,
+                                                 smooth);
         else
           evas_gl_common_context_image_push(gc,
                                             im->tex,
@@ -1017,6 +1055,13 @@ evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
                                       nx, ny, nw, nh,
                                       r, g, b, a,
                                       smooth);
+   else if (rgb_a_pair)
+     evas_gl_common_context_rgb_a_pair_push(gc,
+                                            im->tex,
+                                            ssx, ssy, ssw, ssh,
+                                            nx, ny, nw, nh,
+                                            r, g, b, a,
+                                            smooth);
    else
      evas_gl_common_context_image_push(gc,
                                        im->tex,
@@ -1035,9 +1080,10 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
    Cutout_Rect  *rct;
    int c, cx, cy, cw, ch;
    int i;
-   int yuv = 0;
-   int yuy2 = 0;
-   int nv12 = 0;
+   Eina_Bool yuv = EINA_FALSE;
+   Eina_Bool yuy2 = EINA_FALSE;
+   Eina_Bool nv12 = EINA_FALSE;
+   Eina_Bool rgb_a_pair = EINA_FALSE;
 
    if (sw < 1) sw = 1;
    if (sh < 1) sh = 1;
@@ -1061,14 +1107,24 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
         return;
      }
 
-   if ((im->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
-       (im->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL))
-     yuv = 1;
-   if (im->cs.space == EVAS_COLORSPACE_YCBCR422601_PL)
-     yuy2 = 1;
-   if ((im->cs.space == EVAS_COLORSPACE_YCBCR420NV12601_PL) ||
-       (im->cs.space == EVAS_COLORSPACE_YCBCR420TM12601_PL))
-     nv12 = 1;
+   switch (im->cs.space)
+     {
+      case EVAS_COLORSPACE_YCBCR422P601_PL:
+      case EVAS_COLORSPACE_YCBCR422P709_PL:
+        yuv = EINA_TRUE;
+        break;
+      case EVAS_COLORSPACE_YCBCR422601_PL:
+        yuy2 = EINA_TRUE;
+        break;
+      case EVAS_COLORSPACE_YCBCR420NV12601_PL:
+      case EVAS_COLORSPACE_YCBCR420TM12601_PL:
+        nv12 = EINA_TRUE;
+        break;
+      case EVAS_COLORSPACE_ETC1_ALPHA:
+        rgb_a_pair = EINA_TRUE;
+        break;
+      default: break;
+     }
 
    if ((sw == dw) && (sh == dh)) smooth = 0;
    
@@ -1079,22 +1135,22 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
      {
         if (gc->dc->clip.use)
           {
-             evas_gl_common_image_push(gc, im,
-                                       dx, dy, dw, dh,
-                                       sx, sy, sw, sh,
-                                       gc->dc->clip.x, gc->dc->clip.y,
-                                       gc->dc->clip.w, gc->dc->clip.h,
-                                       r, g, b, a, smooth,
-                                       yuv, yuy2, nv12);
+             _evas_gl_common_image_push(gc, im,
+                                        dx, dy, dw, dh,
+                                        sx, sy, sw, sh,
+                                        gc->dc->clip.x, gc->dc->clip.y,
+                                        gc->dc->clip.w, gc->dc->clip.h,
+                                        r, g, b, a, smooth,
+                                        yuv, yuy2, nv12, rgb_a_pair);
           }
         else
           {
-             evas_gl_common_image_push(gc, im,
-                                       dx, dy, dw, dh,
-                                       sx, sy, sw, sh,
-                                       dx, dy, dw, dh,
-                                       r, g, b, a, smooth,
-                                       yuv, yuy2, nv12);
+             _evas_gl_common_image_push(gc, im,
+                                        dx, dy, dw, dh,
+                                        sx, sy, sw, sh,
+                                        dx, dy, dw, dh,
+                                        r, g, b, a, smooth,
+                                        yuv, yuy2, nv12, rgb_a_pair);
           }
         return;
      }
@@ -1114,12 +1170,12 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
      {
         rct = rects->rects + i;
 
-        evas_gl_common_image_push(gc, im,
-                                  dx, dy, dw, dh,
-                                  sx, sy, sw, sh,
-                                  rct->x, rct->y, rct->w, rct->h,
-                                  r, g, b, a, smooth,
-                                  yuv, yuy2, nv12);
+        _evas_gl_common_image_push(gc, im,
+                                   dx, dy, dw, dh,
+                                   sx, sy, sw, sh,
+                                   rct->x, rct->y, rct->w, rct->h,
+                                   r, g, b, a, smooth,
+                                   yuv, yuy2, nv12, rgb_a_pair);
      }
    /* restore clip info */
    gc->dc->clip.use = c; gc->dc->clip.x = cx; gc->dc->clip.y = cy; gc->dc->clip.w = cw; gc->dc->clip.h = ch;
index ef37278..3f16040 100644 (file)
@@ -771,6 +771,43 @@ Evas_GL_Program_Source shader_yuv_nomul_vert_src =
    NULL, 0
 };
 
+/////////////////////////////////////////////
+const char rgb_a_pair_frag_glsl[] =
+#include "shader/rgb_a_pair_frag.h"
+  ;
+Evas_GL_Program_Source shader_rgb_a_pair_frag_src =
+{
+   rgb_a_pair_frag_glsl,
+   NULL, 0
+};
+
+const char rgb_a_pair_vert_glsl[] =
+#include "shader/rgb_a_pair_vert.h"
+  ;
+Evas_GL_Program_Source shader_rgb_a_pair_vert_src =
+{
+   rgb_a_pair_vert_glsl,
+   NULL, 0
+};
+
+const char rgb_a_pair_nomul_frag_glsl[] =
+#include "shader/rgb_a_pair_nomul_frag.h"
+  ;
+Evas_GL_Program_Source shader_rgb_a_pair_nomul_frag_src =
+{
+   rgb_a_pair_nomul_frag_glsl,
+   NULL, 0
+};
+
+const char rgb_a_pair_nomul_vert_glsl[] =
+#include "shader/rgb_a_pair_nomul_vert.h"
+  ;
+Evas_GL_Program_Source shader_rgb_a_pair_nomul_vert_src =
+{
+   rgb_a_pair_nomul_vert_glsl,
+   NULL, 0
+};
+
 
 /////////////////////////////////////////////
 static void
@@ -1048,6 +1085,9 @@ static const struct {
   SHADER_SOURCE_LINE(YUY2_NOMUL, yuy2_nomul),
   SHADER_SOURCE_LINE(NV12, nv12),
   SHADER_SOURCE_LINE(NV12_NOMUL, nv12_nomul),
+
+  SHADER_SOURCE_LINE(RGB_A_PAIR, rgb_a_pair),
+  SHADER_SOURCE_LINE(RGB_A_PAIR_NOMUL, rgb_a_pair_nomul),
 };
 
 static int
index eaac74b..6012f33 100644 (file)
@@ -71,6 +71,7 @@ static const struct {
   { 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 },
+  // ETC1/2 support
   { 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_FALSE, EVAS_COLORSPACE_RGB8_ETC2, &etc2_rgb_fmt, &etc2_rgb_fmt },
@@ -80,6 +81,8 @@ static const struct {
   // images marked as no alpha but format supports it (RGBA8_ETC2_EAC):
   { 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 },
+  { EINA_TRUE, EINA_FALSE, EVAS_COLORSPACE_ETC1_ALPHA, &etc1_fmt, &etc1_fmt },
+  { EINA_TRUE, EINA_TRUE, EVAS_COLORSPACE_ETC1_ALPHA, &etc1_fmt, &etc1_fmt },
   // S3TC support
   { EINA_FALSE, EINA_FALSE, EVAS_COLORSPACE_RGB_S3TC_DXT1, &s3tc_rgb_dxt1_fmt, &s3tc_rgb_dxt1_fmt },
   { EINA_FALSE, EINA_TRUE, EVAS_COLORSPACE_RGB_S3TC_DXT1, &s3tc_rgb_dxt1_fmt, &s3tc_rgb_dxt1_fmt },
@@ -516,6 +519,7 @@ evas_gl_common_texture_new(Evas_Engine_GL_Context *gc, RGBA_Image *im)
       case EVAS_COLORSPACE_ETC1:
       case EVAS_COLORSPACE_RGB8_ETC2:
       case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
       case EVAS_COLORSPACE_RGB_S3TC_DXT1:
       case EVAS_COLORSPACE_RGBA_S3TC_DXT1:
       case EVAS_COLORSPACE_RGBA_S3TC_DXT2:
@@ -1183,6 +1187,7 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
       case EVAS_COLORSPACE_RGB_S3TC_DXT1:
       case EVAS_COLORSPACE_RGBA_S3TC_DXT1:
       case EVAS_COLORSPACE_ETC1:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
       case EVAS_COLORSPACE_RGB8_ETC2:
         {
            /*
@@ -1205,7 +1210,8 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
            GLERR(__FUNCTION__, __FILE__, __LINE__, "");
 
            if ((tex->gc->shared->info.etc1_subimage ||
-               (im->cache_entry.space != EVAS_COLORSPACE_ETC1))
+               ((im->cache_entry.space != EVAS_COLORSPACE_ETC1) &&
+                (im->cache_entry.space != EVAS_COLORSPACE_ETC1_ALPHA)))
                && (tex->pt->w != width || tex->pt->h != height))
              {
                 int err;
@@ -1225,7 +1231,8 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
                      // 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)
+                     if ((im->cache_entry.space == EVAS_COLORSPACE_ETC1) ||
+                         (im->cache_entry.space == EVAS_COLORSPACE_ETC1_ALPHA))
                        tex->gc->shared->info.etc1_subimage = EINA_FALSE;
                   }
              }
@@ -1462,6 +1469,171 @@ evas_gl_common_texture_alpha_update(Evas_GL_Texture *tex, DATA8 *pixels,
 }
 
 Evas_GL_Texture *
+evas_gl_common_texture_rgb_a_pair_new(Evas_Engine_GL_Context *gc,
+                                      RGBA_Image *im)
+{
+   Evas_GL_Texture *tex;
+   int lformat, w, h;
+
+   // FIXME/TODO: We don't support texture atlasses here (a bit tricky)
+
+   // Some debugging. We could return.
+   if (im->cache_entry.space != EVAS_COLORSPACE_ETC1_ALPHA)
+     WRN("Using RGB+A texture pair with format %d", im->cache_entry.space);
+
+   w = im->cache_entry.w;
+   h = im->cache_entry.h;
+
+   lformat = _evas_gl_texture_search_format(EINA_FALSE, gc->shared->info.bgra,
+                                            im->cache_entry.space);
+   if (lformat < 0) return NULL;
+
+   tex = evas_gl_common_texture_alloc(gc, w, h, EINA_TRUE);
+   if (!tex) return NULL;
+
+   // Allocate RGB texture normally - as a 'whole'
+   tex->pt = _pool_tex_new(gc, w, h,
+                           *matching_format[lformat].intformat,
+                           *matching_format[lformat].format);
+   if (!tex->pt)
+     {
+        evas_gl_common_texture_light_free(tex);
+        return NULL;
+     }
+   pt_link(gc, tex->pt);
+   tex->pt->slot = -1;
+
+   // And now Alpha texture -- FIXME could intformat be different? (eg. ALPHA4)
+   tex->pta = _pool_tex_new(gc, w, h,
+                            *matching_format[lformat].intformat,
+                            *matching_format[lformat].format);
+   if (!tex->pta)
+     {
+        pt_unref(tex->pt);
+        evas_gl_common_texture_light_free(tex);
+        return NULL;
+     }
+   pt_link(gc, tex->pta);
+   tex->pta->slot = -1;
+
+   evas_gl_common_texture_rgb_a_pair_update(tex, im);
+   return tex;
+}
+
+void
+evas_gl_common_texture_rgb_a_pair_update(Evas_GL_Texture *tex,
+                                             RGBA_Image *im)
+{
+   DATA8 *data1, *data2;
+   Eina_Bool comp, upload;
+   int w, h, sz, rowlen, ystep = 1;
+
+   if (!tex->pt) return;
+
+   // Handle compressed formats with 4x4 blocks format
+   if (((int) im->cache_entry.space >= (int) EVAS_COLORSPACE_ETC1) &&
+       ((int) im->cache_entry.space <= (int) EVAS_COLORSPACE_RGBA_S3TC_DXT5))
+     ystep = 4;
+
+   w = im->cache_entry.w + im->cache_entry.borders.l + im->cache_entry.borders.r;
+   h = im->cache_entry.h + im->cache_entry.borders.t + im->cache_entry.borders.b;
+   rowlen = _evas_gl_texture_size_get(w, ystep, tex->pt->intformat, NULL);
+   sz = _evas_gl_texture_size_get(w, h, tex->pt->intformat, &comp);
+   data1 = im->image.data8;
+   data2 = data1 + sz;
+   upload = !!data1;
+
+   if (tex->gc->shared->info.unpack_row_length)
+     {
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, w); GLERRLOG();
+        glPixelStorei(GL_UNPACK_ALIGNMENT, 1); GLERRLOG();
+        glBindTexture(GL_TEXTURE_2D, tex->pt->texture); GLERRLOG();
+        if (!_tex_2d(tex->gc, tex->pt->intformat, w, h, tex->pt->format, tex->pt->dataformat))
+          goto on_error;
+        if (upload)
+          {
+             if (comp)
+               _comp_tex_sub_2d(tex->gc, 0, 0, w, h, tex->pt->format, sz, data1);
+             else
+               _tex_sub_2d(tex->gc, 0, 0, w, h, tex->pt->format, tex->pt->dataformat, data1);
+          }
+        glBindTexture(GL_TEXTURE_2D, tex->pta->texture); GLERRLOG();
+        if (!_tex_2d(tex->gc, tex->pta->intformat, w, h, tex->pta->format, tex->pta->dataformat))
+          goto on_error;
+        if (upload)
+          {
+             if (comp)
+               _comp_tex_sub_2d(tex->gc, 0, 0, w, h, tex->pt->format, sz, data2);
+             else
+               _tex_sub_2d(tex->gc, 0, 0, w, h, tex->pt->format, tex->pt->dataformat, data2);
+          }
+     }
+   else
+     {
+        int y;
+
+        glPixelStorei(GL_UNPACK_ALIGNMENT, 1); GLERRLOG();
+        glBindTexture(GL_TEXTURE_2D, tex->pt->texture); GLERRLOG();
+        if (!_tex_2d(tex->gc, tex->pt->intformat, w, h, tex->pt->format,
+                     tex->pt->dataformat))
+          goto on_error;
+        if (upload)
+          {
+             if (w == tex->w)
+               {
+                  if (comp)
+                    _comp_tex_sub_2d(tex->gc, 0, 0, w, h, tex->pt->format, sz, data1);
+                  else
+                    _tex_sub_2d(tex->gc, 0, 0, w, h, tex->pt->format, tex->pt->dataformat, data1);
+               }
+             else
+               {
+                  for (y = 0; y < h; y += ystep)
+                    {
+                       if (comp)
+                         _comp_tex_sub_2d(tex->gc, 0, 0, w, h, tex->pt->format, sz, data1);
+                       else
+                         _tex_sub_2d(tex->gc, 0, y, w, ystep, tex->pt->format,
+                                     tex->pt->dataformat, data1 + rowlen * y / ystep);
+                    }
+               }
+          }
+
+        glBindTexture(GL_TEXTURE_2D, tex->pta->texture); GLERRLOG();
+        if (!_tex_2d(tex->gc, tex->pta->intformat, w, h, tex->pta->format,
+                     tex->pta->dataformat))
+          goto on_error;
+        if (upload)
+          {
+             if (w == tex->w)
+               {
+                  if (comp)
+                    _comp_tex_sub_2d(tex->gc, 0, 0, w, h, tex->pt->format, sz, data2);
+                  else
+                    _tex_sub_2d(tex->gc, 0, 0, w, h, tex->pt->format, tex->pt->dataformat, data2);
+               }
+             else
+               {
+                  for (y = 0; y < h; y += ystep)
+                    {
+                       if (comp)
+                         _comp_tex_sub_2d(tex->gc, 0, 0, w, h, tex->pt->format, sz, data2);
+                       else
+                         _tex_sub_2d(tex->gc, 0, y, w, ystep, tex->pt->format,
+                                     tex->pt->dataformat, data2 + rowlen * y / ystep);
+                    }
+               }
+          }
+     }
+on_error:
+   if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex)
+     {
+        glBindTexture(GL_TEXTURE_2D, tex->gc->pipe[0].shader.cur_tex);
+        GLERRLOG();
+     }
+}
+
+Evas_GL_Texture *
 evas_gl_common_texture_yuv_new(Evas_Engine_GL_Context *gc, DATA8 **rows, unsigned int w, unsigned int h)
 {
    Evas_GL_Texture *tex;
index 587bc7a..7c607b5 100644 (file)
@@ -2304,6 +2304,7 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i
       case EVAS_COLORSPACE_ETC1:
       case EVAS_COLORSPACE_RGB8_ETC2:
       case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
          ERR("This image is encoded in ETC1 or ETC2, not returning any data");
          error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
          *image_data = NULL;