diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2014-03-23 17:37:54 +0000 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2014-08-12 10:39:28 +0100 |
commit | 5052aa4a9acd18b2cd06d543542ec7f5dce58ef1 (patch) | |
tree | 3be6ceb7ca5d2e746f3cbf5727d3d18374d37602 | |
parent | a6ee04781fa85aae13c4c64583c36a79b787cfef (diff) | |
download | gtk+-5052aa4a9acd18b2cd06d543542ec7f5dce58ef1.tar.gz |
Implement GdkGLContext and GdkGLPixelFormat
GdkGLPixelFormat is an ancillary class to specify pixel formats, buffer
types, and buffer sizes for GL context.
GdkGLContext is the wrapper around platform-specific GL context API.
This commit adds the base classes, and an implementation on X11.
https://bugzilla.gnome.org/show_bug.cgi?id=119189
-rw-r--r-- | gdk/Makefile.am | 6 | ||||
-rw-r--r-- | gdk/gdk.h | 2 | ||||
-rw-r--r-- | gdk/gdkdisplay.c | 130 | ||||
-rw-r--r-- | gdk/gdkdisplay.h | 5 | ||||
-rw-r--r-- | gdk/gdkdisplayprivate.h | 25 | ||||
-rw-r--r-- | gdk/gdkglcontext.c | 489 | ||||
-rw-r--r-- | gdk/gdkglcontext.h | 67 | ||||
-rw-r--r-- | gdk/gdkglcontextprivate.h | 53 | ||||
-rw-r--r-- | gdk/gdkglpixelformat.c | 439 | ||||
-rw-r--r-- | gdk/gdkglpixelformat.h | 55 | ||||
-rw-r--r-- | gdk/gdkglpixelformatprivate.h | 43 | ||||
-rw-r--r-- | gdk/gdkinternals.h | 3 | ||||
-rw-r--r-- | gdk/gdktypes.h | 22 | ||||
-rw-r--r-- | gdk/x11/Makefile.am | 3 | ||||
-rw-r--r-- | gdk/x11/gdkdisplay-x11.c | 6 | ||||
-rw-r--r-- | gdk/x11/gdkdisplay-x11.h | 14 | ||||
-rw-r--r-- | gdk/x11/gdkglcontext-x11.c | 691 | ||||
-rw-r--r-- | gdk/x11/gdkglcontext-x11.h | 56 | ||||
-rw-r--r-- | gdk/x11/gdkx.h | 1 | ||||
-rw-r--r-- | gdk/x11/gdkx11glcontext.h | 24 |
20 files changed, 2132 insertions, 2 deletions
diff --git a/gdk/Makefile.am b/gdk/Makefile.am index d52fdd292b..fd60da1647 100644 --- a/gdk/Makefile.am +++ b/gdk/Makefile.am @@ -75,6 +75,8 @@ gdk_public_h_sources = \ gdkdnd.h \ gdkevents.h \ gdkframetimings.h \ + gdkglcontext.h \ + gdkglpixelformat.h \ gdkkeys.h \ gdkkeysyms.h \ gdkkeysyms-compat.h \ @@ -111,6 +113,8 @@ gdk_private_headers = \ gdkdndprivate.h \ gdkframeclockidle.h \ gdkframeclockprivate.h \ + gdkglcontextprivate.h \ + gdkglpixelformatprivate.h \ gdkscreenprivate.h \ gdkinternals.h \ gdkintl.h \ @@ -135,6 +139,8 @@ gdk_c_sources = \ gdkdnd.c \ gdkevents.c \ gdkframetimings.c \ + gdkglcontext.c \ + gdkglpixelformat.c \ gdkglobals.c \ gdkkeys.c \ gdkkeyuni.c \ @@ -41,6 +41,8 @@ #include <gdk/gdkevents.h> #include <gdk/gdkframeclock.h> #include <gdk/gdkframetimings.h> +#include <gdk/gdkglpixelformat.h> +#include <gdk/gdkglcontext.h> #include <gdk/gdkkeys.h> #include <gdk/gdkkeysyms.h> #include <gdk/gdkmain.h> diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index 34b6cab8ad..2797803ffd 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -2225,3 +2225,133 @@ gdk_error_trap_pop (void) { return gdk_error_trap_pop_internal (TRUE); } + +/*< private > + * gdk_display_create_gl_context: + * @display: a #GdkDisplay + * @format: a #GdkGLPixelFormat + * @share: (optional): an optional shared #GdkGLContext + * + * Creates a new platform-specific #GdkGLContext for the + * given @display and @format. + * + * Returns: (transfer full): the newly created #GdkGLContext + */ +GdkGLContext * +gdk_display_create_gl_context (GdkDisplay *display, + GdkGLPixelFormat *format, + GdkGLContext *share) +{ + return GDK_DISPLAY_GET_CLASS (display)->create_gl_context (display, format, share); +} + +/*< 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) +{ + GDK_DISPLAY_GET_CLASS (display)->destroy_gl_context (display, context); +} + +/*< private > + * gdk_display_make_gl_context_current: + * @display: a #GdkDisplay + * @context: (optional): a #GdkGLContext, or %NULL + * @window: (optional): a #GdkWindow, or %NULL + * + * Makes the given @context the current GL context, or unsets + * the current GL context if @context is %NULL. + * + * Returns: %TRUE if successful + */ +gboolean +gdk_display_make_gl_context_current (GdkDisplay *display, + GdkGLContext *context, + GdkWindow *window) +{ + GdkGLContext *current = gdk_display_get_current_gl_context (display); + + if (current == context) + return TRUE; + + 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); + + return GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context, window); +} + +/*< 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"); +} + +/*< private > + * gdk_display_validate_gl_pixel_format: + * @display: a #GdkDisplay + * @format: a #GdkGLPixelFormat + * @error: return location for a #GError + * + * Validates a #GdkGLPixelFormat for the given display. + * + * If the pixel format is invalid, @error will be set. + * + * Returns: %TRUE if the pixel format is valid + */ +gboolean +gdk_display_validate_gl_pixel_format (GdkDisplay *display, + GdkGLPixelFormat *format, + GError **error) +{ + return GDK_DISPLAY_GET_CLASS (display)->validate_gl_pixel_format (display, format, error); +} + +/** + * gdk_display_get_gl_context: + * @display: a #GdkDisplay + * @format: a #GdkGLPixelFormat + * @share: (optional): a shared #GdkGLContext, or %NULL + * + * Creates a new #GdkGLContext for the given display, with the given + * pixel format. + * + * If @share is not %NULL then the newly created #GdkGLContext will + * share resources with it. + * + * Returns: (transfer full): the newly created #GdkGLContext, or + * %NULL on error + * + * Since: 3.14 + */ +GdkGLContext * +gdk_display_get_gl_context (GdkDisplay *display, + GdkGLPixelFormat *format, + GdkGLContext *share) +{ + g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL); + g_return_val_if_fail (GDK_IS_GL_PIXEL_FORMAT (format), NULL); + g_return_val_if_fail (share == NULL || GDK_IS_GL_CONTEXT (share), NULL); + + return gdk_display_create_gl_context (display, format, share); +} diff --git a/gdk/gdkdisplay.h b/gdk/gdkdisplay.h index 5595cb9fb7..a457d890e7 100644 --- a/gdk/gdkdisplay.h +++ b/gdk/gdkdisplay.h @@ -171,6 +171,11 @@ GdkDeviceManager * gdk_display_get_device_manager (GdkDisplay *display); GDK_AVAILABLE_IN_ALL GdkAppLaunchContext *gdk_display_get_app_launch_context (GdkDisplay *display); +GDK_AVAILABLE_IN_3_14 +GdkGLContext *gdk_display_get_gl_context (GdkDisplay *display, + GdkGLPixelFormat *format, + GdkGLContext *share); + G_END_DECLS #endif /* __GDK_DISPLAY_H__ */ diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h index 7911d25f4f..c7fdb7124d 100644 --- a/gdk/gdkdisplayprivate.h +++ b/gdk/gdkdisplayprivate.h @@ -225,6 +225,18 @@ struct _GdkDisplayClass gchar * (*utf8_to_string_target) (GdkDisplay *display, const gchar *text); + GdkGLContext * (*create_gl_context) (GdkDisplay *display, + GdkGLPixelFormat *format, + GdkGLContext *share); + gboolean (*make_gl_context_current) (GdkDisplay *display, + GdkGLContext *context, + GdkWindow *drawable); + void (*destroy_gl_context) (GdkDisplay *display, + GdkGLContext *context); + gboolean (*validate_gl_pixel_format) (GdkDisplay *display, + GdkGLPixelFormat *format, + GError **error); + /* Signals */ void (*opened) (GdkDisplay *display); void (*closed) (GdkDisplay *display, @@ -303,6 +315,19 @@ void _gdk_display_create_window_impl (GdkDisplay *display gint attributes_mask); GdkWindow * _gdk_display_create_window (GdkDisplay *display); +gboolean gdk_display_validate_gl_pixel_format (GdkDisplay *display, + GdkGLPixelFormat *format, + GError **error); +GdkGLContext * gdk_display_create_gl_context (GdkDisplay *display, + GdkGLPixelFormat *format, + GdkGLContext *share); +void gdk_display_destroy_gl_context (GdkDisplay *display, + GdkGLContext *context); +gboolean gdk_display_make_gl_context_current (GdkDisplay *display, + GdkGLContext *context, + GdkWindow *window); +GdkGLContext * gdk_display_get_current_gl_context (GdkDisplay *display); + G_END_DECLS #endif /* __GDK_DISPLAY_PRIVATE_H__ */ diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c new file mode 100644 index 0000000000..014e7fa826 --- /dev/null +++ b/gdk/gdkglcontext.c @@ -0,0 +1,489 @@ +/* GDK - The GIMP Drawing Kit + * + * gdkglcontext.c: GL context abstraction + * + * Copyright © 2014 Emmanuele Bassi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * SECTION:gdkglcontext + * @Title: GdkGLContext + * @Short_description: GL contexts + * + * #GdkGLContext is an object representing the platform-specific + * GL drawing context. + * + * #GdkGLContexts are created via a #GdkDisplay by specifying a + * #GdkGLPixelFormat to be used by the GL context. + * + * Support for #GdkGLContext is platform specific. + */ + +#include "config.h" + +#include "gdkglcontextprivate.h" +#include "gdkdisplayprivate.h" +#include "gdkglpixelformat.h" +#include "gdkvisual.h" + +#include "gdkintl.h" + +typedef struct { + GdkDisplay *display; + GdkGLPixelFormat *pixel_format; + GdkWindow *window; + GdkVisual *visual; + + guint swap_interval; +} GdkGLContextPrivate; + +enum { + PROP_0, + + PROP_DISPLAY, + PROP_PIXEL_FORMAT, + PROP_WINDOW, + PROP_VISUAL, + + PROP_SWAP_INTERVAL, + + LAST_PROP +}; + +static GParamSpec *obj_pspecs[LAST_PROP] = { NULL, }; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkGLContext, gdk_gl_context, G_TYPE_OBJECT) + +static void +gdk_gl_context_dispose (GObject *gobject) +{ + GdkGLContext *context = GDK_GL_CONTEXT (gobject); + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + + gdk_display_destroy_gl_context (priv->display, context); + + g_clear_object (&priv->display); + g_clear_object (&priv->pixel_format); + g_clear_object (&priv->window); + g_clear_object (&priv->visual); + + G_OBJECT_CLASS (gdk_gl_context_parent_class)->dispose (gobject); +} + +static void +gdk_gl_context_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject); + + switch (prop_id) + { + case PROP_DISPLAY: + priv->display = g_object_ref (g_value_get_object (value)); + break; + + case PROP_PIXEL_FORMAT: + priv->pixel_format = g_object_ref (g_value_get_object (value)); + break; + + case PROP_WINDOW: + { + GdkGLContext *context = GDK_GL_CONTEXT (gobject); + GdkWindow *window = g_value_get_object (value); + + gdk_gl_context_set_window (context, window); + } + break; + + case PROP_VISUAL: + { + GdkVisual *visual = g_value_get_object (value); + + if (visual != NULL) + priv->visual = g_object_ref (visual); + } + break; + + case PROP_SWAP_INTERVAL: + priv->swap_interval = g_value_get_uint (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +gdk_gl_context_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject); + + switch (prop_id) + { + case PROP_DISPLAY: + g_value_set_object (value, priv->display); + break; + + case PROP_PIXEL_FORMAT: + g_value_set_object (value, priv->pixel_format); + break; + + case PROP_WINDOW: + g_value_set_object (value, priv->window); + break; + + case PROP_VISUAL: + g_value_set_object (value, priv->visual); + break; + + case PROP_SWAP_INTERVAL: + g_value_set_uint (value, priv->swap_interval); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +gdk_gl_context_class_init (GdkGLContextClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + /** + * GdkGLContext:display: + * + * The #GdkDisplay used by the GL context. + * + * Since: 3.14 + */ + obj_pspecs[PROP_DISPLAY] = + g_param_spec_object ("display", + "Display", + "The GDK display used by the GL context", + GDK_TYPE_DISPLAY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + /** + * GdkGLContext:pixel-format: + * + * The #GdkGLPixelFormat used to create the GL context. + * + * Since: 3.14 + */ + obj_pspecs[PROP_PIXEL_FORMAT] = + g_param_spec_object ("pixel-format", + "Pixel Format", + "The GDK pixel format used by the GL context", + GDK_TYPE_GL_PIXEL_FORMAT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + /** + * GdkGLContext:window: + * + * The #GdkWindow currently bound to the GL context. + * + * You typically need to bind a #GdkWindow to a #GdkGLContext prior + * to calling gdk_gl_context_make_current(). + * + * Since: 3.14 + */ + obj_pspecs[PROP_WINDOW] = + g_param_spec_object ("window", + P_("Window"), + P_("The GDK window currently bound to the GL context"), + GDK_TYPE_WINDOW, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * GdkGLContext:visual: + * + * The #GdkVisual used by the GL context. + * + * Since: 3.14 + */ + obj_pspecs[PROP_VISUAL] = + g_param_spec_object ("visual", + P_("Visual"), + P_("The GDK visual used by the GL context"), + GDK_TYPE_VISUAL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + /** + * GdkGLContext:swap-interval: + * + * The swap interval of the GL context. + * + * If set to 0 (the default), gdk_gl_context_flush_buffer() will execute + * the buffer flush as soon as possible. + * + * If set to 1, calls buffers will be flushed only during the vertical + * refresh of the display. + * + * Since: 3.14 + */ + obj_pspecs[PROP_SWAP_INTERVAL] = + g_param_spec_uint ("swap-interval", + P_("Swap Interval"), + P_("The swap interval of the GL context"), + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + gobject_class->set_property = gdk_gl_context_set_property; + gobject_class->get_property = gdk_gl_context_get_property; + gobject_class->dispose = gdk_gl_context_dispose; + + g_object_class_install_properties (gobject_class, LAST_PROP, obj_pspecs); +} + +static void +gdk_gl_context_init (GdkGLContext *self) +{ +} + +/** + * gdk_gl_context_get_display: + * @context: a #GdkGLContext + * + * Retrieves the #GdkDisplay associated with the @context. + * + * Returns: (transfer none): the #GdkDisplay + * + * Since: 3.14 + */ +GdkDisplay * +gdk_gl_context_get_display (GdkGLContext *context) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + + g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL); + + return priv->display; +} + +/** + * gdk_gl_context_get_pixel_format: + * @context: a #GdkGLContext + * + * Retrieves the #GdkGLPixelFormat associated with the @context. + * + * Returns: (transfer none): the #GdkDisplay + * + * Since: 3.14 + */ +GdkGLPixelFormat * +gdk_gl_context_get_pixel_format (GdkGLContext *context) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + + g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL); + + return priv->pixel_format; +} + +/** + * gdk_gl_context_get_visual: + * @context: a #GdkGLContext + * + * Retrieves the #GdkVisual associated with the @context. + * + * Returns: (transfer none): the #GdkVisual + * + * Since: 3.14 + */ +GdkVisual * +gdk_gl_context_get_visual (GdkGLContext *context) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + + g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL); + + return priv->visual; +} + +/** + * gdk_gl_context_flush_buffer: + * @context: a #GdkGLContext + * + * Copies the back buffer to the front buffer. + * + * If the #GdkGLContext is not double buffered, this function does not + * do anything. + * + * Depending on the value of the #GdkGLContext:swap-interval property, + * the copy may take place during the vertical refresh of the display + * rather than immediately. + * + * This function calls `glFlush()` implicitly before returning. + * + * Since: 3.14 + */ +void +gdk_gl_context_flush_buffer (GdkGLContext *context) +{ + g_return_if_fail (GDK_IS_GL_CONTEXT (context)); + + GDK_GL_CONTEXT_GET_CLASS (context)->flush_buffer (context); +} + +/** + * gdk_gl_context_make_current: + * @context: a #GdkGLContext + * + * Makes the @context the current one. + * + * Returns: %TRUE if the context is current + * + * Since: 3.14 + */ +gboolean +gdk_gl_context_make_current (GdkGLContext *context) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + + g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), FALSE); + + return gdk_display_make_gl_context_current (priv->display, context, priv->window); +} + +/** + * gdk_gl_context_set_window: + * @context: a #GdkGLContext + * @window: (optional): a #GdkWindow, or %NULL + * + * Sets the #GdkWindow used to display the draw commands. + * + * If @window is %NULL, the @context is detached from the window. + * + * Since: 3.14 + */ +void +gdk_gl_context_set_window (GdkGLContext *context, + GdkWindow *window) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + + g_return_if_fail (GDK_IS_GL_CONTEXT (context)); + g_return_if_fail (window == NULL || GDK_IS_WINDOW (window)); + + if (priv->window == window) + return; + + g_clear_object (&priv->window); + + if (window != NULL) + priv->window = g_object_ref (window); + + GDK_GL_CONTEXT_GET_CLASS (context)->set_window (context, window); +} + +/** + * gdk_gl_context_get_window: + * @context: a #GdkGLContext + * + * Retrieves the #GdkWindow used by the @context. + * + * Returns: (transfer none): a #GdkWindow or %NULL + * + * Since: 3.14 + */ +GdkWindow * +gdk_gl_context_get_window (GdkGLContext *context) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + + g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL); + + return priv->window; +} + +/** + * gdk_gl_context_update: + * @context: a #GdkGLContext + * + * Updates the @context when the #GdkWindow used to display the + * rendering changes size or position. + * + * Since: 3.14 + */ +void +gdk_gl_context_update (GdkGLContext *context) +{ + g_return_if_fail (GDK_IS_GL_CONTEXT (context)); + + GDK_GL_CONTEXT_GET_CLASS (context)->update (context); +} + +/** + * gdk_gl_context_clear_current: + * + * Clears the current #GdkGLContext. + * + * Since: 3.14 + */ +void +gdk_gl_context_clear_current (void) +{ + GdkDisplay *display = gdk_display_get_default (); + + gdk_display_make_gl_context_current (display, NULL, NULL); +} + +/** + * gdk_gl_context_get_current: + * + * Retrieves the current #GdkGLContext. + * + * Returns: (transfer none): the current #GdkGLContext, or %NULL + * + * Since: 3.14 + */ +GdkGLContext * +gdk_gl_context_get_current (void) +{ + GdkDisplay *display = gdk_display_get_default (); + + return gdk_display_get_current_gl_context (display); +} + +/*< private > + * gdk_gl_context_get_swap_interval: + * @context: a #GdkGLContext + * + * Retrieves the swap interval of the context. + * + * Returns: the swap interval + */ +guint +gdk_gl_context_get_swap_interval (GdkGLContext *context) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + + return priv->swap_interval; +} diff --git a/gdk/gdkglcontext.h b/gdk/gdkglcontext.h new file mode 100644 index 0000000000..ff8853d89c --- /dev/null +++ b/gdk/gdkglcontext.h @@ -0,0 +1,67 @@ +/* GDK - The GIMP Drawing Kit + * + * gdkglcontext.h: GL context abstraction + * + * Copyright © 2014 Emmanuele Bassi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GDK_GL_CONTEXT_H__ +#define __GDK_GL_CONTEXT_H__ + +#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION) +#error "Only <gdk/gdk.h> can be included directly." +#endif + +#include <gdk/gdkversionmacros.h> +#include <gdk/gdktypes.h> + +G_BEGIN_DECLS + +#define GDK_TYPE_GL_CONTEXT (gdk_gl_context_get_type ()) +#define GDK_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContext)) +#define GDK_IS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_GL_CONTEXT)) + +GDK_AVAILABLE_IN_3_14 +GType gdk_gl_context_get_type (void) G_GNUC_CONST; + +GDK_AVAILABLE_IN_3_14 +GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context); + +GDK_AVAILABLE_IN_3_14 +GdkGLPixelFormat * gdk_gl_context_get_pixel_format (GdkGLContext *context); + +GDK_AVAILABLE_IN_3_14 +void gdk_gl_context_clear_window (GdkGLContext *context); +GDK_AVAILABLE_IN_3_14 +void gdk_gl_context_flush_buffer (GdkGLContext *context); +GDK_AVAILABLE_IN_3_14 +gboolean gdk_gl_context_make_current (GdkGLContext *context); +GDK_AVAILABLE_IN_3_14 +void gdk_gl_context_set_window (GdkGLContext *context, + GdkWindow *window); +GDK_AVAILABLE_IN_3_14 +GdkWindow * gdk_gl_context_get_window (GdkGLContext *context); +GDK_AVAILABLE_IN_3_14 +void gdk_gl_context_update (GdkGLContext *context); + +GDK_AVAILABLE_IN_3_14 +void gdk_gl_context_clear_current (void); +GDK_AVAILABLE_IN_3_14 +GdkGLContext * gdk_gl_context_get_current (void); + +G_END_DECLS + +#endif /* __GDK_GL_CONTEXT_H__ */ diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h new file mode 100644 index 0000000000..6551adb81a --- /dev/null +++ b/gdk/gdkglcontextprivate.h @@ -0,0 +1,53 @@ +/* GDK - The GIMP Drawing Kit + * + * gdkglcontextprivate.h: GL context abstraction + * + * Copyright © 2014 Emmanuele Bassi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GDK_GL_CONTEXT_PRIVATE_H__ +#define __GDK_GL_CONTEXT_PRIVATE_H__ + +#include "gdkglcontext.h" + +G_BEGIN_DECLS + +#define GDK_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GL_CONTEXT, GdkGLContextClass)) +#define GDK_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GL_CONTEXT)) +#define GDK_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContextClass)) + +typedef struct _GdkGLContextClass GdkGLContextClass; + +struct _GdkGLContext +{ + GObject parent_instance; +}; + +struct _GdkGLContextClass +{ + GObjectClass parent_class; + + void (* set_window) (GdkGLContext *context, + GdkWindow *window); + void (* update) (GdkGLContext *context); + void (* flush_buffer) (GdkGLContext *context); +}; + +guint gdk_gl_context_get_swap_interval (GdkGLContext *context); + +G_END_DECLS + +#endif /* __GDK_GL_CONTEXT_PRIVATE_H__ */ diff --git a/gdk/gdkglpixelformat.c b/gdk/gdkglpixelformat.c new file mode 100644 index 0000000000..10986e2537 --- /dev/null +++ b/gdk/gdkglpixelformat.c @@ -0,0 +1,439 @@ +/* GDK - The GIMP Drawing Kit + * + * gdkglpixelformat.c: GL pixel formats + * + * Copyright © 2014 Emmanuele Bassi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * SECTION:gdkglpixelformat + * @Title: GdkGLPixelFormat + * @Short_description: Specify the pixel format for GL contexts + * + * The #GdkGLPixelFormat class is used to specify the types and sizes of + * buffers to be used by a #GdkGLContext, as well as other configuration + * parameters. + * + * You should typically try to create a #GdkGLPixelFormat for a given + * configuration, and if the creation fails, you can either opt to + * show an error, or change the configuration until you find a suitable + * pixel format. + * + * For instance, the following example creates a #GdkGLPixelFormat with + * double buffering enabled, and a 32-bit depth buffer: + * + * |[<!-- language="C" --> + * GdkGLPixelFormat *format; + * GError *error = NULL; + * + * format = gdk_gl_pixel_format_new (&error, + * "double-buffer", TRUE, + * "depth-size", 32, + * NULL); + * if (format == NULL) + * { + * // creation failed; try again with a different set + * // of attributes + * } + * ]| + */ + +#include "config.h" + +#include <gio/gio.h> + +#include "gdkglpixelformatprivate.h" + +#include "gdkdisplayprivate.h" +#include "gdkenumtypes.h" + +#include "gdkintl.h" + +enum { + PROP_0, + + PROP_DISPLAY, + + /* bool */ + PROP_DOUBLE_BUFFER, + PROP_MULTI_SAMPLE, + + /* uint */ + PROP_AUX_BUFFERS, + PROP_COLOR_SIZE, + PROP_ALPHA_SIZE, + PROP_DEPTH_SIZE, + PROP_STENCIL_SIZE, + PROP_ACCUM_SIZE, + PROP_SAMPLE_BUFFERS, + PROP_SAMPLES, + + /* enum */ + PROP_PROFILE, + + LAST_PROP +}; + +static GParamSpec *obj_props[LAST_PROP] = { NULL, }; + +static void initable_iface_init (GInitableIface *init); + +G_DEFINE_QUARK (gdk-gl-pixel-format-error-quark, gdk_gl_pixel_format_error) + +G_DEFINE_TYPE_WITH_CODE (GdkGLPixelFormat, gdk_gl_pixel_format, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + initable_iface_init)) + +static gboolean +gdk_gl_pixel_format_init_internal (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + GdkGLPixelFormat *self = GDK_GL_PIXEL_FORMAT (initable); + + /* use the default display */ + if (self->display == NULL) + self->display = g_object_ref (gdk_display_get_default ()); + + self->is_valid = gdk_display_validate_gl_pixel_format (self->display, self, error); + self->is_validated = TRUE; + + return self->is_valid; +} + +static void +initable_iface_init (GInitableIface *iface) +{ + iface->init = gdk_gl_pixel_format_init_internal; +} + +static void +gdk_gl_pixel_format_dispose (GObject *gobject) +{ + GdkGLPixelFormat *self = GDK_GL_PIXEL_FORMAT (gobject); + + g_clear_object (&self->display); + + G_OBJECT_CLASS (gdk_gl_pixel_format_parent_class)->dispose (gobject); +} + +static void +gdk_gl_pixel_format_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GdkGLPixelFormat *self = GDK_GL_PIXEL_FORMAT (gobject); + + switch (prop_id) + { + case PROP_DISPLAY: + { + GdkDisplay *display = g_value_get_object (value); + + if (display != NULL) + self->display = g_object_ref (display); + } + break; + + case PROP_DOUBLE_BUFFER: + self->double_buffer = g_value_get_boolean (value); + break; + + case PROP_MULTI_SAMPLE: + self->multi_sample = g_value_get_boolean (value); + break; + + case PROP_AUX_BUFFERS: + self->aux_buffers = g_value_get_int (value); + break; + + case PROP_COLOR_SIZE: + self->color_size = g_value_get_int (value); + break; + + case PROP_ALPHA_SIZE: + self->alpha_size = g_value_get_int (value); + break; + + case PROP_DEPTH_SIZE: + self->depth_size = g_value_get_int (value); + break; + + case PROP_STENCIL_SIZE: + self->stencil_size = g_value_get_int (value); + break; + + case PROP_ACCUM_SIZE: + self->accum_size = g_value_get_int (value); + break; + + case PROP_SAMPLE_BUFFERS: + self->sample_buffers = g_value_get_int (value); + break; + + case PROP_SAMPLES: + self->samples = g_value_get_int (value); + break; + + case PROP_PROFILE: + self->profile = g_value_get_enum (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +gdk_gl_pixel_format_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GdkGLPixelFormat *self = GDK_GL_PIXEL_FORMAT (gobject); + + switch (prop_id) + { + case PROP_DISPLAY: + g_value_set_object (value, self->display); + break; + + case PROP_DOUBLE_BUFFER: + g_value_set_boolean (value, self->double_buffer); + break; + + case PROP_MULTI_SAMPLE: + g_value_set_boolean (value, self->multi_sample); + break; + + case PROP_AUX_BUFFERS: + g_value_set_int (value, self->aux_buffers); + break; + + case PROP_COLOR_SIZE: + g_value_set_int (value, self->color_size); + break; + + case PROP_ALPHA_SIZE: + g_value_set_int (value, self->alpha_size); + break; + + case PROP_DEPTH_SIZE: + g_value_set_int (value, self->depth_size); + break; + + case PROP_STENCIL_SIZE: + g_value_set_int (value, self->stencil_size); + break; + + case PROP_ACCUM_SIZE: + g_value_set_int (value, self->accum_size); + break; + + case PROP_SAMPLE_BUFFERS: + g_value_set_int (value, self->sample_buffers); + break; + + case PROP_SAMPLES: + g_value_set_int (value, self->samples); + break; + + case PROP_PROFILE: + g_value_set_enum (value, self->profile); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +gdk_gl_pixel_format_class_init (GdkGLPixelFormatClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = gdk_gl_pixel_format_set_property; + gobject_class->get_property = gdk_gl_pixel_format_get_property; + gobject_class->dispose = gdk_gl_pixel_format_dispose; + + obj_props[PROP_DISPLAY] = + g_param_spec_object ("display", + P_("Display"), + P_("The GDK display associated with the pixel format"), + GDK_TYPE_DISPLAY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_DOUBLE_BUFFER] = + g_param_spec_boolean ("double-buffer", + P_("Double Buffer"), + P_(""), + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_MULTI_SAMPLE] = + g_param_spec_boolean ("multi-sample", + P_("Multi Sample"), + P_(""), + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_AUX_BUFFERS] = + g_param_spec_int ("aux-buffers", + P_("Auxiliary Buffers"), + P_(""), + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_COLOR_SIZE] = + g_param_spec_int ("color-size", + P_("Color Size"), + P_(""), + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_ALPHA_SIZE] = + g_param_spec_int ("alpha-size", + P_("Alpha Size"), + P_(""), + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_DEPTH_SIZE] = + g_param_spec_int ("depth-size", + P_("Depth Size"), + P_(""), + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_STENCIL_SIZE] = + g_param_spec_int ("stencil-size", + P_("Stencil Size"), + P_(""), + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_ACCUM_SIZE] = + g_param_spec_int ("accum-size", + P_("Accumulation Size"), + P_(""), + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_SAMPLE_BUFFERS] = + g_param_spec_int ("sample-buffers", + P_("Sample Buffers"), + P_(""), + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_SAMPLES] = + g_param_spec_int ("samples", + P_("Samples"), + P_(""), + -1, G_MAXINT, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_props[PROP_PROFILE] = + g_param_spec_enum ("profile", + P_("Profile"), + P_(""), + GDK_TYPE_GL_PIXEL_FORMAT_PROFILE, + GDK_GL_PIXEL_FORMAT_PROFILE_DEFAULT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (gobject_class, LAST_PROP, obj_props); +} + +static void +gdk_gl_pixel_format_init (GdkGLPixelFormat *self) +{ +} + +/** + * gdk_gl_pixel_format_new: + * @error: return location for a #GError, or %NULL + * @first_property: the first property to set + * @...: the value of the @first_property, followed by a %NULL terminated + * set of property, value pairs + * + * Creates a new #GdkGLPixelFormat with the given list of properties. + * + * If the pixel format is not valid, then this function will return + * a %NULL value, and @error will be set. + * + * Returns: the newly created #GdkGLPixelFormat, or %NULL + * + * Since: 3.14 + */ +GdkGLPixelFormat * +gdk_gl_pixel_format_new (GError **error, + const char *first_property, + ...) +{ + gpointer res; + va_list args; + + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + va_start (args, first_property); + res = g_initable_new_valist (GDK_TYPE_GL_PIXEL_FORMAT, first_property, args, NULL, error); + va_end (args); + + return res; +} + +/** + * gdk_gl_pixel_format_get_display: + * @format: a #GdkGLPixelFormat + * + * Retrieves the #GdkDisplay used to validate the pixel format. + * + * Returns: (transfer none): the #GdkDisplay + * + * Since: 3.14 + */ +GdkDisplay * +gdk_gl_pixel_format_get_display (GdkGLPixelFormat *format) +{ + g_return_val_if_fail (GDK_IS_GL_PIXEL_FORMAT (format), NULL); + + return format->display; +} diff --git a/gdk/gdkglpixelformat.h b/gdk/gdkglpixelformat.h new file mode 100644 index 0000000000..9aa9882d6b --- /dev/null +++ b/gdk/gdkglpixelformat.h @@ -0,0 +1,55 @@ +/* GDK - The GIMP Drawing Kit + * + * gdkglpixelformat.h: GL pixel formats + * + * Copyright © 2014 Emmanuele Bassi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GDK_GL_PIXEL_FORMAT_H__ +#define __GDK_GL_PIXEL_FORMAT_H__ + +#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION) +#error "Only <gdk/gdk.h> can be included directly." +#endif + +#include <gdk/gdkversionmacros.h> +#include <gdk/gdktypes.h> + +G_BEGIN_DECLS + +#define GDK_TYPE_GL_PIXEL_FORMAT (gdk_gl_pixel_format_get_type ()) +#define GDK_GL_PIXEL_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_GL_PIXEL_FORMAT, GdkGLPixelFormat)) +#define GDK_IS_GL_PIXEL_FORMAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_GL_PIXEL_FORMAT)) + +#define GDK_GL_PIXEL_FORMAT_ERROR (gdk_gl_pixel_format_error_quark ()) + +typedef struct _GdkGLPixelFormatClass GdkGLPixelFormatClass; + +GDK_AVAILABLE_IN_3_14 +GType gdk_gl_pixel_format_get_type (void) G_GNUC_CONST; +GDK_AVAILABLE_IN_3_14 +GQuark gdk_gl_pixel_format_error_quark (void); + +GDK_AVAILABLE_IN_3_14 +GdkGLPixelFormat * gdk_gl_pixel_format_new (GError **error, + const char *first_property, + ...); +GDK_AVAILABLE_IN_3_14 +GdkDisplay * gdk_gl_pixel_format_get_display (GdkGLPixelFormat *format); + +G_END_DECLS + +#endif /* __GDK_GL_PIXEL_FORMAT_H__ */ diff --git a/gdk/gdkglpixelformatprivate.h b/gdk/gdkglpixelformatprivate.h new file mode 100644 index 0000000000..fd9e614600 --- /dev/null +++ b/gdk/gdkglpixelformatprivate.h @@ -0,0 +1,43 @@ +#ifndef __GDK_GL_PIXEL_FORMAT_PRIVATE_H__ +#define __GDK_GL_PIXEL_FORMAT_PRIVATE_H__ + +#include "gdkglpixelformat.h" + +G_BEGIN_DECLS + +#define GDK_GL_PIXEL_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GL_PIXEL_FORMAT, GdkGLPixelFormatClass)) +#define GDK_IS_GL_PIXEL_FORMAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GL_PIXEL_FORMAT)) +#define GDK_GL_PIXEL_FORMAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GL_PIXEL_FORMAT, GdkGLPixelFormatClass)) + +struct _GdkGLPixelFormat +{ + GObject parent_instance; + + gboolean is_validated; + gboolean is_valid; + + GdkDisplay *display; + + gboolean double_buffer; + gboolean multi_sample; + + int aux_buffers; + int color_size; + int alpha_size; + int depth_size; + int stencil_size; + int accum_size; + int sample_buffers; + int samples; + + GdkGLPixelFormatProfile profile; +}; + +struct _GdkGLPixelFormatClass +{ + GObjectClass parent_class; +}; + +G_END_DECLS + +#endif /* __GDK_GL_PIXEL_FORMAT_PRIVATE_H__ */ diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index f58ccb0084..791fa87b22 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -84,7 +84,8 @@ typedef enum { GDK_DEBUG_DRAW = 1 << 9, GDK_DEBUG_EVENTLOOP = 1 << 10, GDK_DEBUG_FRAMES = 1 << 11, - GDK_DEBUG_SETTINGS = 1 << 12 + GDK_DEBUG_SETTINGS = 1 << 12, + GDK_DEBUG_OPENGL = 1 << 13 } GdkDebugFlag; typedef enum { diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h index be768a794e..4d6e8ccbc1 100644 --- a/gdk/gdktypes.h +++ b/gdk/gdktypes.h @@ -128,6 +128,9 @@ typedef struct _GdkWindow GdkWindow; typedef struct _GdkKeymap GdkKeymap; typedef struct _GdkAppLaunchContext GdkAppLaunchContext; +typedef struct _GdkGLPixelFormat GdkGLPixelFormat; +typedef struct _GdkGLContext GdkGLContext; + /** * GdkByteOrder: * @GDK_LSB_FIRST: The values are stored with the least-significant byte @@ -429,8 +432,25 @@ struct _GdkPoint gint y; }; +/** + * GdkGLPixelFormatProfile: + * @GDK_GL_PIXEL_FORMAT_PROFILE_DEFAULT: ... + * @GDK_GL_PIXEL_FORMAT_PROFILE_LEGACY: ... + * @GDK_GL_PIXEL_FORMAT_PROFILE_3_2_CORE: ... + * + * ... + */ +typedef enum { + GDK_GL_PIXEL_FORMAT_PROFILE_DEFAULT, + GDK_GL_PIXEL_FORMAT_PROFILE_LEGACY, + GDK_GL_PIXEL_FORMAT_PROFILE_3_2_CORE +} GdkGLPixelFormatProfile; + +typedef enum { + GDK_GL_PIXEL_FORMAT_ERROR_INVALID_FORMAT, + GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE +} GdkGLPixelFormatError; G_END_DECLS - #endif /* __GDK_TYPES_H__ */ diff --git a/gdk/x11/Makefile.am b/gdk/x11/Makefile.am index 5930f7e7e4..36e39f0842 100644 --- a/gdk/x11/Makefile.am +++ b/gdk/x11/Makefile.am @@ -39,6 +39,8 @@ libgdk_x11_la_SOURCES = \ gdkeventtranslator.c \ gdkeventtranslator.h \ gdkgeometry-x11.c \ + gdkglcontext-x11.c \ + gdkglcontext-x11.h \ gdkkeys-x11.c \ gdkmain-x11.c \ gdkproperty-x11.c \ @@ -71,6 +73,7 @@ libgdkx11include_HEADERS = \ gdkx11display.h \ gdkx11displaymanager.h \ gdkx11dnd.h \ + gdkx11glcontext.h \ gdkx11keys.h \ gdkx11property.h \ gdkx11screen.h \ diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 1db4742f71..1837347b61 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -37,6 +37,7 @@ #include "gdkdisplay-x11.h" #include "gdkprivate-x11.h" #include "gdkscreen-x11.h" +#include "gdkglcontext-x11.h" #include <glib.h> #include <glib/gprintf.h> @@ -2903,5 +2904,10 @@ 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->validate_gl_pixel_format = gdk_x11_display_validate_gl_pixel_format; + display_class->create_gl_context = gdk_x11_display_create_gl_context; + 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 (); } diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h index 69ba890ca4..07d2cb9f99 100644 --- a/gdk/x11/gdkdisplay-x11.h +++ b/gdk/x11/gdkdisplay-x11.h @@ -124,6 +124,20 @@ struct _GdkX11Display GSList *error_traps; gint wm_moveresize_button; + + /* GLX information */ + guint have_glx : 1; + gint glx_version; + gint glx_error_base; + gint glx_event_base; + + /* GLX extensions we check */ + guint has_glx_swap_interval : 1; + guint has_glx_create_context : 1; + guint has_glx_texture_from_pixmap : 1; + guint has_glx_video_sync : 1; + guint has_glx_buffer_age : 1; + guint has_glx_sync_control : 1; }; struct _GdkX11DisplayClass diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c new file mode 100644 index 0000000000..aee0bf85d5 --- /dev/null +++ b/gdk/x11/gdkglcontext-x11.c @@ -0,0 +1,691 @@ +#include "config.h" + +#include "gdkglcontext-x11.h" +#include "gdkdisplay-x11.h" +#include "gdkscreen-x11.h" + +#include "gdkx11display.h" +#include "gdkx11glcontext.h" +#include "gdkx11screen.h" +#include "gdkx11window.h" +#include "gdkx11visual.h" + +#include "gdkintl.h" + +#include <GL/glx.h> + +G_DEFINE_TYPE (GdkX11GLContext, gdk_x11_gl_context, GDK_TYPE_GL_CONTEXT) + +typedef struct { + GLXDrawable drawable; + + GdkDisplay *display; + GdkGLContext *context; + GdkWindow *window; +} DrawableInfo; + +static void +drawable_info_free (gpointer data_) +{ + DrawableInfo *data = data_; + + glXDestroyWindow (gdk_x11_display_get_xdisplay (data->display), data->drawable); + + g_slice_free (DrawableInfo, data); +} + +static DrawableInfo * +get_glx_drawable_info (GdkWindow *window) +{ + return g_object_get_data (G_OBJECT (window), "-gdk-x11-window-glx-info"); +} + +static void +set_glx_drawable_info (GdkWindow *window, + DrawableInfo *info) +{ + g_object_set_data_full (G_OBJECT (window), "-gdk-x11-window-glx-info", + info, + drawable_info_free); +} + +static void +gdk_x11_gl_context_set_window (GdkGLContext *context, + GdkWindow *window) +{ + GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context); + GdkDisplay *display = gdk_gl_context_get_display (context); + DrawableInfo *info; + + if (window == NULL) + { + gdk_x11_display_make_gl_context_current (display, context, NULL); + return; + } + + /* we need to make sure that the GdkWindow is backed by + * an actual native surface + */ + gdk_window_ensure_native (window); + + /* GLX < 1.3 accepts X11 drawables, so there's no need to + * go through the creation of a GLX drawable + */ + if (GDK_X11_DISPLAY (display)->glx_version < 13) + return; + + info = get_glx_drawable_info (window); + if (info != NULL) + return; + + gdk_x11_display_error_trap_push (display); + + info = g_slice_new (DrawableInfo); + info->window = window; + info->context = context; + info->display = display; + info->drawable = glXCreateWindow (gdk_x11_display_get_xdisplay (display), + context_x11->glx_config, + gdk_x11_window_get_xid (window), + NULL); + + gdk_x11_display_error_trap_pop_ignored (display); + + set_glx_drawable_info (window, info); +} + +static void +gdk_x11_gl_context_update (GdkGLContext *context) +{ + GdkWindow *window = gdk_gl_context_get_window (context); + int x, y, width, height; + + if (window == NULL) + return; + + if (!gdk_gl_context_make_current (context)) + return; + + gdk_window_get_geometry (window, &x, &y, &width, &height); + glViewport (0, 0, width, height); +} + +static void +gdk_x11_gl_context_flush_buffer (GdkGLContext *context) +{ + GdkDisplay *display = gdk_gl_context_get_display (context); + GdkWindow *window = gdk_gl_context_get_window (context); + DrawableInfo *info; + GLXDrawable drawable; + + if (window == NULL) + return; + + info = get_glx_drawable_info (window); + if (info != NULL && info->drawable != None) + drawable = info->drawable; + else + drawable = gdk_x11_window_get_xid (window); + + GDK_NOTE (OPENGL, g_print ("Flushing GLX buffers for %lu\n", (unsigned long) drawable)); + + glFinish (); + + glXSwapBuffers (gdk_x11_display_get_xdisplay (display), drawable); +} + +static void +gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass) +{ + GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass); + + context_class->set_window = gdk_x11_gl_context_set_window; + context_class->update = gdk_x11_gl_context_update; + context_class->flush_buffer = gdk_x11_gl_context_flush_buffer; +} + +static void +gdk_x11_gl_context_init (GdkX11GLContext *self) +{ +} + +gboolean +gdk_x11_display_init_gl (GdkDisplay *display) +{ + GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); + GdkScreen *screen; + Display *dpy; + int error_base, event_base; + int screen_num; + + if (display_x11->have_glx) + return TRUE; + + dpy = gdk_x11_display_get_xdisplay (display); + + if (!glXQueryExtension (dpy, &error_base, &event_base)) + return FALSE; + + screen = gdk_display_get_default_screen (display); + screen_num = GDK_X11_SCREEN (screen)->screen_num; + + display_x11->have_glx = TRUE; + + display_x11->glx_version = epoxy_glx_version (dpy, screen_num); + display_x11->glx_error_base = error_base; + display_x11->glx_event_base = event_base; + + display_x11->has_glx_create_context = + epoxy_has_glx_extension (dpy, screen_num, "GLX_ARB_create_context_profile"); + display_x11->has_glx_swap_interval = + epoxy_has_glx_extension (dpy, screen_num, "GLX_SGI_swap_control"); + display_x11->has_glx_texture_from_pixmap = + epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_texture_from_pixmap"); + display_x11->has_glx_video_sync = + epoxy_has_glx_extension (dpy, screen_num, "GLX_SGI_video_sync"); + display_x11->has_glx_buffer_age = + epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_buffer_age"); + display_x11->has_glx_sync_control = + epoxy_has_glx_extension (dpy, screen_num, "GLX_OML_sync_control"); + + GDK_NOTE (OPENGL, + g_print ("GLX version %d.%d found\n" + " - Vendor: %s\n" + " - Checked extensions:\n" + "\t* GLX_ARB_create_context_profile: %s\n" + "\t* GLX_SGI_swap_control: %s\n" + "\t* GLX_EXT_texture_from_pixmap: %s\n" + "\t* GLX_SGI_video_sync: %s\n" + "\t* GLX_EXT_buffer_age: %s\n" + "\t* GLX_OML_sync_control: %s\n", + display_x11->glx_version / 10, + display_x11->glx_version % 10, + glXGetClientString (dpy, GLX_VENDOR), + display_x11->has_glx_create_context ? "yes" : "no", + display_x11->has_glx_swap_interval ? "yes" : "no", + display_x11->has_glx_texture_from_pixmap ? "yes" : "no", + display_x11->has_glx_video_sync ? "yes" : "no", + display_x11->has_glx_buffer_age ? "yes" : "no", + display_x11->has_glx_sync_control ? "yes" : "no")); + + return TRUE; +} + +#define MAX_GLX_ATTRS 30 + +static void +get_glx_attributes_for_pixel_format (GdkGLPixelFormat *format, + int *attrs) +{ + GdkX11Display *display_x11; + int i = 0; + + attrs[i++] = GLX_DRAWABLE_TYPE; + attrs[i++] = GLX_WINDOW_BIT; + + attrs[i++] = GLX_RENDER_TYPE; + attrs[i++] = GLX_RGBA_BIT; + + if (format->double_buffer) + { + attrs[i++] = GLX_DOUBLEBUFFER; + attrs[i++] = GL_TRUE; + } + + if (format->color_size < 0) + { + attrs[i++] = GLX_RED_SIZE; + attrs[i++] = 1; + attrs[i++] = GLX_GREEN_SIZE; + attrs[i++] = 1; + attrs[i++] = GLX_BLUE_SIZE; + attrs[i++] = 1; + } + else + { + int channel_size = format->color_size / 4; + + attrs[i++] = GLX_RED_SIZE; + attrs[i++] = channel_size; + attrs[i++] = GLX_GREEN_SIZE; + attrs[i++] = channel_size; + attrs[i++] = GLX_BLUE_SIZE; + attrs[i++] = channel_size; + } + + if (format->alpha_size < 0) + { + attrs[i++] = GLX_ALPHA_SIZE; + attrs[i++] = 1; + } + else if (format->alpha_size == 0) + { + attrs[i++] = GLX_ALPHA_SIZE; + attrs[i++] = GLX_DONT_CARE; + } + else + { + attrs[i++] = GLX_ALPHA_SIZE; + attrs[i++] = format->alpha_size; + } + + if (format->depth_size < 0) + { + attrs[i++] = GLX_DEPTH_SIZE; + attrs[i++] = 1; + } + else + { + attrs[i++] = GLX_DEPTH_SIZE; + attrs[i++] = format->depth_size; + } + + if (format->stencil_size < 0) + { + attrs[i++] = GLX_STENCIL_SIZE; + attrs[i++] = GLX_DONT_CARE; + } + else + { + attrs[i++] = GLX_STENCIL_SIZE; + attrs[i++] = format->stencil_size; + } + + display_x11 = GDK_X11_DISPLAY (format->display); + if (display_x11->glx_version >= 14 && format->multi_sample) + { + attrs[i++] = GLX_SAMPLE_BUFFERS; + attrs[i++] = format->sample_buffers > 0 ? format->sample_buffers : 1; + + attrs[i++] = GLX_SAMPLES; + attrs[i++] = format->samples; + } + + attrs[i++] = None; + + g_assert (i < MAX_GLX_ATTRS); +} + +static gboolean +find_fbconfig_for_pixel_format (GdkDisplay *display, + GdkGLPixelFormat *format, + GLXFBConfig *fb_config_out, + XVisualInfo **visinfo_out, + GError **error) +{ + static int attrs[MAX_GLX_ATTRS]; + + Display *dpy = gdk_x11_display_get_xdisplay (display); + GLXFBConfig *configs; + int n_configs, i; + gboolean use_rgba; + gboolean retval = FALSE; + + if (format->display == NULL) + return retval; + + get_glx_attributes_for_pixel_format (format, attrs); + + use_rgba = format->alpha_size != 0; + + configs = glXChooseFBConfig (dpy, DefaultScreen (dpy), attrs, &n_configs); + if (configs == NULL || n_configs == 0) + { + g_set_error_literal (error, GDK_GL_PIXEL_FORMAT_ERROR, + GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE, + _("No available configurations for the given pixel format")); + return FALSE; + } + + /* if we don't care about an alpha channel, then the first + * valid configuration is the one we give back + */ + if (!use_rgba) + { + if (fb_config_out != NULL) + *fb_config_out = configs[0]; + + if (visinfo_out != NULL) + *visinfo_out = glXGetVisualFromFBConfig (dpy, configs[0]); + + retval = TRUE; + goto out; + } + + for (i = 0; i < n_configs; i++) + { + XVisualInfo *visinfo; + unsigned long mask; + + visinfo = glXGetVisualFromFBConfig (dpy, configs[i]); + if (visinfo == NULL) + continue; + + mask = visinfo->red_mask | visinfo->green_mask | visinfo->blue_mask; + if (visinfo->depth == 32 && mask != 0xffffffff) + { + if (fb_config_out != NULL) + *fb_config_out = configs[i]; + + if (visinfo_out != NULL) + *visinfo_out = visinfo; + + retval = TRUE; + goto out; + } + } + + g_set_error (error, GDK_GL_PIXEL_FORMAT_ERROR, + GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE, + _("No available configurations for the given RGBA pixel format")); + +out: + XFree (configs); + + return retval; +} + +static GLXContext +create_gl3_context (GdkDisplay *display, + GLXFBConfig config, + GdkGLContext *share) +{ + static const int attrib_list[] = { + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MAJOR_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); +} + +GdkGLContext * +gdk_x11_display_create_gl_context (GdkDisplay *display, + GdkGLPixelFormat *format, + GdkGLContext *share) +{ + GdkX11GLContext *context; + GdkVisual *gdk_visual; + GLXFBConfig config; + GLXContext glx_context; + Window dummy_xwin; + GLXWindow dummy_glx; + GLXWindow dummy_drawable; + gboolean is_direct; + XVisualInfo *xvisinfo; + XSetWindowAttributes attrs; + unsigned long mask; + Display *dpy; + GError *error; + + if (!gdk_x11_display_init_gl (display)) + return NULL; + + if (G_UNLIKELY (!format->is_validated)) + { + /* force a validation */ + format->is_valid = gdk_x11_display_validate_gl_pixel_format (display, format, NULL); + format->is_validated = TRUE; + } + + if (!format->is_valid) + { + g_critical ("The GdkGLPixelFormat is not valid."); + return NULL; + } + + dpy = gdk_x11_display_get_xdisplay (display); + + error = NULL; + find_fbconfig_for_pixel_format (display, format, &config, &xvisinfo, &error); + if (error != NULL) + { + g_critical ("%s", error->message); + g_error_free (error); + return NULL; + } + + /* we check for the GLX_ARB_create_context_profile extension + * while validating the PixelFormat + */ + if (format->profile == GDK_GL_PIXEL_FORMAT_PROFILE_3_2_CORE) + glx_context = create_gl3_context (display, config, share); + else + glx_context = create_gl_context (display, config, share); + + if (glx_context == NULL) + { + g_critical ("Unable to create a GLX context"); + return NULL; + } + + is_direct = glXIsDirect (dpy, glx_context); + + gdk_x11_display_error_trap_push (display); + + /* create a dummy window; this is needed because GLX does not allow + * us to query the context until it's bound to a drawable; we simply + * create a small OR window, put it off screen, and never map it. in + * order to keep the GL machinery in a sane state, we always make + * the dummy window the current drawable if the user unsets the + * GdkWindow bound to the GdkGLContext. + */ + attrs.override_redirect = True; + attrs.colormap = XCreateColormap (dpy, DefaultRootWindow (dpy), xvisinfo->visual, AllocNone); + attrs.border_pixel = 0; + mask = CWOverrideRedirect | CWColormap | CWBorderPixel; + + dummy_xwin = XCreateWindow (dpy, DefaultRootWindow (dpy), + -100, -100, 1, 1, + 0, + xvisinfo->depth, + CopyFromParent, + xvisinfo->visual, + mask, + &attrs); + + /* GLX API introduced in 1.3 expects GLX drawables */ + if (GDK_X11_DISPLAY (display)->glx_version >= 13) + dummy_glx = glXCreateWindow (dpy, config, dummy_xwin, NULL); + else + dummy_glx = None; + + dummy_drawable = dummy_glx != None + ? dummy_glx + : dummy_xwin; + + glXMakeContextCurrent (dpy, dummy_drawable, dummy_drawable, glx_context); + + gdk_visual = gdk_x11_screen_lookup_visual (gdk_display_get_default_screen (display), + xvisinfo->visualid); + + XFree (xvisinfo); + + if (gdk_x11_display_error_trap_pop (display)) + return NULL; + + GDK_NOTE (OPENGL, + g_print ("Created GLX context[%p], %s, dummy drawable: %lu\n", + glx_context, + is_direct ? "direct" : "indirect", + (unsigned long) dummy_xwin)); + + context = g_object_new (GDK_X11_TYPE_GL_CONTEXT, + "display", display, + "pixel-format", format, + "visual", gdk_visual, + NULL); + + context->glx_config = config; + context->glx_context = glx_context; + context->dummy_drawable = dummy_xwin; + context->dummy_glx_drawable = dummy_glx; + context->current_drawable = dummy_drawable; + context->is_direct = is_direct; + + 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; + } + + if (context_x11->dummy_glx_drawable) + { + GDK_NOTE (OPENGL, g_print ("Destroying dummy GLX drawable\n")); + glXDestroyWindow (dpy, context_x11->dummy_glx_drawable); + context_x11->dummy_glx_drawable = None; + } + + if (context_x11->dummy_drawable) + { + GDK_NOTE (OPENGL, g_print ("Destroying dummy drawable\n")); + XDestroyWindow (dpy, context_x11->dummy_drawable); + context_x11->dummy_drawable = None; + } +} + +gboolean +gdk_x11_display_make_gl_context_current (GdkDisplay *display, + GdkGLContext *context, + GdkWindow *window) +{ + GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context); + GLXDrawable drawable = None; + + if (context_x11->glx_context == NULL) + return FALSE; + + if (window == NULL) + { + /* we re-bind our dummy drawable, so that the context + * can still be used for queries + */ + drawable = context_x11->dummy_glx_drawable != None + ? context_x11->dummy_glx_drawable + : context_x11->dummy_drawable; + } + else + { + DrawableInfo *info = get_glx_drawable_info (window); + + if (info != NULL && info->drawable != None) + drawable = info->drawable; + else + drawable = gdk_x11_window_get_xid (window); + } + + if (G_UNLIKELY (drawable == None)) + return FALSE; + + GDK_NOTE (OPENGL, + g_print ("Making GLX context current to drawable %lu (dummy: %s)\n", + (unsigned long) drawable, + drawable == context_x11->dummy_drawable ? "yes" : "no")); + + if (drawable == context_x11->current_drawable) + return TRUE; + + gdk_x11_display_error_trap_push (display); + + glXMakeContextCurrent (gdk_x11_display_get_xdisplay (display), + drawable, drawable, + context_x11->glx_context); + + XSync (gdk_x11_display_get_xdisplay (display), False); + + if (gdk_x11_display_error_trap_pop (display)) + { + g_critical ("X Error received while calling glXMakeContextCurrent()"); + return FALSE; + } + + context_x11->current_drawable = drawable; + + return TRUE; +} + +gboolean +gdk_x11_display_validate_gl_pixel_format (GdkDisplay *display, + GdkGLPixelFormat *format, + GError **error) +{ + /* shortcut in case we already validated this PixelFormat */ + if (format->is_validated) + { + if (!format->is_valid) + { + g_set_error_literal (error, GDK_GL_PIXEL_FORMAT_ERROR, + GDK_GL_PIXEL_FORMAT_ERROR_INVALID_FORMAT, + _("Invalid pixel format")); + } + + return format->is_valid; + } + + if (!gdk_x11_display_init_gl (display)) + { + g_set_error_literal (error, GDK_GL_PIXEL_FORMAT_ERROR, + GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE, + _("No GL implementation is available")); + return FALSE; + } + + if (format->profile == GDK_GL_PIXEL_FORMAT_PROFILE_3_2_CORE) + { + if (!GDK_X11_DISPLAY (display)->has_glx_create_context) + { + g_set_error_literal (error, GDK_GL_PIXEL_FORMAT_ERROR, + GDK_GL_PIXEL_FORMAT_ERROR_NOT_AVAILABLE, + _("The GLX_ARB_create_context_profile extension " + "needed to create 3.2 core profiles is not " + "available")); + return FALSE; + } + } + + if (!find_fbconfig_for_pixel_format (display, format, NULL, NULL, error)) + return FALSE; + + return TRUE; +} diff --git a/gdk/x11/gdkglcontext-x11.h b/gdk/x11/gdkglcontext-x11.h new file mode 100644 index 0000000000..3c8354827c --- /dev/null +++ b/gdk/x11/gdkglcontext-x11.h @@ -0,0 +1,56 @@ +#ifndef __GDK_X11_GL_CONTEXT__ +#define __GDK_X11_GL_CONTEXT__ + +#include <X11/X.h> +#include <X11/Xlib.h> + +#include <epoxy/gl.h> +#include <epoxy/glx.h> + +#include "gdkglcontextprivate.h" +#include "gdkglpixelformatprivate.h" +#include "gdkdisplayprivate.h" +#include "gdkglpixelformat.h" +#include "gdkvisual.h" +#include "gdkwindow.h" +#include "gdkinternals.h" +#include "gdkmain.h" + +G_BEGIN_DECLS + +struct _GdkX11GLContext +{ + GdkGLContext parent_instance; + + GLXContext glx_context; + GLXFBConfig glx_config; + + GLXDrawable current_drawable; + + Window dummy_drawable; + GLXWindow dummy_glx_drawable; + + guint is_direct : 1; +}; + +struct _GdkX11GLContextClass +{ + GdkGLContextClass parent_class; +}; + +gboolean gdk_x11_display_init_gl (GdkDisplay *display); +gboolean gdk_x11_display_validate_gl_pixel_format (GdkDisplay *display, + GdkGLPixelFormat *format, + GError **error); +GdkGLContext * gdk_x11_display_create_gl_context (GdkDisplay *display, + GdkGLPixelFormat *format, + GdkGLContext *share); +void gdk_x11_display_destroy_gl_context (GdkDisplay *display, + GdkGLContext *context); +gboolean gdk_x11_display_make_gl_context_current (GdkDisplay *display, + GdkGLContext *context, + GdkWindow *window); + +G_END_DECLS + +#endif /* __GDK_X11_GL_CONTEXT__ */ diff --git a/gdk/x11/gdkx.h b/gdk/x11/gdkx.h index b28580dc24..1aa5f7e33d 100644 --- a/gdk/x11/gdkx.h +++ b/gdk/x11/gdkx.h @@ -43,6 +43,7 @@ #include <gdk/x11/gdkx11display.h> #include <gdk/x11/gdkx11displaymanager.h> #include <gdk/x11/gdkx11dnd.h> +#include <gdk/x11/gdkx11glcontext.h> #include <gdk/x11/gdkx11keys.h> #include <gdk/x11/gdkx11property.h> #include <gdk/x11/gdkx11screen.h> diff --git a/gdk/x11/gdkx11glcontext.h b/gdk/x11/gdkx11glcontext.h new file mode 100644 index 0000000000..36ed984ecb --- /dev/null +++ b/gdk/x11/gdkx11glcontext.h @@ -0,0 +1,24 @@ +#ifndef __GDK_X11_GL_CONTEXT_H__ +#define __GDK_X11_GL_CONTEXT_H__ + +#if !defined (__GDKX_H_INSIDE__) && !defined (GDK_COMPILATION) +#error "Only <gdk/gdkx.h> can be included directly." +#endif + +#include <gdk/gdk.h> + +G_BEGIN_DECLS + +#define GDK_X11_TYPE_GL_CONTEXT (gdk_x11_gl_context_get_type ()) +#define GDK_X11_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_X11_TYPE_GL_CONTEXT, GdkX11GLContext)) +#define GDK_X11_IS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_X11_TYPE_GL_CONTEXT)) + +typedef struct _GdkX11GLContext GdkX11GLContext; +typedef struct _GdkX11GLContextClass GdkX11GLContextClass; + +GDK_AVAILABLE_IN_3_14 +GType gdk_x11_gl_context_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __GDK_X11_GL_CONTEXT_H__ */ |