GdkGLContext: Change the way we track the current context

To properly support multithreaded use we use a global GPrivate
to track the current context. Since we also don't need to track
the current context on the display we move gdk_display_destroy_gl_context
to GdkGLContext::discard.
This commit is contained in:
Alexander Larsson 2014-10-30 11:46:09 +01:00
parent eb8f60f141
commit fb50015519
10 changed files with 97 additions and 107 deletions

View File

@ -2244,28 +2244,6 @@ gdk_error_trap_pop (void)
return gdk_error_trap_pop_internal (TRUE);
}
/*< private >
* gdk_display_destroy_gl_context:
* @display: a #GdkDisplay
* @context: a #GdkGLContext
*
* Destroys the platform-specific parts of the @context.
*
* The @context instance is still valid, though inert, after
* this functionr returns.
*/
void
gdk_display_destroy_gl_context (GdkDisplay *display,
GdkGLContext *context)
{
GdkGLContext *current = gdk_display_get_current_gl_context (display);
if (current == context)
g_object_set_data (G_OBJECT (display), "-gdk-gl-current-context", NULL);
GDK_DISPLAY_GET_CLASS (display)->destroy_gl_context (display, context);
}
/*< private >
* gdk_display_make_gl_context_current:
* @display: a #GdkDisplay
@ -2274,35 +2252,9 @@ gdk_display_destroy_gl_context (GdkDisplay *display,
* Makes the given @context the current GL context, or unsets
* the current GL context if @context is %NULL.
*/
void
gboolean
gdk_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context)
{
GdkGLContext *current = gdk_display_get_current_gl_context (display);
if (current == context)
return;
if (context == NULL)
g_object_set_data (G_OBJECT (display), "-gdk-gl-current-context", NULL);
else
g_object_set_data_full (G_OBJECT (display), "-gdk-gl-current-context",
g_object_ref (context),
(GDestroyNotify) g_object_unref);
GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
}
/*< private >
* gdk_display_get_current_gl_context:
* @display: a #GdkDisplay
*
* Retrieves the current #GdkGLContext associated with @display.
*
* Returns: (transfer none): the current #GdkGLContext or %NULL
*/
GdkGLContext *
gdk_display_get_current_gl_context (GdkDisplay *display)
{
return g_object_get_data (G_OBJECT (display), "-gdk-gl-current-context");
return GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
}

View File

@ -228,10 +228,8 @@ struct _GdkDisplayClass
gchar * (*utf8_to_string_target) (GdkDisplay *display,
const gchar *text);
void (*make_gl_context_current) (GdkDisplay *display,
GdkGLContext *context);
void (*destroy_gl_context) (GdkDisplay *display,
GdkGLContext *context);
gboolean (*make_gl_context_current) (GdkDisplay *display,
GdkGLContext *context);
/* Signals */
void (*opened) (GdkDisplay *display);
@ -311,11 +309,8 @@ void _gdk_display_create_window_impl (GdkDisplay *display
gint attributes_mask);
GdkWindow * _gdk_display_create_window (GdkDisplay *display);
void gdk_display_destroy_gl_context (GdkDisplay *display,
gboolean gdk_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context);
void gdk_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context);
GdkGLContext * gdk_display_get_current_gl_context (GdkDisplay *display);
G_END_DECLS

View File

