diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index 829e302c82..0c3f564930 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -89,6 +89,7 @@ typedef struct { guint use_texture_rectangle : 1; guint has_gl_framebuffer_blit : 1; guint has_frame_terminator : 1; + guint extensions_checked : 1; GdkGLContextPaintData *paint_data; } GdkGLContextPrivate; @@ -389,19 +390,54 @@ gdk_gl_context_has_frame_terminator (GdkGLContext *context) return priv->has_frame_terminator; } +/** + * gdk_gl_context_realize: + * @context: a #GdkGLContext + * @error: return location for a #GError + * + * Realizes the given #GdkGLContext. + * + * It is safe to call this function on a realized #GdkGLContext. + * + * Returns: %TRUE if the context is realized + * + * Since: 3.16 + */ +gboolean +gdk_gl_context_realize (GdkGLContext *context, + GError **error) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + + g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), FALSE); + + if (priv->realized) + return priv->realized; + + priv->realized = GDK_GL_CONTEXT_GET_CLASS (context)->realize (context, error); + + return priv->realized; +} + static void -gdk_gl_context_realize (GdkGLContext *context) +gdk_gl_context_check_extensions (GdkGLContext *context) { GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); gboolean has_npot, has_texture_rectangle; + if (!priv->realized) + return; + + if (priv->extensions_checked) + return; + has_npot = epoxy_has_gl_extension ("GL_ARB_texture_non_power_of_two"); has_texture_rectangle = epoxy_has_gl_extension ("GL_ARB_texture_rectangle"); priv->has_gl_framebuffer_blit = epoxy_has_gl_extension ("GL_EXT_framebuffer_blit"); priv->has_frame_terminator = epoxy_has_gl_extension ("GL_GREMEDY_frame_terminator"); - if (_gdk_gl_flags & GDK_GL_TEXTURE_RECTANGLE) + if (G_UNLIKELY (_gdk_gl_flags & GDK_GL_TEXTURE_RECTANGLE)) priv->use_texture_rectangle = TRUE; else if (has_npot) priv->use_texture_rectangle = FALSE; @@ -410,7 +446,7 @@ gdk_gl_context_realize (GdkGLContext *context) else g_warning ("GL implementation doesn't support any form of non-power-of-two textures"); - priv->realized = TRUE; + priv->extensions_checked = TRUE; } /** @@ -433,11 +469,24 @@ gdk_gl_context_make_current (GdkGLContext *context) if (current == context) return; + /* we need to realize the GdkGLContext if it wasn't explicitly realized */ + if (!priv->realized) + { + GError *error = NULL; + + gdk_gl_context_realize (context, &error); + if (error != NULL) + { + g_critical ("Could not realize the GL context: %s", error->message); + g_error_free (error); + return; + } + } + if (gdk_display_make_gl_context_current (priv->display, context)) { g_private_replace (&thread_current_context, g_object_ref (context)); - if (!priv->realized) - gdk_gl_context_realize (context); + gdk_gl_context_check_extensions (context); } } diff --git a/gdk/gdkglcontext.h b/gdk/gdkglcontext.h index be71ae4382..3155948017 100644 --- a/gdk/gdkglcontext.h +++ b/gdk/gdkglcontext.h @@ -43,18 +43,24 @@ GDK_AVAILABLE_IN_3_16 GType gdk_gl_context_get_type (void) G_GNUC_CONST; GDK_AVAILABLE_IN_3_16 -GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context); +GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context); GDK_AVAILABLE_IN_3_16 -GdkWindow * gdk_gl_context_get_window (GdkGLContext *context); +GdkWindow * gdk_gl_context_get_window (GdkGLContext *context); GDK_AVAILABLE_IN_3_16 -GdkGLProfile gdk_gl_context_get_profile (GdkGLContext *context); +GdkGLProfile gdk_gl_context_get_profile (GdkGLContext *context); +GDK_AVAILABLE_IN_3_16 +GdkGLContext * gdk_gl_context_get_shared_context (GdkGLContext *context); GDK_AVAILABLE_IN_3_16 -void gdk_gl_context_make_current (GdkGLContext *context); +gboolean gdk_gl_context_realize (GdkGLContext *context, + GError **error); + GDK_AVAILABLE_IN_3_16 -GdkGLContext * gdk_gl_context_get_current (void); +void gdk_gl_context_make_current (GdkGLContext *context); GDK_AVAILABLE_IN_3_16 -void gdk_gl_context_clear_current (void); +GdkGLContext * gdk_gl_context_get_current (void); +GDK_AVAILABLE_IN_3_16 +void gdk_gl_context_clear_current (void); G_END_DECLS diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h index 4efface088..f282539cfd 100644 --- a/gdk/gdkglcontextprivate.h +++ b/gdk/gdkglcontextprivate.h @@ -40,6 +40,9 @@ struct _GdkGLContextClass { GObjectClass parent_class; + gboolean (* realize) (GdkGLContext *context, + GError **error); + void (* end_frame) (GdkGLContext *context, cairo_region_t *painted, cairo_region_t *damage); diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 31033678db..9cc257b49a 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -2724,8 +2724,11 @@ gdk_window_ref_impl_surface (GdkWindow *window) } GdkGLContext * -gdk_window_get_paint_gl_context (GdkWindow *window, GError **error) +gdk_window_get_paint_gl_context (GdkWindow *window, + GError **error) { + GError *internal_error = NULL; + if (_gdk_gl_flags & GDK_GL_DISABLE) { g_set_error_literal (error, GDK_GL_ERROR, @@ -2741,21 +2744,36 @@ gdk_window_get_paint_gl_context (GdkWindow *window, GError **error) TRUE, GDK_GL_PROFILE_3_2_CORE, NULL, - error); + &internal_error); if (window->impl_window->gl_paint_context == NULL && - g_error_matches (*error, GDK_GL_ERROR, + g_error_matches (internal_error, GDK_GL_ERROR, GDK_GL_ERROR_UNSUPPORTED_PROFILE)) { - g_clear_error (error); + g_clear_error (&internal_error); window->impl_window->gl_paint_context = GDK_WINDOW_IMPL_GET_CLASS (window->impl)->create_gl_context (window->impl_window, TRUE, GDK_GL_PROFILE_DEFAULT, NULL, - error); + &internal_error); } } + if (internal_error != NULL) + { + g_propagate_error (error, internal_error); + g_clear_object (&(window->impl_window->gl_paint_context)); + return NULL; + } + + gdk_gl_context_realize (window->impl_window->gl_paint_context, &internal_error); + if (internal_error != NULL) + { + g_propagate_error (error, internal_error); + g_clear_object (&(window->impl_window->gl_paint_context)); + return NULL; + } + return window->impl_window->gl_paint_context; } @@ -2771,6 +2789,9 @@ gdk_window_get_paint_gl_context (GdkWindow *window, GError **error) * * If the creation of the #GdkGLContext failed, @error will be set. * + * Before using the returned #GdkGLContext, you will need to + * call gdk_gl_context_make_current(). + * * Returns: (transfer full): the newly created #GdkGLContext, or * %NULL on error * diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index 74e23d2369..85a8567dc6 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -1116,7 +1116,6 @@ GdkGLContext * gdk_window_create_gl_context (GdkWindow *window, GdkGLProfile profile, GError **error); - G_END_DECLS #endif /* __GDK_WINDOW_H__ */ diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h index efdaa1f5e3..1ac327ff9a 100644 --- a/gdk/gdkwindowimpl.h +++ b/gdk/gdkwindowimpl.h @@ -296,6 +296,9 @@ struct _GdkWindowImplClass GdkGLProfile profile, GdkGLContext *share, GError **error); + gboolean (* realize_gl_context) (GdkWindow *window, + GdkGLContext *context, + GError **error); void (*invalidate_for_new_frame)(GdkWindow *window, cairo_region_t *update_area); }; @@ -303,7 +306,6 @@ struct _GdkWindowImplClass /* Interface Functions */ GType gdk_window_impl_get_type (void) G_GNUC_CONST; - G_END_DECLS #endif /* __GDK_WINDOW_IMPL_H__ */ diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c index c8d4ed2b22..a5fa5df356 100644 --- a/gdk/wayland/gdkglcontext-wayland.c +++ b/gdk/wayland/gdkglcontext-wayland.c @@ -100,6 +100,47 @@ gdk_wayland_window_invalidate_for_new_frame (GdkWindow *window, } } +static gboolean +gdk_wayland_gl_context_realize (GdkGLContext *context, + GError **error) +{ + GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context); + GdkDisplay *display = gdk_gl_context_get_display (context); + GdkGLContext *share = gdk_gl_context_get_shared_context (context); + GdkGLProfile profile = gdk_gl_context_get_profile (context); + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); + EGLContext ctx; + EGLint context_attribs[3]; + int i; + + i = 0; + if (profile == GDK_GL_PROFILE_3_2_CORE) + { + context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; + context_attribs[i++] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; + } + context_attribs[i++] = EGL_NONE; + + ctx = eglCreateContext (display_wayland->egl_display, + context_wayland->egl_config, + share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context + : EGL_NO_CONTEXT, + context_attribs); + if (ctx == NULL) + { + g_set_error_literal (error, GDK_GL_ERROR, + GDK_GL_ERROR_NOT_AVAILABLE, + _("Unable to create a GL context")); + return FALSE; + } + + GDK_NOTE (OPENGL, g_print ("Created EGL context[%p]\n", ctx)); + + context_wayland->egl_context = ctx; + + return TRUE; +} + static void gdk_wayland_gl_context_end_frame (GdkGLContext *context, cairo_region_t *painted, @@ -142,11 +183,13 @@ gdk_wayland_gl_context_end_frame (GdkGLContext *context, 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); + GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass); - context_class->end_frame = gdk_wayland_gl_context_end_frame; gobject_class->dispose = gdk_x11_gl_context_dispose; + + context_class->realize = gdk_wayland_gl_context_realize; + context_class->end_frame = gdk_wayland_gl_context_end_frame; } static void @@ -213,9 +256,9 @@ gdk_wayland_display_init_gl (GdkDisplay *display) #define MAX_EGL_ATTRS 30 static gboolean -find_eglconfig_for_window (GdkWindow *window, - EGLConfig *egl_config_out, - GError **error) +find_eglconfig_for_window (GdkWindow *window, + EGLConfig *egl_config_out, + GError **error) { GdkDisplay *display = gdk_window_get_display (window); GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); @@ -294,10 +337,7 @@ gdk_wayland_window_create_gl_context (GdkWindow *window, GdkDisplay *display = gdk_window_get_display (window); GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display); GdkWaylandGLContext *context; - EGLContext ctx; EGLConfig config; - int i; - EGLint context_attribs[3]; if (!gdk_wayland_display_init_gl (display)) { @@ -322,29 +362,6 @@ gdk_wayland_window_create_gl_context (GdkWindow *window, if (!find_eglconfig_for_window (window, &config, error)) return NULL; - i = 0; - if (profile == GDK_GL_PROFILE_3_2_CORE) - { - context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; - context_attribs[i++] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; - } - context_attribs[i++] = EGL_NONE; - - ctx = eglCreateContext (display_wayland->egl_display, - config, - share ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context : EGL_NO_CONTEXT, - context_attribs); - if (ctx == NULL) - { - g_set_error_literal (error, GDK_GL_ERROR, - GDK_GL_ERROR_NOT_AVAILABLE, - _("Unable to create a GL context")); - return NULL; - } - - GDK_NOTE (OPENGL, - g_print ("Created EGL context[%p]\n", ctx)); - context = g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT, "display", display, "window", window, @@ -353,7 +370,6 @@ gdk_wayland_window_create_gl_context (GdkWindow *window, NULL); context->egl_config = config; - context->egl_context = ctx; context->is_attached = attached; return GDK_GL_CONTEXT (context); diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c index 6eed9f96c0..9f525ad766 100644 --- a/gdk/x11/gdkglcontext-x11.c +++ b/gdk/x11/gdkglcontext-x11.c @@ -534,6 +534,185 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *paint_context, return TRUE; } +static XVisualInfo * +find_xvisinfo_for_fbconfig (GdkDisplay *display, + GLXFBConfig config) +{ + Display *dpy = gdk_x11_display_get_xdisplay (display); + + return glXGetVisualFromFBConfig (dpy, config); +} + +static GLXContext +create_gl3_context (GdkDisplay *display, + GLXFBConfig config, + GdkGLContext *share) +{ + /* There are no profiles before OpenGL 3.2. + * + * The GLX_ARB_create_context_profile spec says: + * + * If the requested OpenGL version is less than 3.2, + * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality + * of the context is determined solely by the requested version. + * + * Which means we can ask for the CORE_PROFILE_BIT without asking for + * a 3.2 version. + */ + static const int attrib_list[] = { + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 2, + None, + }; + + GdkX11GLContext *context_x11 = NULL; + + if (share != NULL) + context_x11 = GDK_X11_GL_CONTEXT (share); + + return glXCreateContextAttribsARB (gdk_x11_display_get_xdisplay (display), + config, + context_x11 != NULL ? context_x11->glx_context : NULL, + True, + attrib_list); +} + +static GLXContext +create_gl_context (GdkDisplay *display, + GLXFBConfig config, + GdkGLContext *share) +{ + GdkX11GLContext *context_x11 = NULL; + + if (share != NULL) + context_x11 = GDK_X11_GL_CONTEXT (share); + + return glXCreateNewContext (gdk_x11_display_get_xdisplay (display), + config, + GLX_RGBA_TYPE, + context_x11 != NULL ? context_x11->glx_context : NULL, + True); +} + +static gboolean +gdk_x11_gl_context_realize (GdkGLContext *context, + GError **error) +{ + GdkDisplay *display; + GdkX11GLContext *context_x11; + GLXWindow drawable; + XVisualInfo *xvisinfo; + Display *dpy; + DrawableInfo *info; + GdkGLProfile profile; + GdkGLContext *share; + GdkWindow *window; + + window = gdk_gl_context_get_window (context); + display = gdk_window_get_display (window); + dpy = gdk_x11_display_get_xdisplay (display); + context_x11 = GDK_X11_GL_CONTEXT (context); + profile = gdk_gl_context_get_profile (context); + share = gdk_gl_context_get_shared_context (context); + + /* we check for the presence of the GLX_ARB_create_context_profile + * extension before checking for a GLXFBConfig. + */ + if (profile == GDK_GL_PROFILE_3_2_CORE) + { + GDK_NOTE (OPENGL, g_print ("Creating core GLX context\n")); + context_x11->glx_context = create_gl3_context (display, context_x11->glx_config, share); + } + else + { + /* GDK_GL_PROFILE_DEFAULT is currently + * equivalent to the LEGACY profile + */ + profile = GDK_GL_PROFILE_LEGACY; + GDK_NOTE (OPENGL, g_print ("Creating legacy GLX context\n")); + context_x11->glx_context = create_gl_context (display, context_x11->glx_config, share); + } + + if (context_x11->glx_context == NULL) + { + g_set_error_literal (error, GDK_GL_ERROR, + GDK_GL_ERROR_NOT_AVAILABLE, + _("Unable to create a GL context")); + return FALSE; + } + + xvisinfo = find_xvisinfo_for_fbconfig (display, context_x11->glx_config); + + info = get_glx_drawable_info (window->impl_window); + if (info == NULL) + { + XSetWindowAttributes attrs; + unsigned long mask; + + gdk_x11_display_error_trap_push (display); + + info = g_slice_new0 (DrawableInfo); + info->display = display; + info->last_frame_counter = 0; + + attrs.override_redirect = True; + attrs.colormap = XCreateColormap (dpy, DefaultRootWindow (dpy), xvisinfo->visual, AllocNone); + attrs.border_pixel = 0; + mask = CWOverrideRedirect | CWColormap | CWBorderPixel; + info->dummy_xwin = XCreateWindow (dpy, DefaultRootWindow (dpy), + -100, -100, 1, 1, + 0, + xvisinfo->depth, + CopyFromParent, + xvisinfo->visual, + mask, + &attrs); + XMapWindow(dpy, info->dummy_xwin); + + if (GDK_X11_DISPLAY (display)->glx_version >= 13) + { + info->glx_drawable = glXCreateWindow (dpy, context_x11->glx_config, + gdk_x11_window_get_xid (window->impl_window), + NULL); + info->dummy_glx = glXCreateWindow (dpy, context_x11->glx_config, info->dummy_xwin, NULL); + } + + if (gdk_x11_display_error_trap_pop (display)) + { + g_set_error_literal (error, GDK_GL_ERROR, + GDK_GL_ERROR_NOT_AVAILABLE, + _("Unable to create a GL context")); + + XFree (xvisinfo); + drawable_info_free (info); + glXDestroyContext (dpy, context_x11->glx_context); + context_x11->glx_context = NULL; + + return FALSE; + } + + set_glx_drawable_info (window->impl_window, info); + } + + XFree (xvisinfo); + + if (context_x11->is_attached) + drawable = info->glx_drawable ? info->glx_drawable : gdk_x11_window_get_xid (window->impl_window); + else + drawable = info->dummy_glx ? info->dummy_glx : info->dummy_xwin; + + context_x11->is_direct = glXIsDirect (dpy, context_x11->glx_context); + context_x11->drawable = drawable; + + GDK_NOTE (OPENGL, + g_print ("Realized GLX context[%p], %s\n", + context_x11->glx_context, + context_x11->is_direct ? "direct" : "indirect")); + + return TRUE; +} + static void gdk_x11_gl_context_dispose (GObject *gobject) { @@ -562,6 +741,7 @@ 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->realize = gdk_x11_gl_context_realize; context_class->end_frame = gdk_x11_gl_context_end_frame; context_class->texture_from_surface = gdk_x11_gl_context_texture_from_surface; @@ -645,11 +825,10 @@ gdk_x11_screen_init_gl (GdkScreen *screen) #define MAX_GLX_ATTRS 30 static gboolean -find_fbconfig_for_visual (GdkDisplay *display, - GdkVisual *visual, - GLXFBConfig *fb_config_out, - XVisualInfo **visinfo_out, - GError **error) +find_fbconfig_for_visual (GdkDisplay *display, + GdkVisual *visual, + GLXFBConfig *fb_config_out, + GError **error) { static int attrs[MAX_GLX_ATTRS]; Display *dpy = gdk_x11_display_get_xdisplay (display); @@ -710,16 +889,15 @@ find_fbconfig_for_visual (GdkDisplay *display, continue; if (visinfo->visualid != xvisual_id) - continue; + { + XFree (visinfo); + continue; + } if (fb_config_out != NULL) *fb_config_out = configs[i]; - if (visinfo_out != NULL) - *visinfo_out = visinfo; - else - XFree (visinfo); - + XFree (visinfo); retval = TRUE; goto out; } @@ -734,58 +912,6 @@ out: return retval; } -static GLXContext -create_gl3_context (GdkDisplay *display, - GLXFBConfig config, - GdkGLContext *share) -{ - /* There are no profiles before OpenGL 3.2. - * - * The GLX_ARB_create_context_profile spec says: - * - * If the requested OpenGL version is less than 3.2, - * GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality - * of the context is determined solely by the requested version. - * - * Which means we can ask for the CORE_PROFILE_BIT without asking for - * a 3.2 version. - */ - static const int attrib_list[] = { - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 2, - None, - }; - - GdkX11GLContext *context_x11 = NULL; - - if (share != NULL) - context_x11 = GDK_X11_GL_CONTEXT (share); - - return glXCreateContextAttribsARB (gdk_x11_display_get_xdisplay (display), - config, - context_x11 != NULL ? context_x11->glx_context : NULL, - True, - attrib_list); -} - -static GLXContext -create_gl_context (GdkDisplay *display, - GLXFBConfig config, - GdkGLContext *share) -{ - GdkX11GLContext *context_x11 = NULL; - - if (share != NULL) - context_x11 = GDK_X11_GL_CONTEXT (share); - - return glXCreateNewContext (gdk_x11_display_get_xdisplay (display), - config, - GLX_RGBA_TYPE, - context_x11 != NULL ? context_x11->glx_context : NULL, - True); -} - struct glvisualinfo { int supports_gl; int double_buffer; @@ -951,12 +1077,13 @@ save_cached_gl_visuals (GdkDisplay *display, int system, int rgba) visualdata[1] = rgba; gdk_x11_display_error_trap_push (display); - XChangeProperty(dpy, DefaultRootWindow (dpy), gdk_x11_get_xatom_by_name_for_display (display, "GDK_VISUALS"), - XA_INTEGER, 32, PropModeReplace, (unsigned char *)visualdata, 2); + XChangeProperty (dpy, DefaultRootWindow (dpy), + gdk_x11_get_xatom_by_name_for_display (display, "GDK_VISUALS"), + XA_INTEGER, 32, PropModeReplace, + (unsigned char *)visualdata, 2); gdk_x11_display_error_trap_pop_ignored (display); } - void _gdk_x11_screen_update_visuals_for_gl (GdkScreen *screen) { @@ -1038,27 +1165,24 @@ _gdk_x11_screen_update_visuals_for_gl (GdkScreen *screen) x11_screen->rgba_visual ? gdk_x11_visual_get_xvisual (x11_screen->rgba_visual)->visualid : 0); } - GdkGLContext * gdk_x11_window_create_gl_context (GdkWindow *window, - gboolean attached, - GdkGLProfile profile, - GdkGLContext *share, - GError **error) + gboolean attached, + GdkGLProfile profile, + GdkGLContext *share, + GError **error) { GdkDisplay *display; GdkX11GLContext *context; GdkVisual *visual; GLXFBConfig config; - GLXContext glx_context; - GLXWindow drawable; - gboolean is_direct; - XVisualInfo *xvisinfo; - Display *dpy; - DrawableInfo *info; display = gdk_window_get_display (window); + /* GDK_GL_PROFILE_DEFAULT is currently equivalent to the LEGACY profile */ + if (profile == GDK_GL_PROFILE_DEFAULT) + profile = GDK_GL_PROFILE_LEGACY; + if (!gdk_x11_screen_init_gl (gdk_window_get_screen (window))) { g_set_error_literal (error, GDK_GL_ERROR, @@ -1079,101 +1203,9 @@ gdk_x11_window_create_gl_context (GdkWindow *window, } visual = gdk_window_get_visual (window); - - if (!find_fbconfig_for_visual (display, visual, &config, &xvisinfo, error)) + if (!find_fbconfig_for_visual (display, visual, &config, error)) return NULL; - dpy = gdk_x11_display_get_xdisplay (display); - - /* we check for the presence of the GLX_ARB_create_context_profile - * extension before checking for a GLXFBConfig. - */ - if (profile == GDK_GL_PROFILE_3_2_CORE) - { - GDK_NOTE (OPENGL, g_print ("Creating core GLX context\n")); - glx_context = create_gl3_context (display, config, share); - } - else - { - /* GDK_GL_PROFILE_DEFAULT is currently - * equivalent to the LEGACY profile - */ - profile = GDK_GL_PROFILE_LEGACY; - GDK_NOTE (OPENGL, g_print ("Creating legacy GLX context\n")); - glx_context = create_gl_context (display, config, share); - } - - if (glx_context == NULL) - { - g_set_error_literal (error, GDK_GL_ERROR, - GDK_GL_ERROR_NOT_AVAILABLE, - _("Unable to create a GL context")); - return NULL; - } - - is_direct = glXIsDirect (dpy, glx_context); - - info = get_glx_drawable_info (window->impl_window); - if (info == NULL) - { - XSetWindowAttributes attrs; - unsigned long mask; - - gdk_x11_display_error_trap_push (display); - - info = g_slice_new0 (DrawableInfo); - info->display = display; - info->last_frame_counter = 0; - - attrs.override_redirect = True; - attrs.colormap = XCreateColormap (dpy, DefaultRootWindow (dpy), xvisinfo->visual, AllocNone); - attrs.border_pixel = 0; - mask = CWOverrideRedirect | CWColormap | CWBorderPixel; - info->dummy_xwin = XCreateWindow (dpy, DefaultRootWindow (dpy), - -100, -100, 1, 1, - 0, - xvisinfo->depth, - CopyFromParent, - xvisinfo->visual, - mask, - &attrs); - XMapWindow(dpy, info->dummy_xwin); - - if (GDK_X11_DISPLAY (display)->glx_version >= 13) - { - info->glx_drawable = glXCreateWindow (dpy, config, - gdk_x11_window_get_xid (window->impl_window), - NULL); - info->dummy_glx = glXCreateWindow (dpy, config, info->dummy_xwin, NULL); - } - - if (gdk_x11_display_error_trap_pop (display)) - { - g_set_error_literal (error, GDK_GL_ERROR, - GDK_GL_ERROR_NOT_AVAILABLE, - _("Unable to create a GL context")); - - drawable_info_free (info); - glXDestroyContext (dpy, glx_context); - - return NULL; - } - - set_glx_drawable_info (window->impl_window, info); - } - - XFree (xvisinfo); - - if (attached) - drawable = info->glx_drawable ? info->glx_drawable : gdk_x11_window_get_xid (window->impl_window); - else - drawable = info->dummy_glx ? info->dummy_glx : info->dummy_xwin; - - GDK_NOTE (OPENGL, - g_print ("Created GLX context[%p], %s\n", - glx_context, - is_direct ? "direct" : "indirect")); - context = g_object_new (GDK_TYPE_X11_GL_CONTEXT, "display", display, "window", window, @@ -1183,10 +1215,7 @@ gdk_x11_window_create_gl_context (GdkWindow *window, context->profile = profile; context->glx_config = config; - context->glx_context = glx_context; - context->drawable = drawable; context->is_attached = attached; - context->is_direct = is_direct; return GDK_GL_CONTEXT (context); } diff --git a/gtk/gtkglarea.c b/gtk/gtkglarea.c index ee7a30f381..b5f8a655d1 100644 --- a/gtk/gtkglarea.c +++ b/gtk/gtkglarea.c @@ -322,8 +322,21 @@ gtk_gl_area_real_create_context (GtkGLArea *area) GError *error = NULL; GdkGLContext *context; - context = gdk_window_create_gl_context (gtk_widget_get_window (widget), priv->profile, &priv->error); - gtk_gl_area_set_error (area, error); + context = gdk_window_create_gl_context (gtk_widget_get_window (widget), priv->profile, &error); + if (priv->error != NULL) + { + gtk_gl_area_set_error (area, error); + g_clear_object (&context); + return NULL; + } + + gdk_gl_context_realize (context, &error); + if (priv->error != NULL) + { + gtk_gl_area_set_error (area, error); + g_clear_object (&context); + return NULL; + } return context; }