summaryrefslogtreecommitdiffstats
path: root/compton.h
diff options
context:
space:
mode:
authorRichard Grenville <[email protected]>2012-10-08 10:20:01 +0800
committerRichard Grenville <[email protected]>2012-10-08 10:36:28 +0800
commitae5771e1cfad32f0c2a0a8ed59fb04867f43b5b2 (patch)
tree99a73e780b635b87bce6a396bcc26e4d483e6ecc /compton.h
parent3ef937670802ae09662065e23f34355f828bb52b (diff)
downloadtdebase-ae5771e1cfad32f0c2a0a8ed59fb04867f43b5b2.tar.gz
tdebase-ae5771e1cfad32f0c2a0a8ed59fb04867f43b5b2.zip
Feature: #7: VSync
- Add VSync feature. 3 possible VSync methods available: "sw" (software, not too reliable, but at least you have something to fallback to), "drm" (using DRM_IOCTL_WAIT_VBLANK, should work only on DRI drivers), "opengl" (using SGI_swap_control extension OpenGL, might work on more drivers than the DRM method). "sw" and "opengl" are briefly tested, "drm" received utterly no test (because I use the nVidia binary blob). They are enabled with "--vsync sw" / "--vsync drm" / "--vsync opengl". - Add --refresh-rate to let user specify a refresh rate for software VSync, in case the automatic refresh rate detection does not work well. - Seemingly the automatic refresh rate detection using X RandR in software VSync detects refresh rate incorrectly. Need further investigation. - Fix a few bugs in fading timing. - Add a workaround for client window detection on Fluxbox, as Fluxbox (incorrectly?) sets the override-redirect flag upon all frame windows. - Software VSync adds dependency on librt (a part of glibc) for nanosecond-level timing functions, and libXrandr for automatic refresh rate detection; DRM VSync adds dependency on libdrm to use its drm.h, but does not link to libdrm; OpenGL VSync adds dependency on libGL. - Print timing information on DEBUG_REPAINT.
Diffstat (limited to 'compton.h')
-rw-r--r--compton.h123
1 files changed, 121 insertions, 2 deletions
diff --git a/compton.h b/compton.h
index dca11b68a..0f2f35e68 100644
--- a/compton.h
+++ b/compton.h
@@ -26,7 +26,12 @@
// #define CONFIG_REGEX_PCRE_JIT 1
// Whether to enable parsing of configuration files using libconfig
// #define CONFIG_LIBCONFIG 1
+// Whether to enable DRM VSync support
+// #define CONFIG_VSYNC_DRM 1
+// Whether to enable OpenGL VSync support
+// #define CONFIG_VSYNC_OPENGL 1
+#define NDEBUG 1
// === Includes ===
// For some special functions
@@ -44,6 +49,7 @@
#include <getopt.h>
#include <stdbool.h>
#include <locale.h>
+#include <assert.h>
#include <fnmatch.h>
@@ -69,6 +75,21 @@
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/shape.h>
+#include <X11/extensions/Xrandr.h>
+
+#ifdef CONFIG_VSYNC_DRM
+#include <fcntl.h>
+// We references some definitions in drm.h, which could also be found in
+// /usr/src/linux/include/drm/drm.h, but that path is probably even less
+// reliable than libdrm
+#include <libdrm/drm.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#endif
+
+#ifdef CONFIG_VSYNC_OPENGL
+#include <GL/glx.h>
+#endif
// === Constants ===
#if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2
@@ -89,6 +110,13 @@ extern struct timeval time_start;
#define WINDOW_TRANS 1
#define WINDOW_ARGB 2
+#define FADE_DELTA_TOLERANCE 0.2
+#define VSYNC_SW_TOLERANCE 1000
+
+#define NS_PER_SEC 1000000000L
+#define US_PER_SEC 1000000L
+#define MS_PER_SEC 1000
+
// Window flags
// Window size is changed
@@ -259,6 +287,18 @@ typedef struct _win {
struct _win *prev_trans;
} win;
+typedef enum _vsync_t {
+ VSYNC_NONE,
+ VSYNC_SW,
+ VSYNC_DRM,
+ VSYNC_OPENGL,
+} vsync_t;
+
+#ifdef CONFIG_VSYNC_OPENGL
+typedef int (*f_WaitVideoSync) (int, int, unsigned *);
+typedef int (*f_GetVideoSync) (unsigned *);
+#endif
+
typedef struct _options {
// General
char *display;
@@ -273,6 +313,12 @@ typedef struct _options {
/// Whether to work under synchronized mode for debugging.
Bool synchronize;
+ // VSync
+ /// User-specified refresh rate.
+ int refresh_rate;
+ /// VSync method to use;
+ vsync_t vsync;
+
// Shadow
Bool wintype_shadow[NUM_WINTYPES];
/// Red, green and blue tone of the shadow.
@@ -364,6 +410,16 @@ static int
should_ignore(Display *dpy, unsigned long sequence);
/**
+ * Subtract two unsigned long values.
+ *
+ * Truncate to 0 if the result is negative.
+ */
+static inline unsigned long
+sub_unslong(unsigned long a, unsigned long b) {
+ return (a > b) ? a - b : 0;
+}
+
+/**
* Set a Bool array of all wintypes to true.
*/
static void
@@ -524,6 +580,41 @@ timeval_subtract(struct timeval *result,
return x->tv_sec < y->tv_sec;
}
+/*
+ * Subtracting two struct timespec values.
+ *
+ * Taken from glibc manual.
+ *
+ * Subtract the `struct timespec' values X and Y,
+ * storing the result in RESULT.
+ * Return 1 if the difference is negative, otherwise 0.
+ */
+static inline int
+timespec_subtract(struct timespec *result,
+ struct timespec *x,
+ struct timespec *y) {
+ /* Perform the carry for the later subtraction by updating y. */
+ if (x->tv_nsec < y->tv_nsec) {
+ int nsec = (y->tv_nsec - x->tv_nsec) / NS_PER_SEC + 1;
+ y->tv_nsec -= NS_PER_SEC * nsec;
+ y->tv_sec += nsec;
+ }
+
+ if (x->tv_nsec - y->tv_nsec > NS_PER_SEC) {
+ int nsec = (x->tv_nsec - y->tv_nsec) / NS_PER_SEC;
+ y->tv_nsec += NS_PER_SEC * nsec;
+ y->tv_sec -= nsec;
+ }
+
+ /* Compute the time remaining to wait.
+ tv_nsec is certainly positive. */
+ result->tv_sec = x->tv_sec - y->tv_sec;
+ result->tv_nsec = x->tv_nsec - y->tv_nsec;
+
+ /* Return 1 if result is negative. */
+ return x->tv_sec < y->tv_sec;
+}
+
/**
* Print time passed since program starts execution.
*
@@ -586,7 +677,7 @@ free_damage(Display *dpy, Damage *p) {
}
static unsigned long
-get_time_in_milliseconds(void);
+get_time_ms(void);
static int
fade_timeout(void);
@@ -885,7 +976,7 @@ static void
usage(void);
static void
-register_cm(int scr);
+register_cm(Bool want_glxct);
inline static void
ev_focus_in(XFocusChangeEvent *ev);
@@ -1007,3 +1098,31 @@ get_cfg(int argc, char *const *argv);
static void
get_atoms(void);
+
+static void
+update_refresh_rate(Display *dpy);
+
+static Bool
+vsync_sw_init(void);
+
+static struct timespec
+vsync_sw_ntimeout(int timeout);
+
+static Bool
+vsync_drm_init(void);
+
+#ifdef CONFIG_VSYNC_DRM
+static int
+vsync_drm_wait(void);
+#endif
+
+static Bool
+vsync_opengl_init(void);
+
+#ifdef CONFIG_VSYNC_OPENGL
+static void
+vsync_opengl_wait(void);
+#endif
+
+static Bool
+vsync_wait(Display *dpy, struct pollfd *fd, int timeout);