From: Jean-Philippe Andre Date: Wed, 23 Apr 2014 11:02:22 +0000 (+0900) Subject: Evas TGV: Add direct copy mode for ETC1/ETC2 data X-Git-Tag: v1.10.0-alpha1~72 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=947fc3e0988feb0d1f1831ab5063337949be47e1;p=platform%2Fupstream%2Fefl.git Evas TGV: Add direct copy mode for ETC1/ETC2 data If the image is already in ETC1 or ETC2, then just copy its data (and LZ4 compress it). @feature --- diff --git a/src/modules/evas/savers/tgv/evas_image_save_tgv.c b/src/modules/evas/savers/tgv/evas_image_save_tgv.c index 84314b5..8b2b50d 100644 --- a/src/modules/evas/savers/tgv/evas_image_save_tgv.c +++ b/src/modules/evas/savers/tgv/evas_image_save_tgv.c @@ -26,6 +26,121 @@ _block_size_get(int size) } static int +_save_direct_tgv(RGBA_Image *im, const char *file, int compress) +{ + // In case we are directly copying ETC1/2 data, we can't properly + // duplicate the 1 pixel borders. So we just assume the image contains + // them already. + + // TODO: Add block by block compression. + + int image_width, image_height; + uint32_t width, height; + uint8_t header[8] = "TGV1"; + int etc_block_size, etc_data_size, buffer_size, data_size, remain; + uint8_t *buffer = NULL; + uint8_t *data, *ptr; + FILE *f; + + image_width = im->cache_entry.w; + image_height = im->cache_entry.h; + data = im->image.data8; + width = htonl(image_width); + height = htonl(image_height); + compress = !!compress; + + if ((image_width & 0x3) || (image_height & 0x3)) + return 0; + + // header[4]: block size info, unused + header[4] = 0; + + // header[5]: 0 for ETC1 + switch (im->cache_entry.space) + { + case EVAS_COLORSPACE_ETC1: + etc_block_size = 8; + header[5] = 0; + break; + case EVAS_COLORSPACE_RGB8_ETC2: + etc_block_size = 8; + header[5] = 1; + break; + case EVAS_COLORSPACE_RGBA8_ETC2_EAC: + etc_block_size = 16; + header[5] = 2; + break; + default: + return 0; + } + + // header[6]: 0 for raw, 1, for LZ4 compressed, 2 for block-less mode + header[6] = compress | 0x2; + + // header[7]: options (unused) + header[7] = 0; + + f = fopen(file, "w"); + if (!f) return 0; + + // Write header + if (fwrite(header, sizeof (uint8_t), 8, f) != 8) goto on_error; + if (fwrite(&width, sizeof (uint32_t), 1, f) != 1) goto on_error; + if (fwrite(&height, sizeof (uint32_t), 1, f) != 1) goto on_error; + + etc_data_size = image_width * image_height * etc_block_size / 16; + if (compress) + { + buffer_size = LZ4_compressBound(etc_data_size); + buffer = malloc(buffer_size); + if (!buffer) goto on_error; + data_size = LZ4_compressHC((char *) data, (char *) buffer, etc_data_size); + } + else + { + data_size = buffer_size = etc_data_size; + buffer = data; + } + + // Write block length header -- We keep this even in block-less mode + if (data_size > 0) + { + unsigned int blen = data_size; + + while (blen) + { + unsigned char plen; + + plen = blen & 0x7F; + blen = blen >> 7; + + if (blen) plen = 0x80 | plen; + if (fwrite(&plen, 1, 1, f) != 1) goto on_error; + } + } + + // Write data + ptr = buffer; + remain = data_size; + while (remain > 0) + { + int written = fwrite(ptr, 1, remain, f); + if (written < 0) goto on_error; + remain -= written; + ptr += written; + } + + if (compress) free(buffer); + fclose(f); + return 1; + +on_error: + if (compress) free(buffer); + fclose(f); + return 0; +} + +static int evas_image_save_file_tgv(RGBA_Image *im, const char *file, const char *key EINA_UNUSED, int quality, int compress) @@ -43,13 +158,19 @@ evas_image_save_file_tgv(RGBA_Image *im, if (!im || !im->image.data || !file) return 0; - // Surface with alpha are not supported - if (im->cache_entry.flags.alpha) - return 0; - - // Only RGBA encoding for now. TODO: Direct copy of ETC1/2 blocks. - if (im->cache_entry.space != EVAS_COLORSPACE_ARGB8888) - return 0; + switch (im->cache_entry.space) + { + case EVAS_COLORSPACE_ARGB8888: + if (im->cache_entry.flags.alpha) + return 0; + break; + case EVAS_COLORSPACE_ETC1: + case EVAS_COLORSPACE_RGB8_ETC2: + case EVAS_COLORSPACE_RGBA8_ETC2_EAC: + return _save_direct_tgv(im, file, compress); + default: + return 0; + } image_stride = im->cache_entry.w; image_height = im->cache_entry.h; @@ -231,7 +352,7 @@ evas_image_save_file_tgv(RGBA_Image *im, return 1; - on_error: +on_error: fclose(f); return 0; }