Evas: Support duplicated borders in surface alloc
authorJean-Philippe Andre <jp.andre@samsung.com>
Mon, 30 Jun 2014 08:13:51 +0000 (17:13 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Thu, 3 Jul 2014 02:37:48 +0000 (11:37 +0900)
Now, the evas loader is supposed to advertise the actual border
size in case of compressed texture formats.

The only case where the border was non zero was ETC formats,
from the TGV loader, so I think we don't need to keep the
previous behaviour (auto-calculate borders for ETC).

src/lib/evas/Evas_Loader.h
src/lib/evas/cache/evas_cache_image.c
src/lib/evas/cache2/evas_cache2.c
src/lib/evas/common/evas_image_load.c
src/lib/evas/common/evas_image_main.c
src/modules/evas/engines/gl_common/evas_gl_texture.c

index 1b74253..6cabb18 100644 (file)
@@ -183,7 +183,7 @@ struct _Evas_Image_Property
    Evas_Colorspace cspace; /**< Specify the color space handle by the engine @since 1.10 */
 
    struct {
-      unsigned char l, r, t, b; /**< Specify the dimensions of duplicated pixels borders (for OpenGL compressed textures). Set by the loader. @since 1.11 */
+      unsigned char l, r, t, b; /**< Specify the dimensions of duplicated pixels borders for OpenGL compressed textures, set by the loader. @since 1.11 */
    } borders;
 };
 
index 70d0547..dc1d0d8 100644 (file)
@@ -305,8 +305,6 @@ _evas_cache_image_entry_surface_alloc__locked(Evas_Cache_Image *cache,
      }
    ie->w = wmin;
    ie->h = hmin;
-   ie->allocated.w = wmin;
-   ie->allocated.h = hmin;
 }
 
 static void
index 353ab0d..11b2f2e 100644 (file)
@@ -294,8 +294,6 @@ evas_cache2_image_surface_alloc(Image_Entry *ie, int w, int h)
 
    ie->w = wmin;
    ie->h = hmin;
-   ie->allocated.w = wmin;
-   ie->allocated.h = hmin;
    ie->flags.loaded = EINA_TRUE;
 }
 
index dc72986..6158e0b 100644 (file)
@@ -223,6 +223,10 @@ _evas_image_file_header(Evas_Module *em, Image_Entry *ie, int *error)
 
              ie->w = property.w;
              ie->h = property.h;
+             ie->borders.l = property.borders.l;
+             ie->borders.r = property.borders.r;
+             ie->borders.t = property.borders.t;
+             ie->borders.b = property.borders.b;
              ie->scale = property.scale;
              ie->flags.alpha = property.alpha;
              if (property.cspaces)
@@ -417,6 +421,10 @@ evas_common_load_rgba_image_data_from_file(Image_Entry *ie)
    property.cspace = ie->space;
 
    evas_cache_image_surface_alloc(ie, ie->w, ie->h);
+   property.borders.l = ie->borders.l;
+   property.borders.r = ie->borders.r;
+   property.borders.t = ie->borders.t;
+   property.borders.b = ie->borders.b;
 
    pixels = evas_cache_image_pixels(ie);
    if (!pixels)
index e375675..faabda4 100644 (file)
@@ -110,7 +110,9 @@ static const Evas_Cache2_Image_Func      _evas_common_image_func2 =
 #endif
 
 static inline int
