evas: support uploading AGRY88 and GRY8 directly to GPU.

This commit is contained in:
Cedric BAIL 2014-03-21 11:54:27 +09:00 committed by Cedric BAIL
parent eb7071078a
commit d1581f8ca9
3 changed files with 149 additions and 214 deletions

View File

@ -781,6 +781,7 @@ Evas_GL_Texture *evas_gl_common_texture_native_new(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *evas_gl_common_texture_render_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha);
Evas_GL_Texture *evas_gl_common_texture_dynamic_new(Evas_Engine_GL_Context *gc, Evas_GL_Image *im);
void evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im);
void evas_gl_common_texture_upload(Evas_GL_Texture *tex, RGBA_Image *im, unsigned int bytes_count);
void evas_gl_common_texture_free(Evas_GL_Texture *tex, Eina_Bool force);
Evas_GL_Texture *evas_gl_common_texture_alpha_new(Evas_Engine_GL_Context *gc, DATA8 *pixels, unsigned int w, unsigned int h, int fh);
void evas_gl_common_texture_alpha_update(Evas_GL_Texture *tex, DATA8 *pixels, unsigned int w, unsigned int h, int fh);

View File

@ -175,6 +175,7 @@ _evas_gl_preload_tile_async(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED)
while (!async_loader_exit)
{
Evas_GL_Texture_Async_Preload *async;
unsigned int bytes_count;
GLuint fmt;
if (!async_loader_standby && async_loader_tex)
@ -190,6 +191,14 @@ _evas_gl_preload_tile_async(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED)
async_loader_tex = eina_list_remove_list(async_loader_tex, async_loader_tex);
if (!async) continue;
switch (async->im->cache_entry.space)
{
case EVAS_COLORSPACE_ARGB8888: bytes_count = 4; break;
case EVAS_COLORSPACE_GRY8: bytes_count = 1; break;
case EVAS_COLORSPACE_AGRY88: bytes_count = 2; break;
default: continue;
}
async_loader_running = EINA_TRUE;
async_current = async;
@ -210,110 +219,7 @@ _evas_gl_preload_tile_async(void *data EINA_UNUSED, Eina_Thread t EINA_UNUSED)
}
// FIXME: loop until all subtile are uploaded or the image is about to be deleted
// TEMPORARY CODE JUST TO SEE IF IT WORK
fmt = async->tex->pt->format;
glBindTexture(GL_TEXTURE_2D, async->tex->pt->texture);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
if (async->unpack_row_length)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
// +-+
// +-+
//
_tex_sub_2d(async->tex->gc, async->tex->x, async->tex->y,
async->im->cache_entry.w, async->im->cache_entry.h,
fmt, async->tex->pt->dataformat,
async->im->image.data);
// xxx
// xxx
// ---
_tex_sub_2d(async->tex->gc, async->tex->x, async->tex->y + async->im->cache_entry.h,
async->im->cache_entry.w, 1,
fmt, async->tex->pt->dataformat,
async->im->image.data + ((async->im->cache_entry.h - 1) * async->im->cache_entry.w));
// xxx
// xxx
// o
_tex_sub_2d(async->tex->gc, async->tex->x - 1, async->tex->y + async->im->cache_entry.h,
1, 1,
fmt, async->tex->pt->dataformat,
async->im->image.data + ((async->im->cache_entry.h - 1) * async->im->cache_entry.w));
// xxx
// xxx
// o
_tex_sub_2d(async->tex->gc, async->tex->x + async->im->cache_entry.w, async->tex->y + async->im->cache_entry.h,
1, 1,
fmt, async->tex->pt->dataformat,
async->im->image.data + ((async->im->cache_entry.h - 1) * async->im->cache_entry.w) + (async->im->cache_entry.w - 1));
if (async->unpack_row_length)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, async->im->cache_entry.w);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
// |xxx
// |xxx
//
_tex_sub_2d(async->tex->gc, async->tex->x - 1, async->tex->y,
1, async->im->cache_entry.h,
fmt, async->tex->pt->dataformat,
async->im->image.data);
// xxx|
// xxx|
//
_tex_sub_2d(async->tex->gc, async->tex->x + async->im->cache_entry.w, async->tex->y,
1, async->im->cache_entry.h,
fmt, async->tex->pt->dataformat,
async->im->image.data + (async->im->cache_entry.w - 1));
}
else
{
DATA32 *tpix, *ps, *pd;
int i;
tpix = alloca(async->im->cache_entry.h * sizeof(DATA32));
pd = tpix;
ps = async->im->image.data;
for (i = 0; i < (int)async->im->cache_entry.h; i++)
{
*pd = *ps;
pd++;
ps += async->im->cache_entry.w;
}
// |xxx
// |xxx
//
_tex_sub_2d(async->tex->gc, async->tex->x - 1, async->tex->y,
1, async->im->cache_entry.h,
fmt, async->tex->pt->dataformat,
tpix);
pd = tpix;
ps = async->im->image.data + (async->im->cache_entry.w - 1);
for (i = 0; i < (int)async->im->cache_entry.h; i++)
{
*pd = *ps;
pd++;
ps += async->im->cache_entry.w;
}
// xxx|
// xxx|
//
_tex_sub_2d(async->tex->gc, async->tex->x + async->im->cache_entry.w, async->tex->y,
1, async->im->cache_entry.h,
fmt, async->tex->pt->dataformat,
tpix);
}
// Switch back to current texture
if (async->tex->ptt->texture != async->tex->gc->pipe[0].shader.cur_tex)
{
glBindTexture(GL_TEXTURE_2D, async->tex->gc->pipe[0].shader.cur_tex);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
evas_gl_common_texture_upload(async->tex, async->im, bytes_count);
// Shall we block now ?
if (!_evas_gl_preload_lock())

View File

@ -56,7 +56,9 @@ static const struct {
{ EINA_FALSE, EINA_FALSE, EVAS_COLORSPACE_ARGB8888, &rgb_ifmt, &rgb_fmt },
#endif
{ EINA_FALSE, EINA_FALSE, EVAS_COLORSPACE_GRY8, &lum_fmt, &lum_ifmt },
{ EINA_TRUE, EINA_FALSE, EVAS_COLORSPACE_AGRY88, &lum_alpha_fmt, &lum_alpha_ifmt }
{ EINA_FALSE, EINA_TRUE, EVAS_COLORSPACE_GRY8, &lum_fmt, &lum_ifmt },
{ EINA_TRUE, EINA_FALSE, EVAS_COLORSPACE_AGRY88, &lum_alpha_fmt, &lum_alpha_ifmt },
{ EINA_TRUE, EINA_TRUE, EVAS_COLORSPACE_AGRY88, &lum_alpha_fmt, &lum_alpha_ifmt }
};
static const GLenum matching_rgba[] = { GL_RGBA4, GL_RGBA8, GL_RGBA12, GL_RGBA16, 0x0 };
@ -909,10 +911,118 @@ evas_gl_common_texture_dynamic_new(Evas_Engine_GL_Context *gc, Evas_GL_Image *im
}
void
evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
evas_gl_common_texture_upload(Evas_GL_Texture *tex, RGBA_Image *im, unsigned int bytes_count)
{
GLuint fmt;
fmt = tex->pt->format;
glBindTexture(GL_TEXTURE_2D, tex->pt->texture);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
if (tex->gc->shared->info.unpack_row_length)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
// printf("tex upload %ix%i\n", im->cache_entry.w, im->cache_entry.h);
// +-+
// +-+
//
_tex_sub_2d(tex->gc, tex->x, tex->y,
im->cache_entry.w, im->cache_entry.h,
fmt, tex->pt->dataformat,
im->image.data);
// xxx
// xxx
// ---
_tex_sub_2d(tex->gc, tex->x, tex->y + im->cache_entry.h,
im->cache_entry.w, 1,
fmt, tex->pt->dataformat,
(unsigned char *) im->image.data + (((im->cache_entry.h - 1) * im->cache_entry.w)) * bytes_count);
// xxx
// xxx
// o
_tex_sub_2d(tex->gc, tex->x - 1, tex->y + im->cache_entry.h,
1, 1,
fmt, tex->pt->dataformat,
(unsigned char *) im->image.data + (((im->cache_entry.h - 1) * im->cache_entry.w)) * bytes_count);
// xxx
// xxx
// o
_tex_sub_2d(tex->gc, tex->x + im->cache_entry.w, tex->y + im->cache_entry.h,
1, 1,
fmt, tex->pt->dataformat,
(unsigned char *) im->image.data + (((im->cache_entry.h - 1) * im->cache_entry.w) + (im->cache_entry.w - 1)) * bytes_count);
if (tex->gc->shared->info.unpack_row_length)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, im->cache_entry.w);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
// |xxx
// |xxx
//
_tex_sub_2d(tex->gc, tex->x - 1, tex->y,
1, im->cache_entry.h,
fmt, tex->pt->dataformat,
im->image.data);
// xxx|
// xxx|
//
_tex_sub_2d(tex->gc, tex->x + im->cache_entry.w, tex->y,
1, im->cache_entry.h,
fmt, tex->pt->dataformat,
(unsigned char *) im->image.data + (im->cache_entry.w - 1) * bytes_count);
}
else
{
DATA8 *tpix, *ps, *pd;
int i;
tpix = alloca(im->cache_entry.h * bytes_count);
pd = tpix;
ps = (unsigned char*) im->image.data;
for (i = 0; i < (int)im->cache_entry.h; i++)
{
memcpy(pd, ps, bytes_count);
pd++;
ps += im->cache_entry.w * bytes_count;
}
// |xxx
// |xxx
//
_tex_sub_2d(tex->gc, tex->x - 1, tex->y,
1, im->cache_entry.h,
fmt, tex->pt->dataformat,
tpix);
pd = tpix;
ps = (unsigned char*) im->image.data + (im->cache_entry.w - 1) * bytes_count;
for (i = 0; i < (int)im->cache_entry.h; i++)
{
memcpy(pd, ps, bytes_count);
pd++;
ps += im->cache_entry.w * bytes_count;
}
// xxx|
// xxx|
//
_tex_sub_2d(tex->gc, tex->x + im->cache_entry.w, tex->y,
1, im->cache_entry.h,
fmt, tex->pt->dataformat,
tpix);
}
if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex)
{
glBindTexture(GL_TEXTURE_2D, tex->gc->pipe[0].shader.cur_tex);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
}
void
evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
{
unsigned int bytes_count;
if (tex->alpha != im->cache_entry.flags.alpha)
{
int lformat;
@ -931,12 +1041,21 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
if (!tex->pt) return;
if (!im->image.data) return;
switch (im->cache_entry.space)
{
case EVAS_COLORSPACE_ARGB8888: bytes_count = 4; break;
case EVAS_COLORSPACE_GRY8: bytes_count = 1; break;
case EVAS_COLORSPACE_AGRY88: bytes_count = 2; break;
default: return;
}
// if preloaded, then async push it in after uploading a miniature of it
if (im->cache_entry.flags.preload_done && tex->w > 2 * EVAS_GL_TILE_SIZE && tex->h > 2 * EVAS_GL_TILE_SIZE)
{
Evas_GL_Texture_Async_Preload *async;
int *in;
int out[EVAS_GL_TILE_SIZE * EVAS_GL_TILE_SIZE];
unsigned char *in;
unsigned char *out;
GLuint fmt;
float xstep, ystep;
float x, y;
int i, j;
@ -945,19 +1064,28 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
if (tex->ptt) return ;
out = alloca(bytes_count * EVAS_GL_TILE_SIZE * EVAS_GL_TILE_SIZE);
xstep = (float)tex->w / (EVAS_GL_TILE_SIZE - 2);
ystep = (float)tex->h / (EVAS_GL_TILE_SIZE - 1);
in = (int*) im->image.data;
in = (unsigned char*) im->image.data;
for (y = 0, j = 0; j < EVAS_GL_TILE_SIZE - 1; y += ystep, j++)
{
out[j * EVAS_GL_TILE_SIZE] = in[(int)y * im->cache_entry.w];
memcpy(&out[j * EVAS_GL_TILE_SIZE * bytes_count],
&in[(int)y * im->cache_entry.w * bytes_count],
bytes_count);
for (x = 0, i = 1; i < EVAS_GL_TILE_SIZE - 1; x += xstep, i++)
out[j * EVAS_GL_TILE_SIZE + i] = in[(int)y * im->cache_entry.w + (int)x];
out[j * EVAS_GL_TILE_SIZE + i] = in[(int)y * im->cache_entry.w + (int)(x - xstep)];
memcpy(&out[(j * EVAS_GL_TILE_SIZE + i) * bytes_count],
&in[((int)y * im->cache_entry.w + (int)x) * bytes_count],
bytes_count);
memcpy(&out[(j * EVAS_GL_TILE_SIZE + i) * bytes_count],
&in[((int)y * im->cache_entry.w + (int)(x - xstep)) * bytes_count],
bytes_count);
}
memcpy(&out[j * EVAS_GL_TILE_SIZE], &out[(j - 1) * EVAS_GL_TILE_SIZE], EVAS_GL_TILE_SIZE * sizeof (int));
memcpy(&out[(j * EVAS_GL_TILE_SIZE) * bytes_count],
&out[((j - 1) * EVAS_GL_TILE_SIZE) * bytes_count],
EVAS_GL_TILE_SIZE * bytes_count);
// out is a miniature of the texture, upload that now and schedule the data for later.
@ -1033,107 +1161,7 @@ evas_gl_common_texture_update(Evas_GL_Texture *tex, RGBA_Image *im)
tex->ptt = NULL;
}
fmt = tex->pt->format;
glBindTexture(GL_TEXTURE_2D, tex->pt->texture);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
if (tex->gc->shared->info.unpack_row_length)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
// printf("tex upload %ix%i\n", im->cache_entry.w, im->cache_entry.h);
// +-+
// +-+
//
_tex_sub_2d(tex->gc, tex->x, tex->y,
im->cache_entry.w, im->cache_entry.h,
fmt, tex->pt->dataformat,
im->image.data);
// xxx
// xxx
// ---
_tex_sub_2d(tex->gc, tex->x, tex->y + im->cache_entry.h,
im->cache_entry.w, 1,
fmt, tex->pt->dataformat,
im->image.data + ((im->cache_entry.h - 1) * im->cache_entry.w));
// xxx
// xxx
// o
_tex_sub_2d(tex->gc, tex->x - 1, tex->y + im->cache_entry.h,
1, 1,
fmt, tex->pt->dataformat,
im->image.data + ((im->cache_entry.h - 1) * im->cache_entry.w));
// xxx
// xxx
// o
_tex_sub_2d(tex->gc, tex->x + im->cache_entry.w, tex->y + im->cache_entry.h,
1, 1,
fmt, tex->pt->dataformat,
im->image.data + ((im->cache_entry.h - 1) * im->cache_entry.w) + (im->cache_entry.w - 1));
if (tex->gc->shared->info.unpack_row_length)
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, im->cache_entry.w);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
// |xxx
// |xxx
//
_tex_sub_2d(tex->gc, tex->x - 1, tex->y,
1, im->cache_entry.h,
fmt, tex->pt->dataformat,
im->image.data);
// xxx|
// xxx|
//
_tex_sub_2d(tex->gc, tex->x + im->cache_entry.w, tex->y,
1, im->cache_entry.h,
fmt, tex->pt->dataformat,
im->image.data + (im->cache_entry.w - 1));
}
else
{
DATA32 *tpix, *ps, *pd;
int i;
tpix = alloca(im->cache_entry.h * sizeof(DATA32));
pd = tpix;
ps = im->image.data;
for (i = 0; i < (int)im->cache_entry.h; i++)
{
*pd = *ps;
pd++;
ps += im->cache_entry.w;
}
// |xxx
// |xxx
//
_tex_sub_2d(tex->gc, tex->x - 1, tex->y,
1, im->cache_entry.h,
fmt, tex->pt->dataformat,
tpix);
pd = tpix;
ps = im->image.data + (im->cache_entry.w - 1);
for (i = 0; i < (int)im->cache_entry.h; i++)
{
*pd = *ps;
pd++;
ps += im->cache_entry.w;
}
// xxx|
// xxx|
//
_tex_sub_2d(tex->gc, tex->x + im->cache_entry.w, tex->y,
1, im->cache_entry.h,
fmt, tex->pt->dataformat,
tpix);
}
if (tex->pt->texture != tex->gc->pipe[0].shader.cur_tex)
{
glBindTexture(GL_TEXTURE_2D, tex->gc->pipe[0].shader.cur_tex);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
evas_gl_common_texture_upload(tex, im, bytes_count);
}
void