From de1cce21badc436bf501e1f865536688c34a4693 Mon Sep 17 00:00:00 2001 From: Dan Elkouby Date: Fri, 14 Dec 2018 19:21:05 +0200 Subject: [PATCH 1/3] Merge opengl-{,m}swc vsync methods Both methods are redundant. Prefer Mesa's own extension when available, fall back to the old SGI extension otherwise (NVIDIA drivers for the most part). --- man/compton.1.asciidoc | 4 +- src/compton.c | 94 +++++++++++++++--------------------------- 2 files changed, 36 insertions(+), 62 deletions(-) diff --git a/man/compton.1.asciidoc b/man/compton.1.asciidoc index 16953ac..2da8953 100644 --- a/man/compton.1.asciidoc +++ b/man/compton.1.asciidoc @@ -139,8 +139,8 @@ OPTIONS * 'drm': VSync with 'DRM_IOCTL_WAIT_VBLANK'. May only work on some (DRI-based) drivers. * 'opengl': Try to VSync with 'SGI_video_sync' OpenGL extension. Only work on some drivers. * 'opengl-oml': Try to VSync with 'OML_sync_control' OpenGL extension. Only work on some drivers. -* 'opengl-swc': Try to VSync with 'SGI_swap_control' OpenGL extension. Only work on some drivers. Works only with GLX backend. Known to be most effective on many drivers. Does not guarantee to control paint timing. -* 'opengl-mswc': Try to VSync with 'MESA_swap_control' OpenGL extension. Basically the same as 'opengl-swc' above, except the extension we use. +* 'opengl-swc': Try to VSync with 'MESA_swap_control' or 'SGI_swap_control' (in order of preference) OpenGL extension. Works only with GLX backend. Known to be most effective on many drivers. Does not guarantee to control paint timing. +* 'opengl-mswc': Deprecated, use 'opengl-swc' instead. (Note some VSync methods may not be enabled at compile time.) -- diff --git a/src/compton.c b/src/compton.c index fc81976..07f7544 100644 --- a/src/compton.c +++ b/src/compton.c @@ -93,9 +93,6 @@ vsync_opengl_oml_wait(session_t *ps); static void vsync_opengl_swc_deinit(session_t *ps); - -static void -vsync_opengl_mswc_deinit(session_t *ps); #endif static void @@ -195,7 +192,7 @@ static int (* const (VSYNC_FUNCS_WAIT[NUM_VSYNC]))(session_t *ps) = { static void (* const (VSYNC_FUNCS_DEINIT[NUM_VSYNC]))(session_t *ps) = { #ifdef CONFIG_OPENGL [VSYNC_OPENGL_SWC ] = vsync_opengl_swc_deinit, - [VSYNC_OPENGL_MSWC ] = vsync_opengl_mswc_deinit, + [VSYNC_OPENGL_MSWC ] = vsync_opengl_swc_deinit, #endif }; @@ -3478,11 +3475,8 @@ usage(int ret) { " work on some drivers." WARNING"\n" " opengl-oml = Try to VSync with OML_sync_control OpenGL extension.\n" " Only work on some drivers." WARNING"\n" - " opengl-swc = Try to VSync with SGI_swap_control OpenGL extension.\n" - " Only work on some drivers. Works only with GLX backend." WARNING "\n" - " opengl-mswc = Try to VSync with MESA_swap_control OpenGL\n" - " extension. Basically the same as opengl-swc above, except the\n" - " extension we use." WARNING "\n" + " opengl-swc = Enable driver-level VSync. Works only with GLX backend." WARNING "\n" + " opengl-mswc = Deprecated, use opengl-swc instead." WARNING "\n" "\n" "--vsync-aggressive\n" " Attempt to send painting request before VBlank and do XFlush()\n" @@ -4541,30 +4535,45 @@ vsync_opengl_oml_init(session_t *ps) { } static bool -vsync_opengl_swc_init(session_t *ps) { -#ifdef CONFIG_OPENGL +vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) { if (!ensure_glx_context(ps)) return false; - if (!glx_hasglxext(ps, "GLX_SGI_swap_control")) { - printf_errf("(): Your driver doesn't support SGI_swap_control, giving up."); - return false; + if (!ps->psglx->glXSwapIntervalProc && !ps->psglx->glXSwapIntervalMESAProc) { + if (glx_hasglxext(ps, "GLX_MESA_swap_control")) { + ps->psglx->glXSwapIntervalMESAProc = (f_SwapIntervalMESA) + glXGetProcAddress ((const GLubyte *) "glXSwapIntervalMESA"); + } else if (glx_hasglxext(ps, "GLX_SGI_swap_control")) { + ps->psglx->glXSwapIntervalProc = (f_SwapIntervalSGI) + glXGetProcAddress ((const GLubyte *) "glXSwapIntervalSGI"); + } else { + printf_errf("(): Your driver doesn't support SGI_swap_control nor MESA_swap_control, giving up."); + return false; + } } + if (ps->psglx->glXSwapIntervalMESAProc) + ps->psglx->glXSwapIntervalMESAProc(interval); + else if (ps->psglx->glXSwapIntervalProc) + ps->psglx->glXSwapIntervalProc(interval); + else + return false; + + return true; +} + +static bool +vsync_opengl_swc_init(session_t *ps) { +#ifdef CONFIG_OPENGL if (!bkend_use_glx(ps)) { - printf_errf("(): I'm afraid glXSwapIntervalSGI wouldn't help if you are " + printf_errf("(): I'm afraid OpenGL swap control wouldn't help if you are " "not using GLX backend. You could try, nonetheless."); } - // Get video sync functions - if (!ps->psglx->glXSwapIntervalProc) - ps->psglx->glXSwapIntervalProc = (f_SwapIntervalSGI) - glXGetProcAddress ((const GLubyte *) "glXSwapIntervalSGI"); - if (!ps->psglx->glXSwapIntervalProc) { - printf_errf("(): Failed to get SGI_swap_control function."); + if (!vsync_opengl_swc_swap_interval(ps, 1)) { + printf_errf("(): Failed to load a swap control extension."); return false; } - ps->psglx->glXSwapIntervalProc(1); return true; #else @@ -4575,35 +4584,8 @@ vsync_opengl_swc_init(session_t *ps) { static bool vsync_opengl_mswc_init(session_t *ps) { -#ifdef CONFIG_OPENGL - if (!ensure_glx_context(ps)) - return false; - - if (!glx_hasglxext(ps, "GLX_MESA_swap_control")) { - printf_errf("(): Your driver doesn't support MESA_swap_control, giving up."); - return false; - } - - if (!bkend_use_glx(ps)) { - printf_errf("(): I'm afraid glXSwapIntervalMESA wouldn't help if you are " - "not using GLX backend. You could try, nonetheless."); - } - - // Get video sync functions - if (!ps->psglx->glXSwapIntervalMESAProc) - ps->psglx->glXSwapIntervalMESAProc = (f_SwapIntervalMESA) - glXGetProcAddress ((const GLubyte *) "glXSwapIntervalMESA"); - if (!ps->psglx->glXSwapIntervalMESAProc) { - printf_errf("(): Failed to get MESA_swap_control function."); - return false; - } - ps->psglx->glXSwapIntervalMESAProc(1); - - return true; -#else - printf_errf("(): Program not compiled with OpenGL VSync support."); - return false; -#endif + printf_errf("(): opengl-mswc is deprecated, please use opengl-swc instead."); + return vsync_opengl_swc_init(ps); } #ifdef CONFIG_OPENGL @@ -4639,15 +4621,7 @@ vsync_opengl_oml_wait(session_t *ps) { static void vsync_opengl_swc_deinit(session_t *ps) { - // The standard says it doesn't accept 0, but in fact it probably does - if (glx_has_context(ps) && ps->psglx->glXSwapIntervalProc) - ps->psglx->glXSwapIntervalProc(0); -} - -static void -vsync_opengl_mswc_deinit(session_t *ps) { - if (glx_has_context(ps) && ps->psglx->glXSwapIntervalMESAProc) - ps->psglx->glXSwapIntervalMESAProc(0); + vsync_opengl_swc_swap_interval(ps, 0); } #endif From e2182bb00bb418d616dc047d1f2c280e952f8df3 Mon Sep 17 00:00:00 2001 From: Dan Elkouby Date: Fri, 14 Dec 2018 19:22:45 +0200 Subject: [PATCH 2/3] Work around mesa's default-on swap control --- src/compton.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/compton.c b/src/compton.c index 07f7544..b3f9f54 100644 --- a/src/compton.c +++ b/src/compton.c @@ -4630,6 +4630,9 @@ vsync_opengl_swc_deinit(session_t *ps) { */ bool vsync_init(session_t *ps) { + // Mesa turns on swap control by default, undo that + vsync_opengl_swc_swap_interval(ps, 0); + if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync] && !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) { ps->o.vsync = VSYNC_NONE; From 6195422c66d329222f8005efc687840deced6ee7 Mon Sep 17 00:00:00 2001 From: Dan Elkouby Date: Sat, 15 Dec 2018 11:22:38 +0200 Subject: [PATCH 3/3] Swap control only works with OpenGL --- src/compton.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compton.c b/src/compton.c index b3f9f54..5323ae6 100644 --- a/src/compton.c +++ b/src/compton.c @@ -4566,8 +4566,8 @@ static bool vsync_opengl_swc_init(session_t *ps) { #ifdef CONFIG_OPENGL if (!bkend_use_glx(ps)) { - printf_errf("(): I'm afraid OpenGL swap control wouldn't help if you are " - "not using GLX backend. You could try, nonetheless."); + printf_errf("(): OpenGL swap control requires the GLX backend."); + return false; } if (!vsync_opengl_swc_swap_interval(ps, 1)) { @@ -4631,7 +4631,8 @@ vsync_opengl_swc_deinit(session_t *ps) { bool vsync_init(session_t *ps) { // Mesa turns on swap control by default, undo that - vsync_opengl_swc_swap_interval(ps, 0); + if (bkend_use_glx(ps)) + vsync_opengl_swc_swap_interval(ps, 0); if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync] && !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) {