summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Grenville <pyxlcy@gmail.com>2013-01-31 22:53:44 +0800
committerRichard Grenville <pyxlcy@gmail.com>2013-01-31 22:56:54 +0800
commitd1fb8649a4e5d2ec165bd4226d53703043678eb2 (patch)
tree79baf4b2e997aca97a748fc6e468a6e50e7773c6
parent646390149399214ca725b93328e04e71361caa02 (diff)
downloadtdebase-d1fb8649a4e5d2ec165bd4226d53703043678eb2.tar.gz
tdebase-d1fb8649a4e5d2ec165bd4226d53703043678eb2.zip
Improvement: Change VSync mode with D-Bus & Makefile update & Misc
- Add on-the-fly VSync option modification via D-Bus, as requested by kunitoki (#80). Expose parse_vsync(), create vsync_init() and ensure_glx_context(). - Change default value of ps->drm_fd to -1. - Update Makefile. Change the install/uninstall rules and add doc installation, requested by hasufell in #85. - Mark window not damaged in map_win(). It helps in reducing flickering with inverted window color, but I'm not completely sure if it's safe. - Avoid modifying w->invert_color when window is unmapped. - Update documentation. Thanks to hasufell for pointing out.
-rw-r--r--common.h17
-rw-r--r--compton.c120
-rw-r--r--compton.h33
-rw-r--r--dbus.c19
-rw-r--r--dbus.h4
5 files changed, 135 insertions, 58 deletions
diff --git a/common.h b/common.h
index 4bc57bb8f..995553bae 100644
--- a/common.h
+++ b/common.h
@@ -1167,6 +1167,20 @@ normalize_d(double d) {
return normalize_d_range(d, 0.0, 1.0);
}
+/**
+ * Parse a VSync option argument.
+ */
+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)
+ if (!strcasecmp(str, VSYNC_STRS[i])) {
+ ps->o.vsync = i;
+ return true;
+ }
+ printf_errf("(\"%s\"): Invalid vsync 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);
@@ -1421,6 +1435,9 @@ free_winprop(winprop_t *pprop) {
void
force_repaint(session_t *ps);
+bool
+vsync_init(session_t *ps);
+
#ifdef CONFIG_DBUS
/** @name DBus handling
*/
diff --git a/compton.c b/compton.c
index 2389337e4..12dc72ff3 100644
--- a/compton.c
+++ b/compton.c
@@ -1875,7 +1875,7 @@ map_win(session_t *ps, Window id) {
}
win_determine_fade(ps, w);
- w->damaged = true;
+ w->damaged = false;
/* if any configure events happened while
the window was unmapped, then configure
@@ -2184,6 +2184,11 @@ win_determine_shadow(session_t *ps, win *w) {
*/
static void
win_determine_invert_color(session_t *ps, win *w) {
+ // Do not change window invert color state when the window is unmapped,
+ // unless it comes from w->invert_color_force.
+ if (UNSET == w->invert_color_force && IsViewable != w->a.map_state)
+ return;
+
bool invert_color_old = w->invert_color;
if (UNSET != w->invert_color_force)
@@ -3896,7 +3901,7 @@ usage(void) {
" Specify refresh rate of the screen. If not specified or 0, compton\n"
" will try detecting this with X RandR extension.\n"
"--vsync vsync-method\n"
- " Set VSync method. There are up to 2 VSync methods currently available\n"
+ " Set VSync method. There are up to 3 VSync methods currently available\n"
" depending on your compile time settings:\n"
" none = No VSync\n"
#undef WARNING
@@ -3915,6 +3920,8 @@ usage(void) {
#endif
" opengl = Try to VSync with SGI_swap_control OpenGL extension. Only\n"
" work on some drivers. Experimental." WARNING"\n"
+ " opengl-oml = Try to VSync with OML_sync_control OpenGL extension.\n"
+ " Only work on some drivers. Experimental." WARNING"\n"
"--alpha-step val\n"
" Step for pregenerating alpha pictures. 0.01 - 1.0. Defaults to\n"
" 0.03.\n"
@@ -3986,6 +3993,8 @@ usage(void) {
*/
static bool
register_cm(session_t *ps, bool glx) {
+ assert(!ps->reg_win);
+
XVisualInfo *pvi = NULL;
#ifdef CONFIG_VSYNC_OPENGL
@@ -4023,6 +4032,10 @@ register_cm(session_t *ps, bool glx) {
return false;
}
+ // Unredirect the window if it's redirected, just in case
+ if (ps->redirected)
+ XCompositeUnredirectWindow(ps->dpy, ps->reg_win, CompositeRedirectManual);
+
#ifdef CONFIG_VSYNC_OPENGL
if (glx) {
// Get GLX context
@@ -4198,23 +4211,6 @@ open_config_file(char *cpath, char **ppath) {
}
/**
- * Parse a VSync option argument.
- */
-static inline void
-parse_vsync(session_t *ps, const char *optarg) {
- vsync_t i;
-
- for (i = 0; i < (sizeof(VSYNC_STRS) / sizeof(VSYNC_STRS[0])); ++i)
- if (!strcasecmp(optarg, VSYNC_STRS[i])) {
- ps->o.vsync = i;
- break;
- }
- if ((sizeof(VSYNC_STRS) / sizeof(VSYNC_STRS[0])) == i) {
- printf_errfq(1, "(\"%s\"): Invalid --vsync argument.", optarg);
- }
-}
-
-/**
* Parse a condition list in configuration file.
*/
static void
@@ -4357,8 +4353,8 @@ parse_config(session_t *ps, struct options_tmp *pcfgtmp) {
// --refresh-rate
lcfg_lookup_int(&cfg, "refresh-rate", &ps->o.refresh_rate);
// --vsync
- if (config_lookup_string(&cfg, "vsync", &sval))
- parse_vsync(ps, sval);
+ if (config_lookup_string(&cfg, "vsync", &sval) && !parse_vsync(ps, sval))
+ exit(1);
// --alpha-step
config_lookup_float(&cfg, "alpha-step", &ps->o.alpha_step);
// --dbe
@@ -4634,7 +4630,8 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
break;
case 270:
// --vsync
- parse_vsync(ps, optarg);
+ if (!parse_vsync(ps, optarg))
+ exit(1);
break;
case 271:
// --alpha-step
@@ -4905,7 +4902,7 @@ static bool
vsync_drm_init(session_t *ps) {
#ifdef CONFIG_VSYNC_DRM
// Should we always open card0?
- if ((ps->drm_fd = open("/dev/dri/card0", O_RDWR)) < 0) {
+ if (ps->drm_fd < 0 && (ps->drm_fd = open("/dev/dri/card0", O_RDWR)) < 0) {
printf_errf("(): Failed to open device.");
return false;
}
@@ -4959,11 +4956,16 @@ vsync_drm_wait(session_t *ps) {
static bool
vsync_opengl_init(session_t *ps) {
#ifdef CONFIG_VSYNC_OPENGL
+ if (!ensure_glx_context(ps))
+ return false;
+
// Get video sync functions
- ps->glXGetVideoSyncSGI = (f_GetVideoSync)
- glXGetProcAddress ((const GLubyte *) "glXGetVideoSyncSGI");
- ps->glXWaitVideoSyncSGI = (f_WaitVideoSync)
- glXGetProcAddress ((const GLubyte *) "glXWaitVideoSyncSGI");
+ if (!ps->glXWaitVideoSyncSGI)
+ ps->glXGetVideoSyncSGI = (f_GetVideoSync)
+ glXGetProcAddress ((const GLubyte *) "glXGetVideoSyncSGI");
+ if (!ps->glXWaitVideoSyncSGI)
+ ps->glXWaitVideoSyncSGI = (f_WaitVideoSync)
+ glXGetProcAddress ((const GLubyte *) "glXWaitVideoSyncSGI");
if (!ps->glXWaitVideoSyncSGI || !ps->glXGetVideoSyncSGI) {
printf_errf("(): Failed to get glXWait/GetVideoSyncSGI function.");
return false;
@@ -4971,7 +4973,7 @@ vsync_opengl_init(session_t *ps) {
return true;
#else
- printf_errfq(1, "Program not compiled with OpenGL VSync support.");
+ printf_errf("(): Program not compiled with OpenGL VSync support.");
return false;
#endif
}
@@ -4979,11 +4981,16 @@ vsync_opengl_init(session_t *ps) {
static bool
vsync_opengl_oml_init(session_t *ps) {
#ifdef CONFIG_VSYNC_OPENGL
+ if (!ensure_glx_context(ps))
+ return false;
+
// Get video sync functions
- ps->glXGetSyncValuesOML= (f_GetSyncValuesOML)
- glXGetProcAddress ((const GLubyte *) "glXGetSyncValuesOML");
- ps->glXWaitForMscOML = (f_WaitForMscOML)
- glXGetProcAddress ((const GLubyte *) "glXWaitForMscOML");
+ if (!ps->glXGetSyncValuesOML)
+ ps->glXGetSyncValuesOML = (f_GetSyncValuesOML)
+ glXGetProcAddress ((const GLubyte *) "glXGetSyncValuesOML");
+ if (!ps->glXWaitForMscOML)
+ ps->glXWaitForMscOML = (f_WaitForMscOML)
+ glXGetProcAddress ((const GLubyte *) "glXWaitForMscOML");
if (!ps->glXGetSyncValuesOML || !ps->glXWaitForMscOML) {
printf_errf("(): Failed to get OML_sync_control functions.");
return false;
@@ -4991,7 +4998,7 @@ vsync_opengl_oml_init(session_t *ps) {
return true;
#else
- printf_errfq(1, "Program not compiled with OpenGL VSync support.");
+ printf_errf("(): Program not compiled with OpenGL VSync support.");
return false;
#endif
}
@@ -5029,6 +5036,20 @@ vsync_opengl_oml_wait(session_t *ps) {
#endif
/**
+ * Initialize current VSync method.
+ */
+bool
+vsync_init(session_t *ps) {
+ if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync]
+ && !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) {
+ ps->o.vsync = VSYNC_NONE;
+ return false;
+ }
+ else
+ return true;
+}
+
+/**
* Wait for next VSync.
*/
static void
@@ -5534,7 +5555,7 @@ session_init(session_t *ps_old, int argc, char **argv) {
.paint_tm_offset = 0L,
#ifdef CONFIG_VSYNC_DRM
- .drm_fd = 0,
+ .drm_fd = -1,
#endif
#ifdef CONFIG_VSYNC_OPENGL
@@ -5630,9 +5651,6 @@ session_init(session_t *ps_old, int argc, char **argv) {
ps->vis = DefaultVisual(ps->dpy, ps->scr);
ps->depth = DefaultDepth(ps->dpy, ps->scr);
- bool want_glx = (VSYNC_OPENGL == ps->o.vsync
- || VSYNC_OPENGL_OML == ps->o.vsync);
-
if (!XRenderQueryExtension(ps->dpy,
&ps->render_event, &ps->render_error)) {
fprintf(stderr, "No render extension\n");
@@ -5679,19 +5697,6 @@ session_init(session_t *ps_old, int argc, char **argv) {
"detection impossible.");
}
- // Query X GLX extension
- if (want_glx) {
-#ifdef CONFIG_VSYNC_OPENGL
- if (glXQueryExtension(ps->dpy, &ps->glx_event, &ps->glx_error))
- ps->glx_exists = true;
- else {
- printf_errfq(1, "(): No GLX extension, OpenGL VSync impossible.");
- }
-#else
- printf_errfq(1, "(): OpenGL VSync support not compiled in.");
-#endif
- }
-
// Query X DBE extension
if (ps->o.dbe) {
int dbe_ver_major = 0, dbe_ver_minor = 0;
@@ -5708,16 +5713,12 @@ session_init(session_t *ps_old, int argc, char **argv) {
ps->o.dbe = false;
}
- if (!register_cm(ps, want_glx))
- exit(1);
-
// Initialize software optimization
if (ps->o.sw_opti)
ps->o.sw_opti = swopti_init(ps);
// Initialize VSync
- if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync]
- && !VSYNC_FUNCS_INIT[ps->o.vsync](ps))
+ if (!vsync_init(ps))
exit(1);
// Overlay must be initialized before double buffer
@@ -5727,6 +5728,11 @@ session_init(session_t *ps_old, int argc, char **argv) {
if (ps->o.dbe && !init_dbe(ps))
exit(1);
+ // Create registration window
+ // Must not precede VSync init functions because they may create the window
+ if (!ps->reg_win && !register_cm(ps, false))
+ exit(1);
+
init_atoms(ps);
init_alpha_picts(ps);
@@ -5970,9 +5976,9 @@ session_destroy(session_t *ps) {
#ifdef CONFIG_VSYNC_DRM
// Close file opened for DRM VSync
- if (ps->drm_fd) {
+ if (ps->drm_fd >= 0) {
close(ps->drm_fd);
- ps->drm_fd = 0;
+ ps->drm_fd = -1;
}
#endif
diff --git a/compton.h b/compton.h
index ddc17044f..b4f5bfd44 100644
--- a/compton.h
+++ b/compton.h
@@ -707,6 +707,39 @@ usage(void);
static bool
register_cm(session_t *ps, bool glx);
+#ifdef CONFIG_VSYNC_OPENGL
+/**
+ * Ensure we have a GLX context.
+ */
+static inline bool
+ensure_glx_context(session_t *ps) {
+ if (ps->glx_context)
+ return true;
+
+ // Check for GLX extension
+ if (!ps->glx_exists) {
+ if (glXQueryExtension(ps->dpy, &ps->glx_event, &ps->glx_error))
+ ps->glx_exists = true;
+ else {
+ printf_errf("(): No GLX extension.");
+ return false;
+ }
+ }
+
+ // Create GLX context
+ if (ps->reg_win) {
+ XDestroyWindow(ps->dpy, ps->reg_win);
+ ps->reg_win = None;
+ }
+ if (!register_cm(ps, true) || !ps->glx_context) {
+ printf_errf("(): Failed to acquire GLX context.");
+ return false;
+ }
+
+ return true;
+}
+#endif
+
inline static void
ev_focus_in(session_t *ps, XFocusChangeEvent *ev);
diff --git a/dbus.c b/dbus.c
index 44f1369d7..39e4cf3ad 100644
--- a/dbus.c
+++ b/dbus.c
@@ -952,6 +952,25 @@ cdbus_process_opts_set(session_t *ps, DBusMessage *msg) {
}
goto cdbus_process_opts_set_success;
}
+
+ // vsync
+ if (!strcmp("vsync", target)) {
+ const char * val = NULL;
+ if (!cdbus_msg_get_arg(msg, 1, DBUS_TYPE_STRING, &val))
+ return false;
+ if (!parse_vsync(ps, val)) {
+ printf_errf("(): " CDBUS_ERROR_BADARG_S, 1, "Value invalid.");
+ cdbus_reply_err(ps, msg, CDBUS_ERROR_BADARG, CDBUS_ERROR_BADARG_S, 1, "Value invalid.");
+ }
+ else if (!vsync_init(ps)) {
+ printf_errf("(): " CDBUS_ERROR_CUSTOM_S, "Failed to initialize specified VSync method.");
+ cdbus_reply_err(ps, msg, CDBUS_ERROR_CUSTOM, CDBUS_ERROR_CUSTOM_S, "Failed to initialize specified VSync method.");
+ }
+ else
+ goto cdbus_process_opts_set_success;
+ return true;
+ }
+
#undef cdbus_m_opts_set_do
printf_errf("(): " CDBUS_ERROR_BADTGT_S, target);
diff --git a/dbus.h b/dbus.h
index e69a6ae9b..50770d63c 100644
--- a/dbus.h
+++ b/dbus.h
@@ -21,13 +21,15 @@
#define CDBUS_ERROR_BADMSG_S "Unrecognized command. Beware compton " \
"cannot make you a sandwich."
#define CDBUS_ERROR_BADARG CDBUS_ERROR_PREFIX ".bad_argument"
-#define CDBUS_ERROR_BADARG_S "Something wrong in arguments?"
+#define CDBUS_ERROR_BADARG_S "Failed to parse argument %d: %s"
#define CDBUS_ERROR_BADWIN CDBUS_ERROR_PREFIX ".bad_window"
#define CDBUS_ERROR_BADWIN_S "Requested window %#010lx not found."
#define CDBUS_ERROR_BADTGT CDBUS_ERROR_PREFIX ".bad_target"
#define CDBUS_ERROR_BADTGT_S "Target \"%s\" not found."
#define CDBUS_ERROR_FORBIDDEN CDBUS_ERROR_PREFIX ".forbidden"
#define CDBUS_ERROR_FORBIDDEN_S "Incorrect password, access denied."
+#define CDBUS_ERROR_CUSTOM CDBUS_ERROR_PREFIX ".custom"
+#define CDBUS_ERROR_CUSTOM_S "%s"
// Window type
typedef uint32_t cdbus_window_t;