diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c index f0393d4802..9fdbca9c89 100644 --- a/gdk/x11/gdkglcontext-x11.c +++ b/gdk/x11/gdkglcontext-x11.c @@ -582,6 +582,23 @@ create_legacy_context (GdkDisplay *display, } #ifdef HAVE_XDAMAGE +static void +finish_frame (GdkGLContext *context) +{ + GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context); + GdkSurface *surface = gdk_gl_context_get_surface (context); + + if (context_x11->xdamage == 0) + return; + + if (context_x11->frame_fence == 0) + return; + + glDeleteSync (context_x11->frame_fence); + context_x11->frame_fence = 0; + _gdk_x11_surface_set_frame_still_painting (surface, FALSE); +} + static void bind_context_for_frame_fence (GdkGLContext *context) { @@ -628,7 +645,6 @@ on_gl_surface_xevent (GdkGLContext *context, 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) @@ -675,9 +691,7 @@ on_gl_surface_xevent (GdkGLContext *context, case GL_WAIT_FAILED: if (wait_result == GL_WAIT_FAILED) g_warning ("failed to wait on GL fence associated with last swap buffers call"); - glDeleteSync (context_x11->frame_fence); - context_x11->frame_fence = 0; - _gdk_x11_surface_set_frame_still_painting (surface, FALSE); + finish_frame (context); break; /* We assume that if the fence hasn't been signaled, that this @@ -696,6 +710,21 @@ on_gl_surface_xevent (GdkGLContext *context, return FALSE; } + +static void +on_surface_state_changed (GdkGLContext *context) +{ + GdkSurface *surface = gdk_gl_context_get_surface (context); + + if ((surface->state & GDK_SURFACE_STATE_WITHDRAWN) == 0) + return; + + /* If we're about to withdraw the surface, then we don't care if the frame is + * still getting rendered by the GPU. The compositor is going to remove the surface + * from the scene anyway, so wrap up the frame. + */ + finish_frame (context); +} #endif static gboolean @@ -878,13 +907,23 @@ gdk_x11_gl_context_realize (GdkGLContext *context, gdk_x11_surface_get_xid (surface), XDamageReportRawRectangles); if (gdk_x11_display_error_trap_pop (display)) - context_x11->xdamage = 0; + { + context_x11->xdamage = 0; + } else - g_signal_connect_object (G_OBJECT (display), - "xevent", - G_CALLBACK (on_gl_surface_xevent), - context, - G_CONNECT_SWAPPED); + { + g_signal_connect_object (G_OBJECT (display), + "xevent", + G_CALLBACK (on_gl_surface_xevent), + context, + G_CONNECT_SWAPPED); + g_signal_connect_object (G_OBJECT (surface), + "notify::state", + G_CALLBACK (on_surface_state_changed), + context, + G_CONNECT_SWAPPED); + + } } #endif