* The TGV file format is oriented around compression mecanism
* that hardware are good at decompressing. We do still provide
* a fully software implementation in case your hardware doesn't
- * handle it.
+ * handle it. As OpenGL is pretty bad at handling border of
+ * texture, we do duplicate the first pixels of every border.
*
* This file format is designed to compress/decompress things
* in block area. Giving opportunity to store really huge file
- * and only decompress/compress them as we need.
+ * and only decompress/compress them as we need. Note that region
+ * only work with software decompression as we don't have a sane
+ * way to duplicate border to avoid artifact when scaling texture.
*
* The file format is as follow :
* - char magic[4]: "TGV1"
master.y % 4)
abort();
- etc1_width = (prop->w / 4 + (prop->w % 4 ? 1 : 0)) * 8;
+ etc1_width = ((prop->w + 2) / 4 + ((prop->w + 2) % 4 ? 1 : 0)) * 8;
+ }
+ else if (prop->cspace == EVAS_COLORSPACE_ARGB8888)
+ {
+ // Offset to take duplicated pixels into account
+ master.x += 1;
+ master.y += 1;
}
// Allocate space for each ETC1 block (64bytes per 4 * 4 pixels group)
else
buffer = NULL;
- for (y = 0; y < loader->size.height; y += loader->block.height)
- for (x = 0; x < loader->size.width; x += loader->block.width)
+ for (y = 0; y < loader->size.height + 2; y += loader->block.height)
+ for (x = 0; x < loader->size.width + 2; x += loader->block.width)
{
Eina_Rectangle current;
const char *data_start;
offset_y = current_etc.y - y - i;
for (k = 0; k < current_etc.h; k++)
{
- memcpy(&p[current_etc.x +
- (current_etc.y + k) * master.w],
+ memcpy(&p[current_etc.x - 1 +
+ (current_etc.y - 1 + k) * master.w],
&temporary[offset_x + (offset_y + k) * 4],
current_etc.w * sizeof (unsigned int));
}
if (lmax > 0)
{
- for (k = duplicate_h[0]; k < kmax; k++)
- memcpy(&todo[k * 16 + duplicate_w[0] * 4],
+ for (k = 0; k < kmax; k++)
+ memcpy(&todo[(k + duplicate_h[0]) * 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);
+ memcpy(&todo[0], &data[(real_y + i) * im->cache_entry.w + real_x + j], block_length * 4);
+ 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 * 4);
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
+ memcpy(&todo[(k + duplicate_h[0]) * 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
+ memcpy(&todo[(k + duplicate_h[0]) * 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, ¶m);