evas/gl: implement dynamic hint set using tbm surface

Summary:
Currently dynamic hint set is implemented using eglMapImageSEC extension,
which is no longer supported by any drivers (should be deprecated)
This patch implements dynamic hint set using Khronos extension EGL_TIZEN_image_native_surface.
Since tbm surface library is required for this, libtbm.so is queried at context new.

Test Plan: Local tests

Reviewers: raster, Hermet, cedric, jpeg

Subscribers: mer.kim, wonsik, cedric

Differential Revision: https://phab.enlightenment.org/D2027

Signed-off-by: Jean-Philippe Andre <jp.andre@samsung.com>

jpeg: I also fixed a few minor style issues and two warnings (bad function
names, glsym instead of secsym).
This commit is contained in:
Dongyeon Kim 2015-03-02 14:40:12 +09:00 committed by Jean-Philippe Andre
parent 433d24cfa0
commit a32edfaf19
5 changed files with 256 additions and 80 deletions

View File

@ -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);

View File

@ -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"))
{

View File

@ -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

View File

@ -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;

View File

@ -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
}