-_evas_common_rgba_image_surface_size(unsigned int w, unsigned int h, Evas_Colorspace cspace)
+_evas_common_rgba_image_surface_size(unsigned int w, unsigned int h,
+                                     Evas_Colorspace cspace,
+                                     /* inout */ int *l, int *r, int *t, int *b)
 {
 #define PAGE_SIZE (4 * 1024)
 #define HUGE_PAGE_SIZE (2 * 1024 * 1024)
@@ -119,26 +121,40 @@ _evas_common_rgba_image_surface_size(unsigned int w, unsigned int h, Evas_Colors
 #else
 # define ALIGN_TO_PAGE(Siz) Siz
 #endif
-   int siz;
+
+   int siz, block_size = 8;
+   Eina_Bool reset_borders = EINA_TRUE;
 
    switch (cspace)
      {
       case EVAS_COLORSPACE_GRY8: siz = w * h * sizeof(DATA8); break;
       case EVAS_COLORSPACE_AGRY88: siz = w * h * sizeof(DATA16); break;
+      case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+        block_size = 16;
+        // fallthrough
       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;
-         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;
+        reset_borders = EINA_FALSE;
+        if (l && r && t && b)
+          {
+             w += *l + *r;
+             h += *t + *b;
+          }
+        EINA_SAFETY_ON_FALSE_RETURN_VAL(!(w & 0x3) && !(h & 0x3), 0);
+        siz = (w >> 2) * (h >> 2) * block_size;
+        break;
       default:
       case EVAS_COLORSPACE_ARGB8888: siz = w * h * sizeof(DATA32); break;
      }
 
+   if (reset_borders)
+     {
+        if (l) *l = 0;
+        if (r) *r = 0;
+        if (t) *t = 0;
+        if (b) *b = 0;
+     }
+
    if (siz < PAGE_SIZE) return siz;
 
    return ALIGN_TO_PAGE(siz);
@@ -147,14 +163,15 @@ _evas_common_rgba_image_surface_size(unsigned int w, unsigned int h, Evas_Colors
 }
 
 static void *
-_evas_common_rgba_image_surface_mmap(unsigned int w, unsigned int h, Evas_Colorspace cspace)
+_evas_common_rgba_image_surface_mmap(Image_Entry *ie, unsigned int w, unsigned int h,
+                                     /* inout */ int *pl, int *pr, int *pt, int *pb)
 {
    int siz;
 #if defined (HAVE_SYS_MMAN_H) && (!defined (_WIN32))
    void *r = MAP_FAILED;
 #endif
 
-   siz = _evas_common_rgba_image_surface_size(w, h, cspace);
+   siz = _evas_common_rgba_image_surface_size(w, h, ie->space, pl, pr, pt, pb);
 
 #if defined (HAVE_SYS_MMAN_H) && (!defined (_WIN32))
 #ifndef MAP_HUGETLB
@@ -186,7 +203,7 @@ _evas_common_rgba_image_surface_munmap(void *data, unsigned int w, unsigned int
 #if defined (HAVE_SYS_MMAN_H) && (!defined (_WIN32))
    size_t siz;
 
-   siz = _evas_common_rgba_image_surface_size(w, h, cspace);
+   siz = _evas_common_rgba_image_surface_size(w, h, cspace, NULL, NULL, NULL, NULL);
    if (siz < PAGE_SIZE)
      free(data);
    else
@@ -453,7 +470,8 @@ _evas_common_rgba_image_post_surface(Image_Entry *ie)
 static int
 _evas_common_rgba_image_surface_alloc(Image_Entry *ie, unsigned int w, unsigned int h)
 {
-   RGBA_Image   *im = (RGBA_Image *) ie;
+   RGBA_Image *im = (RGBA_Image *) ie;
+   int l = 0, r = 0, t = 0, b = 0;
 
 #ifdef EVAS_CSERVE2
    if (ie->data1) return 0;
@@ -471,16 +489,24 @@ _evas_common_rgba_image_surface_alloc(Image_Entry *ie, unsigned int w, unsigned
 #endif
      }
 
-   im->image.data = _evas_common_rgba_image_surface_mmap(w, h, ie->space);
+   l = ie->borders.l;
+   r = ie->borders.r;
+   t = ie->borders.t;
+   b = ie->borders.b;
+   im->image.data = _evas_common_rgba_image_surface_mmap(ie, w, h, &l, &r, &t, &b);
    if (!im->image.data) return -1;
-   ie->allocated.w = w;
-   ie->allocated.h = h;
+   ie->borders.l = l;
+   ie->borders.r = r;
+   ie->borders.t = t;
+   ie->borders.b = b;
+   ie->allocated.w = w + l + r;
+   ie->allocated.h = h + t + b;
 #ifdef SURFDBG
    surfs = eina_list_append(surfs, ie);
 #endif
 #ifdef HAVE_VALGRIND
    int        siz = 0;
-   siz = _evas_common_rgba_image_surface_size(w, h, ie->space);
+   siz = _evas_common_rgba_image_surface_size(w, h, ie->space, &l, &r, &t, &b);
 # ifdef VALGRIND_MAKE_READABLE
    if (siz > 0) VALGRIND_MAKE_READABLE(im->image.data, siz);
 # else
index 0c69398..16cb9c4 100644 (file)
@@ -453,19 +453,17 @@ evas_gl_common_texture_new(Evas_Engine_GL_Context *gc, RGBA_Image *im)
       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;
+        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;
+        EINA_SAFETY_ON_FALSE_RETURN_VAL(!(w & 0x3) && !(h & 0x3), NULL);
         yoffset = 1;
-
-        // 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;
         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 + 2; /* only one added border for security down */
+        break;
      }
 
    tex->pt = _pool_tex_find(gc, w, h,
@@ -1121,12 +1119,11 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
            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;
-           height = ((height >> 2) + (height & 0x3 ? 1 : 0)) << 2;
+           x = tex->x - im->cache_entry.borders.l;
+           y = tex->y - im->cache_entry.borders.t;
+           width = im->cache_entry.w + im->cache_entry.borders.l + im->cache_entry.borders.r;
+           height = im->cache_entry.h + im->cache_entry.borders.t + im->cache_entry.borders.b;
+           EINA_SAFETY_ON_FALSE_RETURN(!(width & 0x3) && !(height & 0x3));
 
            glBindTexture(GL_TEXTURE_2D, tex->pt->texture);
            GLERR(__FUNCTION__, __FILE__, __LINE__, "");