From 3eb0df10222d81cb1c9ec274b1f497f7c24163f8 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Thu, 17 Nov 2016 12:26:46 +0900 Subject: [PATCH] evas engines - add more support for noscale pixel buffers esp in gl for gl noscale buffers are texture atlases that are fbo's. the point is never to scale or transofmr them but to render them pixel for pixel and just store pre-rendered data where its cheaper to do this than rebuild every time. this is the enigne infra for sw and gl with the gl code... it SHOULD work... in theory... --- src/lib/evas/include/evas_private.h | 1 + .../evas/engines/gl_common/evas_gl_common.h | 2 + .../evas/engines/gl_common/evas_gl_image.c | 22 +++++ .../evas/engines/gl_common/evas_gl_texture.c | 93 ++++++++++++++++++- .../evas/engines/gl_generic/evas_engine.c | 25 ++++- .../engines/software_generic/evas_engine.c | 23 +++++ 6 files changed, 163 insertions(+), 3 deletions(-) diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 68b1b52a24..bcb1d84ab4 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1391,6 +1391,7 @@ struct _Evas_Func void (*image_prepare) (void *data, void *image); void *(*image_surface_noscale_new) (void *data, int w, int h, int alpha); + void (*image_surface_noscale_region_get)(void *data, void *image, int *x, int *y, int *w, int *h); int (*image_native_init) (void *data, Evas_Native_Surface_Type type); void (*image_native_shutdown) (void *data, Evas_Native_Surface_Type type); diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 8b56abe7b7..44999916f7 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -651,6 +651,7 @@ void evas_gl_texture_pool_empty(Evas_GL_Texture_Pool *pt); Evas_GL_Texture *evas_gl_common_texture_new(Evas_Engine_GL_Context *gc, RGBA_Image *im, Eina_Bool disable_atlas); Evas_GL_Texture *evas_gl_common_texture_native_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha, Evas_GL_Image *im); Evas_GL_Texture *evas_gl_common_texture_render_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha, int stencil); +Evas_GL_Texture *evas_gl_common_texture_render_noscale_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); @@ -680,6 +681,7 @@ void evas_gl_common_image_scale_hint_set(Evas_GL_Image *im, int hin void evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint); void evas_gl_common_image_cache_flush(Evas_Engine_GL_Context *gc); Evas_GL_Image *evas_gl_common_image_surface_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha, int stencil); +Evas_GL_Image *evas_gl_common_image_surface_noscale_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha); void evas_gl_common_image_dirty(Evas_GL_Image *im, unsigned int x, unsigned int y, unsigned int w, unsigned int h); void evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im); void evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int npoints, RGBA_Map_Point *p, int smooth, int level); diff --git a/src/modules/evas/engines/gl_common/evas_gl_image.c b/src/modules/evas/engines/gl_common/evas_gl_image.c index 99f75be2d2..0d9a5ddb21 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_image.c +++ b/src/modules/evas/engines/gl_common/evas_gl_image.c @@ -743,6 +743,28 @@ evas_gl_common_image_surface_new(Evas_Engine_GL_Context *gc, unsigned int w, uns return im; } +Evas_GL_Image * +evas_gl_common_image_surface_noscale_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha) +{ + Evas_GL_Image *im; + + if (((int)w > gc->shared->info.max_texture_size) || + ((int)h > gc->shared->info.max_texture_size)) + return NULL; + + im = calloc(1, sizeof(Evas_GL_Image)); + if (!im) return NULL; + im->references = 1; + im->gc = gc; + im->cs.space = EVAS_COLORSPACE_ARGB8888; + im->alpha = alpha; + im->w = w; + im->h = h; + im->tex = evas_gl_common_texture_render_noscale_new(gc, w, h, alpha); + im->tex_only = 1; + return im; +} + void evas_gl_common_image_dirty(Evas_GL_Image *im, unsigned int x, unsigned int y, unsigned int w, unsigned int h) { diff --git a/src/modules/evas/engines/gl_common/evas_gl_texture.c b/src/modules/evas/engines/gl_common/evas_gl_texture.c index ff2737f3d5..1d4b7b192e 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_texture.c +++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c @@ -493,6 +493,7 @@ _pool_tex_find(Evas_Engine_GL_Context *gc, int w, int h, if (th2 < 0) return NULL; EINA_LIST_FOREACH(gc->shared->tex.atlas[th2], l, pt) { + if (pt->render) continue; if ((*apt = _pool_tex_alloc(pt, w, h, u, v)) != NULL) { gc->shared->tex.atlas[th2] = @@ -673,6 +674,65 @@ _pool_tex_render_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, in return pt; } +static Evas_GL_Texture_Pool * +_pool_tex_render_find(Evas_Engine_GL_Context *gc, int w, int h, + GLenum intformat, GLenum format, int *u, int *v, + Eina_Rectangle **apt, int atlas_w, Eina_Bool disable_atlas) +{ + Evas_GL_Texture_Pool *pt = NULL; + Eina_List *l; + int th2; + int pool_h; + /*Return texture unit without atlas*/ + if (disable_atlas) + { + pt = _pool_tex_render_new(gc, w, h, intformat, format, EINA_FALSE); + return pt ? pt : NULL; + } + if (atlas_w > gc->shared->info.max_texture_size) + atlas_w = gc->shared->info.max_texture_size; + if ((w > gc->shared->info.tune.atlas.max_w) || + (h > gc->shared->info.tune.atlas.max_h) || + (!gc->shared->info.etc1_subimage && (intformat == etc1_fmt))) + { + pt = _pool_tex_render_new(gc, w, h, intformat, format, EINA_FALSE); + if (!pt) return NULL; + gc->shared->tex.whole = eina_list_prepend(gc->shared->tex.whole, pt); + pt->fslot = -1; + pt->whole = 1; + *apt = _pool_tex_alloc(pt, w, h, u, v); + return pt; + } + + th2 = _tex_format_index(intformat); + if (th2 < 0) return NULL; + EINA_LIST_FOREACH(gc->shared->tex.atlas[th2], l, pt) + { + if (!pt->render) continue; + if ((*apt = _pool_tex_alloc(pt, w, h, u, v)) != NULL) + { + gc->shared->tex.atlas[th2] = + eina_list_promote_list(gc->shared->tex.atlas[th2], l); + return pt; + } + } + pool_h = atlas_w; + if ( h > pool_h || w > atlas_w ) + { + atlas_w = gc->shared->info.tune.atlas.max_w; + pool_h = gc->shared->info.tune.atlas.max_h; + } + pt = _pool_tex_render_new(gc, atlas_w, pool_h, intformat, format, EINA_FALSE); + if (!pt) return NULL; + gc->shared->tex.atlas[th2] = + eina_list_prepend(gc->shared->tex.atlas[th2], pt); + pt->fslot = th2; + + *apt = _pool_tex_alloc(pt, w, h, u, v); + + return pt; +} + static Evas_GL_Texture_Pool * _pool_tex_native_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, int format, Evas_GL_Image *im) { @@ -983,7 +1043,7 @@ pt_unref(Evas_GL_Texture_Pool *pt) pt->references--; if (pt->references != 0) return; - if ((pt->gc) && !((pt->render) || (pt->native))) + if ((pt->gc) && !(pt->native)) { if (pt->whole) pt->gc->shared->tex.whole = @@ -1054,6 +1114,37 @@ evas_gl_common_texture_render_new(Evas_Engine_GL_Context *gc, unsigned int w, un return tex; } +Evas_GL_Texture * +evas_gl_common_texture_render_noscale_new(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, int alpha) +{ + Evas_GL_Texture *tex; + int u = 0, v = 0; + int lformat; + + lformat = _evas_gl_texture_search_format(alpha, gc->shared->info.bgra, EVAS_COLORSPACE_ARGB8888); + if (lformat < 0) return NULL; + + tex = evas_gl_common_texture_alloc(gc, w, h, alpha); + if (!tex) return NULL; + tex->pt = _pool_tex_render_find(gc, w, h, + *matching_format[lformat].intformat, + *matching_format[lformat].format, + &u, &v, &tex->apt, + // XXX: should this be another atlas size? + gc->shared->info.tune.atlas.max_alloc_size, + EINA_FALSE); + if (!tex->pt) + { + evas_gl_common_texture_light_free(tex); + return NULL; + } + tex->x = u; + tex->y = v; + + tex->pt->references++; + return tex; +} + Evas_GL_Texture * evas_gl_common_texture_dynamic_new(Evas_Engine_GL_Context *gc, Evas_GL_Image *im) { diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index dcd66f79ad..4c5a168253 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -3106,10 +3106,30 @@ eng_image_surface_noscale_new(void *engdata, int w, int h, int alpha) re->window_use(re->software.ob); gl_context = re->window_gl_context_get(re->software.ob); - // XXX: FIXME: need a special surface new func that can use an atlas - return evas_gl_common_image_surface_new(gl_context, w, h, alpha); + return evas_gl_common_image_surface_noscale_new(gl_context, w, h, alpha); } +static void +eng_image_surface_noscale_region_get(void *engdata, void *image, int *x, int *y, int *w, int *h) +{ + Evas_GL_Image *im = image; + + if (im) + { + *x = im->tex->x; + *y = im->tex->y; + *w = im->w; + *h = im->h; + return; + } + else + { + *x = 0; + *y = 0; + *w = 0; + *h = 0; + } +} static int module_open(Evas_Module *em) @@ -3198,6 +3218,7 @@ module_open(Evas_Module *em) ORD(image_prepare); ORD(image_surface_noscale_new); + ORD(image_surface_noscale_region_get); ORD(font_cache_flush); ORD(font_cache_set); diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 674c93eac9..69536aecf0 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -1955,6 +1955,28 @@ eng_image_surface_noscale_new(void *engdata, int w, int h, int alpha) return eng_image_map_surface_new(engdata, w, h, alpha); } +static void +eng_image_surface_noscale_region_get(void *engdata, void *image, int *x, int *y, int *w, int *h) +{ + RGBA_Image *im = image; + + if (im) + { + *x = 0; + *y = 0; + *w = im->cache_entry.w; + *h = im->cache_entry.h; + return; + } + else + { + *x = 0; + *y = 0; + *w = 0; + *h = 0; + } +} + static void _image_flip_horizontal(DATA32 *pixels_out, const DATA32 *pixels_in, int iw, int ih) @@ -4669,6 +4691,7 @@ static Evas_Func func = eng_image_data_slice_add, eng_image_prepare, eng_image_surface_noscale_new, + eng_image_surface_noscale_region_get, eng_image_native_init, eng_image_native_shutdown, eng_image_native_set,