forked from AuroraMiddleware/gtk
glcontext: Refactor realize function, fix interaction with shared context
This commit is contained in:
parent
f4f0daa113
commit
549a2b4c86
@ -255,83 +255,83 @@ gdk_gl_context_get_property (GObject *object,
|
||||
}
|
||||
}
|
||||
|
||||
#define N_EGL_ATTRS 16
|
||||
#define N_EGL_ATTRS 16
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
static inline EGLenum
|
||||
gdk_api_to_egl_api (GdkGLAPI api)
|
||||
{
|
||||
switch (api)
|
||||
{
|
||||
case GDK_GL_API_GLES:
|
||||
return EGL_OPENGL_ES_API;
|
||||
case GDK_GL_API_GL:
|
||||
default:
|
||||
return EGL_OPENGL_API;
|
||||
}
|
||||
}
|
||||
|
||||
static GdkGLAPI
|
||||
gdk_gl_context_realize_egl (GdkGLContext *context,
|
||||
GError **error)
|
||||
gdk_gl_context_create_egl_context (GdkGLContext *context,
|
||||
GdkGLAPI api,
|
||||
gboolean legacy)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
EGLDisplay egl_display = gdk_display_get_egl_display (display);
|
||||
|
||||
EGLConfig egl_config;
|
||||
GdkGLContext *share = gdk_display_get_gl_context (display);
|
||||
GdkGLContextPrivate *share_priv = gdk_gl_context_get_instance_private (share);
|
||||
EGLConfig egl_config;
|
||||
EGLContext ctx;
|
||||
EGLint context_attribs[N_EGL_ATTRS];
|
||||
int major, minor, flags;
|
||||
gboolean debug_bit, forward_bit, legacy_bit;
|
||||
GdkGLAPI api;
|
||||
int i = 0;
|
||||
EGLint context_attribs[N_EGL_ATTRS], i = 0, flags = 0;
|
||||
gboolean debug_bit, forward_bit;
|
||||
int min_major, min_minor, major = 0, minor = 0;
|
||||
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
if (share != NULL)
|
||||
gdk_gl_context_get_required_version (share, &major, &minor);
|
||||
else
|
||||
gdk_gl_context_get_required_version (context, &major, &minor);
|
||||
if (!gdk_gl_context_is_api_allowed (context, api, NULL))
|
||||
return 0;
|
||||
|
||||
/* We will use the default version matching the context status
|
||||
* unless the user requested a version which makes sense */
|
||||
gdk_gl_context_get_matching_version (api, legacy,
|
||||
display->have_egl_win32_libangle,
|
||||
&min_major, &min_minor);
|
||||
gdk_gl_context_get_clipped_version (context,
|
||||
min_major, min_minor,
|
||||
&major, &minor);
|
||||
|
||||
if (!eglBindAPI (gdk_api_to_egl_api (api)))
|
||||
return 0;
|
||||
|
||||
debug_bit = gdk_gl_context_get_debug_enabled (context);
|
||||
forward_bit = gdk_gl_context_get_forward_compatible (context);
|
||||
legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ||
|
||||
(share != NULL && gdk_gl_context_is_legacy (share));
|
||||
|
||||
if (display->have_egl_no_config_context)
|
||||
egl_config = NULL;
|
||||
else
|
||||
egl_config = gdk_display_get_egl_config (display);
|
||||
|
||||
flags = 0;
|
||||
|
||||
if (debug_bit)
|
||||
flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
|
||||
if (forward_bit)
|
||||
flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
||||
|
||||
if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL) &&
|
||||
eglBindAPI (EGL_OPENGL_API))
|
||||
if (api == GDK_GL_API_GL)
|
||||
{
|
||||
/* We want a core profile, unless in legacy mode */
|
||||
context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
|
||||
context_attribs[i++] = legacy_bit
|
||||
? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR
|
||||
: EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
||||
|
||||
/* Specify the version */
|
||||
context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR;
|
||||
context_attribs[i++] = legacy_bit ? 3 : major;
|
||||
context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR;
|
||||
context_attribs[i++] = legacy_bit ? 0 : minor;
|
||||
api = GDK_GL_API_GL;
|
||||
}
|
||||
else if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL) &&
|
||||
eglBindAPI (EGL_OPENGL_ES_API))
|
||||
{
|
||||
context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION;
|
||||
if (major == 3)
|
||||
context_attribs[i++] = 3;
|
||||
else
|
||||
context_attribs[i++] = 2;
|
||||
api = GDK_GL_API_GLES;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("The EGL implementation does not support any allowed APIs"));
|
||||
return 0;
|
||||
context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK;
|
||||
context_attribs[i++] = legacy
|
||||
? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT
|
||||
: EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
|
||||
}
|
||||
|
||||
/* Specify the flags */
|
||||
if (legacy || api == GDK_GL_API_GLES)
|
||||
flags &= ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
||||
|
||||
context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION;
|
||||
context_attribs[i++] = major;
|
||||
context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION;
|
||||
context_attribs[i++] = minor;
|
||||
context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
|
||||
context_attribs[i++] = flags;
|
||||
|
||||
@ -343,91 +343,82 @@ gdk_gl_context_realize_egl (GdkGLContext *context,
|
||||
major, minor,
|
||||
debug_bit ? "yes" : "no",
|
||||
forward_bit ? "yes" : "no",
|
||||
legacy_bit ? "yes" : "no",
|
||||
legacy ? "yes" : "no",
|
||||
api == GDK_GL_API_GLES ? "yes" : "no"));
|
||||
|
||||
ctx = eglCreateContext (egl_display,
|
||||
egl_config,
|
||||
share != NULL ? share_priv->egl_context
|
||||
: EGL_NO_CONTEXT,
|
||||
share ? share_priv->egl_context : EGL_NO_CONTEXT,
|
||||
context_attribs);
|
||||
|
||||
/* If context creation failed without the ES bit, let's try again with it */
|
||||
if (ctx == NULL && gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL) && eglBindAPI (EGL_OPENGL_ES_API))
|
||||
{
|
||||
i = 0;
|
||||
context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION;
|
||||
context_attribs[i++] = 2;
|
||||
context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION;
|
||||
context_attribs[i++] = 0;
|
||||
context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
|
||||
context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
||||
context_attribs[i++] = EGL_NONE;
|
||||
g_assert (i < N_EGL_ATTRS);
|
||||
|
||||
legacy_bit = FALSE;
|
||||
api = GDK_GL_API_GLES;
|
||||
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("eglCreateContext failed, switching to OpenGL ES"));
|
||||
ctx = eglCreateContext (egl_display,
|
||||
egl_config,
|
||||
share != NULL ? share_priv->egl_context
|
||||
: EGL_NO_CONTEXT,
|
||||
context_attribs);
|
||||
}
|
||||
|
||||
/* If context creation failed without the legacy bit, let's try again with it */
|
||||
if (ctx == NULL && gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL) && eglBindAPI (EGL_OPENGL_API))
|
||||
{
|
||||
i = 0;
|
||||
context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
|
||||
context_attribs[i++] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
|
||||
context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION;
|
||||
context_attribs[i++] = 3;
|
||||
context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION;
|
||||
context_attribs[i++] = 0;
|
||||
context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR;
|
||||
context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
|
||||
context_attribs[i++] = EGL_NONE;
|
||||
g_assert (i < N_EGL_ATTRS);
|
||||
|
||||
legacy_bit = TRUE;
|
||||
api = GDK_GL_API_GL;
|
||||
|
||||
GDK_DISPLAY_NOTE (display, OPENGL,
|
||||
g_message ("eglCreateContext failed, switching to legacy"));
|
||||
ctx = eglCreateContext (egl_display,
|
||||
egl_config,
|
||||
share != NULL ? share_priv->egl_context
|
||||
: EGL_NO_CONTEXT,
|
||||
context_attribs);
|
||||
}
|
||||
|
||||
if (ctx == NULL)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Unable to create a GL context"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Created EGL context[%p]", ctx));
|
||||
|
||||
priv->egl_context = ctx;
|
||||
|
||||
gdk_gl_context_set_is_legacy (context, legacy_bit);
|
||||
gdk_gl_context_set_is_legacy (context, legacy);
|
||||
|
||||
if (epoxy_has_egl_extension (egl_display, "EGL_KHR_swap_buffers_with_damage"))
|
||||
priv->eglSwapBuffersWithDamage = (gpointer)epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageKHR");
|
||||
priv->eglSwapBuffersWithDamage = (gpointer) epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageKHR");
|
||||
else if (epoxy_has_egl_extension (egl_display, "EGL_EXT_swap_buffers_with_damage"))
|
||||
priv->eglSwapBuffersWithDamage = (gpointer)epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageEXT");
|
||||
priv->eglSwapBuffersWithDamage = (gpointer) epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageEXT");
|
||||
|
||||
gdk_profiler_end_mark (start_time, "realize GdkWaylandGLContext", NULL);
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
static GdkGLAPI
|
||||
gdk_gl_context_realize_egl (GdkGLContext *context,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkGLContext *share = gdk_display_get_gl_context (display);
|
||||
GdkGLAPI api, preferred_api;
|
||||
gboolean prefer_legacy;
|
||||
|
||||
if (share && gdk_gl_context_is_api_allowed (context,
|
||||
gdk_gl_context_get_api (share),
|
||||
NULL))
|
||||
preferred_api = gdk_gl_context_get_api (share);
|
||||
else if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL))
|
||||
preferred_api = GDK_GL_API_GL;
|
||||
else if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL))
|
||||
preferred_api = GDK_GL_API_GLES;
|
||||
else
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("No GL API allowed."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
prefer_legacy = (GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) ||
|
||||
(share != NULL && gdk_gl_context_is_legacy (share)));
|
||||
|
||||
if (preferred_api == GDK_GL_API_GL)
|
||||
{
|
||||
if ((api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GL, prefer_legacy)) ||
|
||||
(api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GLES, FALSE)) ||
|
||||
(api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GL, TRUE)))
|
||||
return api;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GLES, FALSE)) ||
|
||||
(api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GL, prefer_legacy)) ||
|
||||
(api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GL, TRUE)))
|
||||
return api;
|
||||
}
|
||||
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("Unable to create a GL context"));
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_EGL */
|
||||
|
||||
static GdkGLAPI
|
||||
gdk_gl_context_default_realize (GdkGLContext *context,
|
||||
GError **error)
|
||||
@ -966,6 +957,48 @@ gdk_gl_context_get_forward_compatible (GdkGLContext *context)
|
||||
return priv->forward_compatible;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_gl_context_get_matching_version (GdkGLAPI api,
|
||||
gboolean legacy,
|
||||
gboolean win32_libangle,
|
||||
int *major,
|
||||
int *minor)
|
||||
{
|
||||
int maj, min;
|
||||
|
||||
if (api == GDK_GL_API_GL)
|
||||
{
|
||||
if (legacy)
|
||||
{
|
||||
maj = GDK_GL_MIN_GL_LEGACY_VERSION_MAJOR;
|
||||
min = GDK_GL_MIN_GL_LEGACY_VERSION_MINOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
maj = GDK_GL_MIN_GL_VERSION_MAJOR;
|
||||
min = GDK_GL_MIN_GL_VERSION_MINOR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (win32_libangle)
|
||||
{
|
||||
maj = GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MAJOR;
|
||||
min = GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MINOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
maj = GDK_GL_MIN_GLES_VERSION_MAJOR;
|
||||
min = GDK_GL_MIN_GLES_VERSION_MINOR;
|
||||
}
|
||||
}
|
||||
|
||||
if (major != NULL)
|
||||
*major = maj;
|
||||
if (minor != NULL)
|
||||
*minor = min;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_context_set_required_version:
|
||||
* @context: a `GdkGLContext`
|
||||
|
@ -33,6 +33,22 @@ G_BEGIN_DECLS
|
||||
#define GDK_EGL_MIN_VERSION_MAJOR (1)
|
||||
#define GDK_EGL_MIN_VERSION_MINOR (4)
|
||||
|
||||
/* Minimum OpenGL versions supported by GTK.
|
||||
* Backends should make sure to never create a context of a previous version.
|
||||
*
|
||||
* The macros refer to OpenGL; OpenGL with OPENGL_COMPATIBILITY_PROFILE_BIT as
|
||||
* OPENGL_PROFILE_MASK; OpenGL ES; and OpenGL ES win32 Angle implementation,
|
||||
* respectively
|
||||
*/
|
||||
#define GDK_GL_MIN_GL_VERSION_MAJOR (3)
|
||||
#define GDK_GL_MIN_GL_VERSION_MINOR (2)
|
||||
#define GDK_GL_MIN_GL_LEGACY_VERSION_MAJOR (3)
|
||||
#define GDK_GL_MIN_GL_LEGACY_VERSION_MINOR (0)
|
||||
#define GDK_GL_MIN_GLES_VERSION_MAJOR (2)
|
||||
#define GDK_GL_MIN_GLES_VERSION_MINOR (0)
|
||||
#define GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MAJOR (3)
|
||||
#define GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MINOR (0)
|
||||
|
||||
typedef enum {
|
||||
GDK_GL_NONE = 0,
|
||||
GDK_GL_EGL,
|
||||
@ -122,6 +138,11 @@ void gdk_gl_context_get_clipped_version (GdkGLContext
|
||||
int min_minor,
|
||||
int *major,
|
||||
int *minor);
|
||||
void gdk_gl_context_get_matching_version (GdkGLAPI api,
|
||||
gboolean legacy,
|
||||
gboolean win32_libangle,
|
||||
int *major,
|
||||
int *minor);
|
||||
|
||||
gboolean gdk_gl_context_has_unpack_subimage (GdkGLContext *context);
|
||||
void gdk_gl_context_push_debug_group (GdkGLContext *context,
|
||||
|
Loading…
Reference in New Issue
Block a user