|
|
67f8b7 |
From 4d1005e3b86050f8b5bab41baf08704117f89b21 Mon Sep 17 00:00:00 2001
|
|
|
67f8b7 |
From: "Owen W. Taylor" <otaylor@fishsoup.net>
|
|
|
67f8b7 |
Date: Thu, 11 Feb 2016 15:06:23 -0500
|
|
|
67f8b7 |
Subject: [PATCH 1/7] CoglGPUInfo - fix check for NVIDIA
|
|
|
67f8b7 |
|
|
|
67f8b7 |
NVIDIA drivers have a vendor of "NVIDIA Corporation" not "NVIDIA".
|
|
|
67f8b7 |
Check for both in case older drivers did use "NVIDIA"
|
|
|
67f8b7 |
|
|
|
67f8b7 |
https://bugzilla.gnome.org/show_bug.cgi?id=779039
|
|
|
67f8b7 |
---
|
|
|
67f8b7 |
cogl/cogl/cogl-gpu-info.c | 3 ++-
|
|
|
67f8b7 |
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
67f8b7 |
|
|
|
67f8b7 |
diff --git a/cogl/cogl/cogl-gpu-info.c b/cogl/cogl/cogl-gpu-info.c
|
|
|
67f8b7 |
index 845382881..23a846616 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/cogl-gpu-info.c
|
|
|
67f8b7 |
+++ b/cogl/cogl/cogl-gpu-info.c
|
|
|
67f8b7 |
@@ -169,7 +169,8 @@ check_qualcomm_vendor (const CoglGpuInfoStrings *strings)
|
|
|
67f8b7 |
static CoglBool
|
|
|
67f8b7 |
check_nvidia_vendor (const CoglGpuInfoStrings *strings)
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
- if (strcmp (strings->vendor_string, "NVIDIA") != 0)
|
|
|
67f8b7 |
+ if (strcmp (strings->vendor_string, "NVIDIA") != 0 &&
|
|
|
67f8b7 |
+ strcmp (strings->vendor_string, "NVIDIA Corporation") != 0)
|
|
|
67f8b7 |
return FALSE;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
return TRUE;
|
|
|
67f8b7 |
--
|
|
|
67f8b7 |
2.12.0
|
|
|
67f8b7 |
|
|
|
67f8b7 |
|
|
|
67f8b7 |
From 62a66bddf3aba14e65ab913746237d3d19a502dd Mon Sep 17 00:00:00 2001
|
|
|
67f8b7 |
From: "Owen W. Taylor" <otaylor@fishsoup.net>
|
|
|
67f8b7 |
Date: Thu, 11 Feb 2016 16:33:03 -0500
|
|
|
67f8b7 |
Subject: [PATCH 2/7] CoglWinsysGLX: factor out some duplicated code
|
|
|
67f8b7 |
|
|
|
67f8b7 |
Add a helper function for repeated calls to clock_gettime(CLOCK_MONOTONIC)
|
|
|
67f8b7 |
|
|
|
67f8b7 |
https://bugzilla.gnome.org/show_bug.cgi?id=779039
|
|
|
67f8b7 |
---
|
|
|
67f8b7 |
cogl/cogl/winsys/cogl-winsys-glx.c | 24 ++++++++++++------------
|
|
|
67f8b7 |
1 file changed, 12 insertions(+), 12 deletions(-)
|
|
|
67f8b7 |
|
|
|
67f8b7 |
diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
index c50db3a04..379658e8a 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
+++ b/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
@@ -192,6 +192,15 @@ find_onscreen_for_xid (CoglContext *context, uint32_t xid)
|
|
|
67f8b7 |
return NULL;
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
67f8b7 |
+static int64_t
|
|
|
67f8b7 |
+get_monotonic_time_ns (void)
|
|
|
67f8b7 |
+{
|
|
|
67f8b7 |
+ struct timespec ts;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ clock_gettime (CLOCK_MONOTONIC, &ts);
|
|
|
67f8b7 |
+ return ts.tv_sec * G_GINT64_CONSTANT (1000000000) + ts.tv_nsec;
|
|
|
67f8b7 |
+}
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
static void
|
|
|
67f8b7 |
ensure_ust_type (CoglRenderer *renderer,
|
|
|
67f8b7 |
GLXDrawable drawable)
|
|
|
67f8b7 |
@@ -202,7 +211,6 @@ ensure_ust_type (CoglRenderer *renderer,
|
|
|
67f8b7 |
int64_t msc;
|
|
|
67f8b7 |
int64_t sbc;
|
|
|
67f8b7 |
struct timeval tv;
|
|
|
67f8b7 |
- struct timespec ts;
|
|
|
67f8b7 |
int64_t current_system_time;
|
|
|
67f8b7 |
int64_t current_monotonic_time;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
@@ -232,9 +240,7 @@ ensure_ust_type (CoglRenderer *renderer,
|
|
|
67f8b7 |
|
|
|
67f8b7 |
/* This is the time source that the newer (fixed) linux drm
|
|
|
67f8b7 |
* drivers use (Linux >= 3.8) */
|
|
|
67f8b7 |
- clock_gettime (CLOCK_MONOTONIC, &ts);
|
|
|
67f8b7 |
- current_monotonic_time = (ts.tv_sec * G_GINT64_CONSTANT (1000000)) +
|
|
|
67f8b7 |
- (ts.tv_nsec / G_GINT64_CONSTANT (1000));
|
|
|
67f8b7 |
+ current_monotonic_time = get_monotonic_time_ns () / 1000;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
if (current_monotonic_time > ust - 1000000 &&
|
|
|
67f8b7 |
current_monotonic_time < ust + 1000000)
|
|
|
67f8b7 |
@@ -310,10 +316,7 @@ _cogl_winsys_get_clock_time (CoglContext *context)
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
case COGL_GLX_UST_IS_MONOTONIC_TIME:
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
- struct timespec ts;
|
|
|
67f8b7 |
-
|
|
|
67f8b7 |
- clock_gettime (CLOCK_MONOTONIC, &ts);
|
|
|
67f8b7 |
- return ts.tv_sec * G_GINT64_CONSTANT (1000000000) + ts.tv_nsec;
|
|
|
67f8b7 |
+ return get_monotonic_time_ns ();
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
67f8b7 |
@@ -1682,16 +1685,13 @@ _cogl_winsys_wait_for_vblank (CoglOnscreen *onscreen)
|
|
|
67f8b7 |
else
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
uint32_t current_count;
|
|
|
67f8b7 |
- struct timespec ts;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
glx_renderer->glXGetVideoSync (¤t_count);
|
|
|
67f8b7 |
glx_renderer->glXWaitVideoSync (2,
|
|
|
67f8b7 |
(current_count + 1) % 2,
|
|
|
67f8b7 |
¤t_count);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
- clock_gettime (CLOCK_MONOTONIC, &ts);
|
|
|
67f8b7 |
- info->presentation_time =
|
|
|
67f8b7 |
- ts.tv_sec * G_GINT64_CONSTANT (1000000000) + ts.tv_nsec;
|
|
|
67f8b7 |
+ info->presentation_time = get_monotonic_time_ns ();
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
--
|
|
|
67f8b7 |
2.12.0
|
|
|
67f8b7 |
|
|
|
67f8b7 |
|
|
|
67f8b7 |
From 69e156c91c663e6f41759eec9f7c729a67da7dc5 Mon Sep 17 00:00:00 2001
|
|
|
67f8b7 |
From: "Owen W. Taylor" <otaylor@fishsoup.net>
|
|
|
67f8b7 |
Date: Thu, 11 Feb 2016 17:04:08 -0500
|
|
|
67f8b7 |
Subject: [PATCH 3/7] Usability of SGI_video_sync is per-display not
|
|
|
67f8b7 |
per-renderer
|
|
|
67f8b7 |
|
|
|
67f8b7 |
As previously commented in the code, SGI_video_sync is per-display, rather
|
|
|
67f8b7 |
than per-renderer. The is_direct flag for the renderer was tested before
|
|
|
67f8b7 |
it was initialized (per-display) and that resulted in SGI_video_sync
|
|
|
67f8b7 |
never being used.
|
|
|
67f8b7 |
|
|
|
67f8b7 |
https://bugzilla.gnome.org/show_bug.cgi?id=779039
|
|
|
67f8b7 |
---
|
|
|
67f8b7 |
cogl/cogl/cogl-glx-display-private.h | 3 ++
|
|
|
67f8b7 |
cogl/cogl/cogl-glx-renderer-private.h | 2 --
|
|
|
67f8b7 |
cogl/cogl/winsys/cogl-winsys-glx.c | 52 +++++++++++++++++++----------------
|
|
|
67f8b7 |
3 files changed, 31 insertions(+), 26 deletions(-)
|
|
|
67f8b7 |
|
|
|
67f8b7 |
diff --git a/cogl/cogl/cogl-glx-display-private.h b/cogl/cogl/cogl-glx-display-private.h
|
|
|
67f8b7 |
index 133c1188c..1d1afc0cf 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/cogl-glx-display-private.h
|
|
|
67f8b7 |
+++ b/cogl/cogl/cogl-glx-display-private.h
|
|
|
67f8b7 |
@@ -51,6 +51,9 @@ typedef struct _CoglGLXDisplay
|
|
|
67f8b7 |
|
|
|
67f8b7 |
CoglBool found_fbconfig;
|
|
|
67f8b7 |
CoglBool fbconfig_has_rgba_visual;
|
|
|
67f8b7 |
+ CoglBool is_direct;
|
|
|
67f8b7 |
+ CoglBool have_vblank_counter;
|
|
|
67f8b7 |
+ CoglBool can_vblank_wait;
|
|
|
67f8b7 |
GLXFBConfig fbconfig;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
/* Single context for all wins */
|
|
|
67f8b7 |
diff --git a/cogl/cogl/cogl-glx-renderer-private.h b/cogl/cogl/cogl-glx-renderer-private.h
|
|
|
67f8b7 |
index cb8ff97f8..061f2ccb5 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/cogl-glx-renderer-private.h
|
|
|
67f8b7 |
+++ b/cogl/cogl/cogl-glx-renderer-private.h
|
|
|
67f8b7 |
@@ -43,8 +43,6 @@ typedef struct _CoglGLXRenderer
|
|
|
67f8b7 |
int glx_error_base;
|
|
|
67f8b7 |
int glx_event_base;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
- CoglBool is_direct;
|
|
|
67f8b7 |
-
|
|
|
67f8b7 |
/* Vblank stuff */
|
|
|
67f8b7 |
int dri_fd;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
index 379658e8a..5a2700176 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
+++ b/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
@@ -715,23 +715,25 @@ update_base_winsys_features (CoglRenderer *renderer)
|
|
|
67f8b7 |
|
|
|
67f8b7 |
g_strfreev (split_extensions);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
- /* Note: the GLX_SGI_video_sync spec explicitly states this extension
|
|
|
67f8b7 |
- * only works for direct contexts. */
|
|
|
67f8b7 |
- if (!glx_renderer->is_direct)
|
|
|
67f8b7 |
- {
|
|
|
67f8b7 |
- glx_renderer->glXGetVideoSync = NULL;
|
|
|
67f8b7 |
- glx_renderer->glXWaitVideoSync = NULL;
|
|
|
67f8b7 |
- COGL_FLAGS_SET (glx_renderer->base_winsys_features,
|
|
|
67f8b7 |
- COGL_WINSYS_FEATURE_VBLANK_COUNTER,
|
|
|
67f8b7 |
- FALSE);
|
|
|
67f8b7 |
- }
|
|
|
67f8b7 |
+ /* The GLX_SGI_video_sync spec explicitly states this extension
|
|
|
67f8b7 |
+ * only works for direct contexts; we don't know per-renderer
|
|
|
67f8b7 |
+ * if the context is direct or not, so we turn off the feature
|
|
|
67f8b7 |
+ * flag; we still use the extension within this file looking
|
|
|
67f8b7 |
+ * instead at glx_display->have_vblank_counter.
|
|
|
67f8b7 |
+ */
|
|
|
67f8b7 |
+ COGL_FLAGS_SET (glx_renderer->base_winsys_features,
|
|
|
67f8b7 |
+ COGL_WINSYS_FEATURE_VBLANK_COUNTER,
|
|
|
67f8b7 |
+ FALSE);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
|
|
|
67f8b7 |
COGL_FLAGS_SET (glx_renderer->base_winsys_features,
|
|
|
67f8b7 |
COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
|
|
|
67f8b7 |
TRUE);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
- if (glx_renderer->glXWaitVideoSync ||
|
|
|
67f8b7 |
- glx_renderer->glXWaitForMsc)
|
|
|
67f8b7 |
+ /* Because of the direct-context dependency, the VBLANK_WAIT feature
|
|
|
67f8b7 |
+ * doesn't reflect the presence of GLX_SGI_video_sync.
|
|
|
67f8b7 |
+ */
|
|
|
67f8b7 |
+ if (glx_renderer->glXWaitForMsc)
|
|
|
67f8b7 |
COGL_FLAGS_SET (glx_renderer->base_winsys_features,
|
|
|
67f8b7 |
COGL_WINSYS_FEATURE_VBLANK_WAIT,
|
|
|
67f8b7 |
TRUE);
|
|
|
67f8b7 |
@@ -864,7 +866,7 @@ update_winsys_features (CoglContext *context, CoglError **error)
|
|
|
67f8b7 |
* by the SwapInterval so we have to throttle swap_region requests
|
|
|
67f8b7 |
* manually... */
|
|
|
67f8b7 |
if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION) &&
|
|
|
67f8b7 |
- _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT))
|
|
|
67f8b7 |
+ (glx_display->have_vblank_counter || glx_display->can_vblank_wait))
|
|
|
67f8b7 |
COGL_FLAGS_SET (context->winsys_features,
|
|
|
67f8b7 |
COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
@@ -1142,11 +1144,13 @@ create_context (CoglDisplay *display, CoglError **error)
|
|
|
67f8b7 |
return FALSE;
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
67f8b7 |
- glx_renderer->is_direct =
|
|
|
67f8b7 |
+ glx_display->is_direct =
|
|
|
67f8b7 |
glx_renderer->glXIsDirect (xlib_renderer->xdpy, glx_display->glx_context);
|
|
|
67f8b7 |
+ glx_display->have_vblank_counter = glx_display->is_direct && glx_renderer->glXWaitVideoSync;
|
|
|
67f8b7 |
+ glx_display->can_vblank_wait = glx_renderer->glXWaitForMsc || glx_display->have_vblank_counter;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
COGL_NOTE (WINSYS, "Setting %s context",
|
|
|
67f8b7 |
- glx_renderer->is_direct ? "direct" : "indirect");
|
|
|
67f8b7 |
+ glx_display->is_direct ? "direct" : "indirect");
|
|
|
67f8b7 |
|
|
|
67f8b7 |
/* XXX: GLX doesn't let us make a context current without a window
|
|
|
67f8b7 |
* so we create a dummy window that we can use while no CoglOnscreen
|
|
|
67f8b7 |
@@ -1658,12 +1662,13 @@ _cogl_winsys_wait_for_vblank (CoglOnscreen *onscreen)
|
|
|
67f8b7 |
CoglContext *ctx = framebuffer->context;
|
|
|
67f8b7 |
CoglGLXRenderer *glx_renderer;
|
|
|
67f8b7 |
CoglXlibRenderer *xlib_renderer;
|
|
|
67f8b7 |
+ CoglGLXDisplay *glx_display;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
glx_renderer = ctx->display->renderer->winsys;
|
|
|
67f8b7 |
xlib_renderer = _cogl_xlib_renderer_get_data (ctx->display->renderer);
|
|
|
67f8b7 |
+ glx_display = ctx->display->winsys;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
- if (glx_renderer->glXWaitForMsc ||
|
|
|
67f8b7 |
- glx_renderer->glXGetVideoSync)
|
|
|
67f8b7 |
+ if (glx_display->can_vblank_wait)
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
CoglFrameInfo *info = g_queue_peek_tail (&onscreen->pending_frame_infos);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
@@ -1759,6 +1764,7 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
|
|
|
67f8b7 |
CoglXlibRenderer *xlib_renderer =
|
|
|
67f8b7 |
_cogl_xlib_renderer_get_data (context->display->renderer);
|
|
|
67f8b7 |
CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
|
|
|
67f8b7 |
+ CoglGLXDisplay *glx_display = context->display->winsys;
|
|
|
67f8b7 |
CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
|
|
|
67f8b7 |
CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
|
|
|
67f8b7 |
GLXDrawable drawable =
|
|
|
67f8b7 |
@@ -1815,9 +1821,8 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
|
|
|
67f8b7 |
|
|
|
67f8b7 |
if (framebuffer->config.swap_throttled)
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
- have_counter =
|
|
|
67f8b7 |
- _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_COUNTER);
|
|
|
67f8b7 |
- can_wait = _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT);
|
|
|
67f8b7 |
+ have_counter = glx_display->have_vblank_counter;
|
|
|
67f8b7 |
+ can_wait = glx_display->can_vblank_wait;
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
else
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
@@ -1974,6 +1979,7 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
|
67f8b7 |
CoglXlibRenderer *xlib_renderer =
|
|
|
67f8b7 |
_cogl_xlib_renderer_get_data (context->display->renderer);
|
|
|
67f8b7 |
CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
|
|
|
67f8b7 |
+ CoglGLXDisplay *glx_display = context->display->winsys;
|
|
|
67f8b7 |
CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
|
|
|
67f8b7 |
CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
|
|
|
67f8b7 |
CoglBool have_counter;
|
|
|
67f8b7 |
@@ -1993,8 +1999,7 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
uint32_t end_frame_vsync_counter = 0;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
- have_counter =
|
|
|
67f8b7 |
- _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_COUNTER);
|
|
|
67f8b7 |
+ have_counter = glx_display->have_vblank_counter;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
/* If the swap_region API is also being used then we need to track
|
|
|
67f8b7 |
* the vsync counter for each swap request so we can manually
|
|
|
67f8b7 |
@@ -2004,8 +2009,7 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
|
67f8b7 |
|
|
|
67f8b7 |
if (!glx_renderer->glXSwapInterval)
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
- CoglBool can_wait =
|
|
|
67f8b7 |
- _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT);
|
|
|
67f8b7 |
+ CoglBool can_wait = glx_display->can_vblank_wait;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
/* If we are going to wait for VBLANK manually, we not only
|
|
|
67f8b7 |
* need to flush out pending drawing to the GPU before we
|
|
|
67f8b7 |
--
|
|
|
67f8b7 |
2.12.0
|
|
|
67f8b7 |
|
|
|
67f8b7 |
|
|
|
67f8b7 |
From 55b8900c1d66a4568ff261a0498d12ca857d2431 Mon Sep 17 00:00:00 2001
|
|
|
67f8b7 |
From: "Owen W. Taylor" <otaylor@fishsoup.net>
|
|
|
67f8b7 |
Date: Thu, 11 Feb 2016 17:12:09 -0500
|
|
|
67f8b7 |
Subject: [PATCH 4/7] Fix the get_clock_time() without GLX_OML_sync_control
|
|
|
67f8b7 |
|
|
|
67f8b7 |
When we don't have GLX_OML_sync_control, we still can set the
|
|
|
67f8b7 |
frame presentation time, but we always use the system monotonic time,
|
|
|
67f8b7 |
so return that from get_clock_time().
|
|
|
67f8b7 |
|
|
|
67f8b7 |
https://bugzilla.gnome.org/show_bug.cgi?id=779039
|
|
|
67f8b7 |
---
|
|
|
67f8b7 |
cogl/cogl/winsys/cogl-winsys-glx.c | 3 +++
|
|
|
67f8b7 |
1 file changed, 3 insertions(+)
|
|
|
67f8b7 |
|
|
|
67f8b7 |
diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
index 5a2700176..7ad1a3fdf 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
+++ b/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
@@ -296,6 +296,9 @@ _cogl_winsys_get_clock_time (CoglContext *context)
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
+ if (!glx_renderer->glXWaitForMsc)
|
|
|
67f8b7 |
+ return get_monotonic_time_ns ();
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
/* We don't call ensure_ust_type() because we don't have a drawable
|
|
|
67f8b7 |
* to work with. cogl_get_clock_time() is documented to only work
|
|
|
67f8b7 |
* once a valid, non-zero, timestamp has been retrieved from Cogl.
|
|
|
67f8b7 |
--
|
|
|
67f8b7 |
2.12.0
|
|
|
67f8b7 |
|
|
|
67f8b7 |
|
|
|
67f8b7 |
From cb784a7be6c72453bc441f03ced27a531ee687d5 Mon Sep 17 00:00:00 2001
|
|
|
67f8b7 |
From: "Owen W. Taylor" <otaylor@fishsoup.net>
|
|
|
67f8b7 |
Date: Thu, 11 Feb 2016 17:15:13 -0500
|
|
|
67f8b7 |
Subject: [PATCH 5/7] For NVIDIA proprietary drivers, implement sync events
|
|
|
67f8b7 |
with a thread
|
|
|
67f8b7 |
|
|
|
67f8b7 |
It's a good guess that the buffer swap will occur at the next vblank,
|
|
|
67f8b7 |
so use glXWaitVideoSync in a separate thread to deliver a sync event
|
|
|
67f8b7 |
rather than just letting the client block when frame drawing, which
|
|
|
67f8b7 |
can signficantly change app logic as compared to the INTEL_swap_event
|
|
|
67f8b7 |
case.
|
|
|
67f8b7 |
|
|
|
67f8b7 |
https://bugzilla.gnome.org/show_bug.cgi?id=779039
|
|
|
67f8b7 |
---
|
|
|
67f8b7 |
cogl/cogl/cogl-private.h | 3 +
|
|
|
67f8b7 |
cogl/cogl/winsys/cogl-winsys-glx.c | 294 +++++++++++++++++++++++++++++++++++--
|
|
|
67f8b7 |
2 files changed, 286 insertions(+), 11 deletions(-)
|
|
|
67f8b7 |
|
|
|
67f8b7 |
diff --git a/cogl/cogl/cogl-private.h b/cogl/cogl/cogl-private.h
|
|
|
67f8b7 |
index 333955c65..e5dc9feda 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/cogl-private.h
|
|
|
67f8b7 |
+++ b/cogl/cogl/cogl-private.h
|
|
|
67f8b7 |
@@ -77,6 +77,9 @@ typedef enum
|
|
|
67f8b7 |
COGL_PRIVATE_FEATURE_GL_PROGRAMMABLE,
|
|
|
67f8b7 |
COGL_PRIVATE_FEATURE_GL_EMBEDDED,
|
|
|
67f8b7 |
COGL_PRIVATE_FEATURE_GL_WEB,
|
|
|
67f8b7 |
+ /* This is currently only implemented for GLX, but isn't actually
|
|
|
67f8b7 |
+ * that winsys dependent */
|
|
|
67f8b7 |
+ COGL_PRIVATE_FEATURE_THREADED_SWAP_WAIT,
|
|
|
67f8b7 |
|
|
|
67f8b7 |
COGL_N_PRIVATE_FEATURES
|
|
|
67f8b7 |
} CoglPrivateFeature;
|
|
|
67f8b7 |
diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
index 7ad1a3fdf..1418d1501 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
+++ b/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
@@ -65,12 +65,16 @@
|
|
|
67f8b7 |
#include <sys/types.h>
|
|
|
67f8b7 |
#include <sys/stat.h>
|
|
|
67f8b7 |
#include <sys/time.h>
|
|
|
67f8b7 |
+#include <errno.h>
|
|
|
67f8b7 |
#include <fcntl.h>
|
|
|
67f8b7 |
#include <time.h>
|
|
|
67f8b7 |
+#include <unistd.h>
|
|
|
67f8b7 |
|
|
|
67f8b7 |
#include <GL/glx.h>
|
|
|
67f8b7 |
#include <X11/Xlib.h>
|
|
|
67f8b7 |
|
|
|
67f8b7 |
+#include <glib.h>
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
/* This is a relatively new extension */
|
|
|
67f8b7 |
#ifndef GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV
|
|
|
67f8b7 |
#define GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x20F7
|
|
|
67f8b7 |
@@ -100,6 +104,14 @@ typedef struct _CoglOnscreenGLX
|
|
|
67f8b7 |
CoglBool pending_sync_notify;
|
|
|
67f8b7 |
CoglBool pending_complete_notify;
|
|
|
67f8b7 |
CoglBool pending_resize_notify;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ GThread *swap_wait_thread;
|
|
|
67f8b7 |
+ GQueue *swap_wait_queue;
|
|
|
67f8b7 |
+ GCond swap_wait_cond;
|
|
|
67f8b7 |
+ GMutex swap_wait_mutex;
|
|
|
67f8b7 |
+ int swap_wait_pipe[2];
|
|
|
67f8b7 |
+ GLXContext swap_wait_context;
|
|
|
67f8b7 |
+ CoglBool closing_down;
|
|
|
67f8b7 |
} CoglOnscreenGLX;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
typedef struct _CoglPixmapTextureEyeGLX
|
|
|
67f8b7 |
@@ -885,6 +897,28 @@ update_winsys_features (CoglContext *context, CoglError **error)
|
|
|
67f8b7 |
COGL_FEATURE_ID_PRESENTATION_TIME,
|
|
|
67f8b7 |
TRUE);
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
+ else
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ CoglGpuInfo *info = &context->gpu;
|
|
|
67f8b7 |
+ if (glx_display->have_vblank_counter &&
|
|
|
67f8b7 |
+ info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ COGL_FLAGS_SET (context->winsys_features,
|
|
|
67f8b7 |
+ COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT, TRUE);
|
|
|
67f8b7 |
+ COGL_FLAGS_SET (context->winsys_features,
|
|
|
67f8b7 |
+ COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT, TRUE);
|
|
|
67f8b7 |
+ /* TODO: remove this deprecated feature */
|
|
|
67f8b7 |
+ COGL_FLAGS_SET (context->features,
|
|
|
67f8b7 |
+ COGL_FEATURE_ID_SWAP_BUFFERS_EVENT,
|
|
|
67f8b7 |
+ TRUE);
|
|
|
67f8b7 |
+ COGL_FLAGS_SET (context->features,
|
|
|
67f8b7 |
+ COGL_FEATURE_ID_PRESENTATION_TIME,
|
|
|
67f8b7 |
+ TRUE);
|
|
|
67f8b7 |
+ COGL_FLAGS_SET (context->private_features,
|
|
|
67f8b7 |
+ COGL_PRIVATE_FEATURE_THREADED_SWAP_WAIT,
|
|
|
67f8b7 |
+ TRUE);
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
|
|
|
67f8b7 |
/* We'll manually handle queueing dirty events in response to
|
|
|
67f8b7 |
* Expose events from X */
|
|
|
67f8b7 |
@@ -1481,7 +1515,8 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
67f8b7 |
#ifdef GLX_INTEL_swap_event
|
|
|
67f8b7 |
- if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT))
|
|
|
67f8b7 |
+ if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT) &&
|
|
|
67f8b7 |
+ !_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_THREADED_SWAP_WAIT))
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
GLXDrawable drawable =
|
|
|
67f8b7 |
glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
|
|
|
67f8b7 |
@@ -1524,6 +1559,31 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
|
|
|
67f8b7 |
xlib_onscreen->output = NULL;
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
67f8b7 |
+ if (glx_onscreen->swap_wait_thread)
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ g_mutex_lock (&glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+ glx_onscreen->closing_down = TRUE;
|
|
|
67f8b7 |
+ g_cond_signal (&glx_onscreen->swap_wait_cond);
|
|
|
67f8b7 |
+ g_mutex_unlock (&glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+ g_thread_join (glx_onscreen->swap_wait_thread);
|
|
|
67f8b7 |
+ glx_onscreen->swap_wait_thread = NULL;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ g_cond_clear (&glx_onscreen->swap_wait_cond);
|
|
|
67f8b7 |
+ g_mutex_clear (&glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ g_queue_free (glx_onscreen->swap_wait_queue);
|
|
|
67f8b7 |
+ glx_onscreen->swap_wait_queue = NULL;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ _cogl_poll_renderer_remove_fd (context->display->renderer,
|
|
|
67f8b7 |
+ glx_onscreen->swap_wait_pipe[0]);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ close (glx_onscreen->swap_wait_pipe[0]);
|
|
|
67f8b7 |
+ close (glx_onscreen->swap_wait_pipe[1]);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ glx_renderer->glXDestroyContext (xlib_renderer->xdpy,
|
|
|
67f8b7 |
+ glx_onscreen->swap_wait_context);
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
_cogl_xlib_renderer_trap_errors (context->display->renderer, &old_state);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
drawable =
|
|
|
67f8b7 |
@@ -1757,6 +1817,199 @@ set_frame_info_output (CoglOnscreen *onscreen,
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
67f8b7 |
+static gpointer
|
|
|
67f8b7 |
+threaded_swap_wait (gpointer data)
|
|
|
67f8b7 |
+{
|
|
|
67f8b7 |
+ CoglOnscreen *onscreen = data;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
|
|
67f8b7 |
+ CoglContext *context = framebuffer->context;
|
|
|
67f8b7 |
+ CoglDisplay *display = context->display;
|
|
|
67f8b7 |
+ CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (display->renderer);
|
|
|
67f8b7 |
+ CoglGLXDisplay *glx_display = display->winsys;
|
|
|
67f8b7 |
+ CoglGLXRenderer *glx_renderer = display->renderer->winsys;
|
|
|
67f8b7 |
+ GLXDrawable dummy_drawable;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ if (glx_display->dummy_glxwin)
|
|
|
67f8b7 |
+ dummy_drawable = glx_display->dummy_glxwin;
|
|
|
67f8b7 |
+ else
|
|
|
67f8b7 |
+ dummy_drawable = glx_display->dummy_xwin;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy,
|
|
|
67f8b7 |
+ dummy_drawable,
|
|
|
67f8b7 |
+ dummy_drawable,
|
|
|
67f8b7 |
+ glx_onscreen->swap_wait_context);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ g_mutex_lock (&glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ while (TRUE)
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ gpointer queue_element;
|
|
|
67f8b7 |
+ uint32_t vblank_counter;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ while (!glx_onscreen->closing_down && glx_onscreen->swap_wait_queue->length == 0)
|
|
|
67f8b7 |
+ g_cond_wait (&glx_onscreen->swap_wait_cond, &glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ if (glx_onscreen->closing_down)
|
|
|
67f8b7 |
+ break;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ queue_element = g_queue_pop_tail (glx_onscreen->swap_wait_queue);
|
|
|
67f8b7 |
+ vblank_counter = GPOINTER_TO_UINT(queue_element);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ g_mutex_unlock (&glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+ glx_renderer->glXWaitVideoSync (2,
|
|
|
67f8b7 |
+ (vblank_counter + 1) % 2,
|
|
|
67f8b7 |
+ &vblank_counter);
|
|
|
67f8b7 |
+ g_mutex_lock (&glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ if (!glx_onscreen->closing_down)
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ int bytes_written = 0;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ union {
|
|
|
67f8b7 |
+ char bytes[8];
|
|
|
67f8b7 |
+ int64_t presentation_time;
|
|
|
67f8b7 |
+ } u;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ u.presentation_time = get_monotonic_time_ns ();
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ while (bytes_written < 8)
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ int res = write (glx_onscreen->swap_wait_pipe[1], u.bytes + bytes_written, 8 - bytes_written);
|
|
|
67f8b7 |
+ if (res == -1)
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ if (errno != EINTR)
|
|
|
67f8b7 |
+ g_error ("Error writing to swap notification pipe: %s\n",
|
|
|
67f8b7 |
+ g_strerror (errno));
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+ else
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ bytes_written += res;
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ g_mutex_unlock (&glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ glx_renderer->glXMakeContextCurrent (xlib_renderer->xdpy,
|
|
|
67f8b7 |
+ None,
|
|
|
67f8b7 |
+ None,
|
|
|
67f8b7 |
+ NULL);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ return NULL;
|
|
|
67f8b7 |
+}
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+static int64_t
|
|
|
67f8b7 |
+threaded_swap_wait_pipe_prepare (void *user_data)
|
|
|
67f8b7 |
+{
|
|
|
67f8b7 |
+ return -1;
|
|
|
67f8b7 |
+}
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+static void
|
|
|
67f8b7 |
+threaded_swap_wait_pipe_dispatch (void *user_data, int revents)
|
|
|
67f8b7 |
+{
|
|
|
67f8b7 |
+ CoglOnscreen *onscreen = user_data;
|
|
|
67f8b7 |
+ CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ CoglFrameInfo *info;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ if ((revents & COGL_POLL_FD_EVENT_IN))
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ int bytes_read = 0;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ union {
|
|
|
67f8b7 |
+ char bytes[8];
|
|
|
67f8b7 |
+ int64_t presentation_time;
|
|
|
67f8b7 |
+ } u;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ while (bytes_read < 8)
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ int res = read (glx_onscreen->swap_wait_pipe[0], u.bytes + bytes_read, 8 - bytes_read);
|
|
|
67f8b7 |
+ if (res == -1)
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ if (errno != EINTR)
|
|
|
67f8b7 |
+ g_error ("Error reading from swap notification pipe: %s\n",
|
|
|
67f8b7 |
+ g_strerror (errno));
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+ else
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ bytes_read += res;
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ set_sync_pending (onscreen);
|
|
|
67f8b7 |
+ set_complete_pending (onscreen);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ info = g_queue_peek_head (&onscreen->pending_frame_infos);
|
|
|
67f8b7 |
+ info->presentation_time = u.presentation_time;
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+}
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+static void
|
|
|
67f8b7 |
+start_threaded_swap_wait (CoglOnscreen *onscreen,
|
|
|
67f8b7 |
+ uint32_t vblank_counter)
|
|
|
67f8b7 |
+{
|
|
|
67f8b7 |
+ CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
|
|
|
67f8b7 |
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
|
|
67f8b7 |
+ CoglContext *context = framebuffer->context;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ if (glx_onscreen->swap_wait_thread == NULL)
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ CoglDisplay *display = context->display;
|
|
|
67f8b7 |
+ CoglGLXRenderer *glx_renderer = display->renderer->winsys;
|
|
|
67f8b7 |
+ CoglGLXDisplay *glx_display = display->winsys;
|
|
|
67f8b7 |
+ CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
|
|
|
67f8b7 |
+ CoglXlibRenderer *xlib_renderer =
|
|
|
67f8b7 |
+ _cogl_xlib_renderer_get_data (display->renderer);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ GLXDrawable drawable =
|
|
|
67f8b7 |
+ glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
|
|
|
67f8b7 |
+ int i;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ ensure_ust_type (display->renderer, drawable);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ if ((pipe (glx_onscreen->swap_wait_pipe) == -1))
|
|
|
67f8b7 |
+ g_error ("Couldn't create pipe for swap notification: %s\n",
|
|
|
67f8b7 |
+ g_strerror (errno));
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ for (i = 0; i < 2; i++)
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ if (fcntl(glx_onscreen->swap_wait_pipe[i], F_SETFD,
|
|
|
67f8b7 |
+ fcntl(glx_onscreen->swap_wait_pipe[i], F_GETFD, 0) | FD_CLOEXEC) == -1)
|
|
|
67f8b7 |
+ g_error ("Couldn't set swap notification pipe CLOEXEC: %s\n",
|
|
|
67f8b7 |
+ g_strerror (errno));
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ _cogl_poll_renderer_add_fd (display->renderer,
|
|
|
67f8b7 |
+ glx_onscreen->swap_wait_pipe[0],
|
|
|
67f8b7 |
+ COGL_POLL_FD_EVENT_IN,
|
|
|
67f8b7 |
+ threaded_swap_wait_pipe_prepare,
|
|
|
67f8b7 |
+ threaded_swap_wait_pipe_dispatch,
|
|
|
67f8b7 |
+ onscreen);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ glx_onscreen->swap_wait_queue = g_queue_new ();
|
|
|
67f8b7 |
+ g_mutex_init (&glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+ g_cond_init (&glx_onscreen->swap_wait_cond);
|
|
|
67f8b7 |
+ glx_onscreen->swap_wait_context =
|
|
|
67f8b7 |
+ glx_renderer->glXCreateNewContext (xlib_renderer->xdpy,
|
|
|
67f8b7 |
+ glx_display->fbconfig,
|
|
|
67f8b7 |
+ GLX_RGBA_TYPE,
|
|
|
67f8b7 |
+ glx_display->glx_context,
|
|
|
67f8b7 |
+ True);
|
|
|
67f8b7 |
+ glx_onscreen->swap_wait_thread = g_thread_new ("cogl_glx_swap_wait",
|
|
|
67f8b7 |
+ threaded_swap_wait,
|
|
|
67f8b7 |
+ onscreen);
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ g_mutex_lock (&glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+ g_queue_push_head (glx_onscreen->swap_wait_queue, GUINT_TO_POINTER(vblank_counter));
|
|
|
67f8b7 |
+ g_cond_signal (&glx_onscreen->swap_wait_cond);
|
|
|
67f8b7 |
+ g_mutex_unlock (&glx_onscreen->swap_wait_mutex);
|
|
|
67f8b7 |
+}
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
static void
|
|
|
67f8b7 |
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
|
|
|
67f8b7 |
const int *user_rectangles,
|
|
|
67f8b7 |
@@ -2000,19 +2253,38 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
|
67f8b7 |
|
|
|
67f8b7 |
if (framebuffer->config.swap_throttled)
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
- uint32_t end_frame_vsync_counter = 0;
|
|
|
67f8b7 |
-
|
|
|
67f8b7 |
have_counter = glx_display->have_vblank_counter;
|
|
|
67f8b7 |
|
|
|
67f8b7 |
- /* If the swap_region API is also being used then we need to track
|
|
|
67f8b7 |
- * the vsync counter for each swap request so we can manually
|
|
|
67f8b7 |
- * throttle swap_region requests. */
|
|
|
67f8b7 |
- if (have_counter)
|
|
|
67f8b7 |
- end_frame_vsync_counter = _cogl_winsys_get_vsync_counter (context);
|
|
|
67f8b7 |
-
|
|
|
67f8b7 |
- if (!glx_renderer->glXSwapInterval)
|
|
|
67f8b7 |
+ if (glx_renderer->glXSwapInterval)
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
- CoglBool can_wait = glx_display->can_vblank_wait;
|
|
|
67f8b7 |
+ if (_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_THREADED_SWAP_WAIT))
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ /* If we didn't wait for the GPU here, then it's easy to get the case
|
|
|
67f8b7 |
+ * where there is a VBlank between the point where we get the vsync counter
|
|
|
67f8b7 |
+ * and the point where the GPU is ready to actually perform the glXSwapBuffers(),
|
|
|
67f8b7 |
+ * and the swap wait terminates at the first VBlank rather than the one
|
|
|
67f8b7 |
+ * where the swap buffers happens. Calling glFinish() here makes this a
|
|
|
67f8b7 |
+ * rare race since the GPU is already ready to swap when we call glXSwapBuffers().
|
|
|
67f8b7 |
+ * The glFinish() also prevents any serious damage if the rare race happens,
|
|
|
67f8b7 |
+ * since it will wait for the preceding glXSwapBuffers() and prevent us from
|
|
|
67f8b7 |
+ * getting premanently ahead. (For NVIDIA drivers, glFinish() after glXSwapBuffers()
|
|
|
67f8b7 |
+ * waits for the buffer swap to happen.)
|
|
|
67f8b7 |
+ */
|
|
|
67f8b7 |
+ _cogl_winsys_wait_for_gpu (onscreen);
|
|
|
67f8b7 |
+ start_threaded_swap_wait (onscreen, _cogl_winsys_get_vsync_counter (context));
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+ }
|
|
|
67f8b7 |
+ else
|
|
|
67f8b7 |
+ {
|
|
|
67f8b7 |
+ CoglBool can_wait = have_counter || glx_display->can_vblank_wait;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ uint32_t end_frame_vsync_counter = 0;
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ /* If the swap_region API is also being used then we need to track
|
|
|
67f8b7 |
+ * the vsync counter for each swap request so we can manually
|
|
|
67f8b7 |
+ * throttle swap_region requests. */
|
|
|
67f8b7 |
+ if (have_counter)
|
|
|
67f8b7 |
+ end_frame_vsync_counter = _cogl_winsys_get_vsync_counter (context);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
/* If we are going to wait for VBLANK manually, we not only
|
|
|
67f8b7 |
* need to flush out pending drawing to the GPU before we
|
|
|
67f8b7 |
--
|
|
|
67f8b7 |
2.12.0
|
|
|
67f8b7 |
|
|
|
67f8b7 |
|
|
|
67f8b7 |
From fb0978b4ea33c88e7a42d4f478d60ef86e271414 Mon Sep 17 00:00:00 2001
|
|
|
67f8b7 |
From: "Owen W. Taylor" <otaylor@fishsoup.net>
|
|
|
67f8b7 |
Date: Wed, 29 Jun 2016 13:52:59 -0400
|
|
|
67f8b7 |
Subject: [PATCH 6/7] Add cogl_xlib_renderer_set_threaded_swap_wait_enabled()
|
|
|
67f8b7 |
|
|
|
67f8b7 |
Because the threaded-swap-wait functionality requires XInitThreads(),
|
|
|
67f8b7 |
and because it isn't clear that it is a win for all applications,
|
|
|
67f8b7 |
add a API function to conditionally enable it.
|
|
|
67f8b7 |
|
|
|
67f8b7 |
Fix the cogl-crate example not to just have a hard-coded dependency
|
|
|
67f8b7 |
on libX11.
|
|
|
67f8b7 |
|
|
|
67f8b7 |
https://bugzilla.gnome.org/show_bug.cgi?id=779039
|
|
|
67f8b7 |
---
|
|
|
67f8b7 |
cogl/cogl/cogl-renderer-private.h | 1 +
|
|
|
67f8b7 |
cogl/cogl/cogl-renderer.c | 11 +++++++++++
|
|
|
67f8b7 |
cogl/cogl/cogl-xlib-renderer.h | 30 ++++++++++++++++++++++++++++++
|
|
|
67f8b7 |
cogl/cogl/winsys/cogl-winsys-glx.c | 1 +
|
|
|
67f8b7 |
4 files changed, 43 insertions(+)
|
|
|
67f8b7 |
|
|
|
67f8b7 |
diff --git a/cogl/cogl/cogl-renderer-private.h b/cogl/cogl/cogl-renderer-private.h
|
|
|
67f8b7 |
index 8627b6cc6..33ed0ceac 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/cogl-renderer-private.h
|
|
|
67f8b7 |
+++ b/cogl/cogl/cogl-renderer-private.h
|
|
|
67f8b7 |
@@ -69,6 +69,7 @@ struct _CoglRenderer
|
|
|
67f8b7 |
Display *foreign_xdpy;
|
|
|
67f8b7 |
CoglBool xlib_enable_event_retrieval;
|
|
|
67f8b7 |
CoglBool xlib_want_reset_on_video_memory_purge;
|
|
|
67f8b7 |
+ CoglBool xlib_enable_threaded_swap_wait;
|
|
|
67f8b7 |
#endif
|
|
|
67f8b7 |
|
|
|
67f8b7 |
CoglDriver driver;
|
|
|
67f8b7 |
diff --git a/cogl/cogl/cogl-renderer.c b/cogl/cogl/cogl-renderer.c
|
|
|
67f8b7 |
index 51a04ffdd..e6575d808 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/cogl-renderer.c
|
|
|
67f8b7 |
+++ b/cogl/cogl/cogl-renderer.c
|
|
|
67f8b7 |
@@ -285,6 +285,17 @@ cogl_xlib_renderer_request_reset_on_video_memory_purge (CoglRenderer *renderer,
|
|
|
67f8b7 |
|
|
|
67f8b7 |
renderer->xlib_want_reset_on_video_memory_purge = enable;
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+void
|
|
|
67f8b7 |
+cogl_xlib_renderer_set_threaded_swap_wait_enabled (CoglRenderer *renderer,
|
|
|
67f8b7 |
+ CoglBool enable)
|
|
|
67f8b7 |
+{
|
|
|
67f8b7 |
+ _COGL_RETURN_IF_FAIL (cogl_is_renderer (renderer));
|
|
|
67f8b7 |
+ /* NB: Renderers are considered immutable once connected */
|
|
|
67f8b7 |
+ _COGL_RETURN_IF_FAIL (!renderer->connected);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+ renderer->xlib_enable_threaded_swap_wait = enable;
|
|
|
67f8b7 |
+}
|
|
|
67f8b7 |
#endif /* COGL_HAS_XLIB_SUPPORT */
|
|
|
67f8b7 |
|
|
|
67f8b7 |
CoglBool
|
|
|
67f8b7 |
diff --git a/cogl/cogl/cogl-xlib-renderer.h b/cogl/cogl/cogl-xlib-renderer.h
|
|
|
67f8b7 |
index f3c1d7c09..3c0db189b 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/cogl-xlib-renderer.h
|
|
|
67f8b7 |
+++ b/cogl/cogl/cogl-xlib-renderer.h
|
|
|
67f8b7 |
@@ -168,6 +168,36 @@ cogl_xlib_renderer_set_event_retrieval_enabled (CoglRenderer *renderer,
|
|
|
67f8b7 |
CoglBool enable);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
/**
|
|
|
67f8b7 |
+ * cogl_xlib_renderer_set_threaded_swap_wait_enabled:
|
|
|
67f8b7 |
+ * @renderer: a #CoglRenderer
|
|
|
67f8b7 |
+ * @enable: The new value
|
|
|
67f8b7 |
+ *
|
|
|
67f8b7 |
+ * Sets whether Cogl is allowed to use a separate threaded to wait for the
|
|
|
67f8b7 |
+ * completion of glXSwapBuffers() and call the frame callback for the
|
|
|
67f8b7 |
+ * corresponding #CoglOnscreen. This is a way of emulating the
|
|
|
67f8b7 |
+ * INTEL_swap_event extension, and will only ever be used if
|
|
|
67f8b7 |
+ * INTEL_swap_event is not present; it will also only be used for
|
|
|
67f8b7 |
+ * specific white-listed drivers that are known to work correctly with
|
|
|
67f8b7 |
+ * multiple contexts sharing state between threads.
|
|
|
67f8b7 |
+ *
|
|
|
67f8b7 |
+ * The advantage of enabling this is that it will allow your main loop
|
|
|
67f8b7 |
+ * to do other work while waiting for the system to be ready to draw
|
|
|
67f8b7 |
+ * the next frame, instead of blocking in glXSwapBuffers(). A disadvantage
|
|
|
67f8b7 |
+ * is that the driver will be prevented from buffering up multiple frames
|
|
|
67f8b7 |
+ * even if it thinks that it would be advantageous. In general, this
|
|
|
67f8b7 |
+ * will work best for something like a system compositor that is doing
|
|
|
67f8b7 |
+ * simple drawing but handling lots of other complex tasks.
|
|
|
67f8b7 |
+ *
|
|
|
67f8b7 |
+ * If you enable this, you must call XInitThreads() before any other
|
|
|
67f8b7 |
+ * X11 calls in your program. (See the documentation for XInitThreads())
|
|
|
67f8b7 |
+ *
|
|
|
67f8b7 |
+ * Stability: unstable
|
|
|
67f8b7 |
+ */
|
|
|
67f8b7 |
+void
|
|
|
67f8b7 |
+cogl_xlib_renderer_set_threaded_swap_wait_enabled (CoglRenderer *renderer,
|
|
|
67f8b7 |
+ CoglBool enable);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
+/**
|
|
|
67f8b7 |
* cogl_xlib_renderer_get_display: (skip)
|
|
|
67f8b7 |
*/
|
|
|
67f8b7 |
Display *
|
|
|
67f8b7 |
diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
index 1418d1501..74b0895d1 100644
|
|
|
67f8b7 |
--- a/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
+++ b/cogl/cogl/winsys/cogl-winsys-glx.c
|
|
|
67f8b7 |
@@ -901,6 +901,7 @@ update_winsys_features (CoglContext *context, CoglError **error)
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
CoglGpuInfo *info = &context->gpu;
|
|
|
67f8b7 |
if (glx_display->have_vblank_counter &&
|
|
|
67f8b7 |
+ context->display->renderer->xlib_enable_threaded_swap_wait &&
|
|
|
67f8b7 |
info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
COGL_FLAGS_SET (context->winsys_features,
|
|
|
67f8b7 |
--
|
|
|
67f8b7 |
2.12.0
|
|
|
67f8b7 |
|
|
|
67f8b7 |
|
|
|
67f8b7 |
From 9505ce8cce4fe14443b5c9868e4e7301268a8d23 Mon Sep 17 00:00:00 2001
|
|
|
67f8b7 |
From: "Owen W. Taylor" <otaylor@fishsoup.net>
|
|
|
67f8b7 |
Date: Tue, 21 Feb 2017 13:51:16 -0500
|
|
|
67f8b7 |
Subject: [PATCH 7/7] Call cogl_xlib_renderer_set_threaded_swap_wait_enabled()
|
|
|
67f8b7 |
|
|
|
67f8b7 |
Set up things so that if the INTEL_swap_event extension is not present,
|
|
|
67f8b7 |
but the driver is known to have good thread support, we use an extra
|
|
|
67f8b7 |
thread and call glXWaitVideoSync() in the thread. This allows idles
|
|
|
67f8b7 |
to work properly, even when Mutter is constantly redrawing new frames;
|
|
|
67f8b7 |
otherwise, without INTEL_swap_event, we'll just block in glXSwapBuffers().
|
|
|
67f8b7 |
|
|
|
67f8b7 |
https://bugzilla.gnome.org/show_bug.cgi?id=779039
|
|
|
67f8b7 |
---
|
|
|
67f8b7 |
src/backends/x11/meta-backend-x11.c | 6 ++++++
|
|
|
67f8b7 |
src/backends/x11/meta-renderer-x11.c | 8 ++++++++
|
|
|
67f8b7 |
2 files changed, 14 insertions(+)
|
|
|
67f8b7 |
|
|
|
67f8b7 |
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
|
|
|
67f8b7 |
index a0b196efe..413b0622a 100644
|
|
|
67f8b7 |
--- a/src/backends/x11/meta-backend-x11.c
|
|
|
67f8b7 |
+++ b/src/backends/x11/meta-backend-x11.c
|
|
|
67f8b7 |
@@ -913,6 +913,12 @@ meta_backend_x11_init (MetaBackendX11 *x11)
|
|
|
67f8b7 |
{
|
|
|
67f8b7 |
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
+ /* XInitThreads() is needed to use the "threaded swap wait" functionality
|
|
|
67f8b7 |
+ * in Cogl - see meta_renderer_x11_create_cogl_renderer(). We call it here
|
|
|
67f8b7 |
+ * to hopefully call it before any other use of XLib.
|
|
|
67f8b7 |
+ */
|
|
|
67f8b7 |
+ XInitThreads();
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
clutter_x11_request_reset_on_video_memory_purge ();
|
|
|
67f8b7 |
|
|
|
67f8b7 |
/* We do X11 event retrieval ourselves */
|
|
|
67f8b7 |
diff --git a/src/backends/x11/meta-renderer-x11.c b/src/backends/x11/meta-renderer-x11.c
|
|
|
67f8b7 |
index c0405bedc..9a86f493a 100644
|
|
|
67f8b7 |
--- a/src/backends/x11/meta-renderer-x11.c
|
|
|
67f8b7 |
+++ b/src/backends/x11/meta-renderer-x11.c
|
|
|
67f8b7 |
@@ -65,6 +65,14 @@ meta_renderer_x11_create_cogl_renderer (MetaRenderer *renderer)
|
|
|
67f8b7 |
cogl_renderer_set_custom_winsys (cogl_renderer, get_x11_cogl_winsys_vtable);
|
|
|
67f8b7 |
cogl_xlib_renderer_set_foreign_display (cogl_renderer, xdisplay);
|
|
|
67f8b7 |
|
|
|
67f8b7 |
+ /* Set up things so that if the INTEL_swap_event extension is not present,
|
|
|
67f8b7 |
+ * but the driver is known to have good thread support, we use an extra
|
|
|
67f8b7 |
+ * thread and call glXWaitVideoSync() in the thread. This allows idles
|
|
|
67f8b7 |
+ * to work properly, even when Mutter is constantly redrawing new frames;
|
|
|
67f8b7 |
+ * otherwise, without INTEL_swap_event, we'll just block in glXSwapBuffers().
|
|
|
67f8b7 |
+ */
|
|
|
67f8b7 |
+ cogl_xlib_renderer_set_threaded_swap_wait_enabled (cogl_renderer, TRUE);
|
|
|
67f8b7 |
+
|
|
|
67f8b7 |
return cogl_renderer;
|
|
|
67f8b7 |
}
|
|
|
67f8b7 |
|
|
|
67f8b7 |
--
|
|
|
67f8b7 |
2.12.0
|
|
|
67f8b7 |
|