Skip to content

Commit

Permalink
Improvement: --glx-swap-method & --fade-exclude
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
richardgv committed Apr 21, 2013
1 parent a053c0a commit 85e7d18
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 10 deletions.
8 changes: 8 additions & 0 deletions compton.sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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:
{
Expand Down
18 changes: 16 additions & 2 deletions man/compton.1.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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
-------
Expand Down
36 changes: 32 additions & 4 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 ==
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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);
Expand Down
52 changes: 49 additions & 3 deletions src/compton.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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 },
};
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 12 additions & 0 deletions src/dbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
14 changes: 13 additions & 1 deletion src/opengl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -572,6 +582,8 @@ glx_paint_pre(session_t *ps, XserverRegion *preg) {
}
}

free_region(ps, &all_damage_last);

glx_set_clip(ps, *preg, NULL);
}

Expand Down

0 comments on commit 85e7d18

Please sign in to comment.