@ -103,13 +103,18 @@ G_DEFINE_QUARK (gdk-gl-error-quark, gdk_gl_error)
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkGLContext, gdk_gl_context, G_TYPE_OBJECT)
static GPrivate thread_current_context = G_PRIVATE_INIT (g_object_unref);
static void
gdk_gl_context_dispose (GObject *gobject)
{
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLContext *current;
gdk_display_destroy_gl_context (gdk_window_get_display (priv->window), context);
current = g_private_get (&thread_current_context);
if (current == context)
g_private_replace (&thread_current_context, NULL);
g_clear_object (&priv->window);
g_clear_object (&priv->visual);
@ -310,13 +315,20 @@ void
gdk_gl_context_make_current (GdkGLContext *context)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
GdkGLContext *current;
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
gdk_display_make_gl_context_current (gdk_window_get_display (priv->window), context);
current = g_private_get (&thread_current_context);
if (current == context)
return;
if (!priv->realized)
gdk_gl_context_realize (context);
if (gdk_display_make_gl_context_current (gdk_window_get_display (priv->window), context))
{
g_private_replace (&thread_current_context, g_object_ref (context));
if (!priv->realized)
gdk_gl_context_realize (context);
}
}
/**
@ -352,9 +364,16 @@ gdk_gl_context_get_window (GdkGLContext *context)
void
gdk_gl_context_clear_current (void)
{
GdkDisplay *display = gdk_display_get_default ();
GdkGLContext *current;
gdk_display_make_gl_context_current (display, NULL);
current = g_private_get (&thread_current_context);
if (current != NULL)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (current);
if (gdk_display_make_gl_context_current (gdk_window_get_display (priv->window), NULL))
g_private_replace (&thread_current_context, NULL);
}
}
/**
@ -369,7 +388,9 @@ gdk_gl_context_clear_current (void)
GdkGLContext *
gdk_gl_context_get_current (void)
{
GdkDisplay *display = gdk_display_get_default ();
GdkGLContext *current;
return gdk_display_get_current_gl_context (display);
current = g_private_get (&thread_current_context);
return current;
}

View File

@ -40,7 +40,7 @@ struct _GdkGLContextClass
{
GObjectClass parent_class;
void (* update) (GdkGLContext *context);
void (* update) (GdkGLContext *context);
void (* end_frame) (GdkGLContext *context,
cairo_region_t *painted,
cairo_region_t *damage);

View File

@ -534,7 +534,6 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass * class)
display_class->text_property_to_utf8_list = _gdk_wayland_display_text_property_to_utf8_list;
display_class->utf8_to_string_target = _gdk_wayland_display_utf8_to_string_target;
display_class->destroy_gl_context = gdk_wayland_display_destroy_gl_context;
display_class->make_gl_context_current = gdk_wayland_display_make_gl_context_current;
}

View File

@ -35,6 +35,8 @@
G_DEFINE_TYPE (GdkWaylandGLContext, gdk_wayland_gl_context, GDK_TYPE_GL_CONTEXT)
static void gdk_x11_gl_context_dispose (GObject *gobject);
static void
gdk_wayland_gl_context_update (GdkGLContext *context)
{
@ -159,9 +161,11 @@ static void
gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
{
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
context_class->update = gdk_wayland_gl_context_update;
context_class->end_frame = gdk_wayland_gl_context_end_frame;
gobject_class->dispose = gdk_x11_gl_context_dispose;
}
static void
@ -369,16 +373,18 @@ gdk_wayland_window_create_gl_context (GdkWindow *window,
return GDK_GL_CONTEXT (context);
}
void
gdk_wayland_display_destroy_gl_context (GdkDisplay *display,
GdkGLContext *context)
static void
gdk_x11_gl_context_dispose (GObject *gobject)
{
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (gobject);
/* TODO: Unset as current if current? */
if (context_wayland->egl_context != NULL)
{
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
GdkWindow *window = gdk_gl_context_get_window (context);
GdkDisplay *display = gdk_window_get_display (window);
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
if (eglGetCurrentContext () == context_wayland->egl_context)
eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
@ -389,9 +395,11 @@ gdk_wayland_display_destroy_gl_context (GdkDisplay *display,
context_wayland->egl_context);
context_wayland->egl_context = NULL;
}
G_OBJECT_CLASS (gdk_wayland_gl_context_parent_class)->dispose (gobject);
}
void
gboolean
gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context)
{
@ -404,7 +412,7 @@ gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
{
eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
return;
return TRUE;
}
context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
@ -422,6 +430,11 @@ gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
}
if (!eglMakeCurrent (display_wayland->egl_display, egl_surface,
egl_surface, context_wayland->egl_context))
g_critical ("eglMakeCurrent failed");
egl_surface, context_wayland->egl_context))
{
g_warning ("eglMakeCurrent failed");
return FALSE;
}
return TRUE;
}

View File

@ -55,9 +55,7 @@ GdkGLContext * gdk_wayland_window_create_gl_context (GdkWindow
GError **error);
void gdk_wayland_window_invalidate_for_new_frame (GdkWindow *window,
cairo_region_t *update_area);
void gdk_wayland_display_destroy_gl_context (GdkDisplay *display,
GdkGLContext *context);
void gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
gboolean gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context);
G_END_DECLS

