Improvement: --glx-swap-method & --fade-exclude

- GLX backend: Add --glx-swap-method, to reduce painting region if the
  driver uses exchange or copy buffer swaps. Untested.

- Add --fade-exclude, to disable fading on specific windows based on
  some conditions. Untested.

- Expose GLX backend options through configuration file. Add fetching of
  GLX backend options through D-Bus.

- Use NULL pointer instead of element count to delimit string arrays in
  parse_vsync()/parse_backend()/parse_glx_swap_method().

- Add documentation about "wintypes" section in configuration file.
This commit is contained in:
Richard Grenville 2013-04-21 22:30:22 +08:00
parent a053c0ac64
commit 85e7d18803
6 changed files with 130 additions and 10 deletions

View File

@ -34,6 +34,7 @@ fading = true;
fade-in-step = 0.03;
fade-out-step = 0.03;
# no-fading-openclose = true;
fade-exclude = [ ];
# Other
backend = "xrender"
@ -53,6 +54,13 @@ detect-transient = true;
detect-client-leader = true;
invert-color-include = [ ];
# GLX backend
# glx-no-stencil = true;
glx-copy-from-front = false;
# glx-use-copysubbuffermesa = true;
# glx-no-rebind-pixmap = true;
glx-swap-method = "undefined";
# Window type settings
wintypes:
{

View File

@ -2,7 +2,7 @@ compton(1)
==========
:doctype: manpage
:man source: compton
:man version: nightly-20121105
:man version: nightly-20130421
:man manual: LOCAL USER COMMANDS
NAME
@ -154,6 +154,9 @@ OPTIONS
*--shadow-exclude* 'CONDITION'::
Specify a list of conditions of windows that should have no shadow.
*--fade-exclude* 'CONDITION'::
Specify a list of conditions of windows that should not be faded.
*--focus-exclude* 'CONDITION'::
Specify a list of conditions of windows that should always be considered focused.
@ -279,7 +282,18 @@ This is the old condition format we once used. Support of this format might be r
CONFIGURATION FILES
-------------------
compton could read from a configuration file if libconfig support is compiled in. If *--config* is not used, compton will seek for a configuration file in `$XDG_CONFIG_HOME/compton.conf` (`~/.config/compton.conf`, usually), then `~/.compton.conf`, then `compton.conf` under `$XDG_DATA_DIRS` (often `/etc/xdg/compton.conf`). Most commandline switches could be replaced with an option in configuration file, and some options are exposed only in configuration files (presently, some window-type-specific settings). compton uses general libconfig configurtion file format. A sample configuration file is available as `compton.sample.conf` in the source tree.
compton could read from a configuration file if libconfig support is compiled in. If *--config* is not used, compton will seek for a configuration file in `$XDG_CONFIG_HOME/compton.conf` (`~/.config/compton.conf`, usually), then `~/.compton.conf`, then `compton.conf` under `$XDG_DATA_DIRS` (often `/etc/xdg/compton.conf`).
compton uses general libconfig configurtion file format. A sample configuration file is available as `compton.sample.conf` in the source tree. Most commandline switches each could be replaced with an option in configuration file, thus documented above. Window-type-specific settings are exposed only in configuration file and has the following format:
------------
wintypes:
{
WINDOW_TYPE = { fade = BOOL; shadow = BOOL; opacity = FLOAT; focus = BOOL; };
};
------------
'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard: "unknown", "desktop", "dock", "toolbar", "menu", "utility", "splash", "dialog", "normal", "dropdown_menu", "popup_menu", "tooltip", "notify", "combo", and "dnd". "fade" and "shadow" controls window-type-specific shadow and fade settings. "opacity" controls default opacity of the window type. "focus" controls whether the window of this type is to be always considered focused. (By default, all window types except "normal" and "dialog" has this on.)
SIGNALS
-------

View File

@ -284,6 +284,14 @@ enum backend {
NUM_BKEND,
};
/// @brief Possible swap methods.
enum glx_swap_method {
SWAPM_UNDEFINED,
SWAPM_EXCHANGE,
SWAPM_COPY,
NUM_SWAPM,
};
typedef struct _glx_texture glx_texture_t;
#ifdef CONFIG_VSYNC_OPENGL
@ -374,6 +382,8 @@ typedef struct {
bool glx_use_copysubbuffermesa;
/// Whether to avoid rebinding pixmap on window damage.
bool glx_no_rebind_pixmap;
/// GLX swap method we assume OpenGL uses.
enum glx_swap_method glx_swap_method;
/// Whether to try to detect WM windows and mark them as focused.
bool mark_wmwin_focused;
/// Whether to mark override-redirect windows as focused.
@ -563,6 +573,8 @@ typedef struct {
struct timeval time_start;
/// The region needs to painted on next paint.
XserverRegion all_damage;
/// The region damaged on the last paint.
XserverRegion all_damage_last;
/// Whether all windows are currently redirected.
bool redirected;
/// Whether there's a highest full-screen window, and all windows could
@ -942,8 +954,9 @@ typedef enum {
} win_evmode_t;
extern const char * const WINTYPES[NUM_WINTYPES];
extern const char * const VSYNC_STRS[NUM_VSYNC];
extern const char * const BACKEND_STRS[NUM_BKEND];
extern const char * const VSYNC_STRS[NUM_VSYNC + 1];
extern const char * const BACKEND_STRS[NUM_BKEND + 1];
extern const char * const GLX_SWAP_METHODS_STRS[NUM_SWAPM + 1];
extern session_t *ps_g;
// == Debugging code ==
@ -1313,11 +1326,12 @@ normalize_d(double d) {
*/
static inline bool
parse_vsync(session_t *ps, const char *str) {
for (vsync_t i = 0; i < (sizeof(VSYNC_STRS) / sizeof(VSYNC_STRS[0])); ++i)
for (vsync_t i = 0; VSYNC_STRS[i]; ++i)
if (!strcasecmp(str, VSYNC_STRS[i])) {
ps->o.vsync = i;
return true;
}
printf_errf("(\"%s\"): Invalid vsync argument.", str);
return false;
}
@ -1327,7 +1341,7 @@ parse_vsync(session_t *ps, const char *str) {
*/
static inline bool
parse_backend(session_t *ps, const char *str) {
for (enum backend i = 0; i < (sizeof(BACKEND_STRS) / sizeof(BACKEND_STRS[0])); ++i)
for (enum backend i = 0; BACKEND_STRS[i]; ++i)
if (!strcasecmp(str, BACKEND_STRS[i])) {
ps->o.backend = i;
return true;
@ -1336,6 +1350,20 @@ parse_backend(session_t *ps, const char *str) {
return false;
}
/**
* Parse a glx_swap_method option argument.
*/
static inline bool
parse_glx_swap_method(session_t *ps, const char *str) {
for (enum glx_swap_method i = 0; GLX_SWAP_METHODS_STRS[i]; ++i)
if (!strcasecmp(str, GLX_SWAP_METHODS_STRS[i])) {
ps->o.glx_swap_method = i;
return true;
}
printf_errf("(\"%s\"): Invalid GLX swap method argument.", str);
return false;
}
timeout_t *
timeout_insert(session_t *ps, time_ms_t interval,
bool (*callback)(session_t *ps, timeout_t *ptmout), void *data);

View File

@ -32,19 +32,29 @@ const char * const WINTYPES[NUM_WINTYPES] = {
};
/// Names of VSync modes.
const char * const VSYNC_STRS[NUM_VSYNC] = {
const char * const VSYNC_STRS[NUM_VSYNC + 1] = {
"none", // VSYNC_NONE
"drm", // VSYNC_DRM
"opengl", // VSYNC_OPENGL
"opengl-oml", // VSYNC_OPENGL_OML
"opengl-swc", // VSYNC_OPENGL_SWC
"opengl-mswc", // VSYNC_OPENGL_MSWC
NULL
};
/// Names of backends.
const char * const BACKEND_STRS[NUM_BKEND] = {
const char * const BACKEND_STRS[NUM_BKEND + 1] = {
"xrender", // BKEND_XRENDER
"glx", // BKEND_GLX
NULL
};
/// Names of GLX swap methods.
const char * const GLX_SWAP_METHODS_STRS[NUM_SWAPM + 1] = {
"undefined", // SWAPM_UNDEFINED
"exchange", // SWAPM_EXCHANGE
"copy", // SWAPM_COPY
NULL
};
/// Function pointers to init VSync modes.
@ -2205,7 +2215,8 @@ calc_dim(session_t *ps, win *w) {
*/
static void
win_determine_fade(session_t *ps, win *w) {
if (ps->o.no_fading_openclose && w->in_openclose)
if ((ps->o.no_fading_openclose && w->in_openclose)
|| win_match(ps, w, ps->o.fade_blacklist, &w->cache_fblst))
w->fade = false;
else
w->fade = ps->o.wintype_fade[w->window_type];
@ -4129,6 +4140,8 @@ usage(void) {
" Try to detect WM windows and mark them as active.\n"
"--shadow-exclude condition\n"
" Exclude conditions for shadows.\n"
"--fade-exclude condition\n"
" Exclude conditions for fading.\n"
"--mark-ovredir-focused\n"
" Mark windows that have no WM frame as active.\n"
"--no-fading-openclose\n"
@ -4246,6 +4259,12 @@ usage(void) {
" GLX backend: Avoid rebinding pixmap on window damage. Probably\n"
" could improve performance on rapid window content changes, but is\n"
" known to break things on some drivers.\n"
"--glx-swap-method undefined/exchange/copy\n"
" GLX backend: GLX buffer swap method we assume. Could be\n"
" \"undefined\", \"exchange\", or \"copy\". \"undefined\" is the slowest\n"
" and the safest; \"exchange\" and \"copy\" are faster but may fail on\n"
" some drivers. Useless with --glx-use-copysubbuffermesa. Defaults to\n"
" \"undefined\".\n"
#undef WARNING
#ifndef CONFIG_DBUS
#define WARNING WARNING_DISABLED
@ -4631,6 +4650,8 @@ parse_config(session_t *ps, struct options_tmp *pcfgtmp) {
&ps->o.detect_client_leader);
// --shadow-exclude
parse_cfg_condlst(ps, &cfg, &ps->o.shadow_blacklist, "shadow-exclude");
// --fade-exclude
parse_cfg_condlst(ps, &cfg, &ps->o.fade_blacklist, "fade-exclude");
// --focus-exclude
parse_cfg_condlst(ps, &cfg, &ps->o.focus_blacklist, "focus-exclude");
// --invert-color-include
@ -4645,6 +4666,18 @@ parse_config(session_t *ps, struct options_tmp *pcfgtmp) {
// --blur-background-fixed
lcfg_lookup_bool(&cfg, "blur-background-fixed",
&ps->o.blur_background_fixed);
// --glx-no-stencil
lcfg_lookup_bool(&cfg, "glx-no-stencil", &ps->o.glx_no_stencil);
// --glx-copy-from-front
lcfg_lookup_bool(&cfg, "glx-copy-from-front", &ps->o.glx_copy_from_front);
// --glx-use-copysubbuffermesa
lcfg_lookup_bool(&cfg, "glx-use-copysubbuffermesa", &ps->o.glx_use_copysubbuffermesa);
// --glx-no-rebind-pixmap
lcfg_lookup_bool(&cfg, "glx-no-rebind-pixmap", &ps->o.glx_no_rebind_pixmap);
// --glx-swap-method
if (config_lookup_string(&cfg, "glx-swap-method", &sval)
&& !parse_glx_swap_method(ps, sval))
exit(1);
// Wintype settings
{
wintype_t i;
@ -4721,6 +4754,8 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
{ "blur-background-exclude", required_argument, NULL, 296 },
{ "active-opacity", required_argument, NULL, 297 },
{ "glx-no-rebind-pixmap", no_argument, NULL, 298 },
{ "glx-swap-method", required_argument, NULL, 299 },
{ "fade-exclude", required_argument, NULL, 300 },
// Must terminate with a NULL entry
{ NULL, 0, NULL, 0 },
};
@ -4935,6 +4970,15 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
ps->o.active_opacity = (normalize_d(atof(optarg)) * OPAQUE);
break;
P_CASEBOOL(298, glx_no_rebind_pixmap);
case 299:
// --glx-swap-method
if (!parse_glx_swap_method(ps, optarg))
exit(1);
break;
case 300:
// --fade-exclude
condlst_add(ps, &ps->o.fade_blacklist, optarg);
break;
default:
usage();
break;
@ -5842,6 +5886,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
.tmout_lst = NULL,
.all_damage = None,
.all_damage_last = None,
.time_start = { 0, 0 },
.redirected = false,
.unredir_possible = false,
@ -6285,6 +6330,7 @@ session_destroy(session_t *ps) {
free_root_tile(ps);
free_region(ps, &ps->screen_reg);
free_region(ps, &ps->all_damage);
free_region(ps, &ps->all_damage_last);
free(ps->expose_rects);
free(ps->shadow_corner);
free(ps->shadow_top);

View File

@ -909,6 +909,18 @@ cdbus_process_opts_get(session_t *ps, DBusMessage *msg) {
cdbus_m_opts_get_do(detect_transient, cdbus_reply_bool);
cdbus_m_opts_get_do(detect_client_leader, cdbus_reply_bool);
#ifdef CONFIG_VSYNC_OPENGL
cdbus_m_opts_get_do(glx_no_stencil, cdbus_reply_bool);
cdbus_m_opts_get_do(glx_copy_from_front, cdbus_reply_bool);
cdbus_m_opts_get_do(glx_use_copysubbuffermesa, cdbus_reply_bool);
cdbus_m_opts_get_do(glx_no_rebind_pixmap, cdbus_reply_bool);
if (!strcmp("glx_swap_method", target)) {
assert(ps->o.glx_swap_method < sizeof(GLX_SWAP_METHODS_STRS) / sizeof(GLX_SWAP_METHODS_STRS[0]));
cdbus_reply_string(ps, msg, GLX_SWAP_METHODS_STRS[ps->o.glx_swap_method]);
return true;
}
#endif
cdbus_m_opts_get_do(track_focus, cdbus_reply_bool);
cdbus_m_opts_get_do(track_wdata, cdbus_reply_bool);
cdbus_m_opts_get_do(track_leader, cdbus_reply_bool);

View File

@ -545,10 +545,20 @@ glx_paint_pre(session_t *ps, XserverRegion *preg) {
ps->glx_z = 0.0;
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Exchange swap is interested in the raw damaged region only
XserverRegion all_damage_last = ps->all_damage_last;
ps->all_damage_last = None;
if (SWAPM_EXCHANGE == ps->o.glx_swap_method && *preg)
ps->all_damage_last = copy_region(ps, *preg);
// OpenGL doesn't support partial repaint without GLX_MESA_copy_sub_buffer,
// we could redraw the whole screen or copy unmodified pixels from
// front buffer with --glx-copy-from-front.
if (ps->o.glx_use_copysubbuffermesa || !*preg) {
if (ps->o.glx_use_copysubbuffermesa || SWAPM_COPY == ps->o.glx_swap_method
|| !*preg) {
}
else if (SWAPM_EXCHANGE == ps->o.glx_swap_method && all_damage_last) {
XFixesUnionRegion(ps->dpy, *preg, *preg, all_damage_last);
}
else if (!ps->o.glx_copy_from_front) {
free_region(ps, preg);
@ -572,6 +582,8 @@ glx_paint_pre(session_t *ps, XserverRegion *preg) {
}
}
free_region(ps, &all_damage_last);
glx_set_clip(ps, *preg, NULL);
}