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
This commit is contained in:
Jean-Philippe Andre 2016-06-23 11:06:22 +09:00
parent 750d3541c1
commit 17c531658f
5 changed files with 203 additions and 81 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;