From 17c531658fa04a90e52e2dc32d42ce491988d04c Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Thu, 23 Jun 2016 11:06:22 +0900 Subject: [PATCH] win: Add property accel_preference It supports the same syntax as the config value, but overrides it. This provides a more convenient way to select the acceleration for a single window. Its get() value should be what was effective when the window was created. So it can depend on the config or a previous call to set(). @feature --- src/bin/elementary/test_glview.c | 9 +- src/lib/elementary/efl_ui_win.c | 70 +++++++++++---- src/lib/elementary/efl_ui_win.eo | 53 +++++++++++ src/lib/elementary/elm_config.c | 150 +++++++++++++++++-------------- src/lib/elementary/elm_priv.h | 2 + 5 files changed, 203 insertions(+), 81 deletions(-) diff --git a/src/bin/elementary/test_glview.c b/src/bin/elementary/test_glview.c index 31c76cffe3..3136770ae8 100644 --- a/src/bin/elementary/test_glview.c +++ b/src/bin/elementary/test_glview.c @@ -617,13 +617,14 @@ test_glview(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in Evas_Object *win, *bx, *bt, *gl, *lb; Ecore_Animator *ani; GLData *gld = NULL; - const char *accel; // alloc a data struct to hold our relevant gl info in if (!(gld = calloc(1, sizeof(GLData)))) return; gldata_init(gld); +#if 0 // add a Z-depth buffer to the window and try to use GL + Eina_Stringshare *accel; accel = eina_stringshare_add(elm_config_accel_preference_get()); elm_config_accel_preference_set("gl:depth"); @@ -634,6 +635,12 @@ test_glview(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_in // restore previous accel preference elm_config_accel_preference_set(accel); eina_stringshare_del(accel); +#else + win = eo_add(EFL_UI_WIN_STANDARD_CLASS, NULL, + efl_ui_win_name_set(eo_self, "glview"), + efl_text_set(eo_self, "GLView"), + efl_ui_win_accel_preference_set(eo_self, "gl:depth")); +#endif bx = elm_box_add(win); evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); diff --git a/src/lib/elementary/efl_ui_win.c b/src/lib/elementary/efl_ui_win.c index 26876e4d15..da31c73634 100644 --- a/src/lib/elementary/efl_ui_win.c +++ b/src/lib/elementary/efl_ui_win.c @@ -188,6 +188,7 @@ struct _Efl_Ui_Win_Data const char *icon_name; const char *role; Eina_Stringshare *name; + Eina_Stringshare *accel_pref; Evas_Object *main_menu; @@ -2538,6 +2539,7 @@ _efl_ui_win_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Win_Data *sd) eina_stringshare_del(sd->icon_name); eina_stringshare_del(sd->role); eina_stringshare_del(sd->name); + eina_stringshare_del(sd->accel_pref); evas_object_del(sd->icon); evas_object_del(sd->main_menu); @@ -3920,13 +3922,19 @@ _window_layout_stack(Evas_Object *o, Evas_Object_Box_Data *p, void *data) } static Eina_Bool -_accel_is_gl(void) +_accel_is_gl(const char *accel) { const char *env = NULL; const char *str = NULL; + /* current elm config */ if (_elm_config->accel) str = _elm_config->accel; if (_elm_accel_preference) str = _elm_accel_preference; + + /* constructor function */ + if (accel) str = accel; + + /* global overrides */ if ((_elm_config->accel_override) && (_elm_config->accel)) str = _elm_config->accel; env = getenv("ELM_ACCEL"); @@ -3952,6 +3960,10 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W Evas *e; const Eina_List *l; const char *fontpath, *engine = NULL, *enginelist[32], *disp; + int gl_depth = _elm_config->gl_depth; + int gl_stencil = _elm_config->gl_stencil; + int gl_msaa = _elm_config->gl_msaa; + Eina_Stringshare *accel = NULL; int i, p = 0; Efl_Ui_Win_Data tmp_sd; @@ -3961,6 +3973,12 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W /* just to store some data while trying out to create a canvas */ memset(&tmp_sd, 0, sizeof(Efl_Ui_Win_Data)); + if (sd->accel_pref) + { + _elm_config_accel_preference_parse(sd->accel_pref, &accel, &gl_depth, + &gl_stencil, &gl_msaa); + } + switch (type) { case ELM_WIN_FAKE: @@ -4011,7 +4029,7 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W #ifdef HAVE_ELEMENTARY_X else if ((disp) && (!strcmp(disp, "x11"))) { - if (_accel_is_gl()) + if (_accel_is_gl(accel)) { enginelist[p++] = ELM_OPENGL_X11; enginelist[p++] = ELM_SOFTWARE_X11; @@ -4027,7 +4045,7 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W #ifdef HAVE_ELEMENTARY_WL2 else if ((disp) && (!strcmp(disp, "wl"))) { - if (_accel_is_gl()) + if (_accel_is_gl(accel)) { enginelist[p++] = ELM_WAYLAND_EGL; enginelist[p++] = ELM_WAYLAND_SHM; @@ -4051,7 +4069,7 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W #ifdef HAVE_ELEMENTARY_SDL else if ((disp) && (!strcmp(disp, "sdl"))) { - if (_accel_is_gl()) + if (_accel_is_gl(accel)) { enginelist[p++] = ELM_OPENGL_SDL; enginelist[p++] = ELM_SOFTWARE_SDL; @@ -4093,7 +4111,7 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W else if (!_elm_preferred_engine && getenv("DISPLAY") && !getenv("ELM_ENGINE")) { - if (_accel_is_gl()) + if (_accel_is_gl(accel)) { enginelist[p++] = ELM_OPENGL_X11; enginelist[p++] = ELM_SOFTWARE_X11; @@ -4109,7 +4127,7 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W else if (!_elm_preferred_engine && getenv("WAYLAND_DISPLAY") && !getenv("ELM_ENGINE")) { - if (_accel_is_gl()) + if (_accel_is_gl(accel)) { enginelist[p++] = ELM_WAYLAND_EGL; enginelist[p++] = ELM_WAYLAND_SHM; @@ -4123,7 +4141,7 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W #endif else { - if (_accel_is_gl()) + if (_accel_is_gl(accel)) { // add all engines with selected engine first - if any if (ENGINE_GET()) @@ -4172,8 +4190,9 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W enginelist[p++] = elm_config_preferred_engine_get(); // add check _elm_gl_preference whether "none" or not else if (_elm_config->engine && - elm_config_accel_preference_get() && - !strcmp(elm_config_accel_preference_get(),"none")) + ((elm_config_accel_preference_get() && + !strcmp(elm_config_accel_preference_get(), "none")) + || (accel && !strcmp(accel, "none")))) enginelist[p++] = _elm_config->engine; // add all engines with gl/accelerated ones first - only engines compiled #ifdef HAVE_ELEMENTARY_X @@ -4230,20 +4249,20 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W opt[opt_i++] = ECORE_EVAS_GL_X11_OPT_VSYNC; opt[opt_i++] = 1; } - if (_elm_config->gl_depth) + if (gl_depth) { opt[opt_i++] = ECORE_EVAS_GL_X11_OPT_GL_DEPTH; - opt[opt_i++] = _elm_config->gl_depth; + opt[opt_i++] = gl_depth; } - if (_elm_config->gl_stencil) + if (gl_stencil) { opt[opt_i++] = ECORE_EVAS_GL_X11_OPT_GL_STENCIL; - opt[opt_i++] = _elm_config->gl_stencil; + opt[opt_i++] = gl_stencil; } - if (_elm_config->gl_msaa) + if (gl_msaa) { opt[opt_i++] = ECORE_EVAS_GL_X11_OPT_GL_MSAA; - opt[opt_i++] = _elm_config->gl_msaa; + opt[opt_i++] = gl_msaa; } opt[opt_i] = 0; if (opt_i > 0) @@ -4287,12 +4306,16 @@ _elm_win_finalize_internal(Eo *obj, Efl_Ui_Win_Data *sd, const char *name, Elm_W break; } + eina_stringshare_del(accel); if (!tmp_sd.ee) { ERR("Cannot create window."); return NULL; } + if (!sd->accel_pref) + eina_stringshare_replace(&sd->accel_pref, elm_config_accel_preference_get()); + eo_parent_set(obj, ecore_evas_get(tmp_sd.ee)); eo_constructor(eo_super(obj, MY_CLASS)); @@ -4632,6 +4655,23 @@ _efl_ui_win_name_get(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *sd) return sd->name; } +EOLIAN static void +_efl_ui_win_accel_preference_set(Eo *obj, Efl_Ui_Win_Data *pd, const char *accel) +{ + if (eo_finalized_get(obj)) + { + ERR("This function is only allowed during construction."); + return; + } + eina_stringshare_replace(&pd->accel_pref, accel); +} + +EOLIAN static const char * +_efl_ui_win_accel_preference_get(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *pd) +{ + return pd->accel_pref; +} + EOLIAN static void _efl_ui_win_noblank_set(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *pd, Eina_Bool noblank) { diff --git a/src/lib/elementary/efl_ui_win.eo b/src/lib/elementary/efl_ui_win.eo index a2140edf7a..b17add4805 100644 --- a/src/lib/elementary/efl_ui_win.eo +++ b/src/lib/elementary/efl_ui_win.eo @@ -599,6 +599,58 @@ class Efl.Ui.Win (Elm.Widget, Efl.Canvas, Elm.Interface.Atspi.Window, type: Efl.Ui.Win.Type(Efl.Ui.Win.Type.unknown); } } + @property accel_preference { + [[The hardware acceleration preference for this window. + + This is a constructor function, and can only be called before + @Eo.Base.finalize. + + This property overrides the global EFL configuration option + "accel_preference" for this single window, and accepts the same + syntax. + + The $accel string is a freeform C string that indicates + what kind of acceleration is preferred. Here "acceleration" majorly + means to rendering and which hardware unit application renders GUIs + with. This may or may not be honored, but a best attempt will + be made. Known strings are as follows: + + "gl", "opengl" - try use OpenGL. + "3d" - try and use a 3d acceleration unit. + "hw", "hardware", "accel" - try any acceleration unit (best possible) + "none" - use no acceleration. try use software (since 1.16) + + Since 1.14, it is also possible to specify some GL properties for the GL + window surface. This allows applications to use GLView with depth, stencil + and MSAA buffers with direct rendering. The new accel preference string + format is thus "{HW Accel}[:depth{value}[:stencil{value}[:msaa{str}$]$]$]". + + Accepted values for depth are for instance "depth", "depth16", "depth24". + Accepted values for stencil are "stencil", "stencil1", "stencil8". + For MSAA, only predefined strings are accepted: "msaa", "msaa_low", + "msaa_mid" and "msaa_high". The selected configuration is not guaranteed + and is only valid in case of GL acceleration. Only the base acceleration + string will be saved (e.g. "gl" or "hw"). + + Full examples include: + + "gl", - try to use OpenGL + "hw:depth:stencil", - use HW acceleration with default depth and stencil buffers + "opengl:depth24:stencil8:msaa_mid" - use OpenGL with 24-bit depth, + 8-bit stencil and a medium number of MSAA samples in the backbuffer. + + Note that this option may be overriden by environment variables + or the configuration option "accel_preference_override". + ]] + values { + accel: string; + } + set {} + get { + [[This will return the value of "accel_preference" when the window + was created.]] + } + } @property available_profiles { set { [[Set the array of available profiles to a window. @@ -814,6 +866,7 @@ class Efl.Ui.Win (Elm.Widget, Efl.Canvas, Elm.Interface.Atspi.Window, constructors { .name; .type; + .accel_preference; } events { delete,request; diff --git a/src/lib/elementary/elm_config.c b/src/lib/elementary/elm_config.c index 00a4722de4..7dcd06b22b 100644 --- a/src/lib/elementary/elm_config.c +++ b/src/lib/elementary/elm_config.c @@ -4039,85 +4039,105 @@ elm_config_accel_preference_get(void) return _elm_config->accel; } +Eina_Bool +_elm_config_accel_preference_parse(const char *pref, Eina_Stringshare **accel, + int *gl_depth, int *gl_stencil, int *gl_msaa) +{ + Eina_Bool is_hw_accel = EINA_FALSE; + unsigned int tokens = 0, i; + char **arr; + + /* Accel preference's string has the window surface configuration as a hw accel, depth, stencil and msaa. + * The string format is "{HW Accel}:depth{value}:stencil{value}:msaa{msaa string}" + * Especially, msaa string is related Evas GL MSAA enum value(low, mid, high) + * so msaa string has four types as msaa, msaa_low, msaa_mid, msaa_high + * For instance, "opengl:depth24:stencil8:msaa_high". + * It means that using hw accelation, window surface depth buffer's size is 24, stencil buffer's size 8 and msaa bits is the highest. + * The other use-case is "opengl:depth24". + * It measn that using hw accelation, depth buffer size is 24. stencil and msaa are not used. + * The simple case is "opengl:depth:stencil:msaa". + * It means that depth, stencil and msaa are setted by pre-defined value(depth:24, stencil:8, msaa:low) + */ + + DBG("accel preference's string: %s", pref); + + /* split GL items (hw accel, gl depth, gl stencil, gl msaa */ + arr = eina_str_split_full(pref, ":", 0, &tokens); + for (i = 0; arr && arr[i]; i++) + { + if ((!strcasecmp(arr[i], "gl")) || + (!strcasecmp(arr[i], "opengl")) || + (!strcasecmp(arr[i], "3d")) || + (!strcasecmp(arr[i], "hw")) || + (!strcasecmp(arr[i], "accel")) || + (!strcasecmp(arr[i], "hardware")) + ) + { + eina_stringshare_replace(accel, arr[i]); + is_hw_accel = EINA_TRUE; + *gl_depth = 0; + *gl_stencil = 0; + *gl_msaa = 0; + } + else if (!strncmp(arr[i], "depth", 5)) + { + char *value_str = arr[i] + 5; + if ((value_str) && (isdigit(*value_str))) + *gl_depth = atoi(value_str); + else + *gl_depth = 24; + } + else if (!strncmp(arr[i], "stencil", 7)) + { + char *value_str = arr[i] + 7; + if ((value_str) && (isdigit(*value_str))) + *gl_stencil = atoi(value_str); + else + *gl_stencil = 8; + } + else if (!strncmp(arr[i], "msaa_low", 8)) + *gl_msaa = 1; // 1 means msaa low + else if (!strncmp(arr[i], "msaa_mid", 8)) + *gl_msaa = 2; // 2 means msaa mid + else if (!strncmp(arr[i], "msaa_high", 9)) + *gl_msaa = 4; // 4 means msaa high + else if (!strncmp(arr[i], "msaa", 4)) + *gl_msaa = 1; // 1 means msaa low + } + + DBG("accel: %s", *accel); + DBG("gl depth: %d", *gl_depth); + DBG("gl stencil: %d", *gl_stencil); + DBG("gl msaa: %d", *gl_msaa); + free(arr[0]); + free(arr); + + return is_hw_accel; +} + EAPI void elm_config_accel_preference_set(const char *pref) { if (pref) { - Eina_Bool is_hw_accel = EINA_FALSE; - unsigned int tokens = 0, i; - char **arr; + Eina_Bool hw; - /* Accel preference's string has the window surface configuration as a hw accel, depth, stencil and msaa. - * The string format is "{HW Accel}:depth{value}:stencil{value}:msaa{msaa string}" - * Especially, msaa string is related Evas GL MSAA enum value(low, mid, high) - * so msaa string has four types as msaa, msaa_low, msaa_mid, msaa_high - * For instance, "opengl:depth24:stencil8:msaa_high". - * It means that using hw accelation, window surface depth buffer's size is 24, stencil buffer's size 8 and msaa bits is the highest. - * The other use-case is "opengl:depth24". - * It measn that using hw accelation, depth buffer size is 24. stencil and msaa are not used. - * The simple case is "opengl:depth:stencil:msaa". - * It means that depth, stencil and msaa are setted by pre-defined value(depth:24, stencil:8, msaa:low) - */ - - DBG("accel preference's string: %s",pref); /* full string */ eina_stringshare_replace(&(_elm_gl_preference), pref); ELM_SAFE_FREE(_elm_accel_preference, eina_stringshare_del); ELM_SAFE_FREE(_elm_config->accel, eina_stringshare_del); - /* split GL items (hw accel, gl depth, gl stencil, gl msaa */ - arr = eina_str_split_full(pref, ":", 0, &tokens); - for (i = 0; arr && arr[i]; i++) + hw = _elm_config_accel_preference_parse(pref, &_elm_config->accel, + &_elm_config->gl_depth, + &_elm_config->gl_stencil, + &_elm_config->gl_msaa); + + if (hw) { - if ((!strcasecmp(arr[i], "gl")) || - (!strcasecmp(arr[i], "opengl")) || - (!strcasecmp(arr[i], "3d")) || - (!strcasecmp(arr[i], "hw")) || - (!strcasecmp(arr[i], "accel")) || - (!strcasecmp(arr[i], "hardware")) - ) - { - eina_stringshare_replace(&(_elm_accel_preference), arr[i]); - eina_stringshare_replace(&(_elm_config->accel), arr[i]); - is_hw_accel = EINA_TRUE; - } - else if (!strncmp(arr[i], "depth", 5)) - { - char *value_str = arr[i] + 5; - if ((value_str) && (isdigit(*value_str))) - _elm_config->gl_depth = atoi(value_str); - else - _elm_config->gl_depth = 24; - } - else if (!strncmp(arr[i], "stencil", 7)) - { - char *value_str = arr[i] + 7; - if ((value_str) && (isdigit(*value_str))) - _elm_config->gl_stencil = atoi(value_str); - else - _elm_config->gl_stencil = 8; - } - else if (!strncmp(arr[i], "msaa_low", 8)) - _elm_config->gl_msaa = 1; // 1 means msaa low - else if (!strncmp(arr[i], "msaa_mid", 8)) - _elm_config->gl_msaa = 2; // 2 means msaa mid - else if (!strncmp(arr[i], "msaa_high", 9)) - _elm_config->gl_msaa = 4; // 4 means msaa high - else if (!strncmp(arr[i], "msaa", 4)) - _elm_config->gl_msaa = 1; // 1 means msaa low + eina_stringshare_replace(&(_elm_accel_preference), _elm_config->accel); } - - DBG("accel: %s", _elm_accel_preference); - DBG("gl depth: %d", _elm_config->gl_depth); - DBG("gl stencil: %d", _elm_config->gl_stencil); - DBG("gl msaa: %d", _elm_config->gl_msaa); - free(arr[0]); - free(arr); - - if (is_hw_accel == EINA_FALSE) + else { - ELM_SAFE_FREE(_elm_accel_preference, eina_stringshare_del); ELM_SAFE_FREE(_elm_config->accel, eina_stringshare_del); } } diff --git a/src/lib/elementary/elm_priv.h b/src/lib/elementary/elm_priv.h index 4ba5917efc..ff33e4de99 100644 --- a/src/lib/elementary/elm_priv.h +++ b/src/lib/elementary/elm_priv.h @@ -563,6 +563,8 @@ Elm_Url *_elm_url_download(const char *url, Elm_Url_Done done_cb, Elm_Url_Cancel void _elm_url_cancel(Elm_Url *r); const char *_elm_url_get(Elm_Url *r); +Eina_Bool _elm_config_accel_preference_parse(const char *pref, Eina_Stringshare **accel, int *gl_depth, int *gl_stencil, int *gl_msaa); + extern char *_elm_appname; extern Elm_Config *_elm_config; extern const char *_elm_data_dir;