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 0770162d1e..21bf4a7326 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -190,6 +190,9 @@ #ifndef EGL_MAP_GL_TEXTURE_STRIDE_IN_BYTES_SEC # define EGL_MAP_GL_TEXTURE_STRIDE_IN_BYTES_SEC 0x320c #endif +#ifndef EGL_IMAGE_PRESERVED_KHR +# define EGL_IMAGE_PRESERVED_KHR 0x30D2 +#endif #ifndef EGL_NATIVE_SURFACE_TIZEN #define EGL_NATIVE_SURFACE_TIZEN 0x32A1 #endif @@ -327,6 +330,7 @@ struct _Evas_GL_Shared Eina_Bool tex_npo2 : 1; Eina_Bool tex_rect : 1; Eina_Bool sec_image_map : 1; + Eina_Bool sec_tbm_surface : 1; Eina_Bool bin_program : 1; Eina_Bool unpack_row_length : 1; Eina_Bool etc1 : 1; @@ -523,6 +527,7 @@ struct _Evas_GL_Texture_Pool int slot, fslot; struct { void *img; + void *buffer; unsigned int *data; int w, h; int stride; @@ -834,6 +839,58 @@ extern void (*secsym_glEGLImageTargetTexture2DOES) (int a, void *b); extern void *(*secsym_eglMapImageSEC) (void *a, void *b, int c, int d); extern unsigned int (*secsym_eglUnmapImageSEC) (void *a, void *b, int c); extern unsigned int (*secsym_eglGetImageAttribSEC) (void *a, void *b, int c, int *d); + +// TBM Surface stuff +#define TBM_SURF_PLANE_MAX 4 /**< maximum number of planes */ + +/* option to map the tbm_surface */ +#define TBM_SURF_OPTION_READ (1 << 0) /**< access option to read */ +#define TBM_SURF_OPTION_WRITE (1 << 1) /**< access option to write */ + +#define __tbm_fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \ + ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) + +#define TBM_FORMAT_C8 __tbm_fourcc_code('C', '8', ' ', ' ') +#define TBM_FORMAT_RGBA8888 __tbm_fourcc_code('R', 'A', '2', '4') +#define TBM_FORMAT_BGRA8888 __tbm_fourcc_code('B', 'A', '2', '4') +#define TBM_FORMAT_RGB888 __tbm_fourcc_code('R', 'G', '2', '4') + +typedef struct _tbm_surface * tbm_surface_h; +typedef uint32_t tbm_format; +typedef struct _tbm_surface_plane +{ + unsigned char *ptr; /**< Plane pointer */ + uint32_t size; /**< Plane size */ + uint32_t offset; /**< Plane offset */ + uint32_t stride; /**< Plane stride */ + + void *reserved1; /**< Reserved pointer1 */ + void *reserved2; /**< Reserved pointer2 */ + void *reserved3; /**< Reserved pointer3 */ +} tbm_surface_plane_s; + +typedef struct _tbm_surface_info +{ + uint32_t width; /**< TBM surface width */ + uint32_t height; /**< TBM surface height */ + tbm_format format; /**< TBM surface format*/ + uint32_t bpp; /**< TBM surface bbp */ + uint32_t size; /**< TBM surface size */ + + uint32_t num_planes; /**< The number of planes */ + tbm_surface_plane_s planes[TBM_SURF_PLANE_MAX]; /**< Array of planes */ + + void *reserved4; /**< Reserved pointer4 */ + void *reserved5; /**< Reserved pointer5 */ + void *reserved6; /**< Reserved pointer6 */ +} tbm_surface_info_s; + + +extern void *(*secsym_tbm_surface_create) (int width, int height, unsigned int format); +extern int (*secsym_tbm_surface_destroy) (void *surface); +extern int (*secsym_tbm_surface_map) (void *surface, int opt, void *info); +extern int (*secsym_tbm_surface_unmap) (void *surface); +extern int (*secsym_tbm_surface_get_info) (void *surface, void *info); #endif Eina_Bool evas_gl_preload_push(Evas_GL_Texture_Async_Preload *async); diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index ff9ff260bf..878484fa54 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -10,6 +10,7 @@ #define GLPIPES 1 static int sym_done = 0; +static int tbm_sym_done = 0; int _evas_engine_GL_common_log_dom = -1; Cutout_Rects *_evas_gl_common_cutout_rects = NULL; @@ -41,6 +42,7 @@ void (*glsym_glEndTiling) (GLuint a) = NULL; typedef void (*_eng_fn) (void); typedef _eng_fn (*glsym_func_eng_fn) (); +typedef int (*secsym_func_int) (); typedef unsigned int (*secsym_func_uint) (); typedef void *(*secsym_func_void_ptr) (); @@ -50,6 +52,17 @@ void (*secsym_glEGLImageTargetTexture2DOES) (int a, void *b) = NULL; void *(*secsym_eglMapImageSEC) (void *a, void *b, int c, int d) = NULL; unsigned int (*secsym_eglUnmapImageSEC) (void *a, void *b, int c) = NULL; unsigned int (*secsym_eglGetImageAttribSEC) (void *a, void *b, int c, int *d) = NULL; + +//////////////////////////////////// +//libtbm.so.1 +static void *tbm_lib_handle; + +void *(*secsym_tbm_surface_create) (int width, int height, unsigned int format) = NULL; +int (*secsym_tbm_surface_destroy) (void *surface) = NULL; +int (*secsym_tbm_surface_map) (void *surface, int opt, void *info) = NULL; +int (*secsym_tbm_surface_unmap) (void *surface) = NULL; +int (*secsym_tbm_surface_get_info) (void *surface, void *info) = NULL; +//////////////////////////////////// #else typedef void (*_eng_fn) (void); @@ -194,6 +207,42 @@ evas_gl_symbols(void *(*GetProcAddress)(const char *name)) FINDSYM(secsym_eglGetImageAttribSEC, "eglGetImageAttribSEC", secsym_func_uint); #endif + +#undef FINDSYM +#undef FINDSYM2 +#undef FALLBAK +} + +static void +tbm_symbols(void) +{ + if (tbm_sym_done) return; + tbm_sym_done = 1; + +#ifdef GL_GLES + tbm_lib_handle = dlopen("libtbm.so.1", RTLD_NOW); + if (!tbm_lib_handle) + { + DBG("Unable to open libtbm: %s", dlerror()); + return; + } + +#define FINDSYM(dst, sym, typ) \ + if (!dst) dst = (typ)dlsym(tbm_lib_handle, sym); \ + if (!dst) \ + { \ + ERR("Symbol not found %s\n", sym); \ + return; \ + } + + FINDSYM(secsym_tbm_surface_create, "tbm_surface_create", secsym_func_void_ptr); + FINDSYM(secsym_tbm_surface_destroy, "tbm_surface_destroy", secsym_func_int); + FINDSYM(secsym_tbm_surface_map, "tbm_surface_map", secsym_func_int); + FINDSYM(secsym_tbm_surface_unmap, "tbm_surface_unmap", secsym_func_int); + FINDSYM(secsym_tbm_surface_get_info, "tbm_surface_get_info", secsym_func_int); + +#undef FINDSYM +#endif } static void shader_array_flush(Evas_Engine_GL_Context *gc); @@ -544,6 +593,8 @@ evas_gl_common_context_new(void) gc = calloc(1, sizeof(Evas_Engine_GL_Context)); if (!gc) return NULL; + tbm_symbols(); + gc->references = 1; _evas_gl_common_context = gc; @@ -623,6 +674,14 @@ evas_gl_common_context_new(void) (secsym_eglGetImageAttribSEC)) shared->info.sec_image_map = 1; } + i = 0; + + if ((secsym_tbm_surface_create) && + (secsym_tbm_surface_destroy) && + (secsym_tbm_surface_map) && + (secsym_tbm_surface_unmap) && + (secsym_tbm_surface_get_info)) + shared->info.sec_tbm_surface = 1; #endif if (!strstr(ext, "GL_QCOM_tiled_rendering")) { 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 f4efb18ec7..ec5eddb8cc 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_image.c +++ b/src/modules/evas/engines/gl_common/evas_gl_image.c @@ -599,7 +599,8 @@ evas_gl_common_image_content_hint_set(Evas_GL_Image *im, int hint) if (im->content_hint == hint) return; im->content_hint = hint; if (!im->gc) return; - if (!im->gc->shared->info.sec_image_map) return; + if ((!im->gc->shared->info.sec_image_map) + && (!im->gc->shared->info.sec_tbm_surface)) return; if (!im->gc->shared->info.bgra) return; // does not handle yuv yet. // TODO: Check this list of cspaces 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 c2af7f349b..2f3852f7cd 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_texture.c +++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c @@ -692,33 +692,10 @@ _pool_tex_dynamic_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, i Evas_GL_Texture_Pool *pt = NULL; #ifdef GL_GLES - int fmt; // EGL_MAP_GL_TEXTURE_RGBA_SEC or EGL_MAP_GL_TEXTURE_RGB_SEC or bust - int pixtype; // EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC or bust - int attr[] = - { - EGL_MAP_GL_TEXTURE_WIDTH_SEC, 32, - EGL_MAP_GL_TEXTURE_HEIGHT_SEC, 32, - EGL_MAP_GL_TEXTURE_FORMAT_SEC, EGL_MAP_GL_TEXTURE_RGBA_SEC, - EGL_MAP_GL_TEXTURE_PIXEL_TYPE_SEC, EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC, - EGL_NONE - }; void *egldisplay; if (intformat != format) return NULL; - switch (intformat) - { -#ifdef EGL_MAP_GL_TEXTURE_LUMINANCE_SEC - case GL_LUMINANCE: attr[5] = EGL_MAP_GL_TEXTURE_LUMINANCE_SEC; break; -#endif -#ifdef EGL_MAP_GL_TEXTURE_LUMINANCE_ALPHA_SEC - case GL_LUMINANCE_ALPHA: attr[5] = EGL_MAP_GL_TEXTURE_LUMINANCE_ALPHA_SEC; break; -#endif - case GL_RGBA: attr[5] = EGL_MAP_GL_TEXTURE_RGBA_SEC; break; - case GL_BGRA: attr[5] = EGL_MAP_GL_TEXTURE_BGRA_SEC; break; - default: fprintf(stderr, "unknown format\n"); return NULL; - } - pt = calloc(1, sizeof(Evas_GL_Texture_Pool)); if (!pt) return NULL; _tex_adjust(gc, &w, &h); @@ -745,48 +722,110 @@ _pool_tex_dynamic_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, i egldisplay = pt->gc->egldisp; - attr[1] = pt->w; - attr[3] = pt->h; - - // FIXME: seems a bit slower than i'd like - maybe too many flushes? - // FIXME: YCbCr no support as yet - pt->dyn.img = secsym_eglCreateImage(egldisplay, - EGL_NO_CONTEXT, - EGL_MAP_GL_TEXTURE_2D_SEC, - 0, attr); - GLERRV("secsym_eglCreateImage"); - if (!pt->dyn.img) + if (gc->shared->info.sec_tbm_surface) { - glBindTexture(GL_TEXTURE_2D, 0); - glDeleteTextures(1, &(pt->texture)); - if (pt->eina_pool) - eina_rectangle_pool_free(pt->eina_pool); - free(pt); - return NULL; + tbm_format buffer_format = TBM_FORMAT_RGBA8888; + tbm_surface_info_s info; + int attr[] = + { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE, + }; + + switch (intformat) + { + case GL_LUMINANCE: buffer_format = TBM_FORMAT_C8; break; + case GL_LUMINANCE_ALPHA: buffer_format = TBM_FORMAT_C8; break; + case GL_RGBA: buffer_format = TBM_FORMAT_RGBA8888; break; + case GL_BGRA: buffer_format = TBM_FORMAT_BGRA8888; break; + case GL_RGB: buffer_format = TBM_FORMAT_RGB888; break; + default: ERR("TBM: unknown format"); return NULL; + } + + pt->dyn.buffer = (void *)secsym_tbm_surface_create(pt->w, pt->h, + buffer_format); + if (!pt->dyn.buffer) goto error; + + pt->dyn.img = secsym_eglCreateImage(egldisplay, + EGL_NO_CONTEXT, + EGL_NATIVE_SURFACE_TIZEN, + pt->dyn.buffer, attr); + if (!pt->dyn.img) + { + secsym_tbm_surface_destroy(pt->dyn.buffer); + goto error; + } + secsym_tbm_surface_get_info(pt->dyn.buffer, &info); + pt->dyn.w = info.width; + pt->dyn.h = info.height; + pt->dyn.stride = info.planes[0].stride; } - if (secsym_eglGetImageAttribSEC(egldisplay, - pt->dyn.img, - EGL_MAP_GL_TEXTURE_WIDTH_SEC, - &(pt->dyn.w)) != EGL_TRUE) goto error; - if (secsym_eglGetImageAttribSEC(egldisplay, - pt->dyn.img, - EGL_MAP_GL_TEXTURE_HEIGHT_SEC, - &(pt->dyn.h)) != EGL_TRUE) goto error; - if (secsym_eglGetImageAttribSEC(egldisplay, - pt->dyn.img, - EGL_MAP_GL_TEXTURE_STRIDE_IN_BYTES_SEC, - &(pt->dyn.stride)) != EGL_TRUE) goto error; - if (secsym_eglGetImageAttribSEC(egldisplay, - pt->dyn.img, - EGL_MAP_GL_TEXTURE_FORMAT_SEC, - &(fmt)) != EGL_TRUE) goto error; + else if (gc->shared->info.sec_image_map) + { + int fmt; // EGL_MAP_GL_TEXTURE_RGBA_SEC or EGL_MAP_GL_TEXTURE_RGB_SEC or bust + int pixtype; // EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC or bust + int attr[] = + { + EGL_MAP_GL_TEXTURE_WIDTH_SEC, 32, + EGL_MAP_GL_TEXTURE_HEIGHT_SEC, 32, + EGL_MAP_GL_TEXTURE_FORMAT_SEC, EGL_MAP_GL_TEXTURE_RGBA_SEC, + EGL_MAP_GL_TEXTURE_PIXEL_TYPE_SEC, EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC, + EGL_NONE + }; - if (secsym_eglGetImageAttribSEC(egldisplay, - pt->dyn.img, - EGL_MAP_GL_TEXTURE_PIXEL_TYPE_SEC, - &(pixtype)) != EGL_TRUE) goto error; + switch (intformat) + { +#ifdef EGL_MAP_GL_TEXTURE_LUMINANCE_SEC + case GL_LUMINANCE: attr[5] = EGL_MAP_GL_TEXTURE_LUMINANCE_SEC; break; +#endif +#ifdef EGL_MAP_GL_TEXTURE_LUMINANCE_ALPHA_SEC + case GL_LUMINANCE_ALPHA: attr[5] = EGL_MAP_GL_TEXTURE_LUMINANCE_ALPHA_SEC; break; +#endif + case GL_RGBA: attr[5] = EGL_MAP_GL_TEXTURE_RGBA_SEC; break; + case GL_BGRA: attr[5] = EGL_MAP_GL_TEXTURE_BGRA_SEC; break; + default: ERR("SEC map: unknown format"); return NULL; + } - if (pixtype != EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC) goto error; + attr[1] = pt->w; + attr[3] = pt->h; + + // FIXME: seems a bit slower than i'd like - maybe too many flushes? + // FIXME: YCbCr no support as yet + pt->dyn.img = secsym_eglCreateImage(egldisplay, + EGL_NO_CONTEXT, + EGL_MAP_GL_TEXTURE_2D_SEC, + 0, attr); + GLERRV("secsym_eglCreateImage"); + if (!pt->dyn.img) goto error; + + if (secsym_eglGetImageAttribSEC(egldisplay, + pt->dyn.img, + EGL_MAP_GL_TEXTURE_WIDTH_SEC, + &(pt->dyn.w)) != EGL_TRUE) goto error; + if (secsym_eglGetImageAttribSEC(egldisplay, + pt->dyn.img, + EGL_MAP_GL_TEXTURE_HEIGHT_SEC, + &(pt->dyn.h)) != EGL_TRUE) goto error; + if (secsym_eglGetImageAttribSEC(egldisplay, + pt->dyn.img, + EGL_MAP_GL_TEXTURE_STRIDE_IN_BYTES_SEC, + &(pt->dyn.stride)) != EGL_TRUE) goto error; + if (secsym_eglGetImageAttribSEC(egldisplay, + pt->dyn.img, + EGL_MAP_GL_TEXTURE_FORMAT_SEC, + &(fmt)) != EGL_TRUE) goto error; + if (secsym_eglGetImageAttribSEC(egldisplay, + pt->dyn.img, + EGL_MAP_GL_TEXTURE_PIXEL_TYPE_SEC, + &(pixtype)) != EGL_TRUE) goto error; + + if (pixtype != EGL_MAP_GL_TEXTURE_UNSIGNED_BYTE_SEC) goto error; + } + else + { + ERR("TBM surface or SEC image map should be enabled!"); + goto error; + } glBindTexture(GL_TEXTURE_2D, gc->pipe[0].shader.cur_tex); #else @@ -797,9 +836,12 @@ _pool_tex_dynamic_new(Evas_Engine_GL_Context *gc, int w, int h, int intformat, i /* ERROR HANDLING */ #ifdef GL_GLES error: - secsym_eglDestroyImage(egldisplay, pt->dyn.img); - GLERRV("secsym_eglDestroyImage"); - pt->dyn.img = NULL; + if (pt->dyn.img) + { + secsym_eglDestroyImage(egldisplay, pt->dyn.img); + GLERRV("secsym_eglDestroyImage"); + pt->dyn.img = NULL; + } glBindTexture(GL_TEXTURE_2D, 0); glDeleteTextures(1, &(pt->texture)); if (pt->eina_pool) @@ -853,9 +895,17 @@ evas_gl_texture_pool_empty(Evas_GL_Texture_Pool *pt) if (pt->dyn.img) { if (pt->dyn.checked_out > 0) - secsym_eglUnmapImageSEC(pt->gc->egldisp, pt->dyn.img, EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC); + { + if (pt->gc->shared->info.sec_tbm_surface) + secsym_tbm_surface_unmap(pt->dyn.buffer); + else if (pt->gc->shared->info.sec_image_map) + secsym_eglUnmapImageSEC(pt->gc->egldisp, pt->dyn.img, EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC); + } + if (pt->dyn.buffer) + secsym_tbm_surface_destroy(pt->dyn.buffer); secsym_eglDestroyImage(pt->gc->egldisp, pt->dyn.img); pt->dyn.img = NULL; + pt->dyn.buffer = NULL; pt->dyn.data = NULL; pt->dyn.w = 0; pt->dyn.h = 0; diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index edc85b5673..ee7e9be675 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -558,8 +558,6 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.img) && (im->cs.space == EVAS_COLORSPACE_ARGB8888)) { - void *disp; - if (im->tex->pt->dyn.checked_out > 0) { im->tex->pt->dyn.checked_out++; @@ -567,12 +565,22 @@ eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, i if (err) *err = EVAS_LOAD_ERROR_NONE; return im; } - disp = re->window_egl_display_get(re->software.ob); - *image_data = im->tex->pt->dyn.data = - secsym_eglMapImageSEC(disp, - im->tex->pt->dyn.img, - EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC, - EGL_MAP_GL_TEXTURE_OPTION_WRITE_SEC); + if (im->gc->shared->info.sec_tbm_surface) + { + tbm_surface_info_s info; + secsym_tbm_surface_map(im->tex->pt->dyn.buffer, + TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, + &info); + *image_data = im->tex->pt->dyn.data = (DATA32 *) info.planes[0].ptr; + } + else if (im->gc->shared->info.sec_image_map) + { + void *disp = re->window_egl_display_get(re->software.ob); + *image_data = im->tex->pt->dyn.data = secsym_eglMapImageSEC(disp, + im->tex->pt->dyn.img, + EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC, + EGL_MAP_GL_TEXTURE_OPTION_WRITE_SEC); + } if (!im->tex->pt->dyn.data) { @@ -689,12 +697,13 @@ eng_image_data_put(void *data, void *image, DATA32 *image_data) #ifdef GL_GLES if (im->tex->pt->dyn.checked_out == 0) { - void *disp; - - disp = re->window_egl_display_get(re->software.ob); - secsym_eglUnmapImageSEC(disp, - im->tex->pt->dyn.img, - EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC); + if (im->gc->shared->info.sec_tbm_surface) + secsym_tbm_surface_unmap(im->tex->pt->dyn.buffer); + else if (im->gc->shared->info.sec_image_map) + { + void *disp = disp = re->window_egl_display_get(re->software.ob); + secsym_eglUnmapImageSEC(disp, im->tex->pt->dyn.img, EGL_MAP_GL_TEXTURE_DEVICE_CPU_SEC); + } } #endif }