evas: change TGV internal encoding to account for GPU needs of duplicated border.

With OpenGL, the border of a texture are not "well" defined. So interpolation at
the border can result in weird/bad looking texture border. To avoid that we do
duplicate the border in all direction at the time of the texture upload. But with
ETC1 it is not possible as the border are grouped with 15 others pixels. It needs
to be done at saving time. So internally we do have an image that would be of
size width + 2 pixels and height + 2 pixels.
This commit is contained in:
Cedric BAIL 2014-03-24 19:55:45 +09:00 committed by Cedric BAIL
parent d1581f8ca9
commit 2fd69743f9
1 changed files with 90 additions and 48 deletions

View File

@ -28,6 +28,7 @@ evas_image_save_file_tgv(RGBA_Image *im,
unsigned int x, y;
unsigned int compress_length;
unsigned int block_count;
unsigned int real_x, real_y;
if (!im || !im->image.data || !file)
return 0;
@ -86,63 +87,104 @@ evas_image_save_file_tgv(RGBA_Image *im,
}
// Write block
for (y = 0; y < im->cache_entry.h; y += block)
for (x = 0; x < im->cache_entry.w; x += block)
{
unsigned int i, j;
int wlen;
char *offset = buffer;
for (y = 0; y < im->cache_entry.h + 2; y += block)
{
real_y = y > 0 ? y - 1 : 0;
for (i = 0; i < block; i += 4)
for (j = 0; j < block; j += 4)
{
unsigned char todo[64] = { 0 };
int k, kmax, lmax;
for (x = 0; x < im->cache_entry.w + 2; x += block)
{
unsigned int i, j;
unsigned char duplicate_w[2], duplicate_h[2];
int wlen;
char *offset = buffer;
kmax = y + i + 4 < im->cache_entry.h ?
4 : im->cache_entry.h - y - i - 1;
lmax = x + j + 4 < im->cache_entry.w ?
4 : im->cache_entry.w - x - j - 1;
real_x = x > 0 ? x - 1 : 0;
if (lmax > 0)
{
for (k = 0; k < kmax; k++)
memcpy(&todo[k * 16],
&data[(y + i + k) * im->cache_entry.w + x + j],
4 * lmax);
}
for (i = 0; i < block; i += 4)
{
unsigned char block_h;
int kmax;
rg_etc1_pack_block(offset, (unsigned int*) todo, &param);
offset += 8;
}
duplicate_h[0] = !!((real_y + i) == 0);
duplicate_h[1] = !!((real_y + i + (4 - duplicate_h[0])) >= im->cache_entry.h);
block_h = 4 - duplicate_h[0] - duplicate_h[1];
if (compress)
{
wlen = LZ4_compress(buffer, comp, block_count * 8);
}
else
{
comp = buffer;
wlen = block_count * 8;
}
kmax = real_y + i + block_h < im->cache_entry.h ?
block_h : im->cache_entry.h - real_y - i - 1;
if (wlen > 0)
{
unsigned int blen = wlen;
for (j = 0; j < block; j += 4)
{
unsigned char todo[64] = { 0 };
unsigned char block_w;
int block_length;
int k, lmax;
while (blen)
{
unsigned char plen;
duplicate_w[0] = !!((real_x + j) == 0);
duplicate_w[1] = !!(((real_x + j + (4 - duplicate_w[0]))) >= im->cache_entry.w);
block_w = 4 - duplicate_w[0] - duplicate_w[1];
plen = blen & 0x7F;
blen = blen >> 7;
lmax = real_x + j + block_w < im->cache_entry.w ?
block_w : im->cache_entry.w - real_x - j - 1;
block_length = real_x + j + 4 < im->cache_entry.w ?
4 : im->cache_entry.w - real_x - j - 1;
if (blen) plen = 0x80 | plen;
fwrite(&plen, 1, 1, f);
}
fwrite(comp, wlen, 1, f);
}
}
if (lmax > 0)
{
for (k = duplicate_h[0]; k < kmax; k++)
memcpy(&todo[k * 16 + duplicate_w[0] * 4],
&data[(real_y + i + k) * im->cache_entry.w + real_x + j],
4 * lmax);
}
if (duplicate_h[0] && block_length > 0) // Duplicate first line
memcpy(&todo[0], &data[(real_y + i) * im->cache_entry.w + real_x + j], block_length);
if (duplicate_h[1] && block_length > 0 && kmax > 0) // Duplicate last line
memcpy(&todo[kmax * 16], &data[(real_y + i + kmax) * im->cache_entry.w + real_x + j], block_length);
if (duplicate_w[0]) // Duplicate first row
{
for (k = 0; k < kmax; k++)
memcpy(&todo[k * 16], &data[(real_y + i + k) * im->cache_entry.w + real_x + j], 4); // Copy a pixel at a time
}
if (duplicate_w[1] && lmax >= 0) // Duplicate last row
{
for (k = 0; k < kmax; k++)
memcpy(&todo[k * 16 + (duplicate_w[0] + lmax) * 4],
&data[(real_y + i + k) * im->cache_entry.w + real_x + j + lmax], 4); // Copy a pixel at a time
}
rg_etc1_pack_block(offset, (unsigned int*) todo, &param);
offset += 8;
}
}
if (compress)
{
wlen = LZ4_compress(buffer, comp, block_count * 8);
}
else
{
comp = buffer;
wlen = block_count * 8;
}
if (wlen > 0)
{
unsigned int blen = wlen;
while (blen)
{
unsigned char plen;
plen = blen & 0x7F;
blen = blen >> 7;
if (blen) plen = 0x80 | plen;
fwrite(&plen, 1, 1, f);
}
fwrite(comp, wlen, 1, f);
}
}
}
fclose(f);
return 1;