View File

@ -2894,7 +2894,6 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
display_class->text_property_to_utf8_list = _gdk_x11_display_text_property_to_utf8_list;
display_class->utf8_to_string_target = _gdk_x11_display_utf8_to_string_target;
display_class->destroy_gl_context = gdk_x11_display_destroy_gl_context;
display_class->make_gl_context_current = gdk_x11_display_make_gl_context_current;
_gdk_x11_windowing_init ();

View File

@ -495,14 +495,40 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
return TRUE;
}
static void
gdk_x11_gl_context_dispose (GObject *gobject)
{
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (gobject);
if (context_x11->glx_context != NULL)
{
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
GdkWindow *window = gdk_gl_context_get_window (context);
GdkDisplay *display = gdk_window_get_display (window);
Display *dpy = gdk_x11_display_get_xdisplay (display);
if (glXGetCurrentContext () == context_x11->glx_context)
glXMakeContextCurrent (dpy, None, None, NULL);
GDK_NOTE (OPENGL, g_print ("Destroying GLX context\n"));
glXDestroyContext (dpy, context_x11->glx_context);
context_x11->glx_context = NULL;
}
G_OBJECT_CLASS (gdk_x11_gl_context_parent_class)->dispose (gobject);
}
static void
gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass)
{
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
context_class->update = gdk_x11_gl_context_update;
context_class->end_frame = gdk_x11_gl_context_end_frame;
context_class->texture_from_surface = gdk_x11_gl_context_texture_from_surface;
gobject_class->dispose = gdk_x11_gl_context_dispose;
}
static void
@ -1110,25 +1136,7 @@ gdk_x11_window_create_gl_context (GdkWindow *window,
return GDK_GL_CONTEXT (context);
}
void
gdk_x11_display_destroy_gl_context (GdkDisplay *display,
GdkGLContext *context)
{
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
Display *dpy = gdk_x11_display_get_xdisplay (display);
if (context_x11->glx_context != NULL)
{
if (glXGetCurrentContext () == context_x11->glx_context)
glXMakeContextCurrent (dpy, None, None, NULL);
GDK_NOTE (OPENGL, g_print ("Destroying GLX context\n"));
glXDestroyContext (dpy, context_x11->glx_context);
context_x11->glx_context = NULL;
}
}
void
gboolean
gdk_x11_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context)
{
@ -1141,7 +1149,7 @@ gdk_x11_display_make_gl_context_current (GdkDisplay *display,
if (context == NULL)
{
glXMakeContextCurrent (dpy, None, None, NULL);
return;
return TRUE;
}
context_x11 = GDK_X11_GL_CONTEXT (context);
@ -1161,8 +1169,13 @@ gdk_x11_display_make_gl_context_current (GdkDisplay *display,
g_print ("Making GLX context current to drawable %lu\n",
(unsigned long) context_x11->drawable));
glXMakeContextCurrent (dpy, context_x11->drawable, context_x11->drawable,
context_x11->glx_context);
if (!glXMakeContextCurrent (dpy, context_x11->drawable, context_x11->drawable,
context_x11->glx_context))
{
GDK_NOTE (OPENGL,
g_print ("Making GLX context current failed\n"));
return FALSE;
}
if (context_x11->is_attached && GDK_X11_DISPLAY (display)->has_glx_swap_interval)
{
@ -1171,6 +1184,8 @@ gdk_x11_display_make_gl_context_current (GdkDisplay *display,
else
glXSwapIntervalSGI (0);
}
return TRUE;
}
/**

View File

@ -64,9 +64,7 @@ GdkGLContext * gdk_x11_window_create_gl_context (GdkWindow
GError **error);
void gdk_x11_window_invalidate_for_new_frame (GdkWindow *window,
cairo_region_t *update_area);
void gdk_x11_display_destroy_gl_context (GdkDisplay *display,
GdkGLContext *context);
void gdk_x11_display_make_gl_context_current (GdkDisplay *display,
gboolean gdk_x11_display_make_gl_context_current (GdkDisplay *display,
GdkGLContext *context);
G_END_DECLS