[evas_gl] Add lock to wait compiling shader
authorsunghyun kim <scholb.kim@samsung.com>
Tue, 18 Jul 2017 02:57:49 +0000 (11:57 +0900)
committerJiyoun Park <jy0703.park@samsung.com>
Thu, 21 Dec 2017 11:53:42 +0000 (20:53 +0900)
when application compile shader, shader files are created at the end.
so if other proceess try creating shader before shader file is created,
it also try again compile shader.
so add lock to wait compiling shader

Change-Id: Id9da72f226e180cc18fcaaa65d639676ccfe9114

src/modules/evas/engines/gl_common/evas_gl_common.h
src/modules/evas/engines/gl_common/evas_gl_shader.c

index 4b2b16e..1ec1878 100755 (executable)
@@ -11,6 +11,7 @@
 #include <sys/time.h>
 #include <unistd.h>
 #include <Eet.h>
+#include <fcntl.h>
 
 #define GL_GLEXT_PROTOTYPES
 
@@ -238,6 +239,7 @@ struct _Evas_GL_Shared
    int offx, offy;
    GLfloat proj[16];
    Eina_Bool needs_shaders_flush : 1;
+   int lock_shader;
 };
 
 typedef enum _Shader_Sampling Shader_Sampling;
index 698e94a..d1bde35 100755 (executable)
@@ -414,6 +414,51 @@ _shaders_hash_free_cb(void *data)
    _program_del(data);
 }
 
+static void
+_shader_lock(Evas_GL_Shared *shared,const char *cache_dir)
+{
+   char lock_path[PATH_MAX];
+   snprintf(lock_path, sizeof(lock_path), "%s/shader_compile.lock", cache_dir);
+   shared->lock_shader = open(lock_path, O_RDWR | O_CREAT , S_IRUSR | S_IWUSR);
+   if(shared->lock_shader<0)
+     {
+        ERR("lock create is failed ");
+        return;
+     }
+
+   /* lock for wait creating shader*/
+   struct flock filelock;
+   filelock.l_type = F_WRLCK;
+   filelock.l_whence = SEEK_SET;
+   filelock.l_start = 0;
+   filelock.l_len = 0;
+   if (fcntl(shared->lock_shader, F_SETLKW, &filelock) == -1)
+     {
+        ERR("lock take fail");
+        return;
+     }
+}
+
+static void
+_shader_unlock(Evas_GL_Shared *shared)
+{
+   if(shared->lock_shader < 0) return;
+
+    /* reset lock */
+   struct flock filelock;
+   filelock.l_type = F_UNLCK;
+   filelock.l_whence = SEEK_SET;
+   filelock.l_start = 0;
+   filelock.l_len = 0;
+   if (fcntl(shared->lock_shader, F_SETLKW, &filelock) == -1)
+     {
+        ERR("lock release fail");
+     }
+
+   /* need to close lock file */
+   close(shared->lock_shader);
+}
+
 static char *
 evas_gl_common_shader_glsl_get(unsigned int flags, const char *base)
 {
@@ -644,31 +689,46 @@ evas_gl_common_shader_program_init(Evas_GL_Shared *shared)
    };
    Evas_GL_Program *p;
    unsigned i;
+   char bin_dir_path[PATH_MAX];
 
    shared->shaders_hash = eina_hash_int32_new(_shaders_hash_free_cb);
-   if (_evas_gl_common_shader_binary_init(shared))
+   if (!evas_gl_common_file_cache_dir_check(bin_dir_path, sizeof(bin_dir_path)))
+     evas_gl_common_file_cache_mkpath(bin_dir_path);
+
+   if(_evas_gl_common_shader_binary_init(shared))
+     goto Load;
+
+   //shader lock for wait other process
+   _shader_lock(shared,bin_dir_path);
+   if(_evas_gl_common_shader_binary_init(shared))
      {
-        for (i = 0; i < (sizeof(autoload) / sizeof(autoload[0])); i++)
-          {
-             p = _evas_gl_common_shader_program_binary_load(shared->shaders_cache, autoload[i]);
-             if (p)
-               {
-                  evas_gl_common_shader_textures_bind(p);
-                  eina_hash_add(shared->shaders_hash, &autoload[i], p);
-               }
-          }
+        _shader_unlock(shared);
+        goto Load;
      }
-   else
+
+   //precompile shader
+   evas_gl_common_shader_precompile_all(shared);
+   for (i = 0; i < (sizeof(autoload) / sizeof(autoload[0])); i++)
+     {
+        p = eina_hash_find(shared->shaders_hash, &autoload[i]);
+        if (p) p->delete_me = 0;
+     }
+   evas_gl_common_shaders_flush(shared);
+
+   //shader un-lock for wait other process
+   _shader_unlock(shared);
+   return 1;
+
+Load:
+   for (i = 0; i < (sizeof(autoload) / sizeof(autoload[0])); i++)
      {
-        evas_gl_common_shader_precompile_all(shared);
-        for (i = 0; i < (sizeof(autoload) / sizeof(autoload[0])); i++)
+        p = _evas_gl_common_shader_program_binary_load(shared->shaders_cache, autoload[i]);
+        if (p)
           {
-             p = eina_hash_find(shared->shaders_hash, &autoload[i]);
-             if (p) p->delete_me = 0;
+             evas_gl_common_shader_textures_bind(p);
+             eina_hash_add(shared->shaders_hash, &autoload[i], p);
           }
-        evas_gl_common_shaders_flush(shared);
      }
-
    return 1;
 }