From 56111d2b6903abca742bdd0877232ef4c4b3225f Mon Sep 17 00:00:00 2001 From: Jiyoun Park Date: Wed, 4 May 2011 06:15:00 +0000 Subject: [PATCH] From: Jiyoun Park Subject: [E-devel] [Patch] Evas gl shader use binary shader I make patch related with evas gl binary shader. The concept of binary shader is compile shader only once. Some people want to use binary shader because of performance issue. In current evas gl engine, every application have to compile shader each time. But I modify code , so only first running application need compile shader. Other application use already compiled shader(binary shader) The binary shader is made under HOME/.evas/gl_common_shaders directory. Binary shader is created according to GL vendor,GL renderer, GL version and Module_arch. The basic flow is 1. First running application which use gl engine check binary shader directory, but it can't find binary shader. 2. After compiling shader, It saves compiled shaders.. 3. Other application checks shader directory, it can use binary shaders. In mobile target, using binary shader, I can save 150ms. (that time, there is 11 shaders). If there is more shaders and more applications, this flow maybe save more total time. (the above is now in, changelog coming, with change to using ~/.cache, some formatting fixes, make ity do the desktop gl one right with the retrievable hint parameter ont he program etc. - doesn't break desktop gl at least. yay. a,so fixes to mke it compile at all). SVN revision: 59167 --- legacy/evas/m4/evas_check_engine.m4 | 34 +- .../src/modules/engines/gl_common/Makefile.am | 5 +- .../engines/gl_common/evas_gl_common.h | 22 +- .../engines/gl_common/evas_gl_context.c | 154 ++---- .../engines/gl_common/evas_gl_shader.c | 494 +++++++++++++++++- .../src/modules/engines/gl_x11/Makefile.am | 3 +- 6 files changed, 565 insertions(+), 147 deletions(-) diff --git a/legacy/evas/m4/evas_check_engine.m4 b/legacy/evas/m4/evas_check_engine.m4 index b1f60c7e3a..b968602b93 100644 --- a/legacy/evas/m4/evas_check_engine.m4 +++ b/legacy/evas/m4/evas_check_engine.m4 @@ -113,16 +113,19 @@ if test "x$gl_flavor_gles" = "xyes" ; then fi if test "x${have_dep}" = "xyes" ; then - if test "x$2" = "xyes" ; then - x_libs="${x_libs} -lX11 -lXext -lXrender" - else - x_dir=${x_dir:-/usr/X11R6} - x_cflags=${x_cflags:--I${x_includes:-$x_dir/include}} - x_libs="${x_libs:--L${x_libraries:-$x_dir/lib}} -lX11 -lXext -lXrender" - fi + PKG_CHECK_MODULES([GL_EET], [eet >= 1.4.0], [have_dep="yes"], [have_dep="no"]) + if test "x${have_dep}" = "xyes" ; then + if test "x$2" = "xyes" ; then + x_libs="${x_libs} -lX11 -lXext -lXrender" + else + x_dir=${x_dir:-/usr/X11R6} + x_cflags=${x_cflags:--I${x_includes:-$x_dir/include}} + x_libs="${x_libs:--L${x_libraries:-$x_dir/lib}} -lX11 -lXext -lXrender" + fi evas_engine_[]$1[]_cflags="-I/usr/include ${x_cflags}" evas_engine_[]$1[]_libs="${x_libs} -lGL $gl_pt_lib" evas_engine_gl_common_libs="-lGL $gl_pt_lib" + fi else if test "x$2" = "xyes" ; then x_libs="${x_libs} -lX11 -lXext -lXrender" @@ -147,13 +150,16 @@ else if test "x${have_egl}" = "xyes" ; then AC_CHECK_LIB(GLESv2, glTexImage2D, [have_glesv2="yes"], , -lEGL ${x_libs} -lm $gl_pt_lib) if test "x${have_glesv2}" = "xyes" ; then - evas_engine_[]$1[]_cflags="${x_cflags}" - evas_engine_[]$1[]_libs="${x_libs} -lGLESv2 -lEGL -lm $gl_pt_lib" - evas_engine_gl_common_libs="-lGLESv2 -lm $gl_pt_lib" - have_dep="yes" - gl_flavor_gles="no" - AC_DEFINE(GLES_VARIETY_SGX, 1, [Imagination SGX GLES2 support]) - gles_variety_sgx="yes" + PKG_CHECK_MODULES([GL_EET], [eet >= 1.4.0], [have_dep="yes"], [have_dep="no"]) + if test "x${have_dep}" = "xyes" ; then + evas_engine_[]$1[]_cflags="${x_cflags}" + evas_engine_[]$1[]_libs="${x_libs} -lGLESv2 -lEGL -lm $gl_pt_lib" + evas_engine_gl_common_libs="-lGLESv2 -lm $gl_pt_lib" + have_dep="yes" + gl_flavor_gles="no" + AC_DEFINE(GLES_VARIETY_SGX, 1, [Imagination SGX GLES2 support]) + gles_variety_sgx="yes" + fi fi fi fi diff --git a/legacy/evas/src/modules/engines/gl_common/Makefile.am b/legacy/evas/src/modules/engines/gl_common/Makefile.am index ac74f132f0..2bc7c9566d 100644 --- a/legacy/evas/src/modules/engines/gl_common/Makefile.am +++ b/legacy/evas/src/modules/engines/gl_common/Makefile.am @@ -7,6 +7,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib/include \ @FREETYPE_CFLAGS@ \ @PIXMAN_CFLAGS@ \ +@GL_EET_CFLAGS@ \ @EINA_CFLAGS@ if BUILD_ENGINE_GL_COMMON @@ -81,9 +82,7 @@ shader/filter_blur_nomul.h \ shader/filter_blur_bgra.h \ shader/filter_blur_bgra_nomul.h - - -libevas_engine_gl_common_la_LIBADD = @EINA_LIBS@ @evas_engine_gl_common_libs@ @dlopen_libs@ +libevas_engine_gl_common_la_LIBADD = @EINA_LIBS@ @GL_EET_LIBS@ @evas_engine_gl_common_libs@ @dlopen_libs@ endif EXTRA_DIST = \ diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h b/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h index 8474a7e01a..fb3b9d7a45 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_common.h @@ -12,6 +12,7 @@ #include #include #include +#include #define GL_GLEXT_PROTOTYPES @@ -87,6 +88,18 @@ #ifndef EGL_MAP_GL_TEXTURE_STRIDE_IN_BYTES_SEC # define EGL_MAP_GL_TEXTURE_STRIDE_IN_BYTES_SEC 0x3208 #endif +#ifndef GL_PROGRAM_BINARY_LENGTH +# define GL_PROGRAM_BINARY_LENGTH 0x8741 +#endif +#ifndef GL_NUM_PROGRAM_BINARY_FORMATS +# define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#endif +#ifndef GL_PROGRAM_BINARY_FORMATS +# define GL_PROGRAM_BINARY_FORMATS 0x87FF +#endif +#ifndef GL_PROGRAM_BINARY_RETRIEVABLE_HINT +# define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#endif #define SHAD_VERTEX 0 #define SHAD_COLOR 1 @@ -134,6 +147,7 @@ struct _Evas_GL_Shared Eina_Bool tex_npo2 : 1; Eina_Bool tex_rect : 1; Eina_Bool sec_image_map : 1; + Eina_Bool bin_program : 1; // tuning params - per gpu/cpu combo? #define MAX_CUTOUT 512 #define DEF_CUTOUT 512 @@ -497,10 +511,7 @@ void evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *g Eina_Bool yuv); void evas_gl_common_context_flush(Evas_Engine_GL_Context *gc); -int evas_gl_common_shader_program_init(Evas_GL_Program *p, - Evas_GL_Program_Source *vert, - Evas_GL_Program_Source *frag, - const char *name); +int evas_gl_common_shader_program_init(Evas_GL_Shared *shared); void evas_gl_common_shader_program_init_done(void); void evas_gl_common_shader_program_shutdown(Evas_GL_Program *p); @@ -559,6 +570,9 @@ extern void (*glsym_glGenFramebuffers) (GLsizei a, GLuint *b); extern void (*glsym_glBindFramebuffer) (GLenum a, GLuint b); extern void (*glsym_glFramebufferTexture2D) (GLenum a, GLenum b, GLenum c, GLuint d, GLint e); extern void (*glsym_glDeleteFramebuffers) (GLsizei a, const GLuint *b); +extern void (*glsym_glGetProgramBinary) (GLuint a, GLsizei b, GLsizei *c, GLenum *d, void *e); +extern void (*glsym_glProgramBinary) (GLuint a, GLenum b, const void *c, GLint d); +extern void (*glsym_glProgramParameteri) (GLuint a, GLuint b, GLint d); #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) extern void *(*secsym_eglCreateImage) (void *a, void *b, GLenum c, void *d, const int *e); diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c index 83ec9cf6ad..639277fd5d 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_context.c @@ -11,6 +11,9 @@ void (*glsym_glGenFramebuffers) (GLsizei a, GLuint *b) = NULL; void (*glsym_glBindFramebuffer) (GLenum a, GLuint b) = NULL; void (*glsym_glFramebufferTexture2D) (GLenum a, GLenum b, GLenum c, GLuint d, GLint e) = NULL; void (*glsym_glDeleteFramebuffers) (GLsizei a, const GLuint *b) = NULL; +void (*glsym_glGetProgramBinary) (GLuint a, GLsizei b, GLsizei *c, GLenum *d, void *e) = NULL; +void (*glsym_glProgramBinary) (GLuint a, GLenum b, const void *c, GLint d) = NULL; +void (*glsym_glProgramParameteri) (GLuint a, GLuint b, GLint d) = NULL; #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) // just used for finding symbols :) @@ -71,6 +74,19 @@ gl_symbols(void) FINDSYM(glsym_glDeleteFramebuffers, "glDeleteFramebuffersARB", glsym_func_void); FALLBAK(glsym_glDeleteFramebuffers, glsym_func_void); + FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinary", glsym_func_void); + FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryEXT", glsym_func_void); + FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryARB", glsym_func_void); + FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryOES", glsym_func_void); + + FINDSYM(glsym_glProgramBinary, "glProgramBinary", glsym_func_void); + FINDSYM(glsym_glProgramBinary, "glProgramBinaryEXT", glsym_func_void); + FINDSYM(glsym_glProgramBinary, "glProgramBinaryARB", glsym_func_void); + + FINDSYM(glsym_glProgramParameteri, "glProgramParameteri", glsym_func_void); + FINDSYM(glsym_glProgramParameteri, "glProgramParameteriEXT", glsym_func_void); + FINDSYM(glsym_glProgramParameteri, "glProgramParameteriARB", glsym_func_void); + #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) #undef FINDSYM #define FINDSYM(dst, sym, typ) \ @@ -97,6 +113,24 @@ gl_symbols(void) FINDSYM(secsym_eglDestroyImage, "eglDestroyImageARB", secsym_func_uint); FINDSYM(secsym_eglDestroyImage, "eglDestroyImageKHR", secsym_func_uint); + FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinary", glsym_func_void); + FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryEXT", glsym_func_void); + FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryARB", glsym_func_void); + FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryOES", glsym_func_void); + FINDSYM(glsym_glGetProgramBinary, "glGetProgramBinaryKHR", glsym_func_void); + + FINDSYM(glsym_glProgramBinary, "glProgramBinary", glsym_func_void); + FINDSYM(glsym_glProgramBinary, "glProgramBinaryEXT", glsym_func_void); + FINDSYM(glsym_glProgramBinary, "glProgramBinaryARB", glsym_func_void); + FINDSYM(glsym_glProgramBinary, "glProgramBinaryOES", glsym_func_void); + FINDSYM(glsym_glProgramBinary, "glProgramBinaryKHR", glsym_func_void); + + FINDSYM(glsym_glProgramParameteri, "glProgramParameteri", glsym_func_void); + FINDSYM(glsym_glProgramParameteri, "glProgramParameteriEXT", glsym_func_void); + FINDSYM(glsym_glProgramParameteri, "glProgramParameteriARB", glsym_func_void); + FINDSYM(glsym_glProgramParameteri, "glProgramParameteriOES", glsym_func_void); + FINDSYM(glsym_glProgramParameteri, "glProgramParameteriKHR", glsym_func_void); + FINDSYM(secsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", glsym_func_void); FINDSYM(secsym_eglMapImageSEC, "eglMapImageSEC", secsym_func_void_ptr); @@ -607,6 +641,9 @@ evas_gl_common_context_new(void) (strstr((char *)ext, "GL_EXT_texture_rectangle")) || (strstr((char *)ext, "GL_ARB_texture_rectangle"))) shared->info.tex_rect = 1; + if ((strstr((char *)ext, "GL_ARB_get_program_binary")) || + (strstr((char *)ext, "GL_OES_get_program_binary"))) + shared->info.bin_program = 1; #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT if ((strstr((char *)ext, "GL_EXT_texture_filter_anisotropic"))) glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @@ -765,122 +802,7 @@ evas_gl_common_context_new(void) glEnableVertexAttribArray(SHAD_COLOR); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); - if (!evas_gl_common_shader_program_init(&(shared->shader.rect), - &(shader_rect_vert_src), - &(shader_rect_frag_src), - "rect")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.font), - &(shader_font_vert_src), - &(shader_font_frag_src), - "font")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.img), - &(shader_img_vert_src), - &(shader_img_frag_src), - "img")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.img_nomul), - &(shader_img_nomul_vert_src), - &(shader_img_nomul_frag_src), - "img_nomul")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.img_bgra), - &(shader_img_bgra_vert_src), - &(shader_img_bgra_frag_src), - "img_bgra")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.img_bgra_nomul), - &(shader_img_bgra_nomul_vert_src), - &(shader_img_bgra_nomul_frag_src), - "img_bgra_nomul")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.img_mask), - &(shader_img_mask_vert_src), - &(shader_img_mask_frag_src), - "img_mask")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.tex), - &(shader_tex_vert_src), - &(shader_tex_frag_src), - "tex")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.tex_nomul), - &(shader_tex_nomul_vert_src), - &(shader_tex_nomul_frag_src), - "tex_nomul")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.yuv), - &(shader_yuv_vert_src), - &(shader_yuv_frag_src), - "yuv")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.yuv_nomul), - &(shader_yuv_nomul_vert_src), - &(shader_yuv_nomul_frag_src), - "yuv_nomul")) goto error; - - /* Most of the filters use the image fragment shader */ - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_invert), - &(shader_img_vert_src), - &(shader_filter_invert_frag_src), - "filter_invert")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_invert_nomul), - &(shader_img_vert_src), - &(shader_filter_invert_nomul_frag_src), - "filter_invert_nomul")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_invert_bgra), - &(shader_img_vert_src), - &(shader_filter_invert_bgra_frag_src), - "filter_invert_bgra")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_invert_bgra_nomul), - &(shader_img_vert_src), - &(shader_filter_invert_bgra_nomul_frag_src), - "filter_invert_bgra_nomul")) goto error; - - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_sepia), - &(shader_img_vert_src), - &(shader_filter_sepia_frag_src), - "filter_sepia")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_sepia_nomul), - &(shader_img_vert_src), - &(shader_filter_sepia_nomul_frag_src), - "filter_sepia_nomul")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_sepia_bgra), - &(shader_img_vert_src), - &(shader_filter_sepia_bgra_frag_src), - "filter_sepia_bgra")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_sepia_bgra_nomul), - &(shader_img_vert_src), - &(shader_filter_sepia_bgra_nomul_frag_src), - "filter_sepia_bgra_nomul")) goto error; - - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_greyscale), - &(shader_img_vert_src), - &(shader_filter_greyscale_frag_src), - "filter_greyscale")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_greyscale_nomul), - &(shader_img_vert_src), - &(shader_filter_greyscale_nomul_frag_src), - "filter_greyscale_nomul")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_greyscale_bgra), - &(shader_img_vert_src), - &(shader_filter_greyscale_bgra_frag_src), - "filter_greyscale_bgra")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_greyscale_bgra_nomul), - &(shader_img_vert_src), - &(shader_filter_greyscale_bgra_nomul_frag_src), - "filter_greyscale_bgra_nomul")) goto error; -#if 0 - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_blur), - &(shader_filter_blur_vert_src), - &(shader_filter_blur_frag_src), - "filter_blur")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_blur_nomul), - &(shader_filter_blur_vert_src), - &(shader_filter_blur_nomul_frag_src), - "filter_blur_nomul")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_blur_bgra), - &(shader_filter_blur_vert_src), - &(shader_filter_blur_bgra_frag_src), - "filter_blur_bgra")) goto error; - if (!evas_gl_common_shader_program_init(&(shared->shader.filter_blur_bgra_nomul), - &(shader_filter_blur_vert_src), - &(shader_filter_blur_bgra_nomul_frag_src), - "filter_blur_bgra_nomul")) goto error; -#endif - - + if (!evas_gl_common_shader_program_init(shared)) goto error; glUseProgram(shared->shader.yuv.prog); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); diff --git a/legacy/evas/src/modules/engines/gl_common/evas_gl_shader.c b/legacy/evas/src/modules/engines/gl_common/evas_gl_shader.c index 2a5c69e542..d1c0a72015 100644 --- a/legacy/evas/src/modules/engines/gl_common/evas_gl_shader.c +++ b/legacy/evas/src/modules/engines/gl_common/evas_gl_shader.c @@ -637,14 +637,210 @@ gl_compile_link_error(GLuint target, const char *action) } } -int -evas_gl_common_shader_program_init(Evas_GL_Program *p, - Evas_GL_Program_Source *vert, - Evas_GL_Program_Source *frag, - const char *name) +static mode_t default_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + +static Eina_Bool +_evas_gl_shader_file_is_dir(const char *file) +{ + struct stat st; + + if (stat(file, &st) < 0) return EINA_FALSE; + if (S_ISDIR(st.st_mode)) return EINA_TRUE; + return EINA_FALSE; +} + +static Eina_Bool +_evas_gl_shader_file_mkdir(const char *dir) +{ + /* evas gl shader only call this function when the dir is not exist */ + if (mkdir(dir, default_mode) < 0) return EINA_FALSE; + return EINA_TRUE; +} + +static Eina_Bool +_evas_gl_shader_file_exists(const char *file) +{ + struct stat st; + if (!file) return EINA_FALSE; + if (stat(file, &st) < 0) return EINA_FALSE; + + return EINA_TRUE; +} + +static inline Eina_Bool +_evas_gl_shader_file_mkpath_if_not_exists(const char *path) +{ + struct stat st; + + if (stat(path, &st) < 0) + return _evas_gl_shader_file_mkdir(path); + else if (!S_ISDIR(st.st_mode)) + return EINA_FALSE; + else + return EINA_TRUE; +} + +static Eina_Bool +_evas_gl_shader_file_mkpath(const char *path) +{ + char ss[PATH_MAX]; + unsigned int i; + + if (_evas_gl_shader_file_is_dir(path)) return EINA_TRUE; + + for (i = 0; path[i]; ss[i] = path[i], i++) + { + if (i == sizeof(ss) - 1) return EINA_FALSE; + if ((path[i] == '/') && (i > 0)) + { + ss[i] = 0; + if (!_evas_gl_shader_file_mkpath_if_not_exists(ss)) + return EINA_FALSE; + } + } + ss[i] = 0; + return _evas_gl_shader_file_mkpath_if_not_exists(ss); +} + +static int +_evas_gl_shader_dir_check(char *bin_shader_dir, int num) +{ + char *home = NULL; + char *subdir = ".cache/evas_gl_common_shaders"; + + home = getenv("HOME"); + if ((!home) || (!home[0])) return 0; + + snprintf(bin_shader_dir, num, "%s/%s", home, subdir); + return _evas_gl_shader_file_exists(bin_shader_dir); +} + +static int +_evas_gl_shader_file_check(const char *bin_shader_dir, char *bin_shader_file, int dir_num) +{ + char before_name[PATH_MAX]; + char after_name[PATH_MAX]; + int new_path_len = 0; + int i = 0, j = 0; + + char *vendor = NULL; + char *driver = NULL; + char *version = NULL; + + vendor = (char *)glGetString(GL_VENDOR); + driver = (char *)glGetString(GL_RENDERER); + version = (char *)glGetString(GL_VERSION); + + new_path_len = snprintf(before_name, sizeof(before_name), "%s::%s::%s::%s::binary_shader.eet", vendor, version, driver, MODULE_ARCH); + + /* remove '/' from file name */ + for (i = 0; i < new_path_len; i++) + { + if (before_name[i] != '/') + { + after_name[j] = before_name[i]; + j++; + } + } + after_name[j] = 0; + + snprintf(bin_shader_file, dir_num, "%s/%s", bin_shader_dir, after_name); + + return _evas_gl_shader_file_exists(bin_shader_file); +} + +static int +_evas_gl_common_shader_program_binary_init(Evas_GL_Program *p, + const char *pname, + Eet_File *ef) +{ + int res = 0, num = 0, length = 0; + int *formats = NULL; + void *data = NULL; + + if (!ef) return res; + + data = eet_read(ef, pname, &length); + if ((!data) || (length <= 0)) goto finish; + + glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &num); + if (num <= 0) goto finish; + + formats = calloc(num, sizeof(int)); + if (!formats) goto finish; + + glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, formats); + if (!formats[0]) goto finish; + + p->prog = glCreateProgram(); + +#if 0 + // TOOD: invalid rendering error occurs when attempting to use a glProgramBinary. + // in order to render correctly we should create a dummy vertex shader. + p->vert = glCreateShader(GL_VERTEX_SHADER); + glAttachShader(p->prog, p->vert); + p->frag = glCreateShader(GL_FRAGMENT_SHADER); + glAttachShader(p->prog, p->frag); +#endif + glsym_glProgramBinary(p->prog, formats[0], data, length); + + glBindAttribLocation(p->prog, SHAD_VERTEX, "vertex"); + glBindAttribLocation(p->prog, SHAD_COLOR, "color"); + glBindAttribLocation(p->prog, SHAD_TEXUV, "tex_coord"); + glBindAttribLocation(p->prog, SHAD_TEXUV2, "tex_coord2"); + glBindAttribLocation(p->prog, SHAD_TEXUV3, "tex_coord3"); + glBindAttribLocation(p->prog, SHAD_TEXM, "tex_coordm"); + res = 1; + +finish: + if (formats) free(formats); + if (data) free(data); + if ((!res) && (p->prog)) + { + glDeleteProgram(p->prog); + p->prog = 0; + } + return res; +} + +static int +_evas_gl_common_shader_program_binary_save(Evas_GL_Program *p, + const char *pname, + Eet_File *ef) +{ + void* data = NULL; + GLenum format; + int length = 0; + + if (!glsym_glGetProgramBinary) return 0; + + glGetProgramiv(p->prog, GL_PROGRAM_BINARY_LENGTH, &length); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + if (length <= 0) return 0; + + data = malloc(length); + if (!data) return 0; + + glsym_glGetProgramBinary(p->prog, length, NULL, &format, data); + GLERR(__FUNCTION__, __FILE__, __LINE__, ""); + + if (eet_write(ef, pname, data, length, 0) < 0) + { + if (data) free(data); + return 0; + } + if (data) free(data); + return 1; +} + +static int +_evas_gl_common_shader_program_source_init(Evas_GL_Program *p, + Evas_GL_Program_Source *vert, + Evas_GL_Program_Source *frag, + const char *name) { GLint ok; - + p->vert = glCreateShader(GL_VERTEX_SHADER); p->frag = glCreateShader(GL_FRAGMENT_SHADER); #if defined (GLES_VARIETY_S3C6410) @@ -683,6 +879,12 @@ evas_gl_common_shader_program_init(Evas_GL_Program *p, } #endif p->prog = glCreateProgram(); +#if defined(GLES_VARIETY_S3C6410) || defined(GLES_VARIETY_SGX) +#else + if ((glsym_glGetProgramBinary) && (glsym_glProgramParameteri)) + glsym_glProgramParameteri(p->prog, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, + GL_TRUE); +#endif glAttachShader(p->prog, p->vert); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); glAttachShader(p->prog, p->frag); @@ -716,6 +918,280 @@ evas_gl_common_shader_program_init(Evas_GL_Program *p, return 1; } +static int +_evas_gl_common_shader_source_init(Evas_GL_Shared *shared) +{ + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.rect), + &(shader_rect_vert_src), + &(shader_rect_frag_src), + "rect")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.font), + &(shader_font_vert_src), + &(shader_font_frag_src), + "font")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.img), + &(shader_img_vert_src), + &(shader_img_frag_src), + "img")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.img_nomul), + &(shader_img_nomul_vert_src), + &(shader_img_nomul_frag_src), + "img_nomul")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.img_bgra), + &(shader_img_bgra_vert_src), + &(shader_img_bgra_frag_src), + "img_bgra")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.img_bgra_nomul), + &(shader_img_bgra_nomul_vert_src), + &(shader_img_bgra_nomul_frag_src), + "img_bgra_nomul")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.img_mask), + &(shader_img_mask_vert_src), + &(shader_img_mask_frag_src), + "img_mask")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.tex), + &(shader_tex_vert_src), + &(shader_tex_frag_src), + "tex")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.tex_nomul), + &(shader_tex_nomul_vert_src), + &(shader_tex_nomul_frag_src), + "tex_nomul")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.yuv), + &(shader_yuv_vert_src), + &(shader_yuv_frag_src), + "yuv")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.yuv_nomul), + &(shader_yuv_nomul_vert_src), + &(shader_yuv_nomul_frag_src), + "yuv_nomul")) return 0; + + /* Most of the filters use the image fragment shader */ + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_invert), + &(shader_img_vert_src), + &(shader_filter_invert_frag_src), + "filter_invert")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_invert_nomul), + &(shader_img_vert_src), + &(shader_filter_invert_nomul_frag_src), + "filter_invert_nomul")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_invert_bgra), + &(shader_img_vert_src), + &(shader_filter_invert_bgra_frag_src), + "filter_invert_bgra")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_invert_bgra_nomul), + &(shader_img_vert_src), + &(shader_filter_invert_bgra_nomul_frag_src), + "filter_invert_bgra_nomul")) return 0; + + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_sepia), + &(shader_img_vert_src), + &(shader_filter_sepia_frag_src), + "filter_sepia")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_sepia_nomul), + &(shader_img_vert_src), + &(shader_filter_sepia_nomul_frag_src), + "filter_sepia_nomul")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_sepia_bgra), + &(shader_img_vert_src), + &(shader_filter_sepia_bgra_frag_src), + "filter_sepia_bgra")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_sepia_bgra_nomul), + &(shader_img_vert_src), + &(shader_filter_sepia_bgra_nomul_frag_src), + "filter_sepia_bgra_nomul")) return 0; + + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_greyscale), + &(shader_img_vert_src), + &(shader_filter_greyscale_frag_src), + "filter_greyscale")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_greyscale_nomul), + &(shader_img_vert_src), + &(shader_filter_greyscale_nomul_frag_src), + "filter_greyscale_nomul")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_greyscale_bgra), + &(shader_img_vert_src), + &(shader_filter_greyscale_bgra_frag_src), + "filter_greyscale_bgra")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_greyscale_bgra_nomul), + &(shader_img_vert_src), + &(shader_filter_greyscale_bgra_nomul_frag_src), + "filter_greyscale_bgra_nomul")) return 0; +#if 0 + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_blur), + &(shader_filter_blur_vert_src), + &(shader_filter_blur_frag_src), + "filter_blur")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_blur_nomul), + &(shader_filter_blur_vert_src), + &(shader_filter_blur_nomul_frag_src), + "filter_blur_nomul")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_blur_bgra), + &(shader_filter_blur_vert_src), + &(shader_filter_blur_bgra_frag_src), + "filter_blur_bgra")) return 0; + if (!_evas_gl_common_shader_program_source_init(&(shared->shader.filter_blur_bgra_nomul), + &(shader_filter_blur_vert_src), + &(shader_filter_blur_bgra_nomul_frag_src), + "filter_blur_bgra_nomul")) return 0; +#endif + + return 1; +} + +static int +_evas_gl_common_shader_binary_init(Evas_GL_Shared *shared) +{ + /* check eet */ + Eet_File *et = NULL; + + char bin_dir_path[PATH_MAX]; + char bin_file_path[PATH_MAX]; + + if (!_evas_gl_shader_dir_check(bin_dir_path, sizeof(bin_dir_path))) + return 0; + + if (!_evas_gl_shader_file_check(bin_dir_path, bin_file_path, + sizeof(bin_dir_path))) + return 0; + + /* use eet */ + if (!eet_init()) return 0; + et = eet_open(bin_file_path, EET_FILE_MODE_READ); + if (!et) goto error; + + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.rect), "rect", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.font), "font", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.img), "img", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.img_nomul), "img_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.img_bgra), "img_bgra", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.img_bgra_nomul), "img_bgra_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.img_mask), "img_mask", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.tex), "tex", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.tex_nomul),"tex_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.yuv), "yuv", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.yuv_nomul), "yuv_nomul", et)) goto error; + + /* Most of the filters use the image fragment shader */ + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_invert), "filter_invert", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_invert_nomul), "filter_invert_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_invert_bgra), "filter_invert_bgra", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_invert_bgra_nomul), "filter_invert_bgra_nomul", et)) goto error; + + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_sepia), "filter_sepia", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_sepia_nomul), "filter_sepia_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_sepia_bgra), "filter_sepia_bgra", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_sepia_bgra_nomul), "filter_sepia_bgra_nomul", et)) goto error; + + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_greyscale), "filter_greyscale", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_greyscale_nomul), "filter_greyscale_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_greyscale_bgra), "filter_greyscale_bgra", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_greyscale_bgra_nomul), "filter_greyscale_bgra_nomul", et)) goto error; +#if 0 + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_blur), "filter_blur", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_blur_nomul), "filter_blur_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_blur_bgra), "filter_blur_bgra", et)) goto error; + if (!_evas_gl_common_shader_program_binary_init(&(shared->shader.filter_blur_bgra_nomul), "filter_blur_bgra_nomul", et)) goto error; +#endif + + if (et) eet_close(et); + eet_shutdown(); + return 1; + +error: + if (et) eet_close(et); + eet_shutdown(); + return 0; +} + +static int +_evas_gl_common_shader_binary_save(Evas_GL_Shared *shared) +{ + /* check eet */ + Eet_File *et = NULL; //check eet file + int tmpfd; + int res = 0; + char bin_dir_path[PATH_MAX]; + char bin_file_path[PATH_MAX]; + char tmp_file[PATH_MAX]; + + if (!_evas_gl_shader_dir_check(bin_dir_path, sizeof(bin_dir_path))) + res = _evas_gl_shader_file_mkpath(bin_dir_path); + if (!res) return 0; /* we can't make directory */ + + _evas_gl_shader_file_check(bin_dir_path, bin_file_path, + sizeof(bin_dir_path)); + + /* use mkstemp for writing */ + snprintf(tmp_file, sizeof(tmp_file), "%s.XXXXXX", bin_file_path); + tmpfd = mkstemp(tmp_file); + if (tmpfd < 0) goto error; + close(tmpfd); + + /* use eet */ + if (!eet_init()) goto error; + + et = eet_open(tmp_file, EET_FILE_MODE_WRITE); + if (!et) goto error; + + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.rect), "rect", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.font), "font", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.img), "img", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.img_nomul), "img_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.img_bgra), "img_bgra", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.img_bgra_nomul), "img_bgra_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.img_mask), "img_mask", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.tex), "tex", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.tex_nomul),"tex_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.yuv), "yuv", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.yuv_nomul), "yuv_nomul", et)) goto error; + /* Most of the filters use the image fragment shader */ + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_invert), "filter_invert", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_invert_nomul), "filter_invert_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_invert_bgra), "filter_invert_bgra", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_invert_bgra_nomul), "filter_invert_bgra_nomul", et)) goto error; + + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_sepia), "filter_sepia", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_sepia_nomul), "filter_sepia_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_sepia_bgra), "filter_sepia_bgra", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_sepia_bgra_nomul), "filter_sepia_bgra_nomul", et)) goto error; + + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_greyscale), "filter_greyscale", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_greyscale_nomul), "filter_greyscale_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_greyscale_bgra), "filter_greyscale_bgra", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_greyscale_bgra_nomul), "filter_greyscale_bgra_nomul", et)) goto error; +#if 0 + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_blur), "filter_blur", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_blur_nomul), "filter_blur_nomul", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_blur_bgra), "filter_blur_bgra", et)) goto error; + if (!_evas_gl_common_shader_program_binary_save(&(shared->shader.filter_blur_bgra_nomul), "filter_blur_bgra_nomul", et)) goto error; +#endif + + if (eet_close(et) != EET_ERROR_NONE) goto error; + if (rename(tmp_file,bin_file_path) < 0) goto error; + eet_shutdown(); + return 1; + +error: + if (et) eet_close(et); + if (_evas_gl_shader_file_exists(tmp_file)) unlink(tmp_file); + eet_shutdown(); + return 0; +} + +int +evas_gl_common_shader_program_init(Evas_GL_Shared *shared) +{ + // gl support binary shader and get env of binary shader path + if (shared->info.bin_program && _evas_gl_common_shader_binary_init(shared)) return 1; + /* compile all shader.*/ + if (!_evas_gl_common_shader_source_init(shared)) return 0; + /* sucess compile all shader. if gl support binary shader, we need to save */ + if (shared->info.bin_program) _evas_gl_common_shader_binary_save(shared); + + return 1; +} + void evas_gl_common_shader_program_init_done(void) { @@ -727,7 +1203,7 @@ evas_gl_common_shader_program_init_done(void) void evas_gl_common_shader_program_shutdown(Evas_GL_Program *p) { - glDeleteShader(p->vert); - glDeleteShader(p->frag); - glDeleteProgram(p->prog); + if (p->vert) glDeleteShader(p->vert); + if (p->frag) glDeleteShader(p->frag); + if (p->prog) glDeleteProgram(p->prog); } diff --git a/legacy/evas/src/modules/engines/gl_x11/Makefile.am b/legacy/evas/src/modules/engines/gl_x11/Makefile.am index 3701a0dd05..ee5bf04877 100644 --- a/legacy/evas/src/modules/engines/gl_x11/Makefile.am +++ b/legacy/evas/src/modules/engines/gl_x11/Makefile.am @@ -9,6 +9,7 @@ AM_CPPFLAGS = \ @FREETYPE_CFLAGS@ \ @PIXMAN_CFLAGS@ \ @EINA_CFLAGS@ \ +@GL_EET_CFLAGS@ \ @evas_engine_gl_x11_cflags@ if BUILD_ENGINE_GL_X11 @@ -29,7 +30,7 @@ pkgdir = $(libdir)/evas/modules/engines/gl_x11/$(MODULE_ARCH) pkg_LTLIBRARIES = module.la module_la_SOURCES = $(GL_X11_SOURCES) -module_la_LIBADD = @EINA_LIBS@ $(GL_X11_LIBADD) $(top_builddir)/src/lib/libevas.la @dlopen_libs@ +module_la_LIBADD = @EINA_LIBS@ @GL_EET_LIBS@ $(GL_X11_LIBADD) $(top_builddir)/src/lib/libevas.la @dlopen_libs@ module_la_LDFLAGS = -module -avoid-version module_la_LIBTOOLFLAGS = --tag=disable-static