From: Jiyoun Park <jy0703.park@samsung.com>
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 4 May 2011 06:15:00 +0000 (06:15 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 4 May 2011 06:15:00 +0000 (06:15 +0000)
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).

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@59167 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

m4/evas_check_engine.m4
src/modules/engines/gl_common/Makefile.am
src/modules/engines/gl_common/evas_gl_common.h
src/modules/engines/gl_common/evas_gl_context.c
src/modules/engines/gl_common/evas_gl_shader.c
src/modules/engines/gl_x11/Makefile.am

index b1f60c7..b968602 100644 (file)
@@ -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
index ac74f13..2bc7c95 100644 (file)
@@ -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 = \
index 8474a7e..fb3b9d7 100644 (file)
@@ -12,6 +12,7 @@
 #include <math.h>
 #include <sys/time.h>
 #include <unistd.h>
+#include <Eet.h>
 
 #define GL_GLEXT_PROTOTYPES
 
 #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);
index 83ec9cf..639277f 100644 (file)
@@ -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__, "");
index 2a5c69e..d1c0a72 100644 (file)
@@ -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)
 {
-   GLint ok;
+   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);
 }
index 3701a0d..ee5bf04 100644 (file)
@@ -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