Merge pull request #66 from Streetwalrus/vsync

Improve swap-controlled vsync for mesa
This commit is contained in:
yshui 2018-12-15 13:47:40 +00:00 committed by GitHub
commit 61b637f4ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 65 deletions

View File

@ -139,8 +139,8 @@ OPTIONS
* 'drm': VSync with 'DRM_IOCTL_WAIT_VBLANK'. May only work on some (DRI-based) drivers. * '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': 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-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-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': Try to VSync with 'MESA_swap_control' OpenGL extension. Basically the same as 'opengl-swc' above, except the extension we use. * 'opengl-mswc': Deprecated, use 'opengl-swc' instead.
(Note some VSync methods may not be enabled at compile time.) (Note some VSync methods may not be enabled at compile time.)
-- --

View File

@ -93,9 +93,6 @@ vsync_opengl_oml_wait(session_t *ps);
static void static void
vsync_opengl_swc_deinit(session_t *ps); vsync_opengl_swc_deinit(session_t *ps);
static void
vsync_opengl_mswc_deinit(session_t *ps);
#endif #endif
static void 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) = { static void (* const (VSYNC_FUNCS_DEINIT[NUM_VSYNC]))(session_t *ps) = {
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
[VSYNC_OPENGL_SWC ] = vsync_opengl_swc_deinit, [VSYNC_OPENGL_SWC ] = vsync_opengl_swc_deinit,
[VSYNC_OPENGL_MSWC ] = vsync_opengl_mswc_deinit, [VSYNC_OPENGL_MSWC ] = vsync_opengl_swc_deinit,
#endif #endif
}; };
@ -3478,11 +3475,8 @@ usage(int ret) {
" work on some drivers." WARNING"\n" " work on some drivers." WARNING"\n"
" opengl-oml = Try to VSync with OML_sync_control OpenGL extension.\n" " opengl-oml = Try to VSync with OML_sync_control OpenGL extension.\n"
" Only work on some drivers." WARNING"\n" " Only work on some drivers." WARNING"\n"
" opengl-swc = Try to VSync with SGI_swap_control OpenGL extension.\n" " opengl-swc = Enable driver-level VSync. Works only with GLX backend." WARNING "\n"
" Only work on some drivers. Works only with GLX backend." WARNING "\n" " opengl-mswc = Deprecated, use opengl-swc instead." 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"
"\n" "\n"
"--vsync-aggressive\n" "--vsync-aggressive\n"
" Attempt to send painting request before VBlank and do XFlush()\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 static bool
vsync_opengl_swc_init(session_t *ps) { vsync_opengl_swc_swap_interval(session_t *ps, unsigned int interval) {
#ifdef CONFIG_OPENGL
if (!ensure_glx_context(ps)) if (!ensure_glx_context(ps))
return false; return false;
if (!glx_hasglxext(ps, "GLX_SGI_swap_control")) { if (!ps->psglx->glXSwapIntervalProc && !ps->psglx->glXSwapIntervalMESAProc) {
printf_errf("(): Your driver doesn't support SGI_swap_control, giving up."); if (glx_hasglxext(ps, "GLX_MESA_swap_control")) {
return false; 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)) { if (!bkend_use_glx(ps)) {
printf_errf("(): I'm afraid glXSwapIntervalSGI wouldn't help if you are " printf_errf("(): OpenGL swap control requires the GLX backend.");
"not using GLX backend. You could try, nonetheless."); return false;
} }
// Get video sync functions if (!vsync_opengl_swc_swap_interval(ps, 1)) {
if (!ps->psglx->glXSwapIntervalProc) printf_errf("(): Failed to load a swap control extension.");
ps->psglx->glXSwapIntervalProc = (f_SwapIntervalSGI)
glXGetProcAddress ((const GLubyte *) "glXSwapIntervalSGI");
if (!ps->psglx->glXSwapIntervalProc) {
printf_errf("(): Failed to get SGI_swap_control function.");
return false; return false;
} }
ps->psglx->glXSwapIntervalProc(1);
return true; return true;
#else #else
@ -4575,35 +4584,8 @@ vsync_opengl_swc_init(session_t *ps) {
static bool static bool
vsync_opengl_mswc_init(session_t *ps) { vsync_opengl_mswc_init(session_t *ps) {
#ifdef CONFIG_OPENGL printf_errf("(): opengl-mswc is deprecated, please use opengl-swc instead.");
if (!ensure_glx_context(ps)) return vsync_opengl_swc_init(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
} }
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
@ -4639,15 +4621,7 @@ vsync_opengl_oml_wait(session_t *ps) {
static void static void
vsync_opengl_swc_deinit(session_t *ps) { vsync_opengl_swc_deinit(session_t *ps) {
// The standard says it doesn't accept 0, but in fact it probably does vsync_opengl_swc_swap_interval(ps, 0);
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);
} }
#endif #endif
@ -4656,6 +4630,10 @@ vsync_opengl_mswc_deinit(session_t *ps) {
*/ */
bool bool
vsync_init(session_t *ps) { vsync_init(session_t *ps) {
// Mesa turns on swap control by default, undo that
if (bkend_use_glx(ps))
vsync_opengl_swc_swap_interval(ps, 0);
if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync] if (ps->o.vsync && VSYNC_FUNCS_INIT[ps->o.vsync]
&& !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) { && !VSYNC_FUNCS_INIT[ps->o.vsync](ps)) {
ps->o.vsync = VSYNC_NONE; ps->o.vsync = VSYNC_NONE;