mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 06:00:22 +00:00
Merge branch 'wip/otte/gleanup' into 'master'
reorganize GDK's GL code See merge request GNOME/gtk!3726
This commit is contained in:
commit
02c6226741
@ -127,7 +127,9 @@ static const GdkDebugKey gdk_debug_keys[] = {
|
||||
{ "gl-legacy", GDK_DEBUG_GL_LEGACY, "Use a legacy OpenGL context" },
|
||||
{ "gl-gles", GDK_DEBUG_GL_GLES, "Use a GLES OpenGL context" },
|
||||
{ "gl-debug", GDK_DEBUG_GL_DEBUG, "Insert debugging information in OpenGL" },
|
||||
{ "gl-egl", GDK_DEBUG_GL_EGL, "Use EGL on X11 or Windows" },
|
||||
{ "gl-glx", GDK_DEBUG_GL_GLX, "Use GLX on X11" },
|
||||
{ "gl-wgl", GDK_DEBUG_GL_WGL, "Use WGL on Windows" },
|
||||
{ "vulkan-disable", GDK_DEBUG_VULKAN_DISABLE, "Disable Vulkan support" },
|
||||
{ "vulkan-validate", GDK_DEBUG_VULKAN_VALIDATE, "Load the Vulkan validation layer" },
|
||||
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings" },
|
||||
|
@ -41,10 +41,12 @@ typedef enum {
|
||||
GDK_DEBUG_GL_LEGACY = 1 << 15,
|
||||
GDK_DEBUG_GL_GLES = 1 << 16,
|
||||
GDK_DEBUG_GL_DEBUG = 1 << 17,
|
||||
GDK_DEBUG_GL_GLX = 1 << 18,
|
||||
GDK_DEBUG_VULKAN_DISABLE = 1 << 19,
|
||||
GDK_DEBUG_VULKAN_VALIDATE = 1 << 20,
|
||||
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 21
|
||||
GDK_DEBUG_GL_EGL = 1 << 18,
|
||||
GDK_DEBUG_GL_GLX = 1 << 19,
|
||||
GDK_DEBUG_GL_WGL = 1 << 20,
|
||||
GDK_DEBUG_VULKAN_DISABLE = 1 << 21,
|
||||
GDK_DEBUG_VULKAN_VALIDATE = 1 << 22,
|
||||
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 23,
|
||||
} GdkDebugFlags;
|
||||
|
||||
extern guint _gdk_debug_flags;
|
||||
|
204
gdk/gdkdisplay.c
204
gdk/gdkdisplay.c
@ -77,6 +77,23 @@ enum {
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
typedef struct _GdkDisplayPrivate GdkDisplayPrivate;
|
||||
|
||||
struct _GdkDisplayPrivate {
|
||||
/* The base context that all other contexts inherit from.
|
||||
* This context is never exposed to public API and is
|
||||
* allowed to have a %NULL surface.
|
||||
*/
|
||||
GdkGLContext *gl_context;
|
||||
GError *gl_error;
|
||||
|
||||
guint rgba : 1;
|
||||
guint composited : 1;
|
||||
guint input_shapes : 1;
|
||||
|
||||
GdkDebugFlags debug_flags;
|
||||
};
|
||||
|
||||
static void gdk_display_dispose (GObject *object);
|
||||
static void gdk_display_finalize (GObject *object);
|
||||
|
||||
@ -85,7 +102,7 @@ static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gdk_display_get_property (GObject *object,
|
||||
@ -119,10 +136,14 @@ gdk_display_real_make_default (GdkDisplay *display)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_real_opened (GdkDisplay *display)
|
||||
static GdkGLContext *
|
||||
gdk_display_default_init_gl (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
_gdk_display_manager_add_display (gdk_display_manager_get (), display);
|
||||
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("The current backend does not support OpenGL"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GdkSeat *
|
||||
@ -134,6 +155,12 @@ gdk_display_real_get_default_seat (GdkDisplay *display)
|
||||
return display->seats->data;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_real_opened (GdkDisplay *display)
|
||||
{
|
||||
_gdk_display_manager_add_display (gdk_display_manager_get (), display);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_class_init (GdkDisplayClass *class)
|
||||
{
|
||||
@ -143,10 +170,11 @@ gdk_display_class_init (GdkDisplayClass *class)
|
||||
object_class->dispose = gdk_display_dispose;
|
||||
object_class->get_property = gdk_display_get_property;
|
||||
|
||||
class->get_app_launch_context = gdk_display_real_get_app_launch_context;
|
||||
class->opened = gdk_display_real_opened;
|
||||
class->make_default = gdk_display_real_make_default;
|
||||
class->get_app_launch_context = gdk_display_real_get_app_launch_context;
|
||||
class->init_gl = gdk_display_default_init_gl;
|
||||
class->get_default_seat = gdk_display_real_get_default_seat;
|
||||
class->opened = gdk_display_real_opened;
|
||||
|
||||
/**
|
||||
* GdkDisplay:composited: (attributes org.gtk.Property.get=gdk_display_is_composited)
|
||||
@ -294,6 +322,8 @@ free_device_grabs_foreach (gpointer key,
|
||||
static void
|
||||
gdk_display_init (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
display->double_click_time = 250;
|
||||
display->double_click_distance = 5;
|
||||
|
||||
@ -304,22 +334,26 @@ gdk_display_init (GdkDisplay *display)
|
||||
|
||||
g_queue_init (&display->queued_events);
|
||||
|
||||
display->debug_flags = _gdk_debug_flags;
|
||||
priv->debug_flags = _gdk_debug_flags;
|
||||
|
||||
display->composited = TRUE;
|
||||
display->rgba = TRUE;
|
||||
display->input_shapes = TRUE;
|
||||
priv->composited = TRUE;
|
||||
priv->rgba = TRUE;
|
||||
priv->input_shapes = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_dispose (GObject *object)
|
||||
{
|
||||
GdkDisplay *display = GDK_DISPLAY (object);
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
_gdk_display_manager_remove_display (gdk_display_manager_get (), display);
|
||||
|
||||
g_queue_clear (&display->queued_events);
|
||||
|
||||
g_clear_object (&priv->gl_context);
|
||||
g_clear_error (&priv->gl_error);
|
||||
|
||||
G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@ -998,21 +1032,25 @@ gdk_display_get_primary_clipboard (GdkDisplay *display)
|
||||
gboolean
|
||||
gdk_display_supports_input_shapes (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
return display->input_shapes;
|
||||
return priv->input_shapes;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_input_shapes (GdkDisplay *display,
|
||||
gboolean input_shapes)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (display->input_shapes == input_shapes)
|
||||
if (priv->input_shapes == input_shapes)
|
||||
return;
|
||||
|
||||
display->input_shapes = input_shapes;
|
||||
priv->input_shapes = input_shapes;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_INPUT_SHAPES]);
|
||||
}
|
||||
@ -1157,32 +1195,124 @@ gdk_display_get_keymap (GdkDisplay *display)
|
||||
return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_display_make_gl_context_current:
|
||||
* @display: a `GdkDisplay`
|
||||
* @context: (optional): a `GdkGLContext`
|
||||
*
|
||||
* Makes the given @context the current GL context, or unsets
|
||||
* the current GL context if @context is %NULL.
|
||||
*/
|
||||
gboolean
|
||||
gdk_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context)
|
||||
static void
|
||||
gdk_display_init_gl (GdkDisplay *self)
|
||||
{
|
||||
return GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
GdkGLContext *context;
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (self, GL_DISABLE))
|
||||
{
|
||||
g_set_error_literal (&priv->gl_error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("GL support disabled via GDK_DEBUG"));
|
||||
return;
|
||||
}
|
||||
|
||||
context = GDK_DISPLAY_GET_CLASS (self)->init_gl (self, &priv->gl_error);
|
||||
if (context == NULL)
|
||||
return;
|
||||
|
||||
if (!gdk_gl_context_realize (context, &priv->gl_error))
|
||||
{
|
||||
g_object_unref (context);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only assign after realize, so GdkGLContext::realize() can use
|
||||
* gdk_display_get_gl_context() == NULL to differentiate between
|
||||
* the display's context and any other context.
|
||||
*/
|
||||
priv->gl_context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_display_prepare_gl:
|
||||
* @self: a `GdkDisplay`
|
||||
* @error: return location for a `GError`
|
||||
*
|
||||
* Checks that OpenGL is available for @self and ensures that it is
|
||||
* properly initialized.
|
||||
* When this fails, an @error will be set describing the error and this
|
||||
* function returns %FALSE.
|
||||
*
|
||||
* Note that even if this function succeeds, creating a `GdkGLContext`
|
||||
* may still fail.
|
||||
*
|
||||
* This function is idempotent. Calling it multiple times will just
|
||||
* return the same value or error.
|
||||
*
|
||||
* You never need to call this function, GDK will call it automatically
|
||||
* as needed. But you can use it as a check when setting up code that
|
||||
* might make use of OpenGL.
|
||||
*
|
||||
* Returns: %TRUE if the display supports OpenGL
|
||||
*
|
||||
* Since: 4.4
|
||||
**/
|
||||
gboolean
|
||||
gdk_display_prepare_gl (GdkDisplay *self,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (self), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (priv->gl_context)
|
||||
return TRUE;
|
||||
|
||||
if (priv->gl_error != NULL)
|
||||
{
|
||||
if (error)
|
||||
*error = g_error_copy (priv->gl_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gdk_display_init_gl (self);
|
||||
|
||||
/* try again */
|
||||
}
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_display_get_gl_context:
|
||||
* @self: the `GdkDisplay`
|
||||
*
|
||||
* Gets the GL context returned from [vfunc@Gdk.Display.init_gl]
|
||||
* previously.
|
||||
*
|
||||
* If that function has not been called yet or did fail, %NULL is
|
||||
* returned.
|
||||
* Call [method@Gdk.Display.prepare_gl] to avoid this.
|
||||
*
|
||||
* Returns: The `GdkGLContext`
|
||||
*/
|
||||
GdkGLContext *
|
||||
gdk_display_get_gl_context (GdkDisplay *self)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
|
||||
return priv->gl_context;
|
||||
}
|
||||
|
||||
GdkDebugFlags
|
||||
gdk_display_get_debug_flags (GdkDisplay *display)
|
||||
{
|
||||
return display ? display->debug_flags : _gdk_debug_flags;
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
return display ? priv->debug_flags : _gdk_debug_flags;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_debug_flags (GdkDisplay *display,
|
||||
GdkDebugFlags flags)
|
||||
{
|
||||
display->debug_flags = flags;
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
priv->debug_flags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1207,21 +1337,25 @@ gdk_display_set_debug_flags (GdkDisplay *display,
|
||||
gboolean
|
||||
gdk_display_is_composited (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
return display->composited;
|
||||
return priv->composited;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_composited (GdkDisplay *display,
|
||||
gboolean composited)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (display->composited == composited)
|
||||
if (priv->composited == composited)
|
||||
return;
|
||||
|
||||
display->composited = composited;
|
||||
priv->composited = composited;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_COMPOSITED]);
|
||||
}
|
||||
@ -1248,21 +1382,25 @@ gdk_display_set_composited (GdkDisplay *display,
|
||||
gboolean
|
||||
gdk_display_is_rgba (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
return display->rgba;
|
||||
return priv->rgba;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_rgba (GdkDisplay *display,
|
||||
gboolean rgba)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (display->rgba == rgba)
|
||||
if (priv->rgba == rgba)
|
||||
return;
|
||||
|
||||
display->rgba = rgba;
|
||||
priv->rgba = rgba;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_RGBA]);
|
||||
}
|
||||
|
@ -68,6 +68,10 @@ gboolean gdk_display_is_rgba (GdkDisplay *display);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_display_supports_input_shapes (GdkDisplay *display);
|
||||
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
gboolean gdk_display_prepare_gl (GdkDisplay *self,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay *gdk_display_get_default (void);
|
||||
|
||||
|
@ -102,11 +102,6 @@ struct _GdkDisplay
|
||||
|
||||
guint vulkan_refcount;
|
||||
#endif /* GDK_RENDERING_VULKAN */
|
||||
guint rgba : 1;
|
||||
guint composited : 1;
|
||||
guint input_shapes : 1;
|
||||
|
||||
GdkDebugFlags debug_flags;
|
||||
|
||||
GList *seats;
|
||||
};
|
||||
@ -145,8 +140,8 @@ struct _GdkDisplayClass
|
||||
|
||||
GdkKeymap * (*get_keymap) (GdkDisplay *display);
|
||||
|
||||
gboolean (*make_gl_context_current) (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
GdkGLContext * (*init_gl) (GdkDisplay *display,
|
||||
GError **error);
|
||||
|
||||
GdkSeat * (*get_default_seat) (GdkDisplay *display);
|
||||
|
||||
@ -211,8 +206,7 @@ GdkSurface * gdk_display_create_surface (GdkDisplay *display
|
||||
int width,
|
||||
int height);
|
||||
|
||||
gboolean gdk_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display);
|
||||
|
||||
void gdk_display_set_rgba (GdkDisplay *display,
|
||||
gboolean rgba);
|
||||
|
@ -43,6 +43,7 @@
|
||||
typedef struct _GdkDrawContextPrivate GdkDrawContextPrivate;
|
||||
|
||||
struct _GdkDrawContextPrivate {
|
||||
GdkDisplay *display;
|
||||
GdkSurface *surface;
|
||||
|
||||
cairo_region_t *frame_region;
|
||||
@ -77,6 +78,7 @@ gdk_draw_context_dispose (GObject *gobject)
|
||||
priv->surface->draw_contexts = g_slist_remove (priv->surface->draw_contexts, context);
|
||||
g_clear_object (&priv->surface);
|
||||
}
|
||||
g_clear_object (&priv->display);
|
||||
|
||||
G_OBJECT_CLASS (gdk_draw_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
@ -92,10 +94,31 @@ gdk_draw_context_set_property (GObject *gobject,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
if (priv->display != NULL)
|
||||
{
|
||||
g_assert (g_value_get_object (value) == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->display = g_value_dup_object (value);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_SURFACE:
|
||||
priv->surface = g_value_dup_object (value);
|
||||
g_assert (priv->surface != NULL);
|
||||
priv->surface->draw_contexts = g_slist_prepend (priv->surface->draw_contexts, context);
|
||||
if (priv->surface)
|
||||
{
|
||||
priv->surface->draw_contexts = g_slist_prepend (priv->surface->draw_contexts, context);
|
||||
if (priv->display)
|
||||
{
|
||||
g_assert (priv->display == gdk_surface_get_display (priv->surface));
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->display = g_object_ref (gdk_surface_get_display (priv->surface));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -148,7 +171,8 @@ gdk_draw_context_class_init (GdkDrawContextClass *klass)
|
||||
P_("Display"),
|
||||
P_("The GDK display used to create the context"),
|
||||
GDK_TYPE_DISPLAY,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
@ -228,7 +252,7 @@ gdk_draw_context_get_display (GdkDrawContext *context)
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (context), NULL);
|
||||
|
||||
return priv->surface ? gdk_surface_get_display (priv->surface) : NULL;
|
||||
return priv->display;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -89,8 +89,6 @@
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
typedef struct {
|
||||
GdkGLContext *shared_context;
|
||||
|
||||
int major;
|
||||
int minor;
|
||||
int gl_version;
|
||||
@ -127,7 +125,28 @@ G_DEFINE_QUARK (gdk-gl-error-quark, gdk_gl_error)
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkGLContext, gdk_gl_context, GDK_TYPE_DRAW_CONTEXT)
|
||||
|
||||
static GPrivate thread_current_context = G_PRIVATE_INIT (g_object_unref);
|
||||
typedef struct _MaskedContext MaskedContext;
|
||||
|
||||
static inline MaskedContext *
|
||||
mask_context (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
{
|
||||
return (MaskedContext *) GSIZE_TO_POINTER (GPOINTER_TO_SIZE (context) | (surfaceless ? 1 : 0));
|
||||
}
|
||||
|
||||
static inline GdkGLContext *
|
||||
unmask_context (MaskedContext *mask)
|
||||
{
|
||||
return GDK_GL_CONTEXT (GSIZE_TO_POINTER (GPOINTER_TO_SIZE (mask) & ~(gsize) 1));
|
||||
}
|
||||
|
||||
static void
|
||||
unref_unmasked (gpointer data)
|
||||
{
|
||||
g_object_unref (unmask_context (data));
|
||||
}
|
||||
|
||||
static GPrivate thread_current_context = G_PRIVATE_INIT (unref_unmasked);
|
||||
|
||||
static void
|
||||
gdk_gl_context_clear_old_updated_area (GdkGLContext *context)
|
||||
@ -144,17 +163,14 @@ static void
|
||||
gdk_gl_context_dispose (GObject *gobject)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current;
|
||||
|
||||
gdk_gl_context_clear_old_updated_area (context);
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
if (current == context)
|
||||
if (unmask_context (current) == context)
|
||||
g_private_replace (&thread_current_context, NULL);
|
||||
|
||||
g_clear_object (&priv->shared_context);
|
||||
|
||||
G_OBJECT_CLASS (gdk_gl_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@ -174,17 +190,10 @@ gdk_gl_context_set_property (GObject *gobject,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHARED_CONTEXT:
|
||||
{
|
||||
GdkGLContext *context = g_value_get_object (value);
|
||||
|
||||
if (context != NULL)
|
||||
priv->shared_context = g_object_ref (context);
|
||||
}
|
||||
g_assert (g_value_get_object (value) == NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -198,12 +207,10 @@ gdk_gl_context_get_property (GObject *gobject,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHARED_CONTEXT:
|
||||
g_value_set_object (value, priv->shared_context);
|
||||
g_value_set_object (value, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -333,23 +340,27 @@ gdk_gl_context_real_get_damage (GdkGLContext *context)
|
||||
});
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_gl_context_real_is_shared (GdkGLContext *self,
|
||||
GdkGLContext *other)
|
||||
{
|
||||
if (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (self)) != gdk_draw_context_get_display (GDK_DRAW_CONTEXT (other)))
|
||||
return FALSE;
|
||||
|
||||
/* XXX: Should we check es or legacy here? */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkSurface *surface;
|
||||
GdkGLContext *shared;
|
||||
cairo_region_t *damage;
|
||||
int ww, wh;
|
||||
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
if (shared)
|
||||
{
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (GDK_DRAW_CONTEXT (shared))->begin_frame (GDK_DRAW_CONTEXT (shared), region);
|
||||
return;
|
||||
}
|
||||
|
||||
damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);
|
||||
|
||||
if (context->old_updated_area[1])
|
||||
@ -379,15 +390,6 @@ static void
|
||||
gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *painted)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkGLContext *shared;
|
||||
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
if (shared)
|
||||
{
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (GDK_DRAW_CONTEXT (shared))->end_frame (GDK_DRAW_CONTEXT (shared), painted);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -406,6 +408,7 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||
|
||||
klass->realize = gdk_gl_context_real_realize;
|
||||
klass->get_damage = gdk_gl_context_real_get_damage;
|
||||
klass->is_shared = gdk_gl_context_real_is_shared;
|
||||
|
||||
draw_context_class->begin_frame = gdk_gl_context_real_begin_frame;
|
||||
draw_context_class->end_frame = gdk_gl_context_real_end_frame;
|
||||
@ -414,7 +417,13 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||
/**
|
||||
* GdkGLContext:shared-context: (attributes org.gtk.Property.get=gdk_gl_context_get_shared_context)
|
||||
*
|
||||
* The `GdkGLContext` that this context is sharing data with, or %NULL
|
||||
* Always %NULL
|
||||
*
|
||||
* As many contexts can share data now and no single shared context exists
|
||||
* anymore, this function has been deprecated and now always returns %NULL.
|
||||
*
|
||||
* Deprecated: 4.4: Use [method@Gdk.GLContext.is_shared] to check if contexts
|
||||
* can be shared.
|
||||
*/
|
||||
obj_pspecs[PROP_SHARED_CONTEXT] =
|
||||
g_param_spec_object ("shared-context",
|
||||
@ -423,7 +432,8 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||
GDK_TYPE_GL_CONTEXT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_DEPRECATED);
|
||||
|
||||
gobject_class->set_property = gdk_gl_context_set_property;
|
||||
gobject_class->get_property = gdk_gl_context_get_property;
|
||||
@ -441,6 +451,21 @@ gdk_gl_context_init (GdkGLContext *self)
|
||||
priv->use_es = -1;
|
||||
}
|
||||
|
||||
/* Must have called gdk_display_prepare_gl() before */
|
||||
GdkGLContext *
|
||||
gdk_gl_context_new_for_surface (GdkSurface *surface)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkGLContext *shared = gdk_display_get_gl_context (display);
|
||||
|
||||
/* assert gdk_display_prepare_gl() had been called */
|
||||
g_assert (shared);
|
||||
|
||||
return g_object_new (G_OBJECT_TYPE (shared),
|
||||
"surface", surface,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GdkGLContextPaintData *
|
||||
gdk_gl_context_get_paint_data (GdkGLContext *context)
|
||||
{
|
||||
@ -812,6 +837,42 @@ gdk_gl_context_set_is_legacy (GdkGLContext *context,
|
||||
priv->is_legacy = !!is_legacy;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_context_is_shared:
|
||||
* @self: a `GdkGLContext`
|
||||
* @other: the `GdkGLContext` that should be compatible with @self
|
||||
*
|
||||
* Checks if the two GL contexts can share resources.
|
||||
*
|
||||
* When they can, the texture IDs from @other can be used in @self. This
|
||||
* is particularly useful when passing `GdkGLTexture` objects between
|
||||
* different contexts.
|
||||
*
|
||||
* Contexts created for the same display with the same properties will
|
||||
* always be compatible, even if they are created for different surfaces.
|
||||
* For other contexts it depends on the GL backend.
|
||||
*
|
||||
* Both contexts must be realized for this check to succeed. If either one
|
||||
* is not, this function will return %FALSE.
|
||||
*
|
||||
* Returns: %TRUE if the two GL contexts are compatible.
|
||||
*/
|
||||
gboolean
|
||||
gdk_gl_context_is_shared (GdkGLContext *self,
|
||||
GdkGLContext *other)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
|
||||
GdkGLContextPrivate *priv_other = gdk_gl_context_get_instance_private (other);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), FALSE);
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (other), FALSE);
|
||||
|
||||
if (!priv->realized || !priv_other->realized)
|
||||
return FALSE;
|
||||
|
||||
return GDK_GL_CONTEXT_GET_CLASS (self)->is_shared (self, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_context_set_use_es:
|
||||
* @context: a `GdkGLContext`
|
||||
@ -1092,12 +1153,16 @@ void
|
||||
gdk_gl_context_make_current (GdkGLContext *context)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current, *masked_context;
|
||||
gboolean surfaceless;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||
|
||||
surfaceless = !gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context));
|
||||
masked_context = mask_context (context, surfaceless);
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
if (current == context)
|
||||
if (current == masked_context)
|
||||
return;
|
||||
|
||||
/* we need to realize the GdkGLContext if it wasn't explicitly realized */
|
||||
@ -1114,11 +1179,15 @@ gdk_gl_context_make_current (GdkGLContext *context)
|
||||
}
|
||||
}
|
||||
|
||||
if (gdk_display_make_gl_context_current (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)), context))
|
||||
if (!GDK_GL_CONTEXT_GET_CLASS (context)->make_current (context, surfaceless))
|
||||
{
|
||||
g_private_replace (&thread_current_context, g_object_ref (context));
|
||||
gdk_gl_context_check_extensions (context);
|
||||
g_warning ("gdk_gl_context_make_current() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_ref (context);
|
||||
g_private_replace (&thread_current_context, masked_context);
|
||||
gdk_gl_context_check_extensions (context);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1157,18 +1226,22 @@ gdk_gl_context_get_surface (GdkGLContext *context)
|
||||
* gdk_gl_context_get_shared_context: (attributes org.gtk.Method.get_property=shared-context)
|
||||
* @context: a `GdkGLContext`
|
||||
*
|
||||
* Retrieves the `GdkGLContext` that this @context share data with.
|
||||
* Used to retrieves the `GdkGLContext` that this @context share data with.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): a `GdkGLContext`
|
||||
* As many contexts can share data now and no single shared context exists
|
||||
* anymore, this function has been deprecated and now always returns %NULL.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): %NULL
|
||||
*
|
||||
* Deprecated: 4.4: Use [method@Gdk.GLContext.is_shared] to check if contexts
|
||||
* can be shared.
|
||||
*/
|
||||
GdkGLContext *
|
||||
gdk_gl_context_get_shared_context (GdkGLContext *context)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||
|
||||
return priv->shared_context;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1208,12 +1281,14 @@ gdk_gl_context_get_version (GdkGLContext *context,
|
||||
void
|
||||
gdk_gl_context_clear_current (void)
|
||||
{
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current;
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
if (current != NULL)
|
||||
{
|
||||
if (gdk_display_make_gl_context_current (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (current)), NULL))
|
||||
GdkGLContext *context = unmask_context (current);
|
||||
|
||||
if (GDK_GL_CONTEXT_GET_CLASS (context)->clear_current (context))
|
||||
g_private_replace (&thread_current_context, NULL);
|
||||
}
|
||||
}
|
||||
@ -1228,11 +1303,11 @@ gdk_gl_context_clear_current (void)
|
||||
GdkGLContext *
|
||||
gdk_gl_context_get_current (void)
|
||||
{
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current;
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
|
||||
return current;
|
||||
return unmask_context (current);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -45,8 +45,8 @@ GType gdk_gl_context_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gdk_gl_context_get_surface (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gdk_gl_context_get_surface (GdkGLContext *context);
|
||||
GDK_DEPRECATED_IN_4_4_FOR(gdk_gl_context_is_shared)
|
||||
GdkGLContext * gdk_gl_context_get_shared_context (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_gl_context_get_version (GdkGLContext *context,
|
||||
@ -54,6 +54,9 @@ void gdk_gl_context_get_version (GdkGLContext *
|
||||
int *minor);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_gl_context_is_legacy (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
gboolean gdk_gl_context_is_shared (GdkGLContext *self,
|
||||
GdkGLContext *other);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_gl_context_set_required_version (GdkGLContext *context,
|
||||
|
@ -27,6 +27,13 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Version requirements for EGL contexts.
|
||||
*
|
||||
* If you add support for EGL to your backend, please require this.
|
||||
*/
|
||||
#define GDK_EGL_MIN_VERSION_MAJOR (1)
|
||||
#define GDK_EGL_MIN_VERSION_MINOR (4)
|
||||
|
||||
#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))
|
||||
@ -45,10 +52,16 @@ struct _GdkGLContextClass
|
||||
{
|
||||
GdkDrawContextClass parent_class;
|
||||
|
||||
gboolean (* realize) (GdkGLContext *context,
|
||||
GError **error);
|
||||
gboolean (* realize) (GdkGLContext *context,
|
||||
GError **error);
|
||||
|
||||
cairo_region_t * (* get_damage) (GdkGLContext *context);
|
||||
gboolean (* make_current) (GdkGLContext *context,
|
||||
gboolean surfaceless);
|
||||
gboolean (* clear_current) (GdkGLContext *context);
|
||||
cairo_region_t * (* get_damage) (GdkGLContext *context);
|
||||
|
||||
gboolean (* is_shared) (GdkGLContext *self,
|
||||
GdkGLContext *other);
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -73,6 +86,8 @@ typedef struct {
|
||||
guint use_es : 1;
|
||||
} GdkGLContextPaintData;
|
||||
|
||||
GdkGLContext * gdk_gl_context_new_for_surface (GdkSurface *surface);
|
||||
|
||||
void gdk_gl_context_set_is_legacy (GdkGLContext *context,
|
||||
gboolean is_legacy);
|
||||
|
||||
|
@ -1065,87 +1065,23 @@ gdk_surface_get_mapped (GdkSurface *surface)
|
||||
return GDK_SURFACE_IS_MAPPED (surface);
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_surface_get_shared_data_gl_context (GdkSurface *surface)
|
||||
{
|
||||
static int in_shared_data_creation;
|
||||
GdkDisplay *display;
|
||||
GdkGLContext *context;
|
||||
|
||||
if (in_shared_data_creation)
|
||||
return NULL;
|
||||
|
||||
in_shared_data_creation = 1;
|
||||
|
||||
display = gdk_surface_get_display (surface);
|
||||
context = (GdkGLContext *)g_object_get_data (G_OBJECT (display), "gdk-gl-shared-data-context");
|
||||
if (context == NULL)
|
||||
{
|
||||
GError *error = NULL;
|
||||
context = GDK_SURFACE_GET_CLASS (surface)->create_gl_context (surface, FALSE, NULL, &error);
|
||||
if (context == NULL)
|
||||
{
|
||||
g_warning ("Failed to create shared context: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
gdk_gl_context_realize (context, &error);
|
||||
if (context == NULL)
|
||||
{
|
||||
g_warning ("Failed to realize shared context: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
|
||||
g_object_set_data (G_OBJECT (display), "gdk-gl-shared-data-context", context);
|
||||
}
|
||||
|
||||
in_shared_data_creation = 0;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_surface_get_paint_gl_context (GdkSurface *surface,
|
||||
GError **error)
|
||||
GError **error)
|
||||
{
|
||||
GError *internal_error = NULL;
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (surface->display, GL_DISABLE))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("GL support disabled via GDK_DEBUG"));
|
||||
return NULL;
|
||||
}
|
||||
if (!gdk_display_prepare_gl (surface->display, error))
|
||||
return NULL;
|
||||
|
||||
if (surface->gl_paint_context == NULL)
|
||||
{
|
||||
GdkSurfaceClass *class = GDK_SURFACE_GET_CLASS (surface);
|
||||
|
||||
if (class->create_gl_context == NULL)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("The current backend does not support OpenGL"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surface->gl_paint_context =
|
||||
class->create_gl_context (surface, TRUE, NULL, &internal_error);
|
||||
surface->gl_paint_context = gdk_surface_create_gl_context (surface, error);
|
||||
if (surface->gl_paint_context == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (internal_error != NULL)
|
||||
if (!gdk_gl_context_realize (surface->gl_paint_context, error))
|
||||
{
|
||||
g_propagate_error (error, internal_error);
|
||||
g_clear_object (&(surface->gl_paint_context));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gdk_gl_context_realize (surface->gl_paint_context, &internal_error);
|
||||
if (internal_error != NULL)
|
||||
{
|
||||
g_propagate_error (error, internal_error);
|
||||
g_clear_object (&(surface->gl_paint_context));
|
||||
g_clear_object (&surface->gl_paint_context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1170,19 +1106,13 @@ GdkGLContext *
|
||||
gdk_surface_create_gl_context (GdkSurface *surface,
|
||||
GError **error)
|
||||
{
|
||||
GdkGLContext *paint_context;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
paint_context = gdk_surface_get_paint_gl_context (surface, error);
|
||||
if (paint_context == NULL)
|
||||
if (!gdk_display_prepare_gl (surface->display, error))
|
||||
return NULL;
|
||||
|
||||
return GDK_SURFACE_GET_CLASS (surface)->create_gl_context (surface,
|
||||
FALSE,
|
||||
paint_context,
|
||||
error);
|
||||
return gdk_gl_context_new_for_surface (surface);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -160,10 +160,6 @@ struct _GdkSurfaceClass
|
||||
|
||||
void (* set_opaque_region) (GdkSurface *surface,
|
||||
cairo_region_t *region);
|
||||
GdkGLContext *(*create_gl_context) (GdkSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error);
|
||||
void (* request_layout) (GdkSurface *surface);
|
||||
gboolean (* compute_size) (GdkSurface *surface);
|
||||
};
|
||||
@ -266,7 +262,6 @@ void _gdk_surface_update_size (GdkSurface *surface);
|
||||
|
||||
GdkGLContext * gdk_surface_get_paint_gl_context (GdkSurface *surface,
|
||||
GError **error);
|
||||
GdkGLContext * gdk_surface_get_shared_data_gl_context (GdkSurface *surface);
|
||||
|
||||
gboolean gdk_surface_handle_event (GdkEvent *event);
|
||||
GdkSeat * gdk_surface_get_seat_from_event (GdkSurface *surface,
|
||||
|
@ -637,17 +637,13 @@ gdk_macos_display_load_clipboard (GdkMacosDisplay *self)
|
||||
GDK_DISPLAY (self)->clipboard = _gdk_macos_clipboard_new (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_macos_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *gl_context)
|
||||
static GdkGLContext *
|
||||
gdk_macos_display_init_gl (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
g_assert (GDK_IS_MACOS_DISPLAY (display));
|
||||
g_assert (!gl_context || GDK_IS_MACOS_GL_CONTEXT (gl_context));
|
||||
|
||||
if (gl_context == NULL)
|
||||
return FALSE;
|
||||
|
||||
return _gdk_macos_gl_context_make_current (GDK_MACOS_GL_CONTEXT (gl_context));
|
||||
return g_object_new (GDK_TYPE_MACOS_GL_CONTEXT,
|
||||
"display", display,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -695,7 +691,7 @@ gdk_macos_display_class_init (GdkMacosDisplayClass *klass)
|
||||
display_class->get_name = gdk_macos_display_get_name;
|
||||
display_class->get_setting = gdk_macos_display_get_setting;
|
||||
display_class->has_pending = gdk_macos_display_has_pending;
|
||||
display_class->make_gl_context_current = gdk_macos_display_make_gl_context_current;
|
||||
display_class->init_gl = gdk_macos_display_init_gl;
|
||||
display_class->notify_startup_complete = gdk_macos_display_notify_startup_complete;
|
||||
display_class->queue_events = gdk_macos_display_queue_events;
|
||||
display_class->sync = gdk_macos_display_sync;
|
||||
|
@ -19,12 +19,14 @@
|
||||
#ifndef __GDK_MACOS_GL_CONTEXT_PRIVATE_H__
|
||||
#define __GDK_MACOS_GL_CONTEXT_PRIVATE_H__
|
||||
|
||||
#include "gdkmacosglcontext.h"
|
||||
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdksurface.h"
|
||||
#include "gdkinternals.h"
|
||||
|
||||
#include "gdkmacosglcontext.h"
|
||||
#include "gdkmacosdisplay.h"
|
||||
#include "gdkmacossurface.h"
|
||||
|
||||
#import <OpenGL/OpenGL.h>
|
||||
@ -55,11 +57,6 @@ struct _GdkMacosGLContextClass
|
||||
GdkGLContextClass parent_class;
|
||||
};
|
||||
|
||||
GdkGLContext *_gdk_macos_gl_context_new (GdkMacosSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error);
|
||||
gboolean _gdk_macos_gl_context_make_current (GdkMacosGLContext *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -170,12 +170,12 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context,
|
||||
{
|
||||
GdkMacosGLContext *self = (GdkMacosGLContext *)context;
|
||||
GdkSurface *surface;
|
||||
GdkDisplay *display;
|
||||
NSOpenGLContext *shared_gl_context = nil;
|
||||
NSOpenGLContext *gl_context;
|
||||
NSOpenGLPixelFormat *pixelFormat;
|
||||
CGLContextObj cgl_context;
|
||||
GdkGLContext *shared;
|
||||
GdkGLContext *shared_data;
|
||||
NSOpenGLContext *existing;
|
||||
GLint sync_to_framerate = 1;
|
||||
GLint validate = 0;
|
||||
@ -192,21 +192,16 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context,
|
||||
gdk_gl_context_get_required_version (context, &major, &minor);
|
||||
|
||||
surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
shared_data = gdk_surface_get_shared_data_gl_context (surface);
|
||||
display = gdk_gl_context_get_display (context);
|
||||
shared = gdk_display_get_gl_context (display);
|
||||
|
||||
if (shared != NULL)
|
||||
{
|
||||
if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared), error)))
|
||||
return FALSE;
|
||||
}
|
||||
else if (shared_data != NULL)
|
||||
{
|
||||
if (!(shared_gl_context = get_ns_open_gl_context (GDK_MACOS_GL_CONTEXT (shared_data), error)))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GDK_DISPLAY_NOTE (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)),
|
||||
GDK_DISPLAY_NOTE (display,
|
||||
OPENGL,
|
||||
g_message ("Creating NSOpenGLContext (version %d.%d)",
|
||||
major, minor));
|
||||
@ -253,7 +248,7 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context,
|
||||
|
||||
GLint renderer_id = 0;
|
||||
[gl_context getValues:&renderer_id forParameter:NSOpenGLContextParameterCurrentRendererID];
|
||||
GDK_DISPLAY_NOTE (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)),
|
||||
GDK_DISPLAY_NOTE (display,
|
||||
OPENGL,
|
||||
g_message ("Created NSOpenGLContext[%p] using %s",
|
||||
gl_context,
|
||||
@ -315,9 +310,7 @@ gdk_macos_gl_context_begin_frame (GdkDrawContext *context,
|
||||
* want to replace our damage region for the next frame (to avoid
|
||||
* doing it multiple times).
|
||||
*/
|
||||
if (!self->is_attached &&
|
||||
gdk_gl_context_get_shared_context (GDK_GL_CONTEXT (context)))
|
||||
ensure_gl_view (self);
|
||||
ensure_gl_view (self);
|
||||
|
||||
if (self->needs_resize)
|
||||
{
|
||||
@ -410,6 +403,57 @@ gdk_macos_gl_context_surface_resized (GdkDrawContext *draw_context)
|
||||
g_clear_pointer (&self->damage, cairo_region_destroy);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_macos_gl_context_clear_current (GdkGLContext *context)
|
||||
{
|
||||
GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
|
||||
NSOpenGLContext *current;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
|
||||
|
||||
current = [NSOpenGLContext currentContext];
|
||||
|
||||
if (self->gl_context == current)
|
||||
{
|
||||
/* The OpenGL mac programming guide suggests that glFlush() is called
|
||||
* before switching current contexts to ensure that the drawing commands
|
||||
* are submitted.
|
||||
*/
|
||||
if (current != NULL)
|
||||
glFlush ();
|
||||
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_macos_gl_context_make_current (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
{
|
||||
GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
|
||||
NSOpenGLContext *current;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
|
||||
|
||||
current = [NSOpenGLContext currentContext];
|
||||
|
||||
if (self->gl_context != current)
|
||||
{
|
||||
/* The OpenGL mac programming guide suggests that glFlush() is called
|
||||
* before switching current contexts to ensure that the drawing commands
|
||||
* are submitted.
|
||||
*/
|
||||
if (current != NULL)
|
||||
glFlush ();
|
||||
|
||||
[self->gl_context makeCurrentContext];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
gdk_macos_gl_context_get_damage (GdkGLContext *context)
|
||||
{
|
||||
@ -478,52 +522,4 @@ gdk_macos_gl_context_init (GdkMacosGLContext *self)
|
||||
{
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
_gdk_macos_gl_context_new (GdkMacosSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error)
|
||||
{
|
||||
GdkMacosGLContext *context;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MACOS_SURFACE (surface), NULL);
|
||||
g_return_val_if_fail (!share || GDK_IS_MACOS_GL_CONTEXT (share), NULL);
|
||||
|
||||
context = g_object_new (GDK_TYPE_MACOS_GL_CONTEXT,
|
||||
"surface", surface,
|
||||
"shared-context", share,
|
||||
NULL);
|
||||
|
||||
context->is_attached = !!attached;
|
||||
|
||||
return GDK_GL_CONTEXT (context);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gdk_macos_gl_context_make_current (GdkMacosGLContext *self)
|
||||
{
|
||||
NSOpenGLContext *current;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
|
||||
|
||||
if (self->gl_context == NULL)
|
||||
return FALSE;
|
||||
|
||||
current = [NSOpenGLContext currentContext];
|
||||
|
||||
if (self->gl_context != current)
|
||||
{
|
||||
/* The OpenGL mac programming guide suggests that glFlush() is called
|
||||
* before switching current contexts to ensure that the drawing commands
|
||||
* are submitted.
|
||||
*/
|
||||
if (current != NULL)
|
||||
glFlush ();
|
||||
|
||||
[self->gl_context makeCurrentContext];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
@ -358,20 +358,6 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
|
||||
return GDK_DRAG (g_steal_pointer (&drag));
|
||||
}
|
||||
|
||||
static GdkGLContext *
|
||||
gdk_macos_surface_create_gl_context (GdkSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error)
|
||||
{
|
||||
GdkMacosSurface *self = (GdkMacosSurface *)surface;
|
||||
|
||||
g_assert (GDK_IS_MACOS_SURFACE (self));
|
||||
g_assert (!share || GDK_IS_GL_CONTEXT (share));
|
||||
|
||||
return _gdk_macos_gl_context_new (self, attached, share, error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_surface_destroy (GdkSurface *surface,
|
||||
gboolean foreign_destroy)
|
||||
@ -495,7 +481,6 @@ gdk_macos_surface_class_init (GdkMacosSurfaceClass *klass)
|
||||
object_class->get_property = gdk_macos_surface_get_property;
|
||||
object_class->set_property = gdk_macos_surface_set_property;
|
||||
|
||||
surface_class->create_gl_context = gdk_macos_surface_create_gl_context;
|
||||
surface_class->destroy = gdk_macos_surface_destroy;
|
||||
surface_class->drag_begin = gdk_macos_surface_drag_begin;
|
||||
surface_class->get_device_state = gdk_macos_surface_get_device_state;
|
||||
|
@ -969,7 +969,7 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass *class)
|
||||
display_class->create_surface = _gdk_wayland_display_create_surface;
|
||||
display_class->get_keymap = _gdk_wayland_display_get_keymap;
|
||||
|
||||
display_class->make_gl_context_current = gdk_wayland_display_make_gl_context_current;
|
||||
display_class->init_gl = gdk_wayland_display_init_gl;
|
||||
|
||||
display_class->get_monitors = gdk_wayland_display_get_monitors;
|
||||
display_class->get_monitor_at_surface = gdk_wayland_display_get_monitor_at_surface;
|
||||
|
@ -153,14 +153,12 @@ struct _GdkWaylandDisplay
|
||||
|
||||
/* egl info */
|
||||
EGLDisplay egl_display;
|
||||
EGLConfig egl_config;
|
||||
int egl_major_version;
|
||||
int egl_minor_version;
|
||||
|
||||
guint have_egl : 1;
|
||||
guint have_egl_khr_create_context : 1;
|
||||
guint have_egl_buffer_age : 1;
|
||||
guint have_egl_swap_buffers_with_damage : 1;
|
||||
guint have_egl_surfaceless_context : 1;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDisplayClass
|
||||
|
@ -22,7 +22,9 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkglcontext-wayland.h"
|
||||
|
||||
#include "gdkdisplay-wayland.h"
|
||||
#include "gdksurface-wayland.h"
|
||||
|
||||
#include "gdkwaylanddisplay.h"
|
||||
#include "gdkwaylandglcontext.h"
|
||||
@ -53,8 +55,7 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
|
||||
{
|
||||
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkGLContext *share = gdk_gl_context_get_shared_context (context);
|
||||
GdkGLContext *shared_data_context = gdk_surface_get_shared_data_gl_context (gdk_gl_context_get_surface (context));
|
||||
GdkGLContext *share = gdk_display_get_gl_context (display);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
EGLContext ctx;
|
||||
EGLint context_attribs[N_EGL_ATTRS];
|
||||
@ -120,10 +121,9 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
|
||||
use_es ? "yes" : "no"));
|
||||
|
||||
ctx = eglCreateContext (display_wayland->egl_display,
|
||||
context_wayland->egl_config,
|
||||
display_wayland->egl_config,
|
||||
share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
|
||||
: shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT (shared_data_context)->egl_context
|
||||
: EGL_NO_CONTEXT,
|
||||
: EGL_NO_CONTEXT,
|
||||
context_attribs);
|
||||
|
||||
/* If context creation failed without the ES bit, let's try again with it */
|
||||
@ -147,10 +147,9 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("eglCreateContext failed, switching to OpenGL ES"));
|
||||
ctx = eglCreateContext (display_wayland->egl_display,
|
||||
context_wayland->egl_config,
|
||||
display_wayland->egl_config,
|
||||
share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
|
||||
: shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT (shared_data_context)->egl_context
|
||||
: EGL_NO_CONTEXT,
|
||||
: EGL_NO_CONTEXT,
|
||||
context_attribs);
|
||||
}
|
||||
|
||||
@ -177,10 +176,9 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("eglCreateContext failed, switching to legacy"));
|
||||
ctx = eglCreateContext (display_wayland->egl_display,
|
||||
context_wayland->egl_config,
|
||||
display_wayland->egl_config,
|
||||
share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
|
||||
: shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT (shared_data_context)->egl_context
|
||||
: EGL_NO_CONTEXT,
|
||||
: EGL_NO_CONTEXT,
|
||||
context_attribs);
|
||||
}
|
||||
|
||||
@ -213,17 +211,8 @@ gdk_wayland_gl_context_get_damage (GdkGLContext *context)
|
||||
|
||||
if (display_wayland->have_egl_buffer_age)
|
||||
{
|
||||
GdkGLContext *shared;
|
||||
GdkWaylandGLContext *shared_wayland;
|
||||
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
if (shared == NULL)
|
||||
shared = context;
|
||||
shared_wayland = GDK_WAYLAND_GL_CONTEXT (shared);
|
||||
|
||||
egl_surface = gdk_wayland_surface_get_egl_surface (surface,
|
||||
shared_wayland->egl_config);
|
||||
gdk_gl_context_make_current (shared);
|
||||
egl_surface = gdk_wayland_surface_get_egl_surface (surface);
|
||||
gdk_gl_context_make_current (context);
|
||||
eglQuerySurface (display_wayland->egl_display, egl_surface,
|
||||
EGL_BUFFER_AGE_EXT, &buffer_age);
|
||||
|
||||
@ -256,6 +245,47 @@ gdk_wayland_gl_context_get_damage (GdkGLContext *context)
|
||||
return GDK_GL_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->get_damage (context);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_gl_context_clear_current (GdkGLContext *context)
|
||||
{
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
return eglMakeCurrent (display_wayland->egl_display,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_gl_context_make_current (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
{
|
||||
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
EGLSurface egl_surface;
|
||||
|
||||
if (!surfaceless)
|
||||
egl_surface = gdk_wayland_surface_get_egl_surface (gdk_gl_context_get_surface (context));
|
||||
else
|
||||
egl_surface = EGL_NO_SURFACE;
|
||||
|
||||
return eglMakeCurrent (display_wayland->egl_display,
|
||||
egl_surface,
|
||||
egl_surface,
|
||||
context_wayland->egl_context);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_gl_context_begin_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, region);
|
||||
|
||||
glDrawBuffers (1, (GLenum[1]) { GL_BACK });
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *painted)
|
||||
@ -264,18 +294,13 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
|
||||
EGLSurface egl_surface;
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->end_frame (draw_context, painted);
|
||||
if (gdk_gl_context_get_shared_context (context))
|
||||
return;
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
egl_surface = gdk_wayland_surface_get_egl_surface (surface,
|
||||
context_wayland->egl_config);
|
||||
|
||||
egl_surface = gdk_wayland_surface_get_egl_surface (surface);
|
||||
gdk_wayland_surface_sync (surface);
|
||||
gdk_wayland_surface_request_frame (surface);
|
||||
|
||||
@ -322,9 +347,12 @@ gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
|
||||
|
||||
gobject_class->dispose = gdk_wayland_gl_context_dispose;
|
||||
|
||||
draw_context_class->begin_frame = gdk_wayland_gl_context_begin_frame;
|
||||
draw_context_class->end_frame = gdk_wayland_gl_context_end_frame;
|
||||
|
||||
context_class->realize = gdk_wayland_gl_context_realize;
|
||||
context_class->make_current = gdk_wayland_gl_context_make_current;
|
||||
context_class->clear_current = gdk_wayland_gl_context_clear_current;
|
||||
context_class->get_damage = gdk_wayland_gl_context_get_damage;
|
||||
}
|
||||
|
||||
@ -350,7 +378,7 @@ gdk_wayland_display_get_egl_display (GdkDisplay *display)
|
||||
|
||||
g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), NULL);
|
||||
|
||||
if (!gdk_wayland_display_init_gl (display))
|
||||
if (!gdk_display_prepare_gl (display, NULL))
|
||||
return NULL;
|
||||
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
@ -395,71 +423,11 @@ out:
|
||||
return dpy;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_wayland_display_init_gl (GdkDisplay *display)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
EGLint major, minor;
|
||||
EGLDisplay dpy;
|
||||
|
||||
if (display_wayland->have_egl)
|
||||
return TRUE;
|
||||
|
||||
dpy = get_egl_display (display_wayland);
|
||||
|
||||
if (dpy == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!eglInitialize (dpy, &major, &minor))
|
||||
return FALSE;
|
||||
|
||||
if (!eglBindAPI (EGL_OPENGL_API))
|
||||
return FALSE;
|
||||
|
||||
display_wayland->egl_display = dpy;
|
||||
display_wayland->egl_major_version = major;
|
||||
display_wayland->egl_minor_version = minor;
|
||||
|
||||
display_wayland->have_egl = TRUE;
|
||||
|
||||
display_wayland->have_egl_khr_create_context =
|
||||
epoxy_has_egl_extension (dpy, "EGL_KHR_create_context");
|
||||
|
||||
display_wayland->have_egl_buffer_age =
|
||||
epoxy_has_egl_extension (dpy, "EGL_EXT_buffer_age");
|
||||
|
||||
display_wayland->have_egl_swap_buffers_with_damage =
|
||||
epoxy_has_egl_extension (dpy, "EGL_EXT_swap_buffers_with_damage");
|
||||
|
||||
display_wayland->have_egl_surfaceless_context =
|
||||
epoxy_has_egl_extension (dpy, "EGL_KHR_surfaceless_context");
|
||||
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("EGL API version %d.%d found\n"
|
||||
" - Vendor: %s\n"
|
||||
" - Version: %s\n"
|
||||
" - Client APIs: %s\n"
|
||||
" - Extensions:\n"
|
||||
"\t%s",
|
||||
display_wayland->egl_major_version,
|
||||
display_wayland->egl_minor_version,
|
||||
eglQueryString (dpy, EGL_VENDOR),
|
||||
eglQueryString (dpy, EGL_VERSION),
|
||||
eglQueryString (dpy, EGL_CLIENT_APIS),
|
||||
eglQueryString (dpy, EGL_EXTENSIONS)));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define MAX_EGL_ATTRS 30
|
||||
|
||||
static gboolean
|
||||
find_eglconfig_for_surface (GdkSurface *surface,
|
||||
EGLConfig *egl_config_out,
|
||||
GError **error)
|
||||
static EGLConfig
|
||||
get_eglconfig (EGLDisplay dpy)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
EGLint attrs[MAX_EGL_ATTRS];
|
||||
EGLint count;
|
||||
EGLConfig config;
|
||||
@ -484,59 +452,113 @@ find_eglconfig_for_surface (GdkSurface *surface,
|
||||
g_assert (i < MAX_EGL_ATTRS);
|
||||
|
||||
/* Pick first valid configuration i guess? */
|
||||
if (!eglChooseConfig (display_wayland->egl_display, attrs, &config, 1, &count) || count < 1)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
return FALSE;
|
||||
}
|
||||
if (!eglChooseConfig (dpy, attrs, &config, 1, &count) || count < 1)
|
||||
return NULL;
|
||||
|
||||
g_assert (egl_config_out);
|
||||
*egl_config_out = config;
|
||||
|
||||
return TRUE;
|
||||
return config;
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_wayland_surface_create_gl_context (GdkSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GdkWaylandGLContext *context;
|
||||
EGLConfig config;
|
||||
#undef MAX_EGL_ATTRS
|
||||
|
||||
if (!gdk_wayland_display_init_gl (display))
|
||||
GdkGLContext *
|
||||
gdk_wayland_display_init_gl (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
EGLint major, minor;
|
||||
EGLDisplay dpy;
|
||||
|
||||
dpy = get_egl_display (display_wayland);
|
||||
if (dpy == NULL)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Failed to create EGL display"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!eglInitialize (dpy, &major, &minor))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Could not initialize EGL display"));
|
||||
return NULL;
|
||||
}
|
||||
if (major < GDK_EGL_MIN_VERSION_MAJOR ||
|
||||
(major == GDK_EGL_MIN_VERSION_MAJOR && minor < GDK_EGL_MIN_VERSION_MINOR))
|
||||
{
|
||||
eglTerminate (dpy);
|
||||
g_set_error (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("EGL version %d.%d is too old. GTK requires %d.%d"),
|
||||
major, minor, GDK_EGL_MIN_VERSION_MAJOR, GDK_EGL_MIN_VERSION_MINOR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!eglBindAPI (EGL_OPENGL_API))
|
||||
{
|
||||
eglTerminate (dpy);
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No GL implementation is available"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!display_wayland->have_egl_khr_create_context)
|
||||
if (!epoxy_has_egl_extension (dpy, "EGL_KHR_create_context"))
|
||||
{
|
||||
eglTerminate (dpy);
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_PROFILE,
|
||||
_("Core GL is not available on EGL implementation"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!find_eglconfig_for_surface (surface, &config, error))
|
||||
return NULL;
|
||||
if (!epoxy_has_egl_extension (dpy, "EGL_KHR_surfaceless_context"))
|
||||
{
|
||||
eglTerminate (dpy);
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_PROFILE,
|
||||
_("Surfaceless contexts are not supported on this EGL implementation"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context = g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT,
|
||||
"surface", surface,
|
||||
"shared-context", share,
|
||||
NULL);
|
||||
display_wayland->egl_config = get_eglconfig (dpy);
|
||||
if (!display_wayland->egl_config)
|
||||
{
|
||||
eglTerminate (dpy);
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context->egl_config = config;
|
||||
context->is_attached = attached;
|
||||
display_wayland->egl_display = dpy;
|
||||
display_wayland->egl_major_version = major;
|
||||
display_wayland->egl_minor_version = minor;
|
||||
|
||||
return GDK_GL_CONTEXT (context);
|
||||
display_wayland->have_egl_buffer_age =
|
||||
epoxy_has_egl_extension (dpy, "EGL_EXT_buffer_age");
|
||||
|
||||
display_wayland->have_egl_swap_buffers_with_damage =
|
||||
epoxy_has_egl_extension (dpy, "EGL_EXT_swap_buffers_with_damage");
|
||||
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("EGL API version %d.%d found\n"
|
||||
" - Vendor: %s\n"
|
||||
" - Version: %s\n"
|
||||
" - Client APIs: %s\n"
|
||||
" - Extensions:\n"
|
||||
"\t%s",
|
||||
display_wayland->egl_major_version,
|
||||
display_wayland->egl_minor_version,
|
||||
eglQueryString (dpy, EGL_VENDOR),
|
||||
eglQueryString (dpy, EGL_VERSION),
|
||||
eglQueryString (dpy, EGL_CLIENT_APIS),
|
||||
eglQueryString (dpy, EGL_EXTENSIONS)));
|
||||
|
||||
return g_object_new (GDK_TYPE_WAYLAND_GL_CONTEXT,
|
||||
"display", display,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -565,42 +587,3 @@ gdk_wayland_gl_context_dispose (GObject *gobject)
|
||||
G_OBJECT_CLASS (gdk_wayland_gl_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GdkWaylandGLContext *context_wayland;
|
||||
GdkSurface *surface;
|
||||
EGLSurface egl_surface;
|
||||
|
||||
if (context == NULL)
|
||||
{
|
||||
eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
|
||||
surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
if (context_wayland->is_attached || gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context)))
|
||||
egl_surface = gdk_wayland_surface_get_egl_surface (surface, context_wayland->egl_config);
|
||||
else
|
||||
{
|
||||
if (display_wayland->have_egl_surfaceless_context)
|
||||
egl_surface = EGL_NO_SURFACE;
|
||||
else
|
||||
egl_surface = gdk_wayland_surface_get_dummy_egl_surface (surface,
|
||||
context_wayland->egl_config);
|
||||
}
|
||||
|
||||
if (!eglMakeCurrent (display_wayland->egl_display, egl_surface,
|
||||
egl_surface, context_wayland->egl_context))
|
||||
{
|
||||
g_warning ("eglMakeCurrent failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -36,8 +36,6 @@ struct _GdkWaylandGLContext
|
||||
GdkGLContext parent_instance;
|
||||
|
||||
EGLContext egl_context;
|
||||
EGLConfig egl_config;
|
||||
gboolean is_attached;
|
||||
};
|
||||
|
||||
struct _GdkWaylandGLContextClass
|
||||
@ -45,13 +43,8 @@ struct _GdkWaylandGLContextClass
|
||||
GdkGLContextClass parent_class;
|
||||
};
|
||||
|
||||
gboolean gdk_wayland_display_init_gl (GdkDisplay *display);
|
||||
GdkGLContext * gdk_wayland_surface_create_gl_context (GdkSurface *surface,
|
||||
gboolean attach,
|
||||
GdkGLContext *share,
|
||||
GdkGLContext * gdk_wayland_display_init_gl (GdkDisplay *display,
|
||||
GError **error);
|
||||
gboolean gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -182,11 +182,6 @@ cairo_surface_t * _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *di
|
||||
struct wl_buffer *_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface);
|
||||
gboolean _gdk_wayland_is_shm_surface (cairo_surface_t *surface);
|
||||
|
||||
EGLSurface gdk_wayland_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config);
|
||||
EGLSurface gdk_wayland_surface_get_dummy_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config);
|
||||
|
||||
struct gtk_surface1 * gdk_wayland_surface_get_gtk_surface (GdkSurface *surface);
|
||||
|
||||
void gdk_wayland_seat_set_global_cursor (GdkSeat *seat,
|
||||
|
@ -103,7 +103,6 @@ struct _GdkWaylandSurface
|
||||
|
||||
struct gtk_surface1 *gtk_surface;
|
||||
struct wl_egl_window *egl_window;
|
||||
struct wl_egl_window *dummy_egl_window;
|
||||
struct zxdg_exported_v1 *xdg_exported;
|
||||
struct org_kde_kwin_server_decoration *server_decoration;
|
||||
} display_server;
|
||||
@ -111,7 +110,6 @@ struct _GdkWaylandSurface
|
||||
struct wl_event_queue *event_queue;
|
||||
|
||||
EGLSurface egl_surface;
|
||||
EGLSurface dummy_egl_surface;
|
||||
|
||||
uint32_t reposition_token;
|
||||
uint32_t received_reposition_token;
|
||||
@ -2901,18 +2899,6 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
|
||||
|
||||
if (impl->display_server.wl_surface)
|
||||
{
|
||||
if (impl->dummy_egl_surface)
|
||||
{
|
||||
eglDestroySurface (display_wayland->egl_display, impl->dummy_egl_surface);
|
||||
impl->dummy_egl_surface = NULL;
|
||||
}
|
||||
|
||||
if (impl->display_server.dummy_egl_window)
|
||||
{
|
||||
wl_egl_window_destroy (impl->display_server.dummy_egl_window);
|
||||
impl->display_server.dummy_egl_window = NULL;
|
||||
}
|
||||
|
||||
if (impl->egl_surface)
|
||||
{
|
||||
eglDestroySurface (display_wayland->egl_display, impl->egl_surface);
|
||||
@ -4238,7 +4224,6 @@ gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
|
||||
impl_class->drag_begin = _gdk_wayland_surface_drag_begin;
|
||||
impl_class->get_scale_factor = gdk_wayland_surface_get_scale_factor;
|
||||
impl_class->set_opaque_region = gdk_wayland_surface_set_opaque_region;
|
||||
impl_class->create_gl_context = gdk_wayland_surface_create_gl_context;
|
||||
impl_class->request_layout = gdk_wayland_surface_request_layout;
|
||||
impl_class->compute_size = gdk_wayland_surface_compute_size;
|
||||
}
|
||||
@ -4304,8 +4289,7 @@ gdk_wayland_surface_get_wl_egl_window (GdkSurface *surface)
|
||||
}
|
||||
|
||||
EGLSurface
|
||||
gdk_wayland_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config)
|
||||
gdk_wayland_surface_get_egl_surface (GdkSurface *surface)
|
||||
{
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
|
||||
GdkWaylandSurface *impl;
|
||||
@ -4320,35 +4304,12 @@ gdk_wayland_surface_get_egl_surface (GdkSurface *surface,
|
||||
egl_window = gdk_wayland_surface_get_wl_egl_window (surface);
|
||||
|
||||
impl->egl_surface =
|
||||
eglCreateWindowSurface (display->egl_display, config, egl_window, NULL);
|
||||
eglCreateWindowSurface (display->egl_display, display->egl_config, egl_window, NULL);
|
||||
}
|
||||
|
||||
return impl->egl_surface;
|
||||
}
|
||||
|
||||
EGLSurface
|
||||
gdk_wayland_surface_get_dummy_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config)
|
||||
{
|
||||
GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
|
||||
GdkWaylandSurface *impl;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (surface), NULL);
|
||||
|
||||
impl = GDK_WAYLAND_SURFACE (surface);
|
||||
|
||||
if (impl->dummy_egl_surface == NULL)
|
||||
{
|
||||
impl->display_server.dummy_egl_window =
|
||||
wl_egl_window_create (impl->display_server.wl_surface, 1, 1);
|
||||
|
||||
impl->dummy_egl_surface =
|
||||
eglCreateWindowSurface (display->egl_display, config, impl->display_server.dummy_egl_window, NULL);
|
||||
}
|
||||
|
||||
return impl->dummy_egl_surface;
|
||||
}
|
||||
|
||||
struct gtk_surface1 *
|
||||
gdk_wayland_surface_get_gtk_surface (GdkSurface *surface)
|
||||
{
|
||||
|
@ -22,6 +22,9 @@
|
||||
|
||||
#include "gdkwaylandsurface.h"
|
||||
|
||||
#include <wayland-egl.h>
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gdk_wayland_toplevel_set_dbus_properties (GdkToplevel *toplevel,
|
||||
@ -38,4 +41,6 @@ void gdk_wayland_toplevel_announce_ssd (GdkTopl
|
||||
gboolean gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel);
|
||||
void gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel);
|
||||
|
||||
EGLSurface gdk_wayland_surface_get_egl_surface (GdkSurface *surface);
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -481,6 +481,7 @@ register_display_change_notification (GdkDisplay *display)
|
||||
wclass.lpszClassName = "GdkDisplayChange";
|
||||
wclass.lpfnWndProc = display_change_window_procedure;
|
||||
wclass.hInstance = _gdk_app_hmodule;
|
||||
wclass.style = CS_OWNDC;
|
||||
|
||||
klass = RegisterClass (&wclass);
|
||||
if (klass)
|
||||
@ -656,6 +657,13 @@ gdk_win32_display_dispose (GObject *object)
|
||||
|
||||
if (display_win32->hwnd != NULL)
|
||||
{
|
||||
if (display_win32->dummy_context_wgl.hglrc != NULL)
|
||||
{
|
||||
wglMakeCurrent (NULL, NULL);
|
||||
wglDeleteContext (display_win32->dummy_context_wgl.hglrc);
|
||||
display_win32->dummy_context_wgl.hglrc = NULL;
|
||||
}
|
||||
|
||||
DestroyWindow (display_win32->hwnd);
|
||||
display_win32->hwnd = NULL;
|
||||
}
|
||||
@ -1140,6 +1148,85 @@ gdk_win32_display_get_setting (GdkDisplay *display,
|
||||
return _gdk_win32_get_setting (name, value);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_display_init_gl_backend (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_EGL))
|
||||
return gdk_win32_display_init_egl (display, error);
|
||||
#endif
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_WGL))
|
||||
return gdk_win32_display_init_wgl (display, error);
|
||||
|
||||
/* No env vars set, do the regular GL initialization, first WGL and then EGL,
|
||||
* as WGL is the more tried-and-tested configuration.
|
||||
*/
|
||||
|
||||
if (gdk_win32_display_init_wgl (display, error))
|
||||
return TRUE;
|
||||
g_clear_error (error);
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
if (gdk_win32_display_init_egl (display, error))
|
||||
return TRUE;
|
||||
#endif
|
||||
g_clear_error (error);
|
||||
|
||||
return gdk_win32_display_init_wgl (display, error);
|
||||
}
|
||||
|
||||
static GdkGLContext *
|
||||
gdk_win32_display_init_gl (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
GdkGLContext *gl_context = NULL;
|
||||
|
||||
if (!gdk_win32_display_init_gl_backend (display, error))
|
||||
return NULL;
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
if (display_win32->egl_disp)
|
||||
gl_context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_EGL, "display", display, NULL);
|
||||
else
|
||||
#endif
|
||||
if (display_win32->wgl_pixel_format != 0)
|
||||
gl_context = g_object_new (GDK_TYPE_WIN32_GL_CONTEXT_WGL, "display", display, NULL);
|
||||
|
||||
g_return_val_if_fail (gl_context != NULL, NULL);
|
||||
|
||||
return gl_context;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_win32_display_get_egl_display:
|
||||
* @display: (type GdkWin32Display): a Win32 display
|
||||
*
|
||||
* Retrieves the EGL display connection object for the given GDK display.
|
||||
*
|
||||
* Returns: (nullable): the EGL display
|
||||
*/
|
||||
gpointer
|
||||
gdk_win32_display_get_egl_display (GdkDisplay *display)
|
||||
{
|
||||
GdkWin32Display *display_win32;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_WIN32_DISPLAY (display), NULL);
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
|
||||
if (display_win32->wgl_pixel_format != 0)
|
||||
return NULL;
|
||||
|
||||
return display_win32->egl_disp;
|
||||
#else
|
||||
/* no EGL support */
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
|
||||
{
|
||||
@ -1165,7 +1252,6 @@ gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
|
||||
display_class->create_surface = _gdk_win32_display_create_surface;
|
||||
|
||||
display_class->get_keymap = _gdk_win32_display_get_keymap;
|
||||
display_class->make_gl_context_current = _gdk_win32_display_make_gl_context_current;
|
||||
|
||||
display_class->get_monitors = gdk_win32_display_get_monitors;
|
||||
|
||||
@ -1176,6 +1262,7 @@ gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
|
||||
|
||||
display_class->get_setting = gdk_win32_display_get_setting;
|
||||
display_class->set_cursor_theme = gdk_win32_display_set_cursor_theme;
|
||||
display_class->init_gl = gdk_win32_display_init_gl;
|
||||
|
||||
_gdk_win32_surfaceing_init ();
|
||||
}
|
||||
|
@ -106,6 +106,12 @@ typedef struct _GdkWin32KernelCPUFuncs
|
||||
funcIsWow64Process2 isWow64Process2;
|
||||
} GdkWin32KernelCPUFuncs;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HDC hdc;
|
||||
HGLRC hglrc;
|
||||
} GdkWin32GLDummyContextWGL;
|
||||
|
||||
struct _GdkWin32Display
|
||||
{
|
||||
GdkDisplay display;
|
||||
@ -119,14 +125,15 @@ struct _GdkWin32Display
|
||||
HWND hwnd;
|
||||
|
||||
/* WGL/OpenGL Items */
|
||||
guint have_wgl : 1;
|
||||
GdkWin32GLDummyContextWGL dummy_context_wgl;
|
||||
int wgl_pixel_format;
|
||||
guint gl_version;
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
/* EGL (Angle) Items */
|
||||
guint have_egl : 1;
|
||||
guint egl_version;
|
||||
EGLDisplay egl_disp;
|
||||
EGLConfig egl_config;
|
||||
HDC hdc_egl_temp;
|
||||
#endif
|
||||
|
||||
|
504
gdk/win32/gdkglcontext-win32-egl.c
Normal file
504
gdk/win32/gdkglcontext-win32-egl.c
Normal file
@ -0,0 +1,504 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* gdkglcontext-win32.c: Win32 specific OpenGL wrappers
|
||||
*
|
||||
* Copyright © 2014 Emmanuele Bassi
|
||||
* Copyright © 2014 Alexander Larsson
|
||||
* Copyright © 2014 Chun-wei Fan
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkprivate-win32.h"
|
||||
#include "gdksurface-win32.h"
|
||||
#include "gdkglcontext-win32.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
|
||||
#include "gdkwin32display.h"
|
||||
#include "gdkwin32glcontext.h"
|
||||
#include "gdkwin32misc.h"
|
||||
#include "gdkwin32screen.h"
|
||||
#include "gdkwin32surface.h"
|
||||
|
||||
#include "gdkglcontext.h"
|
||||
#include "gdksurface.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkintl.h"
|
||||
|
||||
#include <cairo.h>
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
struct _GdkWin32GLContextEGL
|
||||
{
|
||||
GdkWin32GLContext parent_instance;
|
||||
|
||||
/* EGL (Angle) Context Items */
|
||||
EGLContext egl_context;
|
||||
guint do_frame_sync : 1;
|
||||
};
|
||||
|
||||
typedef struct _GdkWin32GLContextClass GdkWin32GLContextEGLClass;
|
||||
|
||||
G_DEFINE_TYPE (GdkWin32GLContextEGL, gdk_win32_gl_context_egl, GDK_TYPE_WIN32_GL_CONTEXT)
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_egl_dispose (GObject *gobject)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
|
||||
GdkWin32GLContextEGL *context_egl = GDK_WIN32_GL_CONTEXT_EGL (gobject);
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context));
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
if (display_win32 != NULL)
|
||||
{
|
||||
if (eglGetCurrentContext () == context_egl->egl_context)
|
||||
eglMakeCurrent(display_win32->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
|
||||
GDK_NOTE (OPENGL, g_message ("Destroying EGL (ANGLE) context"));
|
||||
|
||||
eglDestroyContext (display_win32->egl_disp,
|
||||
context_egl->egl_context);
|
||||
context_egl->egl_context = EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gdk_win32_gl_context_egl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_egl_force_redraw (GdkSurface *surface)
|
||||
{
|
||||
/* We only need to call gdk_window_invalidate_rect () if necessary */
|
||||
if (surface->gl_paint_context != NULL && gdk_gl_context_get_use_es (surface->gl_paint_context))
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
return impl->egl_force_redraw_all;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_egl_force_redraw (GdkSurface *surface)
|
||||
{
|
||||
if (surface->gl_paint_context != NULL && gdk_gl_context_get_use_es (surface->gl_paint_context))
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
if (impl->egl_force_redraw_all)
|
||||
impl->egl_force_redraw_all = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_egl_end_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *painted)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkWin32GLContextEGL *context_egl = GDK_WIN32_GL_CONTEXT_EGL (context);
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
GdkWin32Display *display_win32 = (GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context)));
|
||||
cairo_rectangle_int_t whole_window;
|
||||
EGLSurface egl_surface;
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->end_frame (draw_context, painted);
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
whole_window =
|
||||
(GdkRectangle) { 0, 0,
|
||||
gdk_surface_get_width (surface),
|
||||
gdk_surface_get_height (surface)
|
||||
};
|
||||
|
||||
egl_surface = gdk_win32_surface_get_egl_surface (surface, display_win32->egl_config, FALSE);
|
||||
|
||||
if (is_egl_force_redraw (surface))
|
||||
{
|
||||
GdkRectangle rect = {0, 0, gdk_surface_get_width (surface), gdk_surface_get_height (surface)};
|
||||
|
||||
/* We need to do gdk_window_invalidate_rect() so that we don't get glitches after maximizing or
|
||||
* restoring or using aerosnap
|
||||
*/
|
||||
gdk_surface_invalidate_rect (surface, &rect);
|
||||
reset_egl_force_redraw (surface);
|
||||
}
|
||||
|
||||
eglSwapBuffers (display_win32->egl_disp, egl_surface);
|
||||
}
|
||||
|
||||
#ifndef EGL_PLATFORM_ANGLE_ANGLE
|
||||
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
|
||||
#endif
|
||||
|
||||
#ifndef EGL_PLATFORM_ANGLE_TYPE_ANGLE
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
|
||||
#endif
|
||||
|
||||
#ifndef EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE
|
||||
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
|
||||
#endif
|
||||
|
||||
static EGLDisplay
|
||||
gdk_win32_get_egl_display (GdkWin32Display *display)
|
||||
{
|
||||
EGLDisplay disp;
|
||||
|
||||
if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base"))
|
||||
{
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = (void *) eglGetProcAddress ("eglGetPlatformDisplayEXT");
|
||||
if (getPlatformDisplay)
|
||||
{
|
||||
EGLint disp_attr[] = {EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE};
|
||||
|
||||
disp = getPlatformDisplay (EGL_PLATFORM_ANGLE_ANGLE, display->hdc_egl_temp, disp_attr);
|
||||
|
||||
if (disp != EGL_NO_DISPLAY)
|
||||
return disp;
|
||||
}
|
||||
}
|
||||
|
||||
return eglGetDisplay (display->hdc_egl_temp);
|
||||
}
|
||||
|
||||
#define MAX_EGL_ATTRS 30
|
||||
|
||||
static gboolean
|
||||
find_eglconfig_for_window (GdkWin32Display *display,
|
||||
EGLConfig *egl_config_out,
|
||||
EGLint *min_swap_interval_out,
|
||||
GError **error)
|
||||
{
|
||||
EGLint attrs[MAX_EGL_ATTRS];
|
||||
EGLint count;
|
||||
EGLConfig *configs, chosen_config;
|
||||
|
||||
int i = 0;
|
||||
|
||||
EGLDisplay egl_disp = display->egl_disp;
|
||||
|
||||
attrs[i++] = EGL_CONFORMANT;
|
||||
attrs[i++] = EGL_OPENGL_ES2_BIT;
|
||||
attrs[i++] = EGL_SURFACE_TYPE;
|
||||
attrs[i++] = EGL_WINDOW_BIT;
|
||||
|
||||
attrs[i++] = EGL_COLOR_BUFFER_TYPE;
|
||||
attrs[i++] = EGL_RGB_BUFFER;
|
||||
|
||||
attrs[i++] = EGL_RED_SIZE;
|
||||
attrs[i++] = 1;
|
||||
attrs[i++] = EGL_GREEN_SIZE;
|
||||
attrs[i++] = 1;
|
||||
attrs[i++] = EGL_BLUE_SIZE;
|
||||
attrs[i++] = 1;
|
||||
attrs[i++] = EGL_ALPHA_SIZE;
|
||||
attrs[i++] = 1;
|
||||
|
||||
attrs[i++] = EGL_NONE;
|
||||
g_assert (i < MAX_EGL_ATTRS);
|
||||
|
||||
if (!eglChooseConfig (display->egl_disp, attrs, NULL, 0, &count) || count < 1)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
configs = g_new (EGLConfig, count);
|
||||
|
||||
if (!eglChooseConfig (display->egl_disp, attrs, configs, count, &count) || count < 1)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Pick first valid configuration i guess? */
|
||||
chosen_config = configs[0];
|
||||
|
||||
if (!eglGetConfigAttrib (display->egl_disp, chosen_config,
|
||||
EGL_MIN_SWAP_INTERVAL, min_swap_interval_out))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
"Could not retrieve the minimum swap interval");
|
||||
g_free (configs);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (egl_config_out != NULL)
|
||||
*egl_config_out = chosen_config;
|
||||
|
||||
g_free (configs);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_win32_display_init_egl (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
int best_idx = 0;
|
||||
EGLDisplay egl_disp;
|
||||
|
||||
if (display_win32->egl_disp != EGL_NO_DISPLAY)
|
||||
return TRUE;
|
||||
|
||||
egl_disp = gdk_win32_get_egl_display (display_win32);
|
||||
|
||||
if (egl_disp == EGL_NO_DISPLAY)
|
||||
return FALSE;
|
||||
|
||||
if (!eglInitialize (egl_disp, NULL, NULL))
|
||||
{
|
||||
eglTerminate (egl_disp);
|
||||
egl_disp = EGL_NO_DISPLAY;
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No GL implementation is available"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
display_win32->egl_disp = egl_disp;
|
||||
display_win32->egl_version = epoxy_egl_version (egl_disp);
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
display_win32->hasEglSurfacelessContext =
|
||||
epoxy_has_egl_extension (egl_disp, "EGL_KHR_surfaceless_context");
|
||||
|
||||
GDK_NOTE (OPENGL,
|
||||
g_print ("EGL API version %d.%d found\n"
|
||||
" - Vendor: %s\n"
|
||||
" - Checked extensions:\n"
|
||||
"\t* EGL_KHR_surfaceless_context: %s\n",
|
||||
display_win32->egl_version / 10,
|
||||
display_win32->egl_version % 10,
|
||||
eglQueryString (display_win32->egl_disp, EGL_VENDOR),
|
||||
display_win32->hasEglSurfacelessContext ? "yes" : "no"));
|
||||
|
||||
return find_eglconfig_for_window (display_win32, &display_win32->egl_config,
|
||||
&display_win32->egl_min_swap_interval, error);
|
||||
}
|
||||
|
||||
#define N_EGL_ATTRS 16
|
||||
|
||||
static EGLContext
|
||||
create_egl_context (EGLDisplay display,
|
||||
EGLConfig config,
|
||||
GdkGLContext *share,
|
||||
int flags,
|
||||
int major,
|
||||
int minor,
|
||||
gboolean *is_legacy)
|
||||
{
|
||||
EGLContext ctx;
|
||||
EGLint context_attribs[N_EGL_ATTRS];
|
||||
int i = 0;
|
||||
|
||||
/* ANGLE does not support the GL_OES_vertex_array_object extension, so we need to use ES3 directly */
|
||||
context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
|
||||
context_attribs[i++] = 3;
|
||||
|
||||
/* Specify the flags */
|
||||
context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
|
||||
context_attribs[i++] = flags;
|
||||
|
||||
context_attribs[i++] = EGL_NONE;
|
||||
g_assert (i < N_EGL_ATTRS);
|
||||
|
||||
ctx = eglCreateContext (display,
|
||||
config,
|
||||
share != NULL ? GDK_WIN32_GL_CONTEXT_EGL (share)->egl_context
|
||||
: EGL_NO_CONTEXT,
|
||||
context_attribs);
|
||||
|
||||
if (ctx != EGL_NO_CONTEXT)
|
||||
GDK_NOTE (OPENGL, g_message ("Created EGL context[%p]", ctx));
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_gl_context_egl_realize (GdkGLContext *context,
|
||||
GError **error)
|
||||
{
|
||||
GdkWin32GLContextEGL *context_egl = GDK_WIN32_GL_CONTEXT_EGL (context);
|
||||
|
||||
gboolean debug_bit, compat_bit, legacy_bit;
|
||||
gboolean use_es = FALSE;
|
||||
EGLContext egl_context;
|
||||
EGLContext ctx;
|
||||
|
||||
/* request flags and specific versions for core (3.2+) WGL context */
|
||||
int flags = 0;
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
GdkGLContext *share = gdk_display_get_gl_context (display);
|
||||
|
||||
gdk_gl_context_get_required_version (context, &major, &minor);
|
||||
debug_bit = gdk_gl_context_get_debug_enabled (context);
|
||||
compat_bit = gdk_gl_context_get_forward_compatible (context);
|
||||
|
||||
/*
|
||||
* A legacy context cannot be shared with core profile ones, so this means we
|
||||
* must stick to a legacy context if the shared context is a legacy context
|
||||
*/
|
||||
|
||||
/* if GDK_GL_LEGACY is set, we default to a legacy context */
|
||||
legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ?
|
||||
TRUE :
|
||||
share != NULL && gdk_gl_context_is_legacy (share);
|
||||
|
||||
use_es = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES) ||
|
||||
(share != NULL && gdk_gl_context_get_use_es (share));
|
||||
|
||||
if (debug_bit)
|
||||
flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
||||
if (compat_bit)
|
||||
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
||||
|
||||
GDK_NOTE (OPENGL, g_message ("Creating EGL context version %d.%d (debug:%s, forward:%s, legacy:%s)",
|
||||
major, minor,
|
||||
debug_bit ? "yes" : "no",
|
||||
compat_bit ? "yes" : "no",
|
||||
legacy_bit ? "yes" : "no"));
|
||||
|
||||
ctx = create_egl_context (display_win32->egl_disp,
|
||||
display_win32->egl_config,
|
||||
share,
|
||||
flags,
|
||||
major,
|
||||
minor,
|
||||
&legacy_bit);
|
||||
|
||||
if (ctx == EGL_NO_CONTEXT)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Unable to create a GL context"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GDK_NOTE (OPENGL, g_print ("Created EGL context[%p]\n", ctx));
|
||||
|
||||
context_egl->egl_context = ctx;
|
||||
|
||||
/* We are using GLES here */
|
||||
gdk_gl_context_set_use_es (context, TRUE);
|
||||
|
||||
/* Ensure that any other context is created with a legacy bit set */
|
||||
gdk_gl_context_set_is_legacy (context, legacy_bit);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_gl_context_egl_clear_current (GdkGLContext *context)
|
||||
{
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
|
||||
if (display_win32->egl_disp != EGL_NO_DISPLAY)
|
||||
return eglMakeCurrent (display_win32->egl_disp,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_gl_context_egl_make_current (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
{
|
||||
GdkWin32GLContextEGL *context_egl = GDK_WIN32_GL_CONTEXT_EGL (context);
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
GdkSurface *surface;
|
||||
|
||||
gboolean do_frame_sync = FALSE;
|
||||
|
||||
EGLSurface egl_surface;
|
||||
|
||||
surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
if (!surfaceless)
|
||||
egl_surface = gdk_win32_surface_get_egl_surface (surface, display_win32->egl_config, FALSE);
|
||||
else
|
||||
{
|
||||
if (display_win32->hasEglSurfacelessContext)
|
||||
egl_surface = EGL_NO_SURFACE;
|
||||
else
|
||||
egl_surface = gdk_win32_surface_get_egl_surface (surface, display_win32->egl_config, TRUE);
|
||||
}
|
||||
|
||||
if (!eglMakeCurrent (display_win32->egl_disp,
|
||||
egl_surface,
|
||||
egl_surface,
|
||||
context_egl->egl_context))
|
||||
return FALSE;
|
||||
|
||||
if (display_win32->egl_min_swap_interval == 0)
|
||||
eglSwapInterval (display_win32->egl_disp, 0);
|
||||
else
|
||||
g_debug ("Can't disable GL swap interval");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *update_area)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkSurface *surface;
|
||||
|
||||
surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
gdk_win32_surface_handle_queued_move_resize (draw_context);
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_egl_parent_class)->begin_frame (draw_context, update_area);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_egl_class_init (GdkWin32GLContextClass *klass)
|
||||
{
|
||||
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS(klass);
|
||||
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS(klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
context_class->realize = gdk_win32_gl_context_egl_realize;
|
||||
context_class->make_current = gdk_win32_gl_context_egl_make_current;
|
||||
context_class->clear_current = gdk_win32_gl_context_egl_clear_current;
|
||||
|
||||
draw_context_class->begin_frame = gdk_win32_gl_context_egl_begin_frame;
|
||||
draw_context_class->end_frame = gdk_win32_gl_context_egl_end_frame;
|
||||
|
||||
gobject_class->dispose = gdk_win32_gl_context_egl_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_egl_init (GdkWin32GLContextEGL *egl_context)
|
||||
{
|
||||
}
|
727
gdk/win32/gdkglcontext-win32-wgl.c
Normal file
727
gdk/win32/gdkglcontext-win32-wgl.c
Normal file
@ -0,0 +1,727 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* gdkglcontext-win32.c: Win32 specific OpenGL wrappers
|
||||
*
|
||||
* Copyright © 2014 Emmanuele Bassi
|
||||
* Copyright © 2014 Alexander Larsson
|
||||
* Copyright © 2014 Chun-wei Fan
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkprivate-win32.h"
|
||||
#include "gdksurface-win32.h"
|
||||
#include "gdkglcontext-win32.h"
|
||||
#include "gdkdisplay-win32.h"
|
||||
|
||||
#include "gdkwin32display.h"
|
||||
#include "gdkwin32glcontext.h"
|
||||
#include "gdkwin32misc.h"
|
||||
#include "gdkwin32screen.h"
|
||||
#include "gdkwin32surface.h"
|
||||
|
||||
#include "gdkglcontext.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdksurface.h"
|
||||
|
||||
#include <cairo.h>
|
||||
#include <epoxy/wgl.h>
|
||||
|
||||
struct _GdkWin32GLContextWGL
|
||||
{
|
||||
GdkWin32GLContext parent_instance;
|
||||
|
||||
HGLRC wgl_context;
|
||||
guint do_frame_sync : 1;
|
||||
};
|
||||
|
||||
typedef struct _GdkWin32GLContextClass GdkWin32GLContextWGLClass;
|
||||
|
||||
G_DEFINE_TYPE (GdkWin32GLContextWGL, gdk_win32_gl_context_wgl, GDK_TYPE_WIN32_GL_CONTEXT)
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_wgl_dispose (GObject *gobject)
|
||||
{
|
||||
GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (gobject);
|
||||
|
||||
if (context_wgl->wgl_context != NULL)
|
||||
{
|
||||
if (wglGetCurrentContext () == context_wgl->wgl_context)
|
||||
wglMakeCurrent (NULL, NULL);
|
||||
|
||||
GDK_NOTE (OPENGL, g_print ("Destroying WGL context\n"));
|
||||
|
||||
wglDeleteContext (context_wgl->wgl_context);
|
||||
context_wgl->wgl_context = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (gdk_win32_gl_context_wgl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_wgl_end_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *painted)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (context);
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
GdkWin32Display *display_win32 = (GDK_WIN32_DISPLAY (gdk_gl_context_get_display (context)));
|
||||
cairo_rectangle_int_t whole_window;
|
||||
gboolean can_wait = display_win32->hasWglOMLSyncControl;
|
||||
HDC hdc;
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->end_frame (draw_context, painted);
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
whole_window = (GdkRectangle) { 0, 0, gdk_surface_get_width (surface), gdk_surface_get_height (surface) };
|
||||
|
||||
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "win32", "swap buffers");
|
||||
|
||||
if (surface != NULL)
|
||||
hdc = GDK_WIN32_SURFACE (surface)->hdc;
|
||||
else
|
||||
hdc = display_win32->dummy_context_wgl.hdc;
|
||||
|
||||
if (context_wgl->do_frame_sync)
|
||||
{
|
||||
|
||||
glFinish ();
|
||||
|
||||
if (can_wait)
|
||||
{
|
||||
gint64 ust, msc, sbc;
|
||||
|
||||
wglGetSyncValuesOML (hdc, &ust, &msc, &sbc);
|
||||
wglWaitForMscOML (hdc,
|
||||
0,
|
||||
2,
|
||||
(msc + 1) % 2,
|
||||
&ust, &msc, &sbc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SwapBuffers (hdc);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *update_area)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkSurface *surface;
|
||||
|
||||
surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
gdk_win32_surface_handle_queued_move_resize (draw_context);
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, update_area);
|
||||
}
|
||||
|
||||
static int
|
||||
gdk_init_dummy_wgl_context (GdkWin32Display *display_win32);
|
||||
|
||||
#define PIXEL_ATTRIBUTES 17
|
||||
|
||||
static int
|
||||
get_wgl_pfd (HDC hdc,
|
||||
PIXELFORMATDESCRIPTOR *pfd,
|
||||
GdkWin32Display *display_win32)
|
||||
{
|
||||
int best_pf = 0;
|
||||
|
||||
pfd->nSize = sizeof (PIXELFORMATDESCRIPTOR);
|
||||
|
||||
if (display_win32 != NULL && display_win32->hasWglARBPixelFormat)
|
||||
{
|
||||
UINT num_formats;
|
||||
int colorbits = GetDeviceCaps (hdc, BITSPIXEL);
|
||||
int i = 0;
|
||||
int pixelAttribs[PIXEL_ATTRIBUTES];
|
||||
|
||||
/* Save up the HDC and HGLRC that we are currently using, to restore back to it when we are done here */
|
||||
HDC hdc_current = wglGetCurrentDC ();
|
||||
HGLRC hglrc_current = wglGetCurrentContext ();
|
||||
|
||||
/* Update PIXEL_ATTRIBUTES above if any groups are added here! */
|
||||
pixelAttribs[i] = WGL_DRAW_TO_WINDOW_ARB;
|
||||
pixelAttribs[i++] = GL_TRUE;
|
||||
|
||||
pixelAttribs[i++] = WGL_SUPPORT_OPENGL_ARB;
|
||||
pixelAttribs[i++] = GL_TRUE;
|
||||
|
||||
pixelAttribs[i++] = WGL_DOUBLE_BUFFER_ARB;
|
||||
pixelAttribs[i++] = GL_TRUE;
|
||||
|
||||
pixelAttribs[i++] = WGL_ACCELERATION_ARB;
|
||||
pixelAttribs[i++] = WGL_FULL_ACCELERATION_ARB;
|
||||
|
||||
pixelAttribs[i++] = WGL_PIXEL_TYPE_ARB;
|
||||
pixelAttribs[i++] = WGL_TYPE_RGBA_ARB;
|
||||
|
||||
pixelAttribs[i++] = WGL_COLOR_BITS_ARB;
|
||||
pixelAttribs[i++] = colorbits;
|
||||
|
||||
/* end of "Update PIXEL_ATTRIBUTES above if any groups are added here!" */
|
||||
|
||||
if (display_win32->hasWglARBmultisample)
|
||||
{
|
||||
pixelAttribs[i++] = WGL_SAMPLE_BUFFERS_ARB;
|
||||
pixelAttribs[i++] = 1;
|
||||
|
||||
pixelAttribs[i++] = WGL_SAMPLES_ARB;
|
||||
pixelAttribs[i++] = 8;
|
||||
}
|
||||
|
||||
pixelAttribs[i++] = 0; /* end of pixelAttribs */
|
||||
best_pf = gdk_init_dummy_wgl_context (display_win32);
|
||||
|
||||
if (!wglMakeCurrent (display_win32->dummy_context_wgl.hdc,
|
||||
display_win32->dummy_context_wgl.hglrc))
|
||||
{
|
||||
wglMakeCurrent (hdc_current, hglrc_current);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wglChoosePixelFormatARB (hdc,
|
||||
pixelAttribs,
|
||||
NULL,
|
||||
1,
|
||||
&best_pf,
|
||||
&num_formats);
|
||||
|
||||
/* Go back to the HDC that we were using, since we are done with the dummy HDC and GL Context */
|
||||
wglMakeCurrent (hdc_current, hglrc_current);
|
||||
}
|
||||
else
|
||||
{
|
||||
pfd->nVersion = 1;
|
||||
pfd->dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
|
||||
pfd->iPixelType = PFD_TYPE_RGBA;
|
||||
pfd->cColorBits = GetDeviceCaps (hdc, BITSPIXEL);
|
||||
pfd->cAlphaBits = 8;
|
||||
pfd->dwLayerMask = PFD_MAIN_PLANE;
|
||||
|
||||
best_pf = ChoosePixelFormat (hdc, pfd);
|
||||
}
|
||||
|
||||
return best_pf;
|
||||
}
|
||||
|
||||
/* in WGL, for many OpenGL items, we need a dummy WGL context, so create
|
||||
* one and cache it for later use
|
||||
*/
|
||||
static int
|
||||
gdk_init_dummy_wgl_context (GdkWin32Display *display_win32)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
gboolean set_pixel_format_result = FALSE;
|
||||
int best_idx = 0;
|
||||
|
||||
if (display_win32->dummy_context_wgl.hdc == NULL)
|
||||
display_win32->dummy_context_wgl.hdc = GetDC (display_win32->hwnd);
|
||||
|
||||
memset (&pfd, 0, sizeof (PIXELFORMATDESCRIPTOR));
|
||||
|
||||
best_idx = get_wgl_pfd (display_win32->dummy_context_wgl.hdc, &pfd, NULL);
|
||||
|
||||
if (best_idx != 0)
|
||||
set_pixel_format_result = SetPixelFormat (display_win32->dummy_context_wgl.hdc,
|
||||
best_idx,
|
||||
&pfd);
|
||||
|
||||
if (best_idx == 0 || !set_pixel_format_result)
|
||||
return 0;
|
||||
|
||||
display_win32->dummy_context_wgl.hglrc =
|
||||
wglCreateContext (display_win32->dummy_context_wgl.hdc);
|
||||
|
||||
if (display_win32->dummy_context_wgl.hglrc == NULL)
|
||||
return 0;
|
||||
|
||||
return best_idx;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_win32_display_init_wgl (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
int best_idx = 0;
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
HDC hdc;
|
||||
|
||||
if (display_win32->wgl_pixel_format != 0)
|
||||
return TRUE;
|
||||
|
||||
/* acquire and cache dummy Window (HWND & HDC) and
|
||||
* dummy GL Context, it is used to query functions
|
||||
* and used for other stuff as well
|
||||
*/
|
||||
best_idx = gdk_init_dummy_wgl_context (display_win32);
|
||||
hdc = display_win32->dummy_context_wgl.hdc;
|
||||
|
||||
if (best_idx == 0 ||
|
||||
!wglMakeCurrent (hdc, display_win32->dummy_context_wgl.hglrc))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No GL implementation is available"));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
display_win32->wgl_pixel_format = best_idx;
|
||||
display_win32->gl_version = epoxy_gl_version ();
|
||||
|
||||
display_win32->hasWglARBCreateContext =
|
||||
epoxy_has_wgl_extension (hdc, "WGL_ARB_create_context");
|
||||
display_win32->hasWglEXTSwapControl =
|
||||
epoxy_has_wgl_extension (hdc, "WGL_EXT_swap_control");
|
||||
display_win32->hasWglOMLSyncControl =
|
||||
epoxy_has_wgl_extension (hdc, "WGL_OML_sync_control");
|
||||
display_win32->hasWglARBPixelFormat =
|
||||
epoxy_has_wgl_extension (hdc, "WGL_ARB_pixel_format");
|
||||
display_win32->hasWglARBmultisample =
|
||||
epoxy_has_wgl_extension (hdc, "WGL_ARB_multisample");
|
||||
|
||||
GDK_NOTE (OPENGL,
|
||||
g_print ("WGL API version %d.%d found\n"
|
||||
" - Vendor: %s\n"
|
||||
" - Checked extensions:\n"
|
||||
"\t* WGL_ARB_pixel_format: %s\n"
|
||||
"\t* WGL_ARB_create_context: %s\n"
|
||||
"\t* WGL_EXT_swap_control: %s\n"
|
||||
"\t* WGL_OML_sync_control: %s\n"
|
||||
"\t* WGL_ARB_multisample: %s\n",
|
||||
display_win32->gl_version / 10,
|
||||
display_win32->gl_version % 10,
|
||||
glGetString (GL_VENDOR),
|
||||
display_win32->hasWglARBPixelFormat ? "yes" : "no",
|
||||
display_win32->hasWglARBCreateContext ? "yes" : "no",
|
||||
display_win32->hasWglEXTSwapControl ? "yes" : "no",
|
||||
display_win32->hasWglOMLSyncControl ? "yes" : "no",
|
||||
display_win32->hasWglARBmultisample ? "yes" : "no"));
|
||||
|
||||
wglMakeCurrent (NULL, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Setup the legacy context after creating it */
|
||||
static gboolean
|
||||
ensure_legacy_wgl_context (HDC hdc,
|
||||
HGLRC hglrc_legacy,
|
||||
GdkGLContext *share)
|
||||
{
|
||||
GdkWin32GLContextWGL *context_wgl;
|
||||
|
||||
if (!wglMakeCurrent (hdc, hglrc_legacy))
|
||||
return FALSE;
|
||||
|
||||
if (share != NULL)
|
||||
{
|
||||
context_wgl = GDK_WIN32_GL_CONTEXT_WGL (share);
|
||||
|
||||
return wglShareLists (hglrc_legacy, context_wgl->wgl_context);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HGLRC
|
||||
create_wgl_context_with_attribs (HDC hdc,
|
||||
HGLRC hglrc_base,
|
||||
GdkGLContext *share,
|
||||
int flags,
|
||||
int major,
|
||||
int minor,
|
||||
gboolean *is_legacy)
|
||||
{
|
||||
HGLRC hglrc;
|
||||
GdkWin32GLContextWGL *context_wgl;
|
||||
|
||||
/* if we have wglCreateContextAttribsARB(), create a
|
||||
* context with the compatibility profile if a legacy
|
||||
* context is requested, or when we go into fallback mode
|
||||
*/
|
||||
int profile = *is_legacy ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :
|
||||
WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||
|
||||
int attribs[] = {
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, profile,
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, *is_legacy ? 3 : major,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, *is_legacy ? 0 : minor,
|
||||
WGL_CONTEXT_FLAGS_ARB, flags,
|
||||
0
|
||||
};
|
||||
|
||||
if (share != NULL)
|
||||
context_wgl = GDK_WIN32_GL_CONTEXT_WGL (share);
|
||||
|
||||
hglrc = wglCreateContextAttribsARB (hdc,
|
||||
share != NULL ? context_wgl->wgl_context : NULL,
|
||||
attribs);
|
||||
|
||||
return hglrc;
|
||||
}
|
||||
|
||||
static HGLRC
|
||||
create_wgl_context (HDC hdc,
|
||||
GdkGLContext *share,
|
||||
int flags,
|
||||
int major,
|
||||
int minor,
|
||||
gboolean *is_legacy,
|
||||
gboolean hasWglARBCreateContext)
|
||||
{
|
||||
/* We need a legacy context for *all* cases */
|
||||
HGLRC hglrc_base = wglCreateContext (hdc);
|
||||
gboolean success = TRUE;
|
||||
|
||||
/* Save up the HDC and HGLRC that we are currently using, to restore back to it when we are done here */
|
||||
HDC hdc_current = wglGetCurrentDC ();
|
||||
HGLRC hglrc_current = wglGetCurrentContext ();
|
||||
|
||||
/* if we have no wglCreateContextAttribsARB(), return the legacy context when all is set */
|
||||
if (*is_legacy && !hasWglARBCreateContext)
|
||||
{
|
||||
if (ensure_legacy_wgl_context (hdc, hglrc_base, share))
|
||||
{
|
||||
wglMakeCurrent (hdc_current, hglrc_current);
|
||||
return hglrc_base;
|
||||
}
|
||||
|
||||
success = FALSE;
|
||||
goto gl_fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
HGLRC hglrc = NULL;
|
||||
|
||||
if (!wglMakeCurrent (hdc, hglrc_base))
|
||||
{
|
||||
success = FALSE;
|
||||
goto gl_fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need a Core GL 4.1 context in order to use the GL support in
|
||||
* the GStreamer media widget backend, but wglCreateContextAttribsARB()
|
||||
* may only give us the GL context version that we ask for here, and
|
||||
* nothing more. So, if we are asking for a pre-GL 4.1 context,
|
||||
* try to ask for a 4.1 context explicitly first. If that is not supported,
|
||||
* then we fall back to whatever version that we were asking for (or, even a
|
||||
* legacy context if that fails), at a price of not able to have GL support
|
||||
* for the media GStreamer backend.
|
||||
*/
|
||||
if (major < 4 || (major == 4 && minor < 1))
|
||||
hglrc = create_wgl_context_with_attribs (hdc,
|
||||
hglrc_base,
|
||||
share,
|
||||
flags,
|
||||
4,
|
||||
1,
|
||||
is_legacy);
|
||||
|
||||
if (hglrc == NULL)
|
||||
hglrc = create_wgl_context_with_attribs (hdc,
|
||||
hglrc_base,
|
||||
share,
|
||||
flags,
|
||||
major,
|
||||
minor,
|
||||
is_legacy);
|
||||
|
||||
/* return the legacy context we have if it could be setup properly, in case the 3.0+ context creation failed */
|
||||
if (hglrc == NULL)
|
||||
{
|
||||
if (!(*is_legacy))
|
||||
{
|
||||
/* If we aren't using a legacy context in the beginning, try again with a compatibility profile 3.0 context */
|
||||
hglrc = create_wgl_context_with_attribs (hdc,
|
||||
hglrc_base,
|
||||
share,
|
||||
flags,
|
||||
0, 0,
|
||||
is_legacy);
|
||||
|
||||
*is_legacy = TRUE;
|
||||
}
|
||||
|
||||
if (hglrc == NULL)
|
||||
{
|
||||
if (!ensure_legacy_wgl_context (hdc, hglrc_base, share))
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
if (success)
|
||||
GDK_NOTE (OPENGL, g_print ("Using legacy context as fallback\n"));
|
||||
}
|
||||
|
||||
gl_fail:
|
||||
|
||||
if (!success)
|
||||
{
|
||||
wglMakeCurrent (NULL, NULL);
|
||||
wglDeleteContext (hglrc_base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wglMakeCurrent (hdc_current, hglrc_current);
|
||||
|
||||
if (hglrc != NULL)
|
||||
{
|
||||
wglDeleteContext (hglrc_base);
|
||||
return hglrc;
|
||||
}
|
||||
|
||||
return hglrc_base;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_wgl_pixformat_for_hdc (HDC hdc,
|
||||
int *best_idx,
|
||||
GdkWin32Display *display_win32)
|
||||
{
|
||||
gboolean already_checked = TRUE;
|
||||
*best_idx = GetPixelFormat (hdc);
|
||||
|
||||
/* one is only allowed to call SetPixelFormat(), and so ChoosePixelFormat()
|
||||
* one single time per window HDC
|
||||
*/
|
||||
if (*best_idx == 0)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
gboolean set_pixel_format_result = FALSE;
|
||||
|
||||
GDK_NOTE (OPENGL, g_print ("requesting pixel format...\n"));
|
||||
already_checked = FALSE;
|
||||
*best_idx = get_wgl_pfd (hdc, &pfd, display_win32);
|
||||
|
||||
if (*best_idx != 0)
|
||||
set_pixel_format_result = SetPixelFormat (hdc, *best_idx, &pfd);
|
||||
|
||||
/* ChoosePixelFormat() or SetPixelFormat() failed, bail out */
|
||||
if (*best_idx == 0 || !set_pixel_format_result)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GDK_NOTE (OPENGL, g_print ("%s""requested and set pixel format: %d\n", already_checked ? "already " : "", *best_idx));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_gl_context_wgl_realize (GdkGLContext *context,
|
||||
GError **error)
|
||||
{
|
||||
GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (context);
|
||||
|
||||
gboolean debug_bit, compat_bit, legacy_bit;
|
||||
|
||||
/* request flags and specific versions for core (3.2+) WGL context */
|
||||
int flags = 0;
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
HGLRC hglrc;
|
||||
int pixel_format;
|
||||
HDC hdc;
|
||||
HWND hwnd;
|
||||
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
GdkGLContext *share = gdk_display_get_gl_context (display);
|
||||
|
||||
gdk_gl_context_get_required_version (context, &major, &minor);
|
||||
debug_bit = gdk_gl_context_get_debug_enabled (context);
|
||||
compat_bit = gdk_gl_context_get_forward_compatible (context);
|
||||
|
||||
if (surface != NULL)
|
||||
hdc = GDK_WIN32_SURFACE (surface)->hdc;
|
||||
else
|
||||
hdc = display_win32->dummy_context_wgl.hdc;
|
||||
|
||||
/*
|
||||
* A legacy context cannot be shared with core profile ones, so this means we
|
||||
* must stick to a legacy context if the shared context is a legacy context
|
||||
*/
|
||||
legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ?
|
||||
TRUE :
|
||||
share != NULL && gdk_gl_context_is_legacy (share);
|
||||
|
||||
if (!set_wgl_pixformat_for_hdc (hdc,
|
||||
&pixel_format,
|
||||
display_win32))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* if there isn't wglCreateContextAttribsARB() on WGL, use a legacy context */
|
||||
if (!legacy_bit)
|
||||
legacy_bit = !display_win32->hasWglARBCreateContext;
|
||||
if (debug_bit)
|
||||
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||
if (compat_bit)
|
||||
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
||||
|
||||
GDK_NOTE (OPENGL,
|
||||
g_print ("Creating %s WGL context (version:%d.%d, debug:%s, forward:%s, legacy: %s)\n",
|
||||
compat_bit ? "core" : "compat",
|
||||
major,
|
||||
minor,
|
||||
debug_bit ? "yes" : "no",
|
||||
compat_bit ? "yes" : "no",
|
||||
legacy_bit ? "yes" : "no"));
|
||||
|
||||
hglrc = create_wgl_context (hdc,
|
||||
share,
|
||||
flags,
|
||||
major,
|
||||
minor,
|
||||
&legacy_bit,
|
||||
display_win32->hasWglARBCreateContext);
|
||||
|
||||
if (hglrc == NULL)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Unable to create a GL context"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GDK_NOTE (OPENGL,
|
||||
g_print ("Created WGL context[%p], pixel_format=%d\n",
|
||||
hglrc,
|
||||
pixel_format));
|
||||
|
||||
context_wgl->wgl_context = hglrc;
|
||||
|
||||
/* No GLES, WGL does not support using EGL contexts */
|
||||
gdk_gl_context_set_use_es (context, FALSE);
|
||||
|
||||
/* Ensure that any other context is created with a legacy bit set */
|
||||
gdk_gl_context_set_is_legacy (context, legacy_bit);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_gl_context_wgl_clear_current (GdkGLContext *context)
|
||||
{
|
||||
return wglMakeCurrent (NULL, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_gl_context_wgl_make_current (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
{
|
||||
GdkWin32GLContextWGL *context_wgl = GDK_WIN32_GL_CONTEXT_WGL (context);
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
HDC hdc;
|
||||
|
||||
if (surfaceless || surface == NULL)
|
||||
hdc = display_win32->dummy_context_wgl.hdc;
|
||||
else
|
||||
hdc = GDK_WIN32_SURFACE (surface)->hdc;
|
||||
|
||||
if (!wglMakeCurrent (hdc, context_wgl->wgl_context))
|
||||
return FALSE;
|
||||
|
||||
if (!surfaceless && display_win32->hasWglEXTSwapControl)
|
||||
{
|
||||
gboolean do_frame_sync = FALSE;
|
||||
|
||||
/* If there is compositing there is no particular need to delay
|
||||
* the swap when drawing on the offscreen, rendering to the screen
|
||||
* happens later anyway, and its up to the compositor to sync that
|
||||
* to the vblank. */
|
||||
do_frame_sync = ! gdk_display_is_composited (display);
|
||||
|
||||
if (do_frame_sync != context_wgl->do_frame_sync)
|
||||
{
|
||||
context_wgl->do_frame_sync = do_frame_sync;
|
||||
|
||||
wglSwapIntervalEXT (do_frame_sync ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_wgl_class_init (GdkWin32GLContextWGLClass *klass)
|
||||
{
|
||||
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
|
||||
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
context_class->realize = gdk_win32_gl_context_wgl_realize;
|
||||
context_class->make_current = gdk_win32_gl_context_wgl_make_current;
|
||||
context_class->clear_current = gdk_win32_gl_context_wgl_clear_current;
|
||||
|
||||
draw_context_class->begin_frame = gdk_win32_gl_context_wgl_begin_frame;
|
||||
draw_context_class->end_frame = gdk_win32_gl_context_wgl_end_frame;
|
||||
gobject_class->dispose = gdk_win32_gl_context_wgl_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_gl_context_wgl_init (GdkWin32GLContextWGL *wgl_context)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gdk_win32_display_get_wgl_version:
|
||||
* @display: a `GdkDisplay`
|
||||
* @major: (out): return location for the WGL major version
|
||||
* @minor: (out): return location for the WGL minor version
|
||||
*
|
||||
* Retrieves the version of the WGL implementation.
|
||||
*
|
||||
* Returns: %TRUE if WGL is available
|
||||
*/
|
||||
gboolean
|
||||
gdk_win32_display_get_wgl_version (GdkDisplay *display,
|
||||
int *major,
|
||||
int *minor)
|
||||
{
|
||||
GdkWin32Display *display_win32;
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
if (!GDK_IS_WIN32_DISPLAY (display))
|
||||
return FALSE;
|
||||
|
||||
display_win32 = GDK_WIN32_DISPLAY (display);
|
||||
if (display_win32->wgl_pixel_format == 0)
|
||||
return FALSE;
|
||||
|
||||
if (major != NULL)
|
||||
*major = display_win32->gl_version / 10;
|
||||
if (minor != NULL)
|
||||
*minor = display_win32->gl_version % 10;
|
||||
|
||||
return TRUE;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -35,24 +35,13 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_WIN32_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WIN32_GL_CONTEXT, GdkWin32GLContextClass))
|
||||
#define GDK_WIN32_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WIN32_GL_CONTEXT, GdkWin32GLContextClass))
|
||||
#define GDK_WIN32_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WIN32_GL_CONTEXT))
|
||||
|
||||
struct _GdkWin32GLContext
|
||||
{
|
||||
GdkGLContext parent_instance;
|
||||
|
||||
/* WGL Context Items */
|
||||
HGLRC hglrc;
|
||||
HDC gl_hdc;
|
||||
guint need_alpha_bits : 1;
|
||||
|
||||
/* other items */
|
||||
guint is_attached : 1;
|
||||
guint do_frame_sync : 1;
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
/* EGL (Angle) Context Items */
|
||||
EGLContext egl_context;
|
||||
EGLConfig egl_config;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _GdkWin32GLContextClass
|
||||
@ -60,15 +49,33 @@ struct _GdkWin32GLContextClass
|
||||
GdkGLContextClass parent_class;
|
||||
};
|
||||
|
||||
GdkGLContext *
|
||||
_gdk_win32_surface_create_gl_context (GdkSurface *window,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error);
|
||||
/* WGL */
|
||||
#define GDK_TYPE_WIN32_GL_CONTEXT_WGL (gdk_win32_gl_context_wgl_get_type())
|
||||
#define GDK_WIN32_GL_CONTEXT_WGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_WIN32_GL_CONTEXT_WGL, GdkWin32GLContextWGL))
|
||||
#define GDK_IS_WIN32_GL_CONTEXT_WGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WIN32_GL_CONTEXT_WGL))
|
||||
|
||||
typedef struct _GdkWin32GLContextWGL GdkWin32GLContextWGL;
|
||||
|
||||
gboolean gdk_win32_display_init_wgl (GdkDisplay *display,
|
||||
GError **error);
|
||||
void gdk_win32_gl_context_wgl_bind_surface (GdkWin32GLContextWGL *ctx,
|
||||
GdkWin32Surface *win32_surface);
|
||||
|
||||
GType gdk_win32_gl_context_wgl_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/* EGL */
|
||||
#define GDK_TYPE_WIN32_GL_CONTEXT_EGL (gdk_win32_gl_context_egl_get_type())
|
||||
#define GDK_WIN32_GL_CONTEXT_EGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_WIN32_GL_CONTEXT_EGL, GdkWin32GLContextEGL))
|
||||
#define GDK_IS_WIN32_GL_CONTEXT_EGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WIN32_GL_CONTEXT_EGL))
|
||||
|
||||
typedef struct _GdkWin32GLContextEGL GdkWin32GLContextEGL;
|
||||
|
||||
gboolean gdk_win32_display_init_egl (GdkDisplay *display,
|
||||
GError **error);
|
||||
void gdk_win32_surface_destroy_egl_surface (GdkWin32Surface *self);
|
||||
|
||||
GType gdk_win32_gl_context_egl_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gboolean
|
||||
_gdk_win32_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
void
|
||||
_gdk_win32_surface_invalidate_egl_framebuffer (GdkSurface *surface);
|
||||
|
||||
|
@ -655,6 +655,7 @@ _gdk_win32_display_create_surface (GdkDisplay *display,
|
||||
impl);
|
||||
|
||||
g_object_unref (frame_clock);
|
||||
impl->hdc = GetDC (impl->handle);
|
||||
|
||||
return surface;
|
||||
}
|
||||
@ -4623,7 +4624,6 @@ gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass)
|
||||
|
||||
impl_class->destroy_notify = gdk_win32_surface_destroy_notify;
|
||||
impl_class->drag_begin = _gdk_win32_surface_drag_begin;
|
||||
impl_class->create_gl_context = _gdk_win32_surface_create_gl_context;
|
||||
impl_class->get_scale_factor = _gdk_win32_surface_get_scale_factor;
|
||||
impl_class->request_layout = _gdk_win32_surface_request_layout;
|
||||
impl_class->compute_size = _gdk_win32_surface_compute_size;
|
||||
@ -5045,9 +5045,9 @@ gdk_win32_drag_surface_iface_init (GdkDragSurfaceInterface *iface)
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
EGLSurface
|
||||
_gdk_win32_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config,
|
||||
gboolean is_dummy)
|
||||
gdk_win32_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config,
|
||||
gboolean is_dummy)
|
||||
{
|
||||
GdkWin32Display *display = GDK_WIN32_DISPLAY (gdk_surface_get_display (surface));
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
@ -5152,3 +5152,20 @@ gdk_win32_surface_handle_queued_move_resize (GdkDrawContext *draw_context)
|
||||
|
||||
return queued_window_rect;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_surface_invalidate_egl_framebuffer (GdkSurface *surface)
|
||||
{
|
||||
/* If we are using ANGLE, we need to force redraw of the whole Window and its child windows
|
||||
* as we need to re-acquire the EGL surfaces that we rendered to upload to Cairo explicitly,
|
||||
* using gdk_window_invalidate_rect (), when we maximize or restore or use aerosnap
|
||||
*/
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
if (surface->gl_paint_context != NULL && gdk_gl_context_get_use_es (surface->gl_paint_context))
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
impl->egl_force_redraw_all = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -379,9 +379,9 @@ RECT
|
||||
gdk_win32_surface_handle_queued_move_resize (GdkDrawContext *draw_context);
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
EGLSurface _gdk_win32_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config,
|
||||
gboolean is_dummy);
|
||||
EGLSurface gdk_win32_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config,
|
||||
gboolean is_dummy);
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -13,6 +13,7 @@ gdk_win32_sources = files([
|
||||
'gdkdrop-win32.c',
|
||||
'gdkevents-win32.c',
|
||||
'gdkglcontext-win32.c',
|
||||
'gdkglcontext-win32-wgl.c',
|
||||
'gdkglobals-win32.c',
|
||||
'gdkhdataoutputstream-win32.c',
|
||||
'gdkkeys-win32.c',
|
||||
@ -47,6 +48,7 @@ GDK_WIN32_EGL_CFLAGS = []
|
||||
|
||||
if win32_has_egl
|
||||
GDK_WIN32_EGL_CFLAGS = ['-DGDK_WIN32_ENABLE_EGL']
|
||||
gdk_win32_sources += ['gdkglcontext-win32-egl.c']
|
||||
endif
|
||||
|
||||
gdk_win32_deps = [ # FIXME
|
||||
|
@ -1335,20 +1335,70 @@ set_sm_client_id (GdkDisplay *display,
|
||||
gdk_x11_get_xatom_by_name_for_display (display, "SM_CLIENT_ID"));
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_setup_window_visual (GdkDisplay *display,
|
||||
int depth,
|
||||
Visual *visual,
|
||||
Colormap colormap,
|
||||
gboolean rgba)
|
||||
static void
|
||||
gdk_x11_display_query_default_visual (GdkX11Display *self,
|
||||
Visual **out_visual,
|
||||
int *out_depth)
|
||||
{
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||
XVisualInfo template, *visinfo;
|
||||
int n_visuals;
|
||||
Display *dpy;
|
||||
|
||||
display_x11->window_depth = depth;
|
||||
display_x11->window_visual = visual;
|
||||
display_x11->window_colormap = colormap;
|
||||
dpy = gdk_x11_display_get_xdisplay (GDK_DISPLAY (self));
|
||||
|
||||
gdk_display_set_rgba (display, rgba);
|
||||
template.screen = self->screen->screen_num;
|
||||
template.depth = 32;
|
||||
template.red_mask = 0xff0000;
|
||||
template.green_mask = 0x00ff00;
|
||||
template.blue_mask = 0x0000ff;
|
||||
|
||||
visinfo = XGetVisualInfo (dpy,
|
||||
VisualScreenMask | VisualDepthMask
|
||||
| VisualRedMaskMask | VisualGreenMaskMask | VisualBlueMaskMask,
|
||||
&template,
|
||||
&n_visuals);
|
||||
if (visinfo != NULL)
|
||||
{
|
||||
*out_visual = visinfo[0].visual;
|
||||
*out_depth = visinfo[0].depth;
|
||||
XFree (visinfo);
|
||||
return;
|
||||
}
|
||||
|
||||
*out_visual = DefaultVisual (dpy, self->screen->screen_num);
|
||||
*out_depth = DefaultDepth (dpy, self->screen->screen_num);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_display_init_leader_surface (GdkX11Display *self)
|
||||
{
|
||||
GdkDisplay *display = GDK_DISPLAY (self);
|
||||
Display *xdisplay = gdk_x11_display_get_xdisplay (display);
|
||||
|
||||
self->window_colormap = XCreateColormap (xdisplay,
|
||||
DefaultRootWindow (xdisplay),
|
||||
self->window_visual,
|
||||
AllocNone);
|
||||
gdk_display_set_rgba (display, self->window_depth == 32);
|
||||
|
||||
/* We need to initialize events after we have the screen
|
||||
* structures in places
|
||||
*/
|
||||
_gdk_x11_xsettings_init (GDK_X11_SCREEN (self->screen));
|
||||
|
||||
self->device_manager = _gdk_x11_device_manager_new (display);
|
||||
|
||||
gdk_event_init (display);
|
||||
|
||||
self->leader_gdk_surface =
|
||||
_gdk_x11_display_create_surface (display,
|
||||
GDK_SURFACE_TEMP,
|
||||
NULL,
|
||||
-100, -100, 1, 1);
|
||||
|
||||
(_gdk_x11_surface_get_toplevel (self->leader_gdk_surface))->is_leader = TRUE;
|
||||
self->leader_window = GDK_SURFACE_XID (self->leader_gdk_surface);
|
||||
self->leader_window_title_set = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1416,28 +1466,20 @@ gdk_x11_display_open (const char *display_name)
|
||||
#endif
|
||||
|
||||
/* initialize the display's screens */
|
||||
display_x11->screen = _gdk_x11_screen_new (display, DefaultScreen (display_x11->xdisplay), TRUE);
|
||||
display_x11->screen = _gdk_x11_screen_new (display, DefaultScreen (display_x11->xdisplay));
|
||||
|
||||
/* We need to initialize events after we have the screen
|
||||
* structures in places
|
||||
/* If GL is available we want to pick better default/rgba visuals,
|
||||
* as we care about GLX details such as alpha/depth/stencil depth,
|
||||
* stereo and double buffering
|
||||
*
|
||||
* Note that this also sets up the leader surface while creating the inital
|
||||
* GL context.
|
||||
*/
|
||||
_gdk_x11_xsettings_init (GDK_X11_SCREEN (display_x11->screen));
|
||||
|
||||
display_x11->device_manager = _gdk_x11_device_manager_new (display);
|
||||
|
||||
gdk_event_init (display);
|
||||
|
||||
display_x11->leader_gdk_surface =
|
||||
_gdk_x11_display_create_surface (display,
|
||||
GDK_SURFACE_TEMP,
|
||||
NULL,
|
||||
-100, -100, 1, 1);
|
||||
|
||||
(_gdk_x11_surface_get_toplevel (display_x11->leader_gdk_surface))->is_leader = TRUE;
|
||||
|
||||
display_x11->leader_window = GDK_SURFACE_XID (display_x11->leader_gdk_surface);
|
||||
|
||||
display_x11->leader_window_title_set = FALSE;
|
||||
if (!gdk_display_prepare_gl (display, NULL))
|
||||
{
|
||||
gdk_x11_display_query_default_visual (display_x11, &display_x11->window_visual, &display_x11->window_depth);
|
||||
gdk_x11_display_init_leader_surface (display_x11);
|
||||
}
|
||||
|
||||
#ifdef HAVE_XFIXES
|
||||
if (XFixesQueryExtension (display_x11->xdisplay,
|
||||
@ -1906,7 +1948,6 @@ gdk_x11_display_finalize (GObject *object)
|
||||
|
||||
/* Free all GdkX11Screens */
|
||||
g_object_unref (display_x11->screen);
|
||||
g_list_free_full (display_x11->screens, g_object_unref);
|
||||
|
||||
g_list_store_remove_all (display_x11->monitors);
|
||||
g_object_unref (display_x11->monitors);
|
||||
@ -1918,6 +1959,8 @@ gdk_x11_display_finalize (GObject *object)
|
||||
|
||||
XCloseDisplay (display_x11->xdisplay);
|
||||
|
||||
g_clear_error (&display_x11->gl_error);
|
||||
|
||||
/* error traps */
|
||||
while (display_x11->error_traps != NULL)
|
||||
{
|
||||
@ -1971,52 +2014,6 @@ gdk_x11_lookup_xdisplay (Display *xdisplay)
|
||||
return display;
|
||||
}
|
||||
|
||||
/*
|
||||
* _gdk_x11_display_screen_for_xrootwin:
|
||||
* @display: a `GdkDisplay`
|
||||
* @xrootwin: window ID for one of the screen’s of the display.
|
||||
*
|
||||
* Given the root window ID of one of the screen’s of a `GdkDisplay`,
|
||||
* finds the screen.
|
||||
*
|
||||
* Returns: (transfer none): the `GdkX11Screen` corresponding to @xrootwin
|
||||
*/
|
||||
GdkX11Screen *
|
||||
_gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
|
||||
Window xrootwin)
|
||||
{
|
||||
GdkX11Screen *screen;
|
||||
XWindowAttributes attrs;
|
||||
gboolean result;
|
||||
GdkX11Display *display_x11;
|
||||
GList *l;
|
||||
|
||||
screen = GDK_X11_DISPLAY (display)->screen;
|
||||
|
||||
if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
|
||||
return screen;
|
||||
|
||||
display_x11 = GDK_X11_DISPLAY (display);
|
||||
|
||||
for (l = display_x11->screens; l; l = l->next)
|
||||
{
|
||||
screen = l->data;
|
||||
if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
|
||||
return screen;
|
||||
}
|
||||
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
result = XGetWindowAttributes (display_x11->xdisplay, xrootwin, &attrs);
|
||||
if (gdk_x11_display_error_trap_pop (display) || !result)
|
||||
return NULL;
|
||||
|
||||
screen = _gdk_x11_screen_new (display, XScreenNumberOfScreen (attrs.screen), FALSE);
|
||||
|
||||
display_x11->screens = g_list_prepend (display_x11->screens, screen);
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_x11_display_get_xdisplay:
|
||||
* @display: (type GdkX11Display): a `GdkDisplay`
|
||||
@ -2888,6 +2885,60 @@ gdk_boolean_handled_accumulator (GSignalInvocationHint *ihint,
|
||||
return continue_emission;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_x11_display_init_gl_backend (GdkX11Display *self,
|
||||
Visual **out_visual,
|
||||
int *out_depth,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplay *display G_GNUC_UNUSED = GDK_DISPLAY (self);
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_EGL))
|
||||
return gdk_x11_display_init_egl (self, TRUE, out_visual, out_depth, error);
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_GLX))
|
||||
return gdk_x11_display_init_glx (self, out_visual, out_depth, error);
|
||||
|
||||
/* No env vars set, do the regular GL initialization.
|
||||
*
|
||||
* We try EGL first, but are very picky about what we accept.
|
||||
* If that fails, we try to go with GLX instead.
|
||||
* And if that also fails, we try EGL again, but this time accept anything.
|
||||
*
|
||||
* The idea here is that EGL is the preferred method going forward, but GLX is
|
||||
* the tried and tested method that we know works. So if we detect issues with
|
||||
* EGL, we want to avoid using it in favor of GLX.
|
||||
*/
|
||||
|
||||
if (gdk_x11_display_init_egl (self, FALSE, out_visual, out_depth, error))
|
||||
return TRUE;
|
||||
g_clear_error (error);
|
||||
|
||||
if (gdk_x11_display_init_glx (self, out_visual, out_depth, error))
|
||||
return TRUE;
|
||||
g_clear_error (error);
|
||||
|
||||
return gdk_x11_display_init_egl (self, TRUE, out_visual, out_depth, error);
|
||||
}
|
||||
|
||||
static GdkGLContext *
|
||||
gdk_x11_display_init_gl (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
GdkX11Display *self = GDK_X11_DISPLAY (display);
|
||||
|
||||
if (!gdk_x11_display_init_gl_backend (self, &self->window_visual, &self->window_depth, error))
|
||||
return FALSE;
|
||||
|
||||
gdk_x11_display_init_leader_surface (self);
|
||||
|
||||
if (self->egl_display)
|
||||
return g_object_new (GDK_TYPE_X11_GL_CONTEXT_EGL, "surface", self->leader_gdk_surface, NULL);
|
||||
else if (self->glx_config != NULL)
|
||||
return g_object_new (GDK_TYPE_X11_GL_CONTEXT_GLX, "surface", self->leader_gdk_surface, NULL);
|
||||
else
|
||||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_display_class_init (GdkX11DisplayClass * class)
|
||||
{
|
||||
@ -2918,7 +2969,7 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
|
||||
display_class->create_surface = _gdk_x11_display_create_surface;
|
||||
display_class->get_keymap = gdk_x11_display_get_keymap;
|
||||
|
||||
display_class->make_gl_context_current = gdk_x11_display_make_gl_context_current;
|
||||
display_class->init_gl = gdk_x11_display_init_gl;
|
||||
|
||||
display_class->get_default_seat = gdk_x11_display_get_default_seat;
|
||||
|
||||
|
@ -42,7 +42,6 @@ struct _GdkX11Display
|
||||
GdkDisplay parent_instance;
|
||||
Display *xdisplay;
|
||||
GdkX11Screen *screen;
|
||||
GList *screens;
|
||||
GList *toplevels;
|
||||
GdkX11DeviceManagerXI2 *device_manager;
|
||||
|
||||
@ -130,12 +129,17 @@ struct _GdkX11Display
|
||||
guint have_damage;
|
||||
#endif
|
||||
|
||||
/* If GL is not supported, store the error here */
|
||||
GError *gl_error;
|
||||
|
||||
/* GLX information */
|
||||
/* GLXFBConfig */ gpointer glx_config;
|
||||
int glx_version;
|
||||
int glx_error_base;
|
||||
int glx_event_base;
|
||||
|
||||
/* EGL information */
|
||||
/* We use gpointer here so we don't have to pull in EGL headers (which glx doesn't like) */
|
||||
/* EGLDisplay */ gpointer egl_display;
|
||||
/* EGLConfig */ gpointer egl_config;
|
||||
int egl_version;
|
||||
|
||||
/* Translation between X server time and system-local monotonic time */
|
||||
@ -144,9 +148,6 @@ struct _GdkX11Display
|
||||
|
||||
guint server_time_is_monotonic_time : 1;
|
||||
|
||||
guint have_glx : 1;
|
||||
guint have_egl : 1;
|
||||
|
||||
/* GLX extensions we check */
|
||||
guint has_glx_swap_interval : 1;
|
||||
guint has_glx_create_context : 1;
|
||||
@ -163,7 +164,6 @@ struct _GdkX11Display
|
||||
guint has_egl_khr_create_context : 1;
|
||||
guint has_egl_buffer_age : 1;
|
||||
guint has_egl_swap_buffers_with_damage : 1;
|
||||
guint has_egl_surfaceless_context : 1;
|
||||
};
|
||||
|
||||
struct _GdkX11DisplayClass
|
||||
@ -174,8 +174,6 @@ struct _GdkX11DisplayClass
|
||||
const XEvent *event);
|
||||
};
|
||||
|
||||
GdkX11Screen * _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
|
||||
Window xrootwin);
|
||||
void _gdk_x11_display_error_event (GdkDisplay *display,
|
||||
XErrorEvent *error);
|
||||
gsize gdk_x11_display_get_max_request_size (GdkDisplay *display);
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "gdkx11glcontext.h"
|
||||
#include "gdkx11screen.h"
|
||||
#include "gdkx11surface.h"
|
||||
#include "gdkvisual-x11.h"
|
||||
#include "gdkx11property.h"
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
@ -35,55 +34,15 @@ struct _GdkX11GLContextEGL
|
||||
{
|
||||
GdkX11GLContext parent_instance;
|
||||
|
||||
EGLDisplay egl_display;
|
||||
EGLConfig egl_config;
|
||||
EGLContext egl_context;
|
||||
|
||||
guint do_frame_sync : 1;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
EGLDisplay egl_display;
|
||||
EGLConfig egl_config;
|
||||
EGLSurface egl_surface;
|
||||
|
||||
/* Only set by the dummy surface we attach to the display */
|
||||
Display *xdisplay;
|
||||
Window dummy_xwin;
|
||||
XVisualInfo *xvisinfo;
|
||||
} DrawableInfo;
|
||||
|
||||
typedef struct _GdkX11GLContextClass GdkX11GLContextEGLClass;
|
||||
|
||||
G_DEFINE_TYPE (GdkX11GLContextEGL, gdk_x11_gl_context_egl, GDK_TYPE_X11_GL_CONTEXT)
|
||||
|
||||
static void
|
||||
drawable_info_free (gpointer data)
|
||||
{
|
||||
DrawableInfo *info = data;
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
if (info->egl_surface != NULL)
|
||||
{
|
||||
eglDestroySurface (info->egl_display, info->egl_surface);
|
||||
info->egl_surface = NULL;
|
||||
}
|
||||
|
||||
if (info->dummy_xwin != None)
|
||||
{
|
||||
XDestroyWindow (info->xdisplay, info->dummy_xwin);
|
||||
info->dummy_xwin = None;
|
||||
}
|
||||
|
||||
if (info->xvisinfo != NULL)
|
||||
{
|
||||
XFree (info->xvisinfo);
|
||||
info->xvisinfo = NULL;
|
||||
}
|
||||
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_x11_display_get_egl_display:
|
||||
* @display: (type GdkX11Display): an X11 display
|
||||
@ -99,19 +58,23 @@ drawable_info_free (gpointer data)
|
||||
gpointer
|
||||
gdk_x11_display_get_egl_display (GdkDisplay *display)
|
||||
{
|
||||
EGLDisplay edpy = NULL;
|
||||
Display *dpy;
|
||||
GdkX11Display *self;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_X11_DISPLAY (display), NULL);
|
||||
|
||||
if (GDK_X11_DISPLAY (display)->have_glx)
|
||||
return NULL;
|
||||
self = GDK_X11_DISPLAY (display);
|
||||
|
||||
edpy = g_object_get_data (G_OBJECT (display), "-gdk-x11-egl-display");
|
||||
if (edpy != NULL)
|
||||
return edpy;
|
||||
return self->egl_display;
|
||||
}
|
||||
|
||||
dpy = gdk_x11_display_get_xdisplay (display);
|
||||
static void
|
||||
gdk_x11_display_create_egl_display (GdkX11Display *self)
|
||||
{
|
||||
Display *dpy;
|
||||
|
||||
g_assert (self->egl_display == NULL);
|
||||
|
||||
dpy = gdk_x11_display_get_xdisplay (GDK_DISPLAY (self));
|
||||
|
||||
if (epoxy_has_egl_extension (NULL, "EGL_KHR_platform_base"))
|
||||
{
|
||||
@ -119,10 +82,10 @@ gdk_x11_display_get_egl_display (GdkDisplay *display)
|
||||
(void *) eglGetProcAddress ("eglGetPlatformDisplay");
|
||||
|
||||
if (getPlatformDisplay != NULL)
|
||||
edpy = getPlatformDisplay (EGL_PLATFORM_X11_KHR, dpy, NULL);
|
||||
self->egl_display = getPlatformDisplay (EGL_PLATFORM_X11_KHR, dpy, NULL);
|
||||
|
||||
if (edpy != NULL)
|
||||
goto out;
|
||||
if (self->egl_display != NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base"))
|
||||
@ -131,145 +94,231 @@ gdk_x11_display_get_egl_display (GdkDisplay *display)
|
||||
(void *) eglGetProcAddress ("eglGetPlatformDisplayEXT");
|
||||
|
||||
if (getPlatformDisplay)
|
||||
edpy = getPlatformDisplay (EGL_PLATFORM_X11_EXT, dpy, NULL);
|
||||
self->egl_display = getPlatformDisplay (EGL_PLATFORM_X11_EXT, dpy, NULL);
|
||||
|
||||
if (edpy != NULL)
|
||||
goto out;
|
||||
if (self->egl_display != NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
edpy = eglGetDisplay ((EGLNativeDisplayType) dpy);
|
||||
|
||||
out:
|
||||
if (edpy != NULL)
|
||||
g_object_set_data (G_OBJECT (display), "-gdk-x11-egl-display", edpy);
|
||||
|
||||
return edpy;
|
||||
self->egl_display = eglGetDisplay ((EGLNativeDisplayType) dpy);
|
||||
}
|
||||
|
||||
static XVisualInfo *
|
||||
get_visual_info_for_egl_config (GdkDisplay *display,
|
||||
EGLConfig egl_config)
|
||||
gdk_x11_display_get_visual_info_for_visual (GdkX11Display *self,
|
||||
VisualID visualid)
|
||||
{
|
||||
XVisualInfo visinfo_template;
|
||||
int template_mask = 0;
|
||||
XVisualInfo *visinfo = NULL;
|
||||
int visinfos_count;
|
||||
EGLint visualid, red_size, green_size, blue_size, alpha_size;
|
||||
EGLDisplay egl_display = gdk_x11_display_get_egl_display (display);
|
||||
XVisualInfo template, *visinfo;
|
||||
int nvisuals;
|
||||
|
||||
eglGetConfigAttrib (egl_display, egl_config, EGL_NATIVE_VISUAL_ID, &visualid);
|
||||
|
||||
if (visualid != 0)
|
||||
{
|
||||
visinfo_template.visualid = visualid;
|
||||
template_mask |= VisualIDMask;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID
|
||||
* attribute, so attempt to find the closest match.
|
||||
*/
|
||||
eglGetConfigAttrib (egl_display, egl_config, EGL_RED_SIZE, &red_size);
|
||||
eglGetConfigAttrib (egl_display, egl_config, EGL_GREEN_SIZE, &green_size);
|
||||
eglGetConfigAttrib (egl_display, egl_config, EGL_BLUE_SIZE, &blue_size);
|
||||
eglGetConfigAttrib (egl_display, egl_config, EGL_ALPHA_SIZE, &alpha_size);
|
||||
|
||||
visinfo_template.depth = red_size + green_size + blue_size + alpha_size;
|
||||
template_mask |= VisualDepthMask;
|
||||
|
||||
visinfo_template.screen = DefaultScreen (gdk_x11_display_get_xdisplay (display));
|
||||
template_mask |= VisualScreenMask;
|
||||
}
|
||||
|
||||
visinfo = XGetVisualInfo (gdk_x11_display_get_xdisplay (display),
|
||||
template_mask,
|
||||
&visinfo_template,
|
||||
&visinfos_count);
|
||||
|
||||
if (visinfos_count < 1)
|
||||
return NULL;
|
||||
template.screen = self->screen->screen_num;
|
||||
template.visualid = visualid;
|
||||
|
||||
visinfo = XGetVisualInfo (gdk_x11_display_get_xdisplay (GDK_DISPLAY (self)),
|
||||
VisualScreenMask | VisualIDMask,
|
||||
&template,
|
||||
&nvisuals);
|
||||
g_warn_if_fail (nvisuals == 1);
|
||||
|
||||
return visinfo;
|
||||
}
|
||||
|
||||
static EGLSurface
|
||||
gdk_x11_display_get_egl_dummy_surface (GdkDisplay *display,
|
||||
EGLConfig egl_config)
|
||||
static gboolean
|
||||
visual_is_rgba (XVisualInfo *visinfo)
|
||||
{
|
||||
DrawableInfo *info;
|
||||
XVisualInfo *xvisinfo;
|
||||
XSetWindowAttributes attrs;
|
||||
|
||||
info = g_object_get_data (G_OBJECT (display), "-gdk-x11-egl-dummy-surface");
|
||||
if (info != NULL)
|
||||
return info->egl_surface;
|
||||
|
||||
xvisinfo = get_visual_info_for_egl_config (display, egl_config);
|
||||
if (xvisinfo == NULL)
|
||||
return NULL;
|
||||
|
||||
info = g_new (DrawableInfo, 1);
|
||||
info->xdisplay = gdk_x11_display_get_xdisplay (display);
|
||||
info->xvisinfo = xvisinfo;
|
||||
info->egl_display = gdk_x11_display_get_egl_display (display);
|
||||
info->egl_config = egl_config;
|
||||
|
||||
attrs.override_redirect = True;
|
||||
attrs.colormap = XCreateColormap (info->xdisplay,
|
||||
DefaultRootWindow (info->xdisplay),
|
||||
xvisinfo->visual,
|
||||
AllocNone);
|
||||
attrs.border_pixel = 0;
|
||||
|
||||
info->dummy_xwin =
|
||||
XCreateWindow (info->xdisplay,
|
||||
DefaultRootWindow (info->xdisplay),
|
||||
-100, -100, 1, 1,
|
||||
0,
|
||||
xvisinfo->depth,
|
||||
CopyFromParent,
|
||||
xvisinfo->visual,
|
||||
CWOverrideRedirect | CWColormap | CWBorderPixel,
|
||||
&attrs);
|
||||
|
||||
info->egl_surface =
|
||||
eglCreateWindowSurface (info->egl_display,
|
||||
info->egl_config,
|
||||
(EGLNativeWindowType) info->dummy_xwin,
|
||||
NULL);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (display), "-gdk-x11-egl-dummy-surface",
|
||||
info,
|
||||
drawable_info_free);
|
||||
|
||||
return info->egl_surface;
|
||||
return
|
||||
visinfo->depth == 32 &&
|
||||
visinfo->visual->red_mask == 0xff0000 &&
|
||||
visinfo->visual->green_mask == 0x00ff00 &&
|
||||
visinfo->visual->blue_mask == 0x0000ff;
|
||||
}
|
||||
|
||||
static EGLSurface
|
||||
gdk_x11_surface_get_egl_surface (GdkSurface *surface,
|
||||
EGLConfig config)
|
||||
#define MAX_EGL_ATTRS 30
|
||||
|
||||
static gboolean
|
||||
gdk_x11_display_create_egl_config (GdkX11Display *display,
|
||||
gboolean force,
|
||||
Visual **out_visual,
|
||||
int *out_depth,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
EGLDisplay egl_display = gdk_x11_display_get_egl_display (display);
|
||||
DrawableInfo *info;
|
||||
GdkX11Display *self = GDK_X11_DISPLAY (display);
|
||||
EGLint attrs[MAX_EGL_ATTRS];
|
||||
EGLConfig *configs;
|
||||
EGLint count, alloced;
|
||||
enum {
|
||||
NO_VISUAL_FOUND,
|
||||
WITH_MULTISAMPLING,
|
||||
WITH_STENCIL_AND_DEPTH_BUFFER,
|
||||
NO_ALPHA,
|
||||
NO_ALPHA_VISUAL,
|
||||
PERFECT
|
||||
} best_features;
|
||||
|
||||
info = g_object_get_data (G_OBJECT (surface), "-gdk-x11-egl-drawable");
|
||||
if (info != NULL)
|
||||
return info->egl_surface;
|
||||
int i = 0;
|
||||
|
||||
info = g_new0 (DrawableInfo, 1);
|
||||
info->egl_display = egl_display;
|
||||
info->egl_config = config;
|
||||
info->egl_surface =
|
||||
eglCreateWindowSurface (info->egl_display, config,
|
||||
attrs[i++] = EGL_SURFACE_TYPE;
|
||||
attrs[i++] = EGL_WINDOW_BIT;
|
||||
|
||||
attrs[i++] = EGL_COLOR_BUFFER_TYPE;
|
||||
attrs[i++] = EGL_RGB_BUFFER;
|
||||
|
||||
attrs[i++] = EGL_RED_SIZE;
|
||||
attrs[i++] = 8;
|
||||
attrs[i++] = EGL_GREEN_SIZE;
|
||||
attrs[i++] = 8;
|
||||
attrs[i++] = EGL_BLUE_SIZE;
|
||||
attrs[i++] = 8;
|
||||
attrs[i++] = EGL_ALPHA_SIZE;
|
||||
attrs[i++] = 8;
|
||||
|
||||
attrs[i++] = EGL_NONE;
|
||||
g_assert (i < MAX_EGL_ATTRS);
|
||||
|
||||
if (!eglChooseConfig (self->egl_display, attrs, NULL, -1, &alloced) || alloced == 0)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No EGL configuration available"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
configs = g_new (EGLConfig, alloced);
|
||||
if (!eglChooseConfig (self->egl_display, attrs, configs, alloced, &count))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Failed to get EGL configurations"));
|
||||
return FALSE;
|
||||
}
|
||||
g_warn_if_fail (alloced == count);
|
||||
|
||||
best_features = NO_VISUAL_FOUND;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
XVisualInfo *visinfo;
|
||||
int tmp, visualid;
|
||||
|
||||
if (!eglGetConfigAttrib (self->egl_display, configs[i], EGL_NATIVE_VISUAL_ID, &visualid))
|
||||
continue;
|
||||
|
||||
visinfo = gdk_x11_display_get_visual_info_for_visual (self, visualid);
|
||||
if (visinfo == NULL)
|
||||
continue;
|
||||
|
||||
if (!eglGetConfigAttrib (self->egl_display, configs[i], EGL_SAMPLE_BUFFERS, &tmp) || tmp != 0)
|
||||
{
|
||||
if (best_features < WITH_MULTISAMPLING)
|
||||
{
|
||||
GDK_NOTE (OPENGL, g_message ("Best EGL config is %u for visual 0x%lX with multisampling", i, visinfo->visualid));
|
||||
best_features = WITH_MULTISAMPLING;
|
||||
*out_visual = visinfo->visual;
|
||||
*out_depth = visinfo->depth;
|
||||
self->egl_config = configs[i];
|
||||
}
|
||||
XFree (visinfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!eglGetConfigAttrib (self->egl_display, configs[i], EGL_DEPTH_SIZE, &tmp) || tmp != 0 ||
|
||||
!eglGetConfigAttrib (self->egl_display, configs[i], EGL_STENCIL_SIZE, &tmp) || tmp != 0)
|
||||
{
|
||||
GDK_NOTE (OPENGL, g_message ("Best EGL config is %u for visual 0x%lX with stencil or depth buffer", i, visinfo->visualid));
|
||||
if (best_features < WITH_STENCIL_AND_DEPTH_BUFFER)
|
||||
{
|
||||
best_features = WITH_STENCIL_AND_DEPTH_BUFFER;
|
||||
*out_visual = visinfo->visual;
|
||||
*out_depth = visinfo->depth;
|
||||
self->egl_config = configs[i];
|
||||
}
|
||||
XFree (visinfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!visual_is_rgba (visinfo))
|
||||
{
|
||||
GDK_NOTE (OPENGL, g_message ("Best EGL config is %u for visual 0x%lX without RGBA Visual", i, visinfo->visualid));
|
||||
if (best_features < NO_ALPHA_VISUAL)
|
||||
{
|
||||
best_features = NO_ALPHA_VISUAL;
|
||||
*out_visual = visinfo->visual;
|
||||
*out_depth = visinfo->depth;
|
||||
self->egl_config = configs[i];
|
||||
}
|
||||
XFree (visinfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
GDK_NOTE (OPENGL, g_message ("EGL Config %u for visual 0x%lX is the perfect choice", i, visinfo->visualid));
|
||||
*out_visual = visinfo->visual;
|
||||
*out_depth = visinfo->depth;
|
||||
self->egl_config = configs[i];
|
||||
XFree (visinfo);
|
||||
/* everything is perfect */
|
||||
best_features = PERFECT;
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (configs);
|
||||
|
||||
if (best_features == NO_VISUAL_FOUND)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No EGL configuration with required features found"));
|
||||
return FALSE;
|
||||
}
|
||||
else if (!force && best_features != PERFECT)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No perfect EGL configuration found"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#undef MAX_EGL_ATTRS
|
||||
|
||||
static EGLSurface
|
||||
gdk_x11_surface_get_egl_surface (GdkSurface *surface)
|
||||
{
|
||||
GdkX11Surface *self = GDK_X11_SURFACE (surface);
|
||||
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (self));
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||
|
||||
if (self->egl_surface)
|
||||
return self->egl_surface;
|
||||
|
||||
self->egl_surface =
|
||||
eglCreateWindowSurface (display_x11->egl_display,
|
||||
display_x11->egl_config,
|
||||
(EGLNativeWindowType) gdk_x11_surface_get_xid (surface),
|
||||
NULL);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (surface), "-gdk-x11-egl-drawable",
|
||||
info,
|
||||
drawable_info_free);
|
||||
return self->egl_surface;
|
||||
}
|
||||
|
||||
return info->egl_surface;
|
||||
void
|
||||
gdk_x11_surface_destroy_egl_surface (GdkX11Surface *self)
|
||||
{
|
||||
GdkX11Display *display_x11;
|
||||
|
||||
if (self->egl_surface == NULL)
|
||||
return;
|
||||
|
||||
display_x11 = GDK_X11_DISPLAY (gdk_surface_get_display (GDK_SURFACE (self)));
|
||||
|
||||
eglDestroySurface (display_x11->egl_display, self->egl_surface);
|
||||
self->egl_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_gl_context_egl_begin_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_x11_gl_context_egl_parent_class)->begin_frame (draw_context, region);
|
||||
|
||||
glDrawBuffers (1, (GLenum[1]) { GL_BACK });
|
||||
}
|
||||
|
||||
static void
|
||||
@ -277,20 +326,16 @@ gdk_x11_gl_context_egl_end_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *painted)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkX11GLContextEGL *context_egl = GDK_X11_GL_CONTEXT_EGL (context);
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||
EGLDisplay egl_display = gdk_x11_display_get_egl_display (display);
|
||||
EGLSurface egl_surface;
|
||||
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_x11_gl_context_egl_parent_class)->end_frame (draw_context, painted);
|
||||
if (gdk_gl_context_get_shared_context (context) != NULL)
|
||||
return;
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
egl_surface = gdk_x11_surface_get_egl_surface (surface, context_egl->egl_config);
|
||||
egl_surface = gdk_x11_surface_get_egl_surface (surface);
|
||||
|
||||
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "x11", "swap buffers");
|
||||
if (display_x11->has_egl_swap_buffers_with_damage)
|
||||
@ -319,11 +364,74 @@ gdk_x11_gl_context_egl_end_frame (GdkDrawContext *draw_context,
|
||||
rects[j++] = rect.height * scale;
|
||||
}
|
||||
|
||||
eglSwapBuffersWithDamageEXT (egl_display, egl_surface, rects, n_rects);
|
||||
eglSwapBuffersWithDamageEXT (display_x11->egl_display, egl_surface, rects, n_rects);
|
||||
g_free (heap_rects);
|
||||
}
|
||||
else
|
||||
eglSwapBuffers (egl_display, egl_surface);
|
||||
eglSwapBuffers (display_x11->egl_display, egl_surface);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_x11_gl_context_egl_clear_current (GdkGLContext *context)
|
||||
{
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||
|
||||
return eglMakeCurrent (display_x11->egl_display,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_x11_gl_context_egl_make_current (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
{
|
||||
GdkX11GLContextEGL *self = GDK_X11_GL_CONTEXT_EGL (context);
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||
GdkSurface *surface;
|
||||
EGLSurface egl_surface;
|
||||
gboolean do_frame_sync = FALSE;
|
||||
|
||||
if (surfaceless)
|
||||
{
|
||||
return eglMakeCurrent (display_x11->egl_display,
|
||||
EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE,
|
||||
self->egl_context);
|
||||
}
|
||||
|
||||
surface = gdk_gl_context_get_surface (context);
|
||||
egl_surface = gdk_x11_surface_get_egl_surface (surface);
|
||||
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("Making EGL context %p current to surface %p",
|
||||
self->egl_context, egl_surface));
|
||||
|
||||
if (!eglMakeCurrent (display_x11->egl_display,
|
||||
egl_surface,
|
||||
egl_surface,
|
||||
self->egl_context))
|
||||
return FALSE;
|
||||
|
||||
/* If the WM is compositing there is no particular need to delay
|
||||
* the swap when drawing on the offscreen, rendering to the screen
|
||||
* happens later anyway, and its up to the compositor to sync that
|
||||
* to the vblank. */
|
||||
do_frame_sync = ! gdk_display_is_composited (display);
|
||||
|
||||
if (do_frame_sync != self->do_frame_sync)
|
||||
{
|
||||
self->do_frame_sync = do_frame_sync;
|
||||
|
||||
if (do_frame_sync)
|
||||
eglSwapInterval (display_x11->egl_display, 1);
|
||||
else
|
||||
eglSwapInterval (display_x11->egl_display, 0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
@ -335,20 +443,13 @@ gdk_x11_gl_context_egl_get_damage (GdkGLContext *context)
|
||||
if (display_x11->has_egl_buffer_age)
|
||||
{
|
||||
GdkSurface *surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (context));
|
||||
GdkGLContext *shared = gdk_gl_context_get_shared_context (context);
|
||||
GdkX11GLContextEGL *shared_egl;
|
||||
EGLSurface egl_surface;
|
||||
int buffer_age = 0;
|
||||
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
if (shared == NULL)
|
||||
shared = context;
|
||||
shared_egl = GDK_X11_GL_CONTEXT_EGL (shared);
|
||||
egl_surface = gdk_x11_surface_get_egl_surface (surface);
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
egl_surface = gdk_x11_surface_get_egl_surface (surface, shared_egl->egl_config);
|
||||
gdk_gl_context_make_current (shared);
|
||||
|
||||
eglQuerySurface (gdk_x11_display_get_egl_display (display),
|
||||
eglQuerySurface (display_x11->egl_display,
|
||||
egl_surface,
|
||||
EGL_BUFFER_AGE_EXT,
|
||||
&buffer_age);
|
||||
@ -389,20 +490,16 @@ gdk_x11_gl_context_egl_realize (GdkGLContext *context,
|
||||
GdkX11Display *display_x11;
|
||||
GdkDisplay *display;
|
||||
GdkX11GLContextEGL *context_egl;
|
||||
GdkGLContext *share, *shared_data_context;
|
||||
GdkSurface *surface;
|
||||
GdkGLContext *share;
|
||||
gboolean debug_bit, forward_bit, legacy_bit, use_es;
|
||||
int major, minor, i = 0;
|
||||
EGLint context_attrs[N_EGL_ATTRS];
|
||||
EGLDisplay egl_display;
|
||||
|
||||
surface = gdk_gl_context_get_surface (context);
|
||||
display = gdk_surface_get_display (surface);
|
||||
display = gdk_gl_context_get_display (context);
|
||||
|
||||
context_egl = GDK_X11_GL_CONTEXT_EGL (context);
|
||||
display_x11 = GDK_X11_DISPLAY (display);
|
||||
share = gdk_gl_context_get_shared_context (context);
|
||||
shared_data_context = gdk_surface_get_shared_data_gl_context (surface);
|
||||
share = gdk_display_get_gl_context (display);
|
||||
|
||||
gdk_gl_context_get_required_version (context, &major, &minor);
|
||||
debug_bit = gdk_gl_context_get_debug_enabled (context);
|
||||
@ -465,16 +562,12 @@ gdk_x11_gl_context_egl_realize (GdkGLContext *context,
|
||||
legacy_bit ? "yes" : "no",
|
||||
use_es ? "yes" : "no"));
|
||||
|
||||
egl_display = gdk_x11_display_get_egl_display (display);
|
||||
|
||||
context_egl->egl_context =
|
||||
eglCreateContext (egl_display,
|
||||
context_egl->egl_config,
|
||||
eglCreateContext (display_x11->egl_display,
|
||||
display_x11->egl_config,
|
||||
share != NULL
|
||||
? GDK_X11_GL_CONTEXT_EGL (share)->egl_context
|
||||
: shared_data_context != NULL
|
||||
? GDK_X11_GL_CONTEXT_EGL (shared_data_context)->egl_context
|
||||
: EGL_NO_CONTEXT,
|
||||
: EGL_NO_CONTEXT,
|
||||
context_attrs);
|
||||
|
||||
/* If we're not asking for a GLES context, and we don't have the legacy bit set
|
||||
@ -493,13 +586,11 @@ gdk_x11_gl_context_egl_realize (GdkGLContext *context,
|
||||
g_message ("Context creation failed; trying legacy EGL context"));
|
||||
|
||||
context_egl->egl_context =
|
||||
eglCreateContext (egl_display,
|
||||
context_egl->egl_config,
|
||||
eglCreateContext (display_x11->egl_display,
|
||||
display_x11->egl_config,
|
||||
share != NULL
|
||||
? GDK_X11_GL_CONTEXT_EGL (share)->egl_context
|
||||
: shared_data_context != NULL
|
||||
? GDK_X11_GL_CONTEXT_EGL (shared_data_context)->egl_context
|
||||
: EGL_NO_CONTEXT,
|
||||
: EGL_NO_CONTEXT,
|
||||
context_attrs);
|
||||
}
|
||||
|
||||
@ -530,15 +621,14 @@ gdk_x11_gl_context_egl_dispose (GObject *gobject)
|
||||
if (context_egl->egl_context != NULL)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
EGLDisplay egl_display = gdk_x11_display_get_egl_display (display);
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (gdk_gl_context_get_display (context));
|
||||
|
||||
/* Unset the current context if we're disposing it */
|
||||
if (eglGetCurrentContext () == context_egl->egl_context)
|
||||
eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglMakeCurrent (display_x11->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
GDK_NOTE (OPENGL, g_message ("Destroying EGL context"));
|
||||
eglDestroyContext (egl_display, context_egl->egl_context);
|
||||
eglDestroyContext (display_x11->egl_display, context_egl->egl_context);
|
||||
context_egl->egl_context = NULL;
|
||||
}
|
||||
|
||||
@ -553,8 +643,11 @@ gdk_x11_gl_context_egl_class_init (GdkX11GLContextEGLClass *klass)
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
context_class->realize = gdk_x11_gl_context_egl_realize;
|
||||
context_class->make_current = gdk_x11_gl_context_egl_make_current;
|
||||
context_class->clear_current = gdk_x11_gl_context_egl_clear_current;
|
||||
context_class->get_damage = gdk_x11_gl_context_egl_get_damage;
|
||||
|
||||
draw_context_class->begin_frame = gdk_x11_gl_context_egl_begin_frame;
|
||||
draw_context_class->end_frame = gdk_x11_gl_context_egl_end_frame;
|
||||
|
||||
gobject_class->dispose = gdk_x11_gl_context_egl_dispose;
|
||||
@ -563,55 +656,84 @@ gdk_x11_gl_context_egl_class_init (GdkX11GLContextEGLClass *klass)
|
||||
static void
|
||||
gdk_x11_gl_context_egl_init (GdkX11GLContextEGL *self)
|
||||
{
|
||||
self->do_frame_sync = TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_x11_screen_init_egl (GdkX11Screen *screen)
|
||||
gdk_x11_display_init_egl (GdkX11Display *self,
|
||||
gboolean force,
|
||||
Visual **out_visual,
|
||||
int *out_depth,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplay *display = GDK_SCREEN_DISPLAY (screen);
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||
EGLDisplay edpy;
|
||||
GdkDisplay *display = GDK_DISPLAY (self);
|
||||
Display *dpy;
|
||||
int major, minor;
|
||||
|
||||
if (display_x11->have_egl)
|
||||
return TRUE;
|
||||
|
||||
dpy = gdk_x11_display_get_xdisplay (display);
|
||||
|
||||
if (!epoxy_has_egl ())
|
||||
return FALSE;
|
||||
|
||||
edpy = gdk_x11_display_get_egl_display (display);
|
||||
if (edpy == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!eglInitialize (edpy, &major, &minor))
|
||||
return FALSE;
|
||||
|
||||
/* While NVIDIA might support EGL, it might very well not support
|
||||
* all the EGL subset we rely on; we should be looking at more
|
||||
* EGL extensions, but for the time being, this is a blanket
|
||||
* fallback to GLX
|
||||
*/
|
||||
const char *vendor = eglQueryString (edpy, EGL_VENDOR);
|
||||
if (strstr (vendor, "NVIDIA") != NULL)
|
||||
{
|
||||
eglTerminate (edpy);
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("EGL is not supported"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
display_x11->have_egl = TRUE;
|
||||
display_x11->egl_version = epoxy_egl_version (dpy);
|
||||
gdk_x11_display_create_egl_display (self);
|
||||
if (self->egl_display == NULL)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Failed to create EGL display"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
display_x11->has_egl_khr_create_context =
|
||||
epoxy_has_egl_extension (edpy, "EGL_KHR_create_context");
|
||||
display_x11->has_egl_buffer_age =
|
||||
epoxy_has_egl_extension (edpy, "EGL_EXT_buffer_age");
|
||||
display_x11->has_egl_swap_buffers_with_damage =
|
||||
epoxy_has_egl_extension (edpy, "EGL_EXT_swap_buffers_with_damage");
|
||||
display_x11->has_egl_surfaceless_context =
|
||||
epoxy_has_egl_extension (edpy, "EGL_KHR_surfaceless_context");
|
||||
if (!eglInitialize (self->egl_display, &major, &minor))
|
||||
{
|
||||
self->egl_display = NULL;
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Could not initialize EGL display"));
|
||||
return FALSE;
|
||||
}
|
||||
if (major < GDK_EGL_MIN_VERSION_MAJOR ||
|
||||
(major == GDK_EGL_MIN_VERSION_MAJOR && minor < GDK_EGL_MIN_VERSION_MINOR))
|
||||
{
|
||||
eglTerminate (dpy);
|
||||
self->egl_display = NULL;
|
||||
g_set_error (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("EGL version %d.%d is too old. GTK requires %d.%d"),
|
||||
major, minor, GDK_EGL_MIN_VERSION_MAJOR, GDK_EGL_MIN_VERSION_MINOR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!epoxy_has_egl_extension (self->egl_display, "EGL_KHR_surfaceless_context"))
|
||||
{
|
||||
eglTerminate (dpy);
|
||||
self->egl_display = NULL;
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_PROFILE,
|
||||
_("Surfaceless contexts are not supported on this EGL implementation"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!gdk_x11_display_create_egl_config (self, force, out_visual, out_depth, error))
|
||||
{
|
||||
eglTerminate (self->egl_display);
|
||||
self->egl_display = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->egl_version = epoxy_egl_version (dpy);
|
||||
|
||||
self->has_egl_khr_create_context =
|
||||
epoxy_has_egl_extension (self->egl_display, "EGL_KHR_create_context");
|
||||
self->has_egl_buffer_age =
|
||||
epoxy_has_egl_extension (self->egl_display, "EGL_EXT_buffer_age");
|
||||
self->has_egl_swap_buffers_with_damage =
|
||||
epoxy_has_egl_extension (self->egl_display, "EGL_EXT_swap_buffers_with_damage");
|
||||
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("EGL found\n"
|
||||
@ -621,162 +743,13 @@ gdk_x11_screen_init_egl (GdkX11Screen *screen)
|
||||
" - Checked extensions:\n"
|
||||
"\t* EGL_KHR_create_context: %s\n"
|
||||
"\t* EGL_EXT_buffer_age: %s\n"
|
||||
"\t* EGL_EXT_swap_buffers_with_damage: %s\n"
|
||||
"\t* EGL_KHR_surfaceless_context: %s\n",
|
||||
eglQueryString (edpy, EGL_VERSION),
|
||||
eglQueryString (edpy, EGL_VENDOR),
|
||||
eglQueryString (edpy, EGL_CLIENT_APIS),
|
||||
display_x11->has_egl_khr_create_context ? "yes" : "no",
|
||||
display_x11->has_egl_buffer_age ? "yes" : "no",
|
||||
display_x11->has_egl_swap_buffers_with_damage ? "yes" : "no",
|
||||
display_x11->has_egl_surfaceless_context ? "yes" : "no"));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define MAX_EGL_ATTRS 30
|
||||
|
||||
static gboolean
|
||||
find_eglconfig_for_display (GdkDisplay *display,
|
||||
EGLConfig *egl_config_out,
|
||||
GError **error)
|
||||
{
|
||||
EGLint attrs[MAX_EGL_ATTRS];
|
||||
EGLint count;
|
||||
EGLConfig egl_config;
|
||||
EGLDisplay egl_display;
|
||||
int i = 0;
|
||||
|
||||
attrs[i++] = EGL_SURFACE_TYPE;
|
||||
attrs[i++] = EGL_WINDOW_BIT;
|
||||
|
||||
attrs[i++] = EGL_COLOR_BUFFER_TYPE;
|
||||
attrs[i++] = EGL_RGB_BUFFER;
|
||||
|
||||
attrs[i++] = EGL_RED_SIZE;
|
||||
attrs[i++] = 8;
|
||||
attrs[i++] = EGL_GREEN_SIZE;
|
||||
attrs[i++] = 8;
|
||||
attrs[i++] = EGL_BLUE_SIZE;
|
||||
attrs[i++] = 8;
|
||||
attrs[i++] = EGL_ALPHA_SIZE;
|
||||
attrs[i++] = 8;
|
||||
|
||||
attrs[i++] = EGL_NONE;
|
||||
g_assert (i < MAX_EGL_ATTRS);
|
||||
|
||||
/* Pick first valid configuration that the driver returns us */
|
||||
egl_display = gdk_x11_display_get_egl_display (display);
|
||||
if (!eglChooseConfig (egl_display, attrs, &egl_config, 1, &count) || count < 1)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_assert (egl_config_out);
|
||||
*egl_config_out = egl_config;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#undef MAX_EGL_ATTRS
|
||||
|
||||
GdkX11GLContext *
|
||||
gdk_x11_gl_context_egl_new (GdkSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkX11GLContextEGL *context;
|
||||
EGLConfig egl_config;
|
||||
|
||||
display = gdk_surface_get_display (surface);
|
||||
|
||||
if (!find_eglconfig_for_display (display, &egl_config, error))
|
||||
return NULL;
|
||||
|
||||
context = g_object_new (GDK_TYPE_X11_GL_CONTEXT_EGL,
|
||||
"surface", surface,
|
||||
"shared-context", share,
|
||||
NULL);
|
||||
|
||||
context->egl_config = egl_config;
|
||||
|
||||
return GDK_X11_GL_CONTEXT (context);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_x11_gl_context_egl_make_current (GdkDisplay *display,
|
||||
GdkGLContext *context)
|
||||
{
|
||||
GdkX11GLContextEGL *context_egl = GDK_X11_GL_CONTEXT_EGL (context);
|
||||
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||
GdkSurface *surface;
|
||||
EGLDisplay egl_display;
|
||||
EGLSurface egl_surface;
|
||||
|
||||
egl_display = gdk_x11_display_get_egl_display (display);
|
||||
|
||||
if (context == NULL)
|
||||
{
|
||||
eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (context_egl->egl_context == NULL)
|
||||
{
|
||||
g_critical ("No EGL context associated to the GdkGLContext; you must "
|
||||
"call gdk_gl_context_realize() first.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
if (context_x11->is_attached || gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context)))
|
||||
egl_surface = gdk_x11_surface_get_egl_surface (surface, context_egl->egl_config);
|
||||
else
|
||||
{
|
||||
if (display_x11->has_egl_surfaceless_context)
|
||||
egl_surface = EGL_NO_SURFACE;
|
||||
else
|
||||
egl_surface = gdk_x11_display_get_egl_dummy_surface (display, context_egl->egl_config);
|
||||
}
|
||||
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("Making EGL context %p current to surface %p",
|
||||
context_egl->egl_context, egl_surface));
|
||||
|
||||
if (!eglMakeCurrent (egl_display, egl_surface, egl_surface, context_egl->egl_context))
|
||||
{
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("Making EGL context current failed"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (context_x11->is_attached)
|
||||
{
|
||||
gboolean do_frame_sync = FALSE;
|
||||
|
||||
/* If the WM is compositing there is no particular need to delay
|
||||
* the swap when drawing on the offscreen, rendering to the screen
|
||||
* happens later anyway, and its up to the compositor to sync that
|
||||
* to the vblank. */
|
||||
do_frame_sync = ! gdk_display_is_composited (display);
|
||||
|
||||
if (do_frame_sync != context_x11->do_frame_sync)
|
||||
{
|
||||
context_x11->do_frame_sync = do_frame_sync;
|
||||
|
||||
if (do_frame_sync)
|
||||
eglSwapInterval (egl_display, 1);
|
||||
else
|
||||
eglSwapInterval (egl_display, 0);
|
||||
}
|
||||
}
|
||||
"\t* EGL_EXT_swap_buffers_with_damage: %s\n",
|
||||
eglQueryString (self->egl_display, EGL_VERSION),
|
||||
eglQueryString (self->egl_display, EGL_VENDOR),
|
||||
eglQueryString (self->egl_display, EGL_CLIENT_APIS),
|
||||
self->has_egl_khr_create_context ? "yes" : "no",
|
||||
self->has_egl_buffer_age ? "yes" : "no",
|
||||
self->has_egl_swap_buffers_with_damage ? "yes" : "no"));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -805,10 +778,7 @@ gdk_x11_display_get_egl_version (GdkDisplay *display,
|
||||
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||
|
||||
if (display_x11->have_glx)
|
||||
return FALSE;
|
||||
|
||||
if (!gdk_x11_screen_init_egl (display_x11->screen))
|
||||
if (display_x11->egl_display == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (major != NULL)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,7 +29,6 @@
|
||||
#include "gdkx11glcontext.h"
|
||||
#include "gdkx11screen.h"
|
||||
#include "gdkx11surface.h"
|
||||
#include "gdkvisual-x11.h"
|
||||
#include "gdkx11property.h"
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
@ -51,78 +50,5 @@ gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass)
|
||||
static void
|
||||
gdk_x11_gl_context_init (GdkX11GLContext *self)
|
||||
{
|
||||
self->do_frame_sync = TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_x11_screen_init_gl (GdkX11Screen *screen)
|
||||
{
|
||||
GdkDisplay *display G_GNUC_UNUSED = GDK_SCREEN_DISPLAY (screen);
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_DISABLE))
|
||||
return FALSE;
|
||||
|
||||
if (!GDK_DISPLAY_DEBUG_CHECK (display, GL_GLX))
|
||||
{
|
||||
/* We favour EGL */
|
||||
if (gdk_x11_screen_init_egl (screen))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (gdk_x11_screen_init_glx (screen))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_x11_surface_create_gl_context (GdkSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error)
|
||||
{
|
||||
GdkX11GLContext *context = NULL;
|
||||
GdkX11Display *display_x11;
|
||||
GdkDisplay *display;
|
||||
|
||||
display = gdk_surface_get_display (surface);
|
||||
|
||||
if (!gdk_x11_screen_init_gl (GDK_SURFACE_SCREEN (surface)))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No GL implementation is available"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
display_x11 = GDK_X11_DISPLAY (display);
|
||||
if (display_x11->have_egl)
|
||||
context = gdk_x11_gl_context_egl_new (surface, attached, share, error);
|
||||
else if (display_x11->have_glx)
|
||||
context = gdk_x11_gl_context_glx_new (surface, attached, share, error);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
if (context == NULL)
|
||||
return NULL;
|
||||
|
||||
context->is_attached = attached;
|
||||
|
||||
return GDK_GL_CONTEXT (context);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_x11_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context)
|
||||
{
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||
|
||||
if (display_x11->have_egl)
|
||||
return gdk_x11_gl_context_egl_make_current (display, context);
|
||||
else if (display_x11->have_glx)
|
||||
return gdk_x11_gl_context_glx_make_current (display, context);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -34,8 +34,7 @@
|
||||
#include <epoxy/glx.h>
|
||||
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkvisual-x11.h"
|
||||
#include "gdkdisplay-x11.h"
|
||||
#include "gdksurface.h"
|
||||
#include "gdkinternals.h"
|
||||
|
||||
@ -48,27 +47,13 @@ G_BEGIN_DECLS
|
||||
struct _GdkX11GLContext
|
||||
{
|
||||
GdkGLContext parent_instance;
|
||||
|
||||
guint do_frame_sync : 1;
|
||||
guint is_attached : 1;
|
||||
};
|
||||
|
||||
struct _GdkX11GLContextClass
|
||||
{
|
||||
GdkGLContextClass parent_class;
|
||||
|
||||
void (* bind_for_frame_fence) (GdkX11GLContext *self);
|
||||
};
|
||||
|
||||
gboolean gdk_x11_screen_init_gl (GdkX11Screen *screen);
|
||||
|
||||
GdkGLContext * gdk_x11_surface_create_gl_context (GdkSurface *window,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error);
|
||||
gboolean gdk_x11_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
|
||||
/* GLX */
|
||||
#define GDK_TYPE_X11_GL_CONTEXT_GLX (gdk_x11_gl_context_glx_get_type())
|
||||
#define GDK_X11_GL_CONTEXT_GLX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_X11_GL_CONTEXT_GLX, GdkX11GLContextGLX))
|
||||
@ -76,16 +61,13 @@ gboolean gdk_x11_display_make_gl_context_current (GdkDisplay *display,
|
||||
|
||||
typedef struct _GdkX11GLContextGLX GdkX11GLContextGLX;
|
||||
|
||||
gboolean gdk_x11_screen_init_glx (GdkX11Screen *screen);
|
||||
void gdk_x11_screen_update_visuals_for_glx (GdkX11Screen *screen);
|
||||
gboolean gdk_x11_display_init_glx (GdkX11Display *display_x11,
|
||||
Visual **out_visual,
|
||||
int *out_depth,
|
||||
GError **error);
|
||||
void gdk_x11_surface_destroy_glx_drawable (GdkX11Surface *self);
|
||||
|
||||
GType gdk_x11_gl_context_glx_get_type (void) G_GNUC_CONST;
|
||||
GdkX11GLContext * gdk_x11_gl_context_glx_new (GdkSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error);
|
||||
gboolean gdk_x11_gl_context_glx_make_current (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
|
||||
|
||||
/* EGL */
|
||||
@ -95,14 +77,14 @@ gboolean gdk_x11_gl_context_glx_make_current (GdkDisplay *
|
||||
|
||||
typedef struct _GdkX11GLContextEGL GdkX11GLContextEGL;
|
||||
|
||||
gboolean gdk_x11_screen_init_egl (GdkX11Screen *screen);
|
||||
GType gdk_x11_gl_context_egl_get_type (void) G_GNUC_CONST;
|
||||
GdkX11GLContext * gdk_x11_gl_context_egl_new (GdkSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
gboolean gdk_x11_display_init_egl (GdkX11Display *display_x11,
|
||||
gboolean force,
|
||||
Visual **out_visual,
|
||||
int *out_depth,
|
||||
GError **error);
|
||||
gboolean gdk_x11_gl_context_egl_make_current (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
void gdk_x11_surface_destroy_egl_surface (GdkX11Surface *self);
|
||||
|
||||
GType gdk_x11_gl_context_egl_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -55,11 +55,6 @@ typedef GdkFilterReturn (*GdkFilterFunc) (const XEvent *xevent,
|
||||
void _gdk_x11_error_handler_push (void);
|
||||
void _gdk_x11_error_handler_pop (void);
|
||||
|
||||
void gdk_display_setup_window_visual (GdkDisplay *display,
|
||||
int depth,
|
||||
Visual *visual,
|
||||
Colormap colormap,
|
||||
gboolean rgba);
|
||||
int gdk_x11_display_get_window_depth (GdkX11Display *display);
|
||||
Visual * gdk_x11_display_get_window_visual (GdkX11Display *display);
|
||||
Colormap gdk_x11_display_get_window_colormap (GdkX11Display *display);
|
||||
|
@ -91,9 +91,6 @@ gdk_x11_screen_dispose (GObject *object)
|
||||
|
||||
_gdk_x11_xsettings_finish (x11_screen);
|
||||
|
||||
for (i = 0; i < x11_screen->nvisuals; i++)
|
||||
g_object_run_dispose (G_OBJECT (x11_screen->visuals[i]));
|
||||
|
||||
G_OBJECT_CLASS (gdk_x11_screen_parent_class)->dispose (object);
|
||||
|
||||
x11_screen->xdisplay = NULL;
|
||||
@ -106,12 +103,6 @@ static void
|
||||
gdk_x11_screen_finalize (GObject *object)
|
||||
{
|
||||
GdkX11Screen *x11_screen = GDK_X11_SCREEN (object);
|
||||
int i;
|
||||
|
||||
/* Visual Part */
|
||||
for (i = 0; i < x11_screen->nvisuals; i++)
|
||||
g_object_unref (x11_screen->visuals[i]);
|
||||
g_free (x11_screen->visuals);
|
||||
|
||||
g_free (x11_screen->window_manager_name);
|
||||
|
||||
@ -866,8 +857,7 @@ init_multihead (GdkX11Screen *screen)
|
||||
|
||||
GdkX11Screen *
|
||||
_gdk_x11_screen_new (GdkDisplay *display,
|
||||
int screen_number,
|
||||
gboolean setup_display)
|
||||
int screen_number)
|
||||
{
|
||||
GdkX11Screen *x11_screen;
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
|
||||
@ -898,8 +888,6 @@ _gdk_x11_screen_new (GdkDisplay *display,
|
||||
init_randr_support (x11_screen);
|
||||
init_multihead (x11_screen);
|
||||
|
||||
_gdk_x11_screen_init_visuals (x11_screen, setup_display);
|
||||
|
||||
return x11_screen;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#define __GDK_X11_SCREEN__
|
||||
|
||||
#include "gdkx11screen.h"
|
||||
#include "gdkvisual-x11.h"
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
@ -71,16 +70,6 @@ struct _GdkX11Screen
|
||||
guint xft_antialias : 1;
|
||||
guint xft_hinting : 1;
|
||||
|
||||
/* Visual Part */
|
||||
int nvisuals;
|
||||
GdkX11Visual **visuals;
|
||||
GdkX11Visual *system_visual;
|
||||
int available_depths[7];
|
||||
GdkVisualType available_types[6];
|
||||
gint16 navailable_depths;
|
||||
gint16 navailable_types;
|
||||
GdkX11Visual *rgba_visual;
|
||||
|
||||
/* cache for window->translate vfunc */
|
||||
GC subwindow_gcs[32];
|
||||
};
|
||||
@ -94,8 +83,7 @@ struct _GdkX11ScreenClass
|
||||
|
||||
GType _gdk_x11_screen_get_type (void);
|
||||
GdkX11Screen *_gdk_x11_screen_new (GdkDisplay *display,
|
||||
int screen_number,
|
||||
gboolean setup_display);
|
||||
int screen_number);
|
||||
|
||||
void _gdk_x11_screen_window_manager_changed (GdkX11Screen *screen);
|
||||
void _gdk_x11_screen_size_changed (GdkX11Screen *screen,
|
||||
@ -120,9 +108,6 @@ _gdk_x11_screen_get_xft_setting (GdkX11Screen *screen,
|
||||
const char *name,
|
||||
GValue *value);
|
||||
|
||||
void _gdk_x11_screen_init_visuals (GdkX11Screen *screen,
|
||||
gboolean setup_display);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_X11_SCREEN__ */
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "gdkpopupprivate.h"
|
||||
#include "gdktoplevelprivate.h"
|
||||
#include "gdkdragsurfaceprivate.h"
|
||||
#include "gdkvisual-x11.h"
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdevice-xi2-private.h"
|
||||
@ -1161,16 +1160,12 @@ _gdk_x11_display_create_surface (GdkDisplay *display,
|
||||
GdkX11Display *display_x11;
|
||||
|
||||
Window xparent;
|
||||
Visual *xvisual;
|
||||
Display *xdisplay;
|
||||
|
||||
XSetWindowAttributes xattributes;
|
||||
long xattributes_mask;
|
||||
XClassHint *class_hint;
|
||||
|
||||
unsigned int class;
|
||||
int depth;
|
||||
|
||||
int abs_x;
|
||||
int abs_y;
|
||||
|
||||
@ -1223,12 +1218,8 @@ _gdk_x11_display_create_surface (GdkDisplay *display,
|
||||
|
||||
xattributes_mask = 0;
|
||||
|
||||
xvisual = gdk_x11_display_get_window_visual (display_x11);
|
||||
|
||||
impl->override_redirect = FALSE;
|
||||
|
||||
class = InputOutput;
|
||||
|
||||
xattributes.background_pixmap = None;
|
||||
xattributes_mask |= CWBackPixmap;
|
||||
|
||||
@ -1252,8 +1243,6 @@ _gdk_x11_display_create_surface (GdkDisplay *display,
|
||||
impl->override_redirect = TRUE;
|
||||
}
|
||||
|
||||
depth = gdk_x11_display_get_window_depth (display_x11);
|
||||
|
||||
if (surface->width * impl->surface_scale > 32767 ||
|
||||
surface->height * impl->surface_scale > 32767)
|
||||
{
|
||||
@ -1276,7 +1265,10 @@ _gdk_x11_display_create_surface (GdkDisplay *display,
|
||||
(surface->y + abs_y) * impl->surface_scale,
|
||||
MAX (1, surface->width * impl->surface_scale),
|
||||
MAX (1, surface->height * impl->surface_scale),
|
||||
0, depth, class, xvisual,
|
||||
0,
|
||||
gdk_x11_display_get_window_depth (display_x11),
|
||||
InputOutput,
|
||||
gdk_x11_display_get_window_visual (display_x11),
|
||||
xattributes_mask, &xattributes);
|
||||
|
||||
g_object_ref (surface);
|
||||
@ -1367,7 +1359,12 @@ gdk_x11_surface_destroy (GdkSurface *surface,
|
||||
}
|
||||
|
||||
if (!foreign_destroy)
|
||||
XDestroyWindow (GDK_SURFACE_XDISPLAY (surface), GDK_SURFACE_XID (surface));
|
||||
{
|
||||
gdk_x11_surface_destroy_egl_surface (impl);
|
||||
gdk_x11_surface_destroy_glx_drawable (impl);
|
||||
|
||||
XDestroyWindow (GDK_SURFACE_XDISPLAY (surface), GDK_SURFACE_XID (surface));
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is called when the XWindow is really gone.
|
||||
@ -1636,6 +1633,8 @@ gdk_x11_surface_hide (GdkSurface *surface)
|
||||
g_clear_pointer (&impl->toplevel_layout, gdk_toplevel_layout_unref);
|
||||
|
||||
gdk_x11_surface_withdraw (surface);
|
||||
|
||||
impl->glx_frame_counter = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -4813,7 +4812,6 @@ gdk_x11_surface_class_init (GdkX11SurfaceClass *klass)
|
||||
impl_class->drag_begin = _gdk_x11_surface_drag_begin;
|
||||
impl_class->get_scale_factor = gdk_x11_surface_get_scale_factor;
|
||||
impl_class->set_opaque_region = gdk_x11_surface_set_opaque_region;
|
||||
impl_class->create_gl_context = gdk_x11_surface_create_gl_context;
|
||||
impl_class->request_layout = gdk_x11_surface_request_layout;
|
||||
impl_class->compute_size = gdk_x11_surface_compute_size;
|
||||
}
|
||||
|
@ -87,6 +87,9 @@ struct _GdkX11Surface
|
||||
guint compute_size_source_id;
|
||||
|
||||
cairo_surface_t *cairo_surface;
|
||||
/* EGLSurface */ gpointer egl_surface;
|
||||
/* GLXDrawable */ XID glx_drawable;
|
||||
guint32 glx_frame_counter;
|
||||
|
||||
int abs_x;
|
||||
int abs_y;
|
||||
|
@ -1,322 +0,0 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkprivate-x11.h"
|
||||
#include "gdkscreen-x11.h"
|
||||
#include "gdkvisual-x11.h"
|
||||
#include "gdkglcontext-x11.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
struct _GdkX11VisualClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkX11Visual, gdk_x11_visual, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gdk_x11_visual_init (GdkX11Visual *x11_visual)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_visual_class_init (GdkX11VisualClass *class)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_x11_screen_init_visuals (GdkX11Screen *x11_screen,
|
||||
gboolean setup_display)
|
||||
{
|
||||
static const int possible_depths[8] = { 32, 30, 24, 16, 15, 8, 4, 1 };
|
||||
static const GdkVisualType possible_types[6] =
|
||||
{
|
||||
GDK_VISUAL_DIRECT_COLOR,
|
||||
GDK_VISUAL_TRUE_COLOR,
|
||||
GDK_VISUAL_PSEUDO_COLOR,
|
||||
GDK_VISUAL_STATIC_COLOR,
|
||||
GDK_VISUAL_GRAYSCALE,
|
||||
GDK_VISUAL_STATIC_GRAY
|
||||
};
|
||||
|
||||
XVisualInfo *visual_list;
|
||||
XVisualInfo visual_template;
|
||||
GdkX11Visual *temp_visual;
|
||||
Visual *default_xvisual;
|
||||
GdkX11Visual **visuals;
|
||||
int nxvisuals;
|
||||
int nvisuals;
|
||||
int i, j;
|
||||
|
||||
nxvisuals = 0;
|
||||
visual_template.screen = x11_screen->screen_num;
|
||||
visual_list = XGetVisualInfo (x11_screen->xdisplay, VisualScreenMask, &visual_template, &nxvisuals);
|
||||
|
||||
visuals = g_new (GdkX11Visual *, nxvisuals);
|
||||
for (i = 0; i < nxvisuals; i++)
|
||||
visuals[i] = g_object_new (GDK_TYPE_X11_VISUAL, NULL);
|
||||
|
||||
default_xvisual = DefaultVisual (x11_screen->xdisplay, x11_screen->screen_num);
|
||||
|
||||
nvisuals = 0;
|
||||
for (i = 0; i < nxvisuals; i++)
|
||||
{
|
||||
if (visual_list[i].depth >= 1)
|
||||
{
|
||||
#ifdef __cplusplus
|
||||
switch (visual_list[i].c_class)
|
||||
#else /* __cplusplus */
|
||||
switch (visual_list[i].class)
|
||||
#endif /* __cplusplus */
|
||||
{
|
||||
case StaticGray:
|
||||
visuals[nvisuals]->type = GDK_VISUAL_STATIC_GRAY;
|
||||
break;
|
||||
case GrayScale:
|
||||
visuals[nvisuals]->type = GDK_VISUAL_GRAYSCALE;
|
||||
break;
|
||||
case StaticColor:
|
||||
visuals[nvisuals]->type = GDK_VISUAL_STATIC_COLOR;
|
||||
break;
|
||||
case PseudoColor:
|
||||
visuals[nvisuals]->type = GDK_VISUAL_PSEUDO_COLOR;
|
||||
break;
|
||||
case TrueColor:
|
||||
visuals[nvisuals]->type = GDK_VISUAL_TRUE_COLOR;
|
||||
break;
|
||||
case DirectColor:
|
||||
visuals[nvisuals]->type = GDK_VISUAL_DIRECT_COLOR;
|
||||
break;
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
visuals[nvisuals]->depth = visual_list[i].depth;
|
||||
visuals[nvisuals]->byte_order =
|
||||
(ImageByteOrder(x11_screen->xdisplay) == LSBFirst) ?
|
||||
GDK_LSB_FIRST : GDK_MSB_FIRST;
|
||||
visuals[nvisuals]->red_mask = visual_list[i].red_mask;
|
||||
visuals[nvisuals]->green_mask = visual_list[i].green_mask;
|
||||
visuals[nvisuals]->blue_mask = visual_list[i].blue_mask;
|
||||
visuals[nvisuals]->colormap_size = visual_list[i].colormap_size;
|
||||
visuals[nvisuals]->bits_per_rgb = visual_list[i].bits_per_rgb;
|
||||
GDK_X11_VISUAL (visuals[nvisuals])->xvisual = visual_list[i].visual;
|
||||
|
||||
if ((visuals[nvisuals]->type != GDK_VISUAL_TRUE_COLOR) &&
|
||||
(visuals[nvisuals]->type != GDK_VISUAL_DIRECT_COLOR))
|
||||
{
|
||||
visuals[nvisuals]->red_mask = 0;
|
||||
visuals[nvisuals]->green_mask = 0;
|
||||
visuals[nvisuals]->blue_mask = 0;
|
||||
}
|
||||
|
||||
nvisuals += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (visual_list)
|
||||
XFree (visual_list);
|
||||
|
||||
for (i = 0; i < nvisuals; i++)
|
||||
{
|
||||
for (j = i+1; j < nvisuals; j++)
|
||||
{
|
||||
if (visuals[j]->depth >= visuals[i]->depth)
|
||||
{
|
||||
if ((visuals[j]->depth == 8) && (visuals[i]->depth == 8))
|
||||
{
|
||||
if (visuals[j]->type == GDK_VISUAL_PSEUDO_COLOR)
|
||||
{
|
||||
temp_visual = visuals[j];
|
||||
visuals[j] = visuals[i];
|
||||
visuals[i] = temp_visual;
|
||||
}
|
||||
else if ((visuals[i]->type != GDK_VISUAL_PSEUDO_COLOR) &&
|
||||
visuals[j]->type > visuals[i]->type)
|
||||
{
|
||||
temp_visual = visuals[j];
|
||||
visuals[j] = visuals[i];
|
||||
visuals[i] = temp_visual;
|
||||
}
|
||||
}
|
||||
else if ((visuals[j]->depth > visuals[i]->depth) ||
|
||||
((visuals[j]->depth == visuals[i]->depth) &&
|
||||
(visuals[j]->type > visuals[i]->type)))
|
||||
{
|
||||
temp_visual = visuals[j];
|
||||
visuals[j] = visuals[i];
|
||||
visuals[i] = temp_visual;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < nvisuals; i++)
|
||||
{
|
||||
if (default_xvisual->visualid == GDK_X11_VISUAL (visuals[i])->xvisual->visualid)
|
||||
x11_screen->system_visual = visuals[i];
|
||||
|
||||
/* For now, we only support 8888 ARGB for the "rgba visual".
|
||||
* Additional formats (like ABGR) could be added later if they
|
||||
* turn up.
|
||||
*/
|
||||
if (x11_screen->rgba_visual == NULL &&
|
||||
visuals[i]->depth == 32 &&
|
||||
(visuals[i]->red_mask == 0xff0000 &&
|
||||
visuals[i]->green_mask == 0x00ff00 &&
|
||||
visuals[i]->blue_mask == 0x0000ff))
|
||||
{
|
||||
x11_screen->rgba_visual = visuals[i];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (GDK_SCREEN_DISPLAY (x11_screen), MISC))
|
||||
{
|
||||
static const char *const visual_names[] =
|
||||
{
|
||||
"static gray",
|
||||
"grayscale",
|
||||
"static color",
|
||||
"pseudo color",
|
||||
"true color",
|
||||
"direct color",
|
||||
};
|
||||
|
||||
for (i = 0; i < nvisuals; i++)
|
||||
g_message ("visual: %s: %d", visual_names[visuals[i]->type], visuals[i]->depth);
|
||||
}
|
||||
#endif /* G_ENABLE_DEBUG */
|
||||
|
||||
x11_screen->navailable_depths = 0;
|
||||
for (i = 0; i < G_N_ELEMENTS (possible_depths); i++)
|
||||
{
|
||||
for (j = 0; j < nvisuals; j++)
|
||||
{
|
||||
if (visuals[j]->depth == possible_depths[i])
|
||||
{
|
||||
x11_screen->available_depths[x11_screen->navailable_depths++] = visuals[j]->depth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (x11_screen->navailable_depths == 0)
|
||||
g_error ("unable to find a usable depth");
|
||||
|
||||
x11_screen->navailable_types = 0;
|
||||
for (i = 0; i < G_N_ELEMENTS (possible_types); i++)
|
||||
{
|
||||
for (j = 0; j < nvisuals; j++)
|
||||
{
|
||||
if (visuals[j]->type == possible_types[i])
|
||||
{
|
||||
x11_screen->available_types[x11_screen->navailable_types++] = visuals[j]->type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (x11_screen->navailable_types == 0)
|
||||
g_error ("unable to find a usable visual type");
|
||||
|
||||
x11_screen->visuals = visuals;
|
||||
x11_screen->nvisuals = nvisuals;
|
||||
|
||||
/* If GL is available we want to pick better default/rgba visuals,
|
||||
* as we care about GLX details such as alpha/depth/stencil depth,
|
||||
* stereo and double buffering
|
||||
*/
|
||||
gdk_x11_screen_update_visuals_for_glx (x11_screen);
|
||||
|
||||
if (setup_display)
|
||||
{
|
||||
if (x11_screen->rgba_visual)
|
||||
{
|
||||
Visual *xvisual = GDK_X11_VISUAL (x11_screen->rgba_visual)->xvisual;
|
||||
Colormap colormap;
|
||||
|
||||
colormap = XCreateColormap (x11_screen->xdisplay,
|
||||
RootWindow (x11_screen->xdisplay, x11_screen->screen_num),
|
||||
xvisual,
|
||||
AllocNone);
|
||||
gdk_display_setup_window_visual (GDK_SCREEN_DISPLAY (x11_screen),
|
||||
x11_screen->rgba_visual->depth,
|
||||
GDK_X11_VISUAL (x11_screen->rgba_visual)->xvisual,
|
||||
colormap,
|
||||
TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_display_setup_window_visual (GDK_SCREEN_DISPLAY (x11_screen),
|
||||
DefaultDepth (x11_screen->xdisplay, x11_screen->screen_num),
|
||||
DefaultVisual (x11_screen->xdisplay, x11_screen->screen_num),
|
||||
DefaultColormap (x11_screen->xdisplay, x11_screen->screen_num),
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_x11_screen_lookup_visual:
|
||||
* @screen: a `GdkX11Screen`
|
||||
* @xvisualid: an X Visual ID.
|
||||
*
|
||||
* Looks up the `GdkVisual` for a particular screen and X Visual ID.
|
||||
*
|
||||
* Returns: (transfer none) (nullable) (type GdkX11Visual): the `GdkVisual`
|
||||
*/
|
||||
GdkX11Visual *
|
||||
gdk_x11_screen_lookup_visual (GdkX11Screen *x11_screen,
|
||||
VisualID xvisualid)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < x11_screen->nvisuals; i++)
|
||||
if (xvisualid == GDK_X11_VISUAL (x11_screen->visuals[i])->xvisual->visualid)
|
||||
return x11_screen->visuals[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_x11_visual_get_xvisual:
|
||||
* @visual: a `GdkX11Visual`
|
||||
*
|
||||
* Returns the X visual belonging to a `GdkX11Visual`.
|
||||
*
|
||||
* Returns: (transfer none): an Xlib Visual*.
|
||||
**/
|
||||
Visual *
|
||||
gdk_x11_visual_get_xvisual (GdkX11Visual *visual)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_X11_VISUAL (visual), NULL);
|
||||
|
||||
return GDK_X11_VISUAL (visual)->xvisual;
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* 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_X11_VISUAL__
|
||||
#define __GDK_X11_VISUAL__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/x11/gdkx11screen.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_X11_VISUAL (gdk_x11_visual_get_type ())
|
||||
#define GDK_X11_VISUAL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_X11_VISUAL, GdkX11Visual))
|
||||
#define GDK_X11_VISUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_X11_VISUAL, GdkX11VisualClass))
|
||||
#define GDK_IS_X11_VISUAL(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_X11_VISUAL))
|
||||
#define GDK_IS_X11_VISUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_X11_VISUAL))
|
||||
#define GDK_X11_VISUAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_X11_VISUAL, GdkX11VisualClass))
|
||||
|
||||
typedef struct _GdkX11Visual GdkX11Visual;
|
||||
typedef struct _GdkX11VisualClass GdkX11VisualClass;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GDK_VISUAL_STATIC_GRAY,
|
||||
GDK_VISUAL_GRAYSCALE,
|
||||
GDK_VISUAL_STATIC_COLOR,
|
||||
GDK_VISUAL_PSEUDO_COLOR,
|
||||
GDK_VISUAL_TRUE_COLOR,
|
||||
GDK_VISUAL_DIRECT_COLOR
|
||||
} GdkVisualType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GDK_LSB_FIRST,
|
||||
GDK_MSB_FIRST
|
||||
} GdkByteOrder;
|
||||
|
||||
struct _GdkX11Visual
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GdkVisualType type;
|
||||
int depth;
|
||||
GdkByteOrder byte_order;
|
||||
int colormap_size;
|
||||
int bits_per_rgb;
|
||||
|
||||
guint32 red_mask;
|
||||
guint32 green_mask;
|
||||
guint32 blue_mask;
|
||||
|
||||
Visual *xvisual;
|
||||
};
|
||||
|
||||
GType gdk_x11_visual_get_type (void);
|
||||
|
||||
Visual * gdk_x11_visual_get_xvisual (GdkX11Visual *visual);
|
||||
|
||||
#define GDK_VISUAL_XVISUAL(visual) (gdk_x11_visual_get_xvisual (visual))
|
||||
|
||||
GdkX11Visual* gdk_x11_screen_lookup_visual (GdkX11Screen *screen,
|
||||
VisualID xvisualid);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
@ -16,7 +16,6 @@ gdk_x11_public_sources = files([
|
||||
'gdkproperty-x11.c',
|
||||
'gdkscreen-x11.c',
|
||||
'gdkselection-x11.c',
|
||||
'gdkvisual-x11.c',
|
||||
'gdksurface-x11.c',
|
||||
'gdkxid.c',
|
||||
'xsettings-client.c',
|
||||
|
@ -518,14 +518,13 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
|
||||
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
{
|
||||
GdkGLContext *texture_context = gdk_gl_texture_get_context ((GdkGLTexture *)texture);
|
||||
GdkGLContext *shared_context = gdk_gl_context_get_shared_context (self->gl_context);
|
||||
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
|
||||
GdkGLContext *texture_context = gdk_gl_texture_get_context (gl_texture);
|
||||
|
||||
if (texture_context == self->gl_context ||
|
||||
(gdk_gl_context_get_shared_context (texture_context) == shared_context && shared_context != NULL))
|
||||
if (gdk_gl_context_is_shared (self->gl_context, texture_context))
|
||||
{
|
||||
/* A GL texture from the same GL context is a simple task... */
|
||||
return gdk_gl_texture_get_id ((GdkGLTexture *)texture);
|
||||
return gdk_gl_texture_get_id (gl_texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdkdisplayprivate.h>
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
#include <gsk/gskdebugprivate.h>
|
||||
#include <gsk/gskglshaderprivate.h>
|
||||
@ -447,30 +448,34 @@ gsk_ngl_driver_new (GskNglCommandQueue *command_queue,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_ngl_driver_from_shared_context:
|
||||
* @context: a shared `GdkGLContext` retrieved with gdk_gl_context_get_shared_context()
|
||||
* gsk_ngl_driver_for_display:
|
||||
* @display: A #GdkDisplay that is known to support GL
|
||||
* @debug_shaders: if debug information for shaders should be displayed
|
||||
* @error: location for error information
|
||||
*
|
||||
* Retrieves a driver for a shared context. Generally this is shared across all GL
|
||||
* Retrieves a driver for a shared display. Generally this is shared across all GL
|
||||
* contexts for a display so that fewer programs are necessary for driving output.
|
||||
*
|
||||
* Returns: (transfer full): a `GskNglDriver` if successful; otherwise %NULL and
|
||||
* @error is set.
|
||||
*/
|
||||
GskNglDriver *
|
||||
gsk_ngl_driver_from_shared_context (GdkGLContext *context,
|
||||
gboolean debug_shaders,
|
||||
GError **error)
|
||||
gsk_ngl_driver_for_display (GdkDisplay *display,
|
||||
gboolean debug_shaders,
|
||||
GError **error)
|
||||
{
|
||||
GdkGLContext *context;
|
||||
GskNglCommandQueue *command_queue = NULL;
|
||||
GskNglDriver *driver;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
||||
|
||||
if ((driver = g_object_get_data (G_OBJECT (context), "GSK_NGL_DRIVER")))
|
||||
if ((driver = g_object_get_data (G_OBJECT (display), "GSK_NGL_DRIVER")))
|
||||
return g_object_ref (driver);
|
||||
|
||||
context = gdk_display_get_gl_context (display);
|
||||
g_assert (context);
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
/* Initially we create a command queue using the shared context. However,
|
||||
@ -484,7 +489,7 @@ gsk_ngl_driver_from_shared_context (GdkGLContext *context,
|
||||
if (!(driver = gsk_ngl_driver_new (command_queue, debug_shaders, error)))
|
||||
goto failure;
|
||||
|
||||
g_object_set_data_full (G_OBJECT (context),
|
||||
g_object_set_data_full (G_OBJECT (display),
|
||||
"GSK_NGL_DRIVER",
|
||||
g_object_ref (driver),
|
||||
g_object_unref);
|
||||
@ -736,16 +741,13 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
|
||||
|
||||
if (GDK_IS_GL_TEXTURE (texture))
|
||||
{
|
||||
GdkGLContext *texture_context = gdk_gl_texture_get_context ((GdkGLTexture *)texture);
|
||||
GdkGLContext *shared_context = gdk_gl_context_get_shared_context (context);
|
||||
|
||||
if (texture_context == context ||
|
||||
(shared_context != NULL &&
|
||||
shared_context == gdk_gl_context_get_shared_context (texture_context)))
|
||||
GdkGLTexture *gl_texture = (GdkGLTexture *) texture;
|
||||
GdkGLContext *texture_context = gdk_gl_texture_get_context (gl_texture);
|
||||
|
||||
if (gdk_gl_context_is_shared (context, texture_context))
|
||||
{
|
||||
/* A GL texture from the same GL context is a simple task... */
|
||||
return gdk_gl_texture_get_id ((GdkGLTexture *)texture);
|
||||
return gdk_gl_texture_get_id (gl_texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -136,7 +136,7 @@ struct _GskNglDriver
|
||||
guint in_frame : 1;
|
||||
};
|
||||
|
||||
GskNglDriver *gsk_ngl_driver_from_shared_context (GdkGLContext *context,
|
||||
GskNglDriver *gsk_ngl_driver_for_display (GdkDisplay *display,
|
||||
gboolean debug_shaders,
|
||||
GError **error);
|
||||
GskNglCommandQueue *gsk_ngl_driver_create_command_queue (GskNglDriver *self,
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
#include <gdk/gdksurfaceprivate.h>
|
||||
#include <gdk/gdkdisplayprivate.h>
|
||||
#include <gsk/gskdebugprivate.h>
|
||||
#include <gsk/gskrendererprivate.h>
|
||||
|
||||
@ -86,7 +86,6 @@ gsk_ngl_renderer_realize (GskRenderer *renderer,
|
||||
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
|
||||
GskNglRenderer *self = (GskNglRenderer *)renderer;
|
||||
GdkGLContext *context = NULL;
|
||||
GdkGLContext *shared_context;
|
||||
GskNglDriver *driver = NULL;
|
||||
gboolean ret = FALSE;
|
||||
gboolean debug_shaders = FALSE;
|
||||
@ -105,21 +104,12 @@ gsk_ngl_renderer_realize (GskRenderer *renderer,
|
||||
!gdk_gl_context_realize (context, error))
|
||||
goto failure;
|
||||
|
||||
if (!(shared_context = gdk_surface_get_shared_data_gl_context (surface)))
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
"Failed to locate shared GL context for driver");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), SHADERS))
|
||||
debug_shaders = TRUE;
|
||||
#endif
|
||||
|
||||
if (!(driver = gsk_ngl_driver_from_shared_context (shared_context, debug_shaders, error)))
|
||||
if (!(driver = gsk_ngl_driver_for_display (gdk_surface_get_display (surface), debug_shaders, error)))
|
||||
goto failure;
|
||||
|
||||
self->command_queue = gsk_ngl_driver_create_command_queue (driver, context);
|
||||
|
@ -87,7 +87,10 @@ struct _GtkInspectorGeneral
|
||||
GtkWidget *pango_fontmap;
|
||||
GtkWidget *media_backend;
|
||||
GtkWidget *gl_version;
|
||||
GtkWidget *gl_error;
|
||||
GtkWidget *gl_error_row;
|
||||
GtkWidget *gl_vendor;
|
||||
GtkWidget *gl_vendor_row;
|
||||
GtkWidget *vk_device;
|
||||
GtkWidget *vk_api_version;
|
||||
GtkWidget *vk_driver_version;
|
||||
@ -298,6 +301,17 @@ get_egl_display (GdkDisplay *display)
|
||||
static void
|
||||
init_gl (GtkInspectorGeneral *gen)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_display_prepare_gl (gen->display, &error))
|
||||
{
|
||||
gtk_label_set_text (GTK_LABEL (gen->gl_version), C_("GL version", "None"));
|
||||
gtk_widget_set_visible (gen->gl_vendor_row, FALSE);
|
||||
gtk_widget_set_visible (gen->gl_error_row, TRUE);
|
||||
gtk_label_set_text (GTK_LABEL (gen->gl_error), error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
if (gdk_display_get_debug_flags (gen->display) & GDK_DEBUG_GL_DISABLE)
|
||||
{
|
||||
gtk_label_set_text (GTK_LABEL (gen->gl_version), C_("GL version", "Disabled"));
|
||||
@ -1053,7 +1067,10 @@ gtk_inspector_general_class_init (GtkInspectorGeneralClass *klass)
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, pango_fontmap);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, media_backend);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_version);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_error);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_error_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_vendor);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, gl_vendor_row);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, vk_device);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, vk_api_version);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorGeneral, vk_driver_version);
|
||||
|
@ -499,7 +499,30 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<object class="GtkListBoxRow" id="gl_error_row">
|
||||
<property name="activatable">0</property>
|
||||
<property name="visible">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">40</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="gl_error">
|
||||
<property name="selectable">1</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="hexpand">1</property>
|
||||
<style>
|
||||
<class name="error"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow" id="gl_vendor_row">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
|
@ -733,11 +733,11 @@ subdir('gtk/css')
|
||||
subdir('gdk')
|
||||
subdir('gsk')
|
||||
subdir('gtk')
|
||||
subdir('tools')
|
||||
subdir('modules')
|
||||
if get_option('demos')
|
||||
subdir('demos')
|
||||
endif
|
||||
subdir('tools')
|
||||
if get_option('build-tests')
|
||||
subdir('tests')
|
||||
subdir('testsuite')
|
||||
|
Loading…
Reference in New Issue
Block a user