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
This commit is contained in:
@@ -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>
|
||||
|
||||
130
gdk/gdkdisplay.c
130
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);
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
489
gdk/gdkglcontext.c
Normal file
489
gdk/gdkglcontext.c
Normal file
@@ -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;
|
||||
}
|
||||
67
gdk/gdkglcontext.h
Normal file
67
gdk/gdkglcontext.h
Normal file
@@ -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__ */
|
||||
53
gdk/gdkglcontextprivate.h
Normal file
53
gdk/gdkglcontextprivate.h
Normal file
@@ -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__ */
|
||||
439
gdk/gdkglpixelformat.c
Normal file
439
gdk/gdkglpixelformat.c
Normal file
@@ -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;
|
||||
}
|
||||
55
gdk/gdkglpixelformat.h
Normal file
55
gdk/gdkglpixelformat.h
Normal file
@@ -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__ */
|
||||
43
gdk/gdkglpixelformatprivate.h
Normal file
43
gdk/gdkglpixelformatprivate.h
Normal file
@@ -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__ */
|
||||
@@ -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 {
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
691
gdk/x11/gdkglcontext-x11.c
Normal file
691
gdk/x11/gdkglcontext-x11.c
Normal file
@@ -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;
|
||||
}
|
||||
56
gdk/x11/gdkglcontext-x11.h
Normal file
56
gdk/x11/gdkglcontext-x11.h
Normal file
@@ -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__ */
|
||||
@@ -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>
|
||||
|
||||
24
gdk/x11/gdkx11glcontext.h
Normal file
24
gdk/x11/gdkx11glcontext.h
Normal file
@@ -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__ */
|
||||
Reference in New Issue
Block a user