From 1b03dd6704abfc0182de61ef86c91c9e2a2639cf Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Thu, 11 Feb 2016 17:04:08 -0500 Subject: [PATCH] Usability of SGI_video_sync is per-display not per-renderer As previously commented in the code, SGI_video_sync is per-display, rather than per-renderer. The is_direct flag for the renderer was tested before it was initialized (per-display) and that resulted in SGI_video_sync never being used. https://bugzilla.gnome.org/show_bug.cgi?id=779039 --- cogl/cogl/cogl-glx-display-private.h | 3 ++ cogl/cogl/cogl-glx-renderer-private.h | 2 -- cogl/cogl/winsys/cogl-winsys-glx.c | 52 ++++++++++++++------------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/cogl/cogl/cogl-glx-display-private.h b/cogl/cogl/cogl-glx-display-private.h index 133c1188c..1d1afc0cf 100644 --- a/cogl/cogl/cogl-glx-display-private.h +++ b/cogl/cogl/cogl-glx-display-private.h @@ -51,6 +51,9 @@ typedef struct _CoglGLXDisplay CoglBool found_fbconfig; CoglBool fbconfig_has_rgba_visual; + CoglBool is_direct; + CoglBool have_vblank_counter; + CoglBool can_vblank_wait; GLXFBConfig fbconfig; /* Single context for all wins */ diff --git a/cogl/cogl/cogl-glx-renderer-private.h b/cogl/cogl/cogl-glx-renderer-private.h index cb8ff97f8..061f2ccb5 100644 --- a/cogl/cogl/cogl-glx-renderer-private.h +++ b/cogl/cogl/cogl-glx-renderer-private.h @@ -43,8 +43,6 @@ typedef struct _CoglGLXRenderer int glx_error_base; int glx_event_base; - CoglBool is_direct; - /* Vblank stuff */ int dri_fd; diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c index 379658e8a..5a2700176 100644 --- a/cogl/cogl/winsys/cogl-winsys-glx.c +++ b/cogl/cogl/winsys/cogl-winsys-glx.c @@ -715,23 +715,25 @@ update_base_winsys_features (CoglRenderer *renderer) g_strfreev (split_extensions); - /* Note: the GLX_SGI_video_sync spec explicitly states this extension - * only works for direct contexts. */ - if (!glx_renderer->is_direct) - { - glx_renderer->glXGetVideoSync = NULL; - glx_renderer->glXWaitVideoSync = NULL; - COGL_FLAGS_SET (glx_renderer->base_winsys_features, - COGL_WINSYS_FEATURE_VBLANK_COUNTER, - FALSE); - } + /* The GLX_SGI_video_sync spec explicitly states this extension + * only works for direct contexts; we don't know per-renderer + * if the context is direct or not, so we turn off the feature + * flag; we still use the extension within this file looking + * instead at glx_display->have_vblank_counter. + */ + COGL_FLAGS_SET (glx_renderer->base_winsys_features, + COGL_WINSYS_FEATURE_VBLANK_COUNTER, + FALSE); + COGL_FLAGS_SET (glx_renderer->base_winsys_features, COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN, TRUE); - if (glx_renderer->glXWaitVideoSync || - glx_renderer->glXWaitForMsc) + /* Because of the direct-context dependency, the VBLANK_WAIT feature + * doesn't reflect the presence of GLX_SGI_video_sync. + */ + if (glx_renderer->glXWaitForMsc) COGL_FLAGS_SET (glx_renderer->base_winsys_features, COGL_WINSYS_FEATURE_VBLANK_WAIT, TRUE); @@ -864,7 +866,7 @@ update_winsys_features (CoglContext *context, CoglError **error) * by the SwapInterval so we have to throttle swap_region requests * manually... */ if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION) && - _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT)) + (glx_display->have_vblank_counter || glx_display->can_vblank_wait)) COGL_FLAGS_SET (context->winsys_features, COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE); @@ -1142,11 +1144,13 @@ create_context (CoglDisplay *display, CoglError **error) return FALSE; } - glx_renderer->is_direct = + glx_display->is_direct = glx_renderer->glXIsDirect (xlib_renderer->xdpy, glx_display->glx_context); + glx_display->have_vblank_counter = glx_display->is_direct && glx_renderer->glXWaitVideoSync; + glx_display->can_vblank_wait = glx_renderer->glXWaitForMsc || glx_display->have_vblank_counter; COGL_NOTE (WINSYS, "Setting %s context", - glx_renderer->is_direct ? "direct" : "indirect"); + glx_display->is_direct ? "direct" : "indirect"); /* XXX: GLX doesn't let us make a context current without a window * so we create a dummy window that we can use while no CoglOnscreen @@ -1658,12 +1662,13 @@ _cogl_winsys_wait_for_vblank (CoglOnscreen *onscreen) CoglContext *ctx = framebuffer->context; CoglGLXRenderer *glx_renderer; CoglXlibRenderer *xlib_renderer; + CoglGLXDisplay *glx_display; glx_renderer = ctx->display->renderer->winsys; xlib_renderer = _cogl_xlib_renderer_get_data (ctx->display->renderer); + glx_display = ctx->display->winsys; - if (glx_renderer->glXWaitForMsc || - glx_renderer->glXGetVideoSync) + if (glx_display->can_vblank_wait) { CoglFrameInfo *info = g_queue_peek_tail (&onscreen->pending_frame_infos); @@ -1759,6 +1764,7 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen, CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (context->display->renderer); CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; + CoglGLXDisplay *glx_display = context->display->winsys; CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; CoglOnscreenGLX *glx_onscreen = onscreen->winsys; GLXDrawable drawable = @@ -1815,9 +1821,8 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen, if (framebuffer->config.swap_throttled) { - have_counter = - _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_COUNTER); - can_wait = _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT); + have_counter = glx_display->have_vblank_counter; + can_wait = glx_display->can_vblank_wait; } else { @@ -1974,6 +1979,7 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (context->display->renderer); CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; + CoglGLXDisplay *glx_display = context->display->winsys; CoglOnscreenXlib *xlib_onscreen = onscreen->winsys; CoglOnscreenGLX *glx_onscreen = onscreen->winsys; CoglBool have_counter; @@ -1993,8 +1999,7 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, { uint32_t end_frame_vsync_counter = 0; - have_counter = - _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_COUNTER); + have_counter = glx_display->have_vblank_counter; /* If the swap_region API is also being used then we need to track * the vsync counter for each swap request so we can manually @@ -2004,8 +2009,7 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, if (!glx_renderer->glXSwapInterval) { - CoglBool can_wait = - _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT); + CoglBool can_wait = glx_display->can_vblank_wait; /* If we are going to wait for VBLANK manually, we not only * need to flush out pending drawing to the GPU before we