[gtk/wip/on-the-fence-about-damage: 4/4] wip! gdkglcontext-x11: freeze frame clock while driver finishes swapping buffers
- From: Ray Strode <halfline src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/on-the-fence-about-damage: 4/4] wip! gdkglcontext-x11: freeze frame clock while driver finishes swapping buffers
- Date: Wed, 27 May 2020 19:45:39 +0000 (UTC)
commit 71a034a8d3957c388141849bf3a9ffb7b6f49efd
Author: Ray Strode <rstrode redhat com>
Date: Wed May 27 14:55:43 2020 -0400
wip! gdkglcontext-x11: freeze frame clock while driver finishes swapping buffers
...and thaw it after the driver says it's finished and after the
X server says the window has been updated.
gdk/x11/gdkglcontext-x11.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++
gdk/x11/gdkglcontext-x11.h | 9 +++++
2 files changed, 93 insertions(+)
---
diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c
index 148a2cb3c4..da5c7cf467 100644
--- a/gdk/x11/gdkglcontext-x11.c
+++ b/gdk/x11/gdkglcontext-x11.c
@@ -183,8 +183,18 @@ gdk_x11_gl_context_end_frame (GdkDrawContext *draw_context,
gdk_x11_surface_pre_damage (surface);
+ if (display_x11->has_glx_implicit_damage)
+ {
+ g_assert (context_x11->frame_fence == 0);
+
+ context_x11->frame_fence = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ }
+
glXSwapBuffers (dpy, drawable);
+ if (display_x11->has_glx_implicit_damage)
+ gdk_surface_freeze_updates (surface);
+
if (context_x11->do_frame_sync && info != NULL && display_x11->has_glx_video_sync)
glXGetVideoSyncSGI (&info->last_frame_counter);
}
@@ -737,6 +747,21 @@ gdk_x11_gl_context_realize (GdkGLContext *context,
context_x11->attached_drawable = info->glx_drawable ? info->glx_drawable : gdk_x11_surface_get_xid
(surface);
context_x11->unattached_drawable = info->dummy_glx ? info->dummy_glx : info->dummy_xwin;
+#ifdef HAVE_XDAMAGE
+ if (display_x11->have_damage)
+ {
+ gdk_x11_display_error_trap_push (display);
+ context_x11->xdamage = XDamageCreate (dpy,
+ gdk_x11_surface_get_xid (surface),
+ XDamageReportRawRectangles);
+ if (gdk_x11_display_error_trap_pop (display))
+ {
+ XDamageDestroy (dpy, context_x11->xdamage);
+ context_x11->xdamage = 0;
+ }
+ }
+#endif
+
context_x11->is_direct = glXIsDirect (dpy, context_x11->glx_context);
GDK_DISPLAY_NOTE (display, OPENGL,
@@ -1214,6 +1239,54 @@ _gdk_x11_screen_update_visuals_for_gl (GdkX11Screen *x11_screen)
x11_screen->rgba_visual ? gdk_x11_visual_get_xvisual
(x11_screen->rgba_visual)->visualid : 0);
}
+#ifdef HAVE_XDAMAGE
+static gboolean
+on_gl_surface_xevent (GdkGLContext *context,
+ XEvent *xevent,
+ GdkX11Display *display_x11)
+{
+ GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
+ GdkSurface *surface = gdk_gl_context_get_surface (context);
+ XDamageNotifyEvent *damage_xevent;
+
+ if (!context_x11->is_attached)
+ return FALSE;
+
+ if (xevent->type != (display_x11->damage_event_base + XDamageNotify))
+ return FALSE;
+
+ damage_xevent = (XDamageNotifyEvent *) xevent;
+
+ if (damage_xevent->damage != context_x11->xdamage)
+ return FALSE;
+
+ if (context_x11->frame_fence)
+ {
+ GLenum wait_result;
+
+ /* This should only block if damage is delivered first, but we should
+ * only be running this code on drivers where damage is delivered last
+ */
+ wait_result = glClientWaitSync (context_x11->frame_fence, 0, 16000000);
+
+ switch (wait_result)
+ {
+ case GL_ALREADY_SIGNALED:
+ case GL_CONDITION_SATISFIED:
+ if (wait_result == GL_CONDITION_SATISFIED)
+ g_warning ("Got damage before fence");
+ glDeleteSync (context_x11->frame_fence);
+ context_x11->frame_fence = 0;
+ gdk_surface_thaw_updates (surface);
+ default:
+ break;
+ }
+ }
+
+ return FALSE;
+}
+#endif
+
GdkGLContext *
gdk_x11_surface_create_gl_context (GdkSurface *surface,
gboolean attached,
@@ -1221,10 +1294,12 @@ gdk_x11_surface_create_gl_context (GdkSurface *surface,
GError **error)
{
GdkDisplay *display;
+ GdkX11Display *display_x11;
GdkX11GLContext *context;
GLXFBConfig config;
display = gdk_surface_get_display (surface);
+ display_x11 = GDK_X11_DISPLAY (display);
if (!gdk_x11_screen_init_gl (GDK_SURFACE_SCREEN (surface)))
{
@@ -1245,6 +1320,15 @@ gdk_x11_surface_create_gl_context (GdkSurface *surface,
context->glx_config = config;
context->is_attached = attached;
+#ifdef HAVE_XDAMAGE
+ if (display_x11->have_damage && display_x11->has_glx_implicit_damage)
+ g_signal_connect_object (G_OBJECT (display),
+ "xevent",
+ G_CALLBACK (on_gl_surface_xevent),
+ context,
+ G_CONNECT_SWAPPED);
+#endif
+
return GDK_GL_CONTEXT (context);
}
diff --git a/gdk/x11/gdkglcontext-x11.h b/gdk/x11/gdkglcontext-x11.h
index 89d1131fcc..cc80396ade 100644
--- a/gdk/x11/gdkglcontext-x11.h
+++ b/gdk/x11/gdkglcontext-x11.h
@@ -24,6 +24,10 @@
#include <X11/X.h>
#include <X11/Xlib.h>
+#ifdef HAVE_XDAMAGE
+#include <X11/extensions/Xdamage.h>
+#endif
+
#include <epoxy/gl.h>
#include <epoxy/glx.h>
@@ -43,6 +47,11 @@ struct _GdkX11GLContext
GLXFBConfig glx_config;
GLXDrawable attached_drawable;
GLXDrawable unattached_drawable;
+ GLsync frame_fence;
+
+#ifdef HAVE_XDAMAGE
+ Damage xdamage;
+#endif
guint is_attached : 1;
guint is_direct : 1;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]