diff --git a/cogl/cogl/cogl-renderer-private.h b/cogl/cogl/cogl-renderer-private.h index 8627b6cc6..33ed0ceac 100644 --- a/cogl/cogl/cogl-renderer-private.h +++ b/cogl/cogl/cogl-renderer-private.h @@ -69,6 +69,7 @@ struct _CoglRenderer Display *foreign_xdpy; CoglBool xlib_enable_event_retrieval; CoglBool xlib_want_reset_on_video_memory_purge; + CoglBool xlib_enable_threaded_swap_wait; #endif CoglDriver driver; diff --git a/cogl/cogl/cogl-renderer.c b/cogl/cogl/cogl-renderer.c index 51a04ffdd..e6575d808 100644 --- a/cogl/cogl/cogl-renderer.c +++ b/cogl/cogl/cogl-renderer.c @@ -285,6 +285,17 @@ cogl_xlib_renderer_request_reset_on_video_memory_purge (CoglRenderer *renderer, renderer->xlib_want_reset_on_video_memory_purge = enable; } + +void +cogl_xlib_renderer_set_threaded_swap_wait_enabled (CoglRenderer *renderer, + CoglBool enable) +{ + _COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer)); + /* NB: Renderers are considered immutable once connected */ + _COGL_RETURN_IF_FAIL (!renderer->connected); + + renderer->xlib_enable_threaded_swap_wait = enable; +} #endif /* COGL_HAS_XLIB_SUPPORT */ CoglBool diff --git a/cogl/cogl/cogl-xlib-renderer.h b/cogl/cogl/cogl-xlib-renderer.h index f3c1d7c09..3c0db189b 100644 --- a/cogl/cogl/cogl-xlib-renderer.h +++ b/cogl/cogl/cogl-xlib-renderer.h @@ -167,6 +167,36 @@ void cogl_xlib_renderer_set_event_retrieval_enabled (CoglRenderer *renderer, CoglBool enable); +/** + * cogl_xlib_renderer_set_threaded_swap_wait_enabled: + * @renderer: a #CoglRenderer + * @enable: The new value + * + * Sets whether Cogl is allowed to use a separate threaded to wait for the + * completion of glXSwapBuffers() and call the frame callback for the + * corresponding #CoglOnscreen. This is a way of emulating the + * INTEL_swap_event extension, and will only ever be used if + * INTEL_swap_event is not present; it will also only be used for + * specific white-listed drivers that are known to work correctly with + * multiple contexts sharing state between threads. + * + * The advantage of enabling this is that it will allow your main loop + * to do other work while waiting for the system to be ready to draw + * the next frame, instead of blocking in glXSwapBuffers(). A disadvantage + * is that the driver will be prevented from buffering up multiple frames + * even if it thinks that it would be advantageous. In general, this + * will work best for something like a system compositor that is doing + * simple drawing but handling lots of other complex tasks. + * + * If you enable this, you must call XInitThreads() before any other + * X11 calls in your program. (See the documentation for XInitThreads()) + * + * Stability: unstable + */ +void +cogl_xlib_renderer_set_threaded_swap_wait_enabled (CoglRenderer *renderer, + CoglBool enable); + /** * cogl_xlib_renderer_get_display: (skip) */ diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c index 1418d1501..74b0895d1 100644 --- a/cogl/cogl/winsys/cogl-winsys-glx.c +++ b/cogl/cogl/winsys/cogl-winsys-glx.c @@ -901,6 +901,7 @@ update_winsys_features (CoglContext *context, CoglError **error) { CoglGpuInfo *info = &context->gpu; if (glx_display->have_vblank_counter && + context->display->renderer->xlib_enable_threaded_swap_wait && info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA) { COGL_FLAGS_SET (context->winsys_features,