summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric@osg.samsung.com>2015-03-17 08:50:16 +0100
committerCedric BAIL <cedric@osg.samsung.com>2015-03-17 09:58:18 +0100
commit8cac4ce5e776c677dd70e16e7a4913101a9fb73b (patch)
tree574b6061121d2d915a7b4dece49ea63f3ca8dd8c
parentb5cea1703d784495005df17f4fc2b663b0880e3e (diff)
evas: use Emile to decode TGV.
-rw-r--r--configure.ac1
-rw-r--r--doc/previews/Makefile.am2
-rw-r--r--m4/efl.m42
-rw-r--r--src/Makefile_Evas.am8
-rw-r--r--src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c476
5 files changed, 31 insertions, 458 deletions
diff --git a/configure.ac b/configure.ac
index 5df945c041..6b0b799214 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1673,6 +1673,7 @@ EFL_INTERNAL_DEPEND_PKG([EVAS], [eo])
1673EFL_INTERNAL_DEPEND_PKG([EVAS], [eet]) 1673EFL_INTERNAL_DEPEND_PKG([EVAS], [eet])
1674EFL_INTERNAL_DEPEND_PKG([EVAS], [eina]) 1674EFL_INTERNAL_DEPEND_PKG([EVAS], [eina])
1675EFL_INTERNAL_DEPEND_PKG([EVAS], [efl]) 1675EFL_INTERNAL_DEPEND_PKG([EVAS], [efl])
1676EFL_INTERNAL_DEPEND_PKG([EVAS], [emile])
1676 1677
1677EFL_ADD_LIBS([EVAS], [-lm]) 1678EFL_ADD_LIBS([EVAS], [-lm])
1678 1679
diff --git a/doc/previews/Makefile.am b/doc/previews/Makefile.am
index ea0d30789c..7b3a87e943 100644
--- a/doc/previews/Makefile.am
+++ b/doc/previews/Makefile.am
@@ -23,7 +23,7 @@ AM_CPPFLAGS = \
23-I$(top_builddir)/src/lib/ecore_evas \ 23-I$(top_builddir)/src/lib/ecore_evas \
24-DEFL_BETA_API_SUPPORT=1 \ 24-DEFL_BETA_API_SUPPORT=1 \
25-DEFL_EO_API_SUPPORT=1 \ 25-DEFL_EO_API_SUPPORT=1 \
26@ECORE_EVAS_LDFLAGS@ 26@ECORE_EVAS_CFLAGS@
27 27
28LDADD = \ 28LDADD = \
29$(top_builddir)/src/lib/eina/libeina.la \ 29$(top_builddir)/src/lib/eina/libeina.la \
diff --git a/m4/efl.m4 b/m4/efl.m4
index 3598ce78fe..3d654c9268 100644
--- a/m4/efl.m4
+++ b/m4/efl.m4
@@ -152,7 +152,7 @@ case "m4_defn([DOWNOTHER])" in
152 ;; 152 ;;
153esac 153esac
154requirements_pc_[]m4_defn([DOWNEFL])="${depname} >= ${PACKAGE_VERSION} ${requirements_pc_[][]m4_defn([DOWNEFL])}" 154requirements_pc_[]m4_defn([DOWNEFL])="${depname} >= ${PACKAGE_VERSION} ${requirements_pc_[][]m4_defn([DOWNEFL])}"
155requirements_cflags_[]m4_defn([DOWNEFL])="-I\$(top_srcdir)/src/lib/${libdirname} -I\$(top_builddir)/src/lib/${libdirname} ${requirements_cflags_[][]m4_defn([DOWNEFL])}" 155requirements_cflags_[]m4_defn([DOWNEFL])="-I\$(top_srcdir)/src/lib/${libdirname} -I\$(top_builddir)/src/lib/${libdirname} ${requirements_cflags_[][]m4_defn([DOWNOTHER])} ${requirements_cflags_[][]m4_defn([DOWNEFL])}"
156requirements_internal_libs_[]m4_defn([DOWNEFL])="lib/${libdirname}/lib${libname}.la ${requirements_internal_libs_[][]m4_defn([DOWNEFL])}" 156requirements_internal_libs_[]m4_defn([DOWNEFL])="lib/${libdirname}/lib${libname}.la ${requirements_internal_libs_[][]m4_defn([DOWNEFL])}"
157requirements_internal_deps_libs_[]m4_defn([DOWNEFL])="${requirements_public_libs_[]m4_defn([DOWNOTHER])} ${requirements_internal_deps_libs_[][]m4_defn([DOWNEFL])}" 157requirements_internal_deps_libs_[]m4_defn([DOWNEFL])="${requirements_public_libs_[]m4_defn([DOWNOTHER])} ${requirements_internal_deps_libs_[][]m4_defn([DOWNEFL])}"
158m4_popdef([DOWNOTHER])dnl 158m4_popdef([DOWNOTHER])dnl
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index d8c6edec1d..cb79b49c40 100644
--- a/src/Makefile_Evas.am
+++ b/src/Makefile_Evas.am
@@ -1343,7 +1343,7 @@ bin/evas/evas_cserve2_client.c
1343bin_evas_evas_cserve2_client_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ 1343bin_evas_evas_cserve2_client_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
1344-I$(top_srcdir)/src/lib/evas \ 1344-I$(top_srcdir)/src/lib/evas \
1345-I$(top_srcdir)/src/lib/evas/cserve2 \ 1345-I$(top_srcdir)/src/lib/evas/cserve2 \
1346@EINA_CFLAGS@ 1346@EVAS_CFLAGS@
1347bin_evas_evas_cserve2_client_LDADD = @USE_EINA_LIBS@ 1347bin_evas_evas_cserve2_client_LDADD = @USE_EINA_LIBS@
1348bin_evas_evas_cserve2_client_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ 1348bin_evas_evas_cserve2_client_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
1349 1349
@@ -1352,7 +1352,7 @@ bin/evas/evas_cserve2_usage.c
1352bin_evas_evas_cserve2_usage_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ 1352bin_evas_evas_cserve2_usage_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
1353-I$(top_srcdir)/src/lib/evas \ 1353-I$(top_srcdir)/src/lib/evas \
1354-I$(top_srcdir)/src/lib/evas/cserve2 \ 1354-I$(top_srcdir)/src/lib/evas/cserve2 \
1355@EINA_CFLAGS@ 1355@EVAS_CFLAGS@
1356bin_evas_evas_cserve2_usage_LDADD = @USE_EINA_LIBS@ 1356bin_evas_evas_cserve2_usage_LDADD = @USE_EINA_LIBS@
1357bin_evas_evas_cserve2_usage_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ 1357bin_evas_evas_cserve2_usage_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
1358 1358
@@ -1361,7 +1361,7 @@ bin/evas/evas_cserve2_debug.c
1361bin_evas_evas_cserve2_debug_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ 1361bin_evas_evas_cserve2_debug_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
1362-I$(top_srcdir)/src/lib/evas \ 1362-I$(top_srcdir)/src/lib/evas \
1363-I$(top_srcdir)/src/lib/evas/cserve2 \ 1363-I$(top_srcdir)/src/lib/evas/cserve2 \
1364@EINA_CFLAGS@ 1364@EVAS_CFLAGS@
1365bin_evas_evas_cserve2_debug_LDADD = @USE_EINA_LIBS@ 1365bin_evas_evas_cserve2_debug_LDADD = @USE_EINA_LIBS@
1366bin_evas_evas_cserve2_debug_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ 1366bin_evas_evas_cserve2_debug_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
1367 1367
@@ -1370,7 +1370,7 @@ bin/evas/evas_cserve2_shm_debug.c
1370bin_evas_evas_cserve2_shm_debug_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ 1370bin_evas_evas_cserve2_shm_debug_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
1371-I$(top_srcdir)/src/lib/evas \ 1371-I$(top_srcdir)/src/lib/evas \
1372-I$(top_srcdir)/src/lib/evas/cserve2 \ 1372-I$(top_srcdir)/src/lib/evas/cserve2 \
1373@EINA_CFLAGS@ 1373@EVAS_CFLAGS@
1374bin_evas_evas_cserve2_shm_debug_LDADD = @USE_EINA_LIBS@ 1374bin_evas_evas_cserve2_shm_debug_LDADD = @USE_EINA_LIBS@
1375bin_evas_evas_cserve2_shm_debug_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ 1375bin_evas_evas_cserve2_shm_debug_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
1376 1376
diff --git a/src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c b/src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c
index b715017831..0b9c65cec5 100644
--- a/src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c
+++ b/src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c
@@ -2,77 +2,14 @@
2# include "config.h" 2# include "config.h"
3#endif 3#endif
4 4
5#ifdef HAVE_NETINET_IN_H 5#include <Emile.h>
6# include <netinet/in.h>
7#endif
8
9#ifdef _WIN32
10# include <winsock2.h>
11#endif /* ifdef _WIN32 */
12
13#ifdef ENABLE_LIBLZ4
14# include <lz4.h>
15#else
16# include "lz4.h"
17#endif
18 6
19#include "rg_etc1.h"
20#include "Evas_Loader.h" 7#include "Evas_Loader.h"
21 8
22#ifdef BUILD_NEON
23#include <arm_neon.h>
24#endif
25
26#ifndef WORDS_BIGENDIAN
27/* x86 */
28#define A_VAL(p) (((uint8_t *)(p))[3])
29#define R_VAL(p) (((uint8_t *)(p))[2])
30#define G_VAL(p) (((uint8_t *)(p))[1])
31#define B_VAL(p) (((uint8_t *)(p))[0])
32#else
33/* ppc */
34#define A_VAL(p) (((uint8_t *)(p))[0])
35#define R_VAL(p) (((uint8_t *)(p))[1])
36#define G_VAL(p) (((uint8_t *)(p))[2])
37#define B_VAL(p) (((uint8_t *)(p))[3])
38#endif
39
40/**************************************************************
41 * The TGV file format is oriented around compression mecanism
42 * that hardware are good at decompressing. We do still provide
43 * a fully software implementation in case your hardware doesn't
44 * handle it. As OpenGL is pretty bad at handling border of
45 * texture, we do duplicate the first pixels of every border.
46 *
47 * This file format is designed to compress/decompress things
48 * in block area. Giving opportunity to store really huge file
49 * and only decompress/compress them as we need. Note that region
50 * only work with software decompression as we don't have a sane
51 * way to duplicate border to avoid artifact when scaling texture.
52 *
53 * The file format is as follow :
54 * - char magic[4]: "TGV1"
55 * - uint8_t block_size (real block size = (4 << bits[0-3], 4 << bits[4-7])
56 * - uint8_t algorithm (0 -> ETC1, 1 -> ETC2 RGB, 2 -> ETC2 RGBA, 3 -> ETC1+Alpha)
57 * - uint8_t options[2] (bitmask: 1 -> lz4, 2 for block-less, 4 -> unpremultiplied)
58 * - uint32_t width
59 * - uint32_t height
60 * - blocks[]
61 * - 0 length encoded compress size (if length == 64 * block_size => no compression)
62 * - lzma encoded etc1 block
63 *
64 * If the format is ETC1+Alpha (algo = 3), then a second image is encoded
65 * in ETC1 right after the first one, and it contains grey-scale alpha
66 * values.
67 **************************************************************/
68
69// FIXME: wondering if we should support mipmap
70// TODO: support ETC1+ETC2 images (RGB only)
71
72typedef struct _Evas_Loader_Internal Evas_Loader_Internal; 9typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
73struct _Evas_Loader_Internal 10struct _Evas_Loader_Internal
74{ 11{
75 Eina_File *f; 12 Emile_Image *image;
76 13
77 Eina_Rectangle region; 14 Eina_Rectangle region;
78 15
@@ -92,26 +29,6 @@ struct _Evas_Loader_Internal
92 Eina_Bool unpremul : 1; 29 Eina_Bool unpremul : 1;
93}; 30};
94 31
95static const Evas_Colorspace cspaces_etc1[2] = {
96 EVAS_COLORSPACE_ETC1,
97 EVAS_COLORSPACE_ARGB8888
98};
99
100static const Evas_Colorspace cspaces_rgb8_etc2[2] = {
101 EVAS_COLORSPACE_RGB8_ETC2,
102 EVAS_COLORSPACE_ARGB8888
103};
104
105static const Evas_Colorspace cspaces_rgba8_etc2_eac[2] = {
106 EVAS_COLORSPACE_RGBA8_ETC2_EAC,
107 EVAS_COLORSPACE_ARGB8888
108};
109
110static const Evas_Colorspace cspaces_etc1_alpha[2] = {
111 EVAS_COLORSPACE_ETC1_ALPHA,
112 EVAS_COLORSPACE_ARGB8888
113};
114
115static void * 32static void *
116evas_image_load_file_open_tgv(Eina_File *f, Eina_Stringshare *key EINA_UNUSED, 33evas_image_load_file_open_tgv(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
117 Evas_Image_Load_Opts *opts, 34 Evas_Image_Load_Opts *opts,
@@ -119,10 +36,13 @@ evas_image_load_file_open_tgv(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
119 int *error) 36 int *error)
120{ 37{
121 Evas_Loader_Internal *loader; 38 Evas_Loader_Internal *loader;
39 Emile_Image *image;
40 Emile_Image_Load_Error image_error;
122 41
123 if (eina_file_size_get(f) <= 16) 42 image = emile_image_tgv_file_open(f, opts, NULL, &image_error);
43 if (!image)
124 { 44 {
125 *error = EVAS_LOAD_ERROR_CORRUPT_FILE; 45 *error = image_error;
126 return NULL; 46 return NULL;
127 } 47 }
128 48
@@ -133,14 +53,7 @@ evas_image_load_file_open_tgv(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
133 return NULL; 53 return NULL;
134 } 54 }
135 55
136 loader->f = eina_file_dup(f); 56 loader->image = image;
137 if (!loader->f)
138 {
139 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
140 free(loader);
141 return NULL;
142 }
143
144 if (opts && (opts->region.w > 0) && (opts->region.h > 0)) 57 if (opts && (opts->region.w > 0) && (opts->region.h > 0))
145 { 58 {
146 EINA_RECTANGLE_SET(&loader->region, 59 EINA_RECTANGLE_SET(&loader->region,
@@ -165,149 +78,27 @@ evas_image_load_file_close_tgv(void *loader_data)
165{ 78{
166 Evas_Loader_Internal *loader = loader_data; 79 Evas_Loader_Internal *loader = loader_data;
167 80
168 eina_file_close(loader->f); 81 emile_image_close(loader->image);
169 free(loader); 82 free(loader);
170} 83}
171 84
172static int
173roundup(int val, int rup)
174{
175 if (val >= 0 && rup > 0)
176 return (val + rup - 1) - ((val + rup - 1) % rup);
177 return 0;
178}
179
180#define OFFSET_BLOCK_SIZE 4
181#define OFFSET_ALGORITHM 5
182#define OFFSET_OPTIONS 6
183#define OFFSET_WIDTH 8
184#define OFFSET_HEIGHT 12
185#define OFFSET_BLOCKS 16
186
187static Eina_Bool 85static Eina_Bool
188evas_image_load_file_head_tgv(void *loader_data, 86evas_image_load_file_head_tgv(void *loader_data,
189 Evas_Image_Property *prop, 87 Evas_Image_Property *prop,
190 int *error) 88 int *error)
191{ 89{
192 Evas_Loader_Internal *loader = loader_data; 90 Evas_Loader_Internal *loader = loader_data;
193 Eina_Bool ret = EINA_FALSE; 91 Emile_Image_Load_Error image_error;
194 char *m; 92 Eina_Bool ret;
195
196 m = eina_file_map_all(loader->f, EINA_FILE_SEQUENTIAL);
197 if (!m)
198 {
199 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
200 return EINA_FALSE;
201 }
202
203 if (strncmp(m, "TGV1", 4) != 0)
204 {
205 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
206 goto on_error;
207 }
208
209 switch (m[OFFSET_ALGORITHM] & 0xFF)
210 {
211 case 0:
212 prop->cspaces = cspaces_etc1;
213 loader->cspace = EVAS_COLORSPACE_ETC1;
214 prop->alpha = EINA_FALSE;
215 break;
216 case 1:
217 prop->cspaces = cspaces_rgb8_etc2;
218 loader->cspace = EVAS_COLORSPACE_RGB8_ETC2;
219 prop->alpha = EINA_FALSE;
220 break;
221 case 2:
222 prop->cspaces = cspaces_rgba8_etc2_eac;
223 loader->cspace = EVAS_COLORSPACE_RGBA8_ETC2_EAC;
224 prop->alpha = EINA_TRUE;
225 break;
226 case 3:
227 prop->cspaces = cspaces_etc1_alpha;
228 loader->cspace = EVAS_COLORSPACE_ETC1_ALPHA;
229 loader->unpremul = !!(m[OFFSET_OPTIONS] & 0x4);
230 prop->alpha = EINA_TRUE;
231 prop->premul = loader->unpremul;
232 break;
233 default:
234 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
235 goto on_error;
236 }
237
238 loader->compress = m[OFFSET_OPTIONS] & 0x1;
239 loader->blockless = (m[OFFSET_OPTIONS] & 0x2) != 0;
240
241 loader->size.width = ntohl(*((unsigned int*) &(m[OFFSET_WIDTH])));
242 loader->size.height = ntohl(*((unsigned int*) &(m[OFFSET_HEIGHT])));
243 93
244 if (loader->blockless) 94 ret = emile_image_head(loader->image,
245 { 95 prop, sizeof (Emile_Image_Property),
246 loader->block.width = roundup(loader->size.width + 2, 4); 96 &image_error);
247 loader->block.height = roundup(loader->size.height + 2, 4); 97 *error = image_error;
248 }
249 else
250 {
251 loader->block.width = 4 << (m[OFFSET_BLOCK_SIZE] & 0x0f);
252 loader->block.height = 4 << ((m[OFFSET_BLOCK_SIZE] & 0xf0) >> 4);
253 }
254 98
255 if (loader->region.w == -1 && loader->region.h == -1)
256 {
257 loader->region.w = loader->size.width;
258 loader->region.h = loader->size.height;
259 }
260 else
261 {
262 Eina_Rectangle r;
263
264 // ETC1 colorspace doesn't work with region
265 prop->cspaces = NULL;
266
267 EINA_RECTANGLE_SET(&r, 0, 0, loader->size.width, loader->size.height);
268 if (!eina_rectangle_intersection(&loader->region, &r))
269 {
270 *error = EVAS_LOAD_ERROR_GENERIC;
271 goto on_error;
272 }
273 }
274
275 prop->w = loader->size.width;
276 prop->h = loader->size.height;
277 prop->borders.l = 1;
278 prop->borders.t = 1;
279 prop->borders.r = roundup(prop->w + 2, 4) - prop->w - 1;
280 prop->borders.b = roundup(prop->h + 2, 4) - prop->h - 1;
281
282 ret = EINA_TRUE;
283
284on_error:
285 eina_file_map_free(loader->f, m);
286 return ret; 99 return ret;
287} 100}
288 101
289static inline unsigned int
290_tgv_length_get(const char *m, unsigned int length, unsigned int *offset)
291{
292 unsigned int r = 0;
293 unsigned int shift = 0;
294
295 while (*offset < length && ((*m) & 0x80))
296 {
297 r = r | (((*m) & 0x7F) << shift);
298 shift += 7;
299 m++;
300 (*offset)++;
301 }
302 if (*offset < length)
303 {
304 r = r | (((*m) & 0x7F) << shift);
305 (*offset)++;
306 }
307
308 return r;
309}
310
311Eina_Bool 102Eina_Bool
312evas_image_load_file_data_tgv(void *loader_data, 103evas_image_load_file_data_tgv(void *loader_data,
313 Evas_Image_Property *prop, 104 Evas_Image_Property *prop,
@@ -315,234 +106,15 @@ evas_image_load_file_data_tgv(void *loader_data,
315 int *error) 106 int *error)
316{ 107{
317 Evas_Loader_Internal *loader = loader_data; 108 Evas_Loader_Internal *loader = loader_data;
318 const char *m; 109 Emile_Image_Load_Error image_error;
319 unsigned int *p = pixels; 110 Eina_Bool ret;
320 unsigned char *p_etc = pixels; 111
321 char *buffer = NULL; 112 ret = emile_image_data(loader->image,
322 Eina_Rectangle master; 113 prop, sizeof (Emile_Image_Property),
323 unsigned int block_length; 114 pixels,
324 unsigned int length, offset; 115 &image_error);
325 unsigned int x, y; 116 *error = image_error;
326 unsigned int block_count; 117 return ret;
327 unsigned int etc_width = 0;
328 unsigned int etc_block_size;
329 Eina_Bool r = EINA_FALSE;
330 int num_planes = 1, plane, alpha_offset = 0;
331
332 length = eina_file_size_get(loader->f);
333 offset = OFFSET_BLOCKS;
334
335 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
336
337 m = eina_file_map_all(loader->f, EINA_FILE_WILLNEED);
338 if (!m) return EINA_FALSE;
339
340 // By definition, prop{.w, .h} == region{.w, .h}
341 EINA_RECTANGLE_SET(&master,
342 loader->region.x, loader->region.y,
343 prop->w, prop->h);
344
345 switch (loader->cspace)
346 {
347 case EVAS_COLORSPACE_ETC1:
348 case EVAS_COLORSPACE_RGB8_ETC2:
349 etc_block_size = 8;
350 break;
351 case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
352 etc_block_size = 16;
353 break;
354 case EVAS_COLORSPACE_ETC1_ALPHA:
355 etc_block_size = 8;
356 num_planes = 2;
357 alpha_offset = ((prop->w + 2 + 3) / 4) * ((prop->h + 2 + 3) / 4) * 8 / sizeof(*p_etc);
358 break;
359 default: abort();
360 }
361 etc_width = ((prop->w + 2 + 3) / 4) * etc_block_size;
362
363 switch (prop->cspace)
364 {
365 case EVAS_COLORSPACE_ETC1:
366 case EVAS_COLORSPACE_RGB8_ETC2:
367 case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
368 case EVAS_COLORSPACE_ETC1_ALPHA:
369 if (master.x % 4 || master.y % 4)
370 abort();
371 break;
372 case EVAS_COLORSPACE_ARGB8888:
373 // Offset to take duplicated pixels into account
374 master.x += 1;
375 master.y += 1;
376 break;
377 default: abort();
378 }
379
380 if (prop->cspace != EVAS_COLORSPACE_ARGB8888 && prop->cspace != loader->cspace)
381 {
382 if (!((prop->cspace == EVAS_COLORSPACE_RGB8_ETC2) &&
383 (loader->cspace == EVAS_COLORSPACE_ETC1)))
384 goto on_error;
385 // else: ETC2 is compatible with ETC1 and is preferred
386 }
387
388 // Allocate space for each ETC block (8 or 16 bytes per 4 * 4 pixels group)
389 block_count = loader->block.width * loader->block.height / (4 * 4);
390 if (loader->compress)
391 buffer = alloca(etc_block_size * block_count);
392
393 for (plane = 0; plane < num_planes; plane++)
394 for (y = 0; y < loader->size.height + 2; y += loader->block.height)
395 for (x = 0; x < loader->size.width + 2; x += loader->block.width)
396 {
397 Eina_Rectangle current;
398 const char *data_start;
399 const char *it;
400 unsigned int expand_length;
401 unsigned int i, j;
402
403 block_length = _tgv_length_get(m + offset, length, &offset);
404
405 if (block_length == 0) goto on_error;
406
407 data_start = m + offset;
408 offset += block_length;
409
410 EINA_RECTANGLE_SET(&current, x, y,
411 loader->block.width, loader->block.height);
412
413 if (!eina_rectangle_intersection(&current, &master))
414 continue;
415
416 if (loader->compress)
417 {
418 expand_length = LZ4_decompress_fast(data_start, buffer,
419 block_count * etc_block_size);
420 // That's an overhead for now, need to be fixed
421 if (expand_length != block_length)
422 goto on_error;
423 }
424 else
425 {
426 buffer = (void*) data_start;
427 if (block_count * etc_block_size != block_length)
428 goto on_error;
429 }
430 it = buffer;
431
432 for (i = 0; i < loader->block.height; i += 4)
433 for (j = 0; j < loader->block.width; j += 4, it += etc_block_size)
434 {
435 Eina_Rectangle current_etc;
436 unsigned int temporary[4 * 4];
437 unsigned int offset_x, offset_y;
438 int k, l;
439
440 EINA_RECTANGLE_SET(&current_etc, x + j, y + i, 4, 4);
441
442 if (!eina_rectangle_intersection(&current_etc, &current))
443 continue;
444
445 switch (prop->cspace)
446 {
447 case EVAS_COLORSPACE_ARGB8888:
448 switch (loader->cspace)
449 {
450 case EVAS_COLORSPACE_ETC1:
451 case EVAS_COLORSPACE_ETC1_ALPHA:
452 if (!rg_etc1_unpack_block(it, temporary, 0))
453 {
454 // TODO: Should we decode as RGB8_ETC2?
455 fprintf(stderr, "ETC1: Block starting at {%i, %i} is corrupted!\n", x + j, y + i);
456 continue;
457 }
458 break;
459 case EVAS_COLORSPACE_RGB8_ETC2:
460 rg_etc2_rgb8_decode_block((uint8_t *) it, temporary);
461 break;
462 case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
463 rg_etc2_rgba8_decode_block((uint8_t *) it, temporary);
464 break;
465 default: abort();
466 }
467
468 offset_x = current_etc.x - x - j;
469 offset_y = current_etc.y - y - i;
470
471 if (!plane)
472 {
473#ifdef BUILD_NEON
474 if (eina_cpu_features_get() & EINA_CPU_NEON)
475 {
476 uint32_t *dst = &p[current_etc.x - 1 + (current_etc.y - 1) * master.w];
477 uint32_t *src = &temporary[offset_x + offset_y * 4];
478 for (k = 0; k < current_etc.h; k++)
479 {
480 if (current_etc.w == 4)
481 vst1q_u32(dst, vld1q_u32(src));
482 else if (current_etc.w == 3)
483 {
484 vst1_u32(dst, vld1_u32(src));
485 *(dst + 2) = *(src + 2);
486 }
487 else if (current_etc.w == 2)
488 vst1_u32(dst, vld1_u32(src));
489 else
490 *dst = *src;
491 dst += master.w;
492 src += 4;
493 }
494 }
495 else
496#endif
497 for (k = 0; k < current_etc.h; k++)
498 {
499 memcpy(&p[current_etc.x - 1 + (current_etc.y - 1 + k) * master.w],
500 &temporary[offset_x + (offset_y + k) * 4],
501 current_etc.w * sizeof (unsigned int));
502 }
503 }
504 else
505 {
506 for (k = 0; k < current_etc.h; k++)
507 for (l = 0; l < current_etc.w; l++)
508 {
509 unsigned int *rgbdata =
510 &p[current_etc.x - 1 + (current_etc.y - 1 + k) * master.w + l];
511 unsigned int *adata =
512 &temporary[offset_x + (offset_y + k) * 4 + l];
513 A_VAL(rgbdata) = G_VAL(adata);
514 }
515 }
516 break;
517 case EVAS_COLORSPACE_ETC1:
518 case EVAS_COLORSPACE_RGB8_ETC2:
519 case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
520 memcpy(&p_etc[(current_etc.x / 4) * etc_block_size +
521 (current_etc.y / 4) * etc_width],
522 it, etc_block_size);
523 break;
524 case EVAS_COLORSPACE_ETC1_ALPHA:
525 memcpy(&p_etc[(current_etc.x / 4) * etc_block_size +
526 (current_etc.y / 4) * etc_width +
527 plane * alpha_offset],
528 it, etc_block_size);
529 break;
530 default:
531 abort();
532 }
533 } // bx,by inside blocks
534 } // x,y macroblocks
535
536 // TODO: Add support for more unpremultiplied modes (ETC2)
537 if (prop->cspace == EVAS_COLORSPACE_ARGB8888)
538 prop->premul = loader->unpremul; // call premul if unpremul data
539
540 r = EINA_TRUE;
541 *error = EVAS_LOAD_ERROR_NONE;
542
543 on_error:
544 eina_file_map_free(loader->f, (void*) m);
545 return r;
546} 118}
547 119
548Evas_Image_Load_Func evas_image_load_tgv_func = 120Evas_Image_Load_Func evas_image_load_tgv_func =