Pulled out evas gl backend binary shader file caching code from

evas_gl_shader.c file and made an internal generic caching api in 
evas_gl_common.h for use in other places ie. evas_gl.

Then implemented evas_gl surface cap. caching code in gl backend to
accelerate the engine creation. 



SVN revision: 82321
This commit is contained in:
Sung Park 2013-01-07 06:16:18 +00:00
parent fb1225caa7
commit edcb4cf295
6 changed files with 326 additions and 148 deletions

View File

@ -1,3 +1,12 @@
2013-01-07 Sung W. Park (sung_)
* Pulled out evas gl backend binary shader file caching code from
evas_gl_shader.c file and made an internal generic caching api in
evas_gl_common.h for use in evas_gl code.
* Implemented evas_gl surface cap. caching code in gl backend to
accelerate the engine creation.
2013-01-07 Thomas Petazzoni
* Fix build of Evas XCB backend.

View File

@ -448,6 +448,7 @@ GL_COMMON_SOURCES = \
modules/evas/engines/gl_common/evas_gl_private.h \
modules/evas/engines/gl_common/evas_gl_common.h \
modules/evas/engines/gl_common/evas_gl_context.c \
modules/evas/engines/gl_common/evas_gl_file_cache.c \
modules/evas/engines/gl_common/evas_gl_shader.c \
modules/evas/engines/gl_common/evas_gl_rectangle.c \
modules/evas/engines/gl_common/evas_gl_texture.c \

View File

@ -555,6 +555,15 @@ 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);
Eina_Bool evas_gl_common_file_cache_is_dir(const char *file);
Eina_Bool evas_gl_common_file_cache_mkdir(const char *dir);
Eina_Bool evas_gl_common_file_cache_file_exists(const char *file);
Eina_Bool evas_gl_common_file_cache_mkpath_if_not_exists(const char *path);
Eina_Bool evas_gl_common_file_cache_mkpath(const char *path);
int evas_gl_common_file_cache_dir_check(char *cache_dir, int num);
int evas_gl_common_file_cache_file_check(const char *cache_dir, const char *cache_name, char *cache_file, int dir_num);
int evas_gl_common_file_cache_save(Evas_GL_Shared *shared);
void evas_gl_common_rect_draw(Evas_Engine_GL_Context *gc, int x, int y, int w, int h);
void evas_gl_texture_pool_empty(Evas_GL_Texture_Pool *pt);

View File

@ -586,6 +586,156 @@ _surface_cap_check(EVGL_Engine *ee)
return num_fmts;
}
static int
_surface_cap_load(EVGL_Engine *ee, Eet_File *ef)
{
int res = 0, i = 0, length = 0;
char tag[80];
void *data = 0;
data = eet_read(ef, "num_fbo_fmts", &length);
if ((!data) || (length <= 0)) goto finish;
ee->caps.num_fbo_fmts = atoi(data);
free(data);
data = 0;
// !!!FIXME
// Should use eet functionality instead of just reading using sscanfs...
for (i = 0; i < ee->caps.num_fbo_fmts; ++i)
{
EVGL_Surface_Format *fmt = &ee->caps.fbo_fmts[i];
snprintf(tag, sizeof(tag), "fbo_%d", i);
data = eet_read(ef, tag, &length);
if ((!data) || (length <= 0)) goto finish;
sscanf(data, "%d%d%d%d%d%d%d%d%d%d",
&(fmt->index),
(int*)(&(fmt->color_bit)), &(fmt->color_ifmt), &(fmt->color_fmt),
(int*)(&(fmt->depth_bit)), &(fmt->depth_fmt),
(int*)(&(fmt->stencil_bit)), &(fmt->stencil_fmt),
&(fmt->depth_stencil_fmt),
&(fmt->samples));
free(data);
data = 0;
}
res = 1;
goto finish;
finish:
if (data) free(data);
return res;
}
static int
_surface_cap_save(EVGL_Engine *ee, Eet_File *ef)
{
int i = 0;
char tag[80], data[80];;
snprintf(data, sizeof(data), "%d", ee->caps.num_fbo_fmts);
if (eet_write(ef, "num_fbo_fmts", data, sizeof(data), 1) < 0)
return 0;
// !!!FIXME
// Should use eet functionality instead of just writing out using snprintfs...
for (i = 0; i < ee->caps.num_fbo_fmts; ++i)
{
EVGL_Surface_Format *fmt = &ee->caps.fbo_fmts[i];
snprintf(tag, sizeof(tag), "fbo_%d", i);
snprintf(data, sizeof(data), "%d %d %d %d %d %d %d %d %d %d",
fmt->index,
fmt->color_bit, fmt->color_ifmt, fmt->color_fmt,
fmt->depth_bit, fmt->depth_fmt,
fmt->stencil_bit, fmt->stencil_fmt,
fmt->depth_stencil_fmt,
fmt->samples);
if (eet_write(ef, tag, data, sizeof(data), 1) < 0) return 0;
}
return 1;
}
static int
_surface_cap_cache_load(EVGL_Engine *ee)
{
/* check eet */
Eet_File *et = NULL;
char cap_dir_path[PATH_MAX];
char cap_file_path[PATH_MAX];
if (!evas_gl_common_file_cache_dir_check(cap_dir_path, sizeof(cap_dir_path)))
return 0;
if (!evas_gl_common_file_cache_file_check(cap_dir_path, "surface_cap",
cap_file_path, sizeof(cap_dir_path)))
return 0;
/* use eet */
if (!eet_init()) return 0;
et = eet_open(cap_file_path, EET_FILE_MODE_READ);
if (!et) goto error;
if (!_surface_cap_load(ee, et))
goto error;
if (et) eet_close(et);
eet_shutdown();
return 1;
error:
if (et) eet_close(et);
eet_shutdown();
return 0;
}
static int
_surface_cap_cache_save(EVGL_Engine *ee)
{
/* check eet */
Eet_File *et = NULL; //check eet file
int tmpfd;
int res = 0;
char cap_dir_path[PATH_MAX];
char cap_file_path[PATH_MAX];
char tmp_file[PATH_MAX];
if (!evas_gl_common_file_cache_dir_check(cap_dir_path, sizeof(cap_dir_path)))
{
res = evas_gl_common_file_cache_mkpath(cap_dir_path);
if (!res) return 0; /* we can't make directory */
}
evas_gl_common_file_cache_file_check(cap_dir_path, "surface_cap", cap_file_path,
sizeof(cap_dir_path));
/* use mkstemp for writing */
snprintf(tmp_file, sizeof(tmp_file), "%s.XXXXXX", cap_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 (!_surface_cap_save(ee, et)) goto error;
if (eet_close(et) != EET_ERROR_NONE) goto error;
if (rename(tmp_file,cap_file_path) < 0) goto error;
eet_shutdown();
return 1;
error:
if (et) eet_close(et);
if (evas_gl_common_file_cache_file_exists(tmp_file)) unlink(tmp_file);
eet_shutdown();
return 0;
}
static int
_surface_cap_init(EVGL_Engine *ee)
{
@ -623,16 +773,23 @@ _surface_cap_init(EVGL_Engine *ee)
}
#endif
int num_fmts = 0;
// Check Surface Cap
num_fmts = _surface_cap_check(ee);
if (num_fmts)
// Load Surface Cap
if (!_surface_cap_cache_load(ee))
{
// Check Surface Cap
ee->caps.num_fbo_fmts = _surface_cap_check(ee);
_surface_cap_cache_save(ee);
DBG("Ran Evas GL Surface Cap and Cached the existing values.");
}
else
{
DBG("Loaded cached Evas GL Surface Cap values.");
}
if (ee->caps.num_fbo_fmts)
{
ee->caps.num_fbo_fmts = num_fmts;
_surface_cap_print(ee, 0);
DBG("Number of supported surface formats: %d", num_fmts);
DBG("Number of supported surface formats: %d", ee->caps.num_fbo_fmts);
return 1;
}
else

View File

@ -0,0 +1,113 @@
#include "evas_gl_private.h"
static mode_t default_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
Eina_Bool
evas_gl_common_file_cache_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;
}
Eina_Bool
evas_gl_common_file_cache_mkdir(const char *dir)
{
/* evas gl only call this function when the dir is not exist */
if (mkdir(dir, default_mode) < 0) return EINA_FALSE;
return EINA_TRUE;
}
Eina_Bool
evas_gl_common_file_cache_file_exists(const char *file)
{
struct stat st;
if (!file) return EINA_FALSE;
if (stat(file, &st) < 0) return EINA_FALSE;
return EINA_TRUE;
}
Eina_Bool
evas_gl_common_file_cache_mkpath_if_not_exists(const char *path)
{
struct stat st;
if (stat(path, &st) < 0)
return evas_gl_common_file_cache_mkdir(path);
else if (!S_ISDIR(st.st_mode))
return EINA_FALSE;
else
return EINA_TRUE;
}
Eina_Bool
evas_gl_common_file_cache_mkpath(const char *path)
{
char ss[PATH_MAX];
unsigned int i;
if (evas_gl_common_file_cache_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_common_file_cache_mkpath_if_not_exists(ss))
return EINA_FALSE;
}
}
ss[i] = 0;
return evas_gl_common_file_cache_mkpath_if_not_exists(ss);
}
int
evas_gl_common_file_cache_dir_check(char *cache_dir, int num)
{
char *home = NULL;
char *subdir = ".cache/evas_gl_common_caches";
home = getenv("HOME");
if ((!home) || (!home[0])) return 0;
snprintf(cache_dir, num, "%s/%s", home, subdir);
return evas_gl_common_file_cache_file_exists(cache_dir);
}
int
evas_gl_common_file_cache_file_check(const char *cache_dir, const char *cache_name, char *cache_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::%s.eet", vendor, version, driver, MODULE_ARCH, cache_name);
/* 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(cache_file, dir_num, "%s/%s", cache_dir, after_name);
return evas_gl_common_file_cache_file_exists(cache_file);
}

View File

@ -321,117 +321,6 @@ gl_compile_link_error(GLuint target, const char *action)
}
}
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,
@ -667,10 +556,10 @@ _evas_gl_common_shader_binary_init(Evas_GL_Shared *shared)
char bin_file_path[PATH_MAX];
unsigned int i;
if (!_evas_gl_shader_dir_check(bin_dir_path, sizeof(bin_dir_path)))
if (!evas_gl_common_file_cache_dir_check(bin_dir_path, sizeof(bin_dir_path)))
return 0;
if (!_evas_gl_shader_file_check(bin_dir_path, bin_file_path,
if (!evas_gl_common_file_cache_file_check(bin_dir_path, "binary_shader", bin_file_path,
sizeof(bin_dir_path)))
return 0;
@ -707,13 +596,13 @@ _evas_gl_common_shader_binary_save(Evas_GL_Shared *shared)
char tmp_file[PATH_MAX];
unsigned int i;
if (!_evas_gl_shader_dir_check(bin_dir_path, sizeof(bin_dir_path)))
if (!evas_gl_common_file_cache_dir_check(bin_dir_path, sizeof(bin_dir_path)))
{
res = _evas_gl_shader_file_mkpath(bin_dir_path);
res = evas_gl_common_file_cache_mkpath(bin_dir_path);
if (!res) return 0; /* we can't make directory */
}
_evas_gl_shader_file_check(bin_dir_path, bin_file_path,
evas_gl_common_file_cache_file_check(bin_dir_path, "binary_shader", bin_file_path,
sizeof(bin_dir_path));
/* use mkstemp for writing */
@ -741,7 +630,7 @@ _evas_gl_common_shader_binary_save(Evas_GL_Shared *shared)
error:
if (et) eet_close(et);
if (_evas_gl_shader_file_exists(tmp_file)) unlink(tmp_file);
if (evas_gl_common_file_cache_file_exists(tmp_file)) unlink(tmp_file);
eet_shutdown();
return 0;
}