diff options
author | Richard Grenville <[email protected]> | 2012-10-08 10:20:01 +0800 |
---|---|---|
committer | Richard Grenville <[email protected]> | 2012-10-08 10:36:28 +0800 |
commit | ae5771e1cfad32f0c2a0a8ed59fb04867f43b5b2 (patch) | |
tree | 99a73e780b635b87bce6a396bcc26e4d483e6ecc /compton.h | |
parent | 3ef937670802ae09662065e23f34355f828bb52b (diff) | |
download | tdebase-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.h | 123 |
1 files changed, 121 insertions, 2 deletions
@@ -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); |