Compare commits

...

3 Commits

Author SHA1 Message Date
Chun-wei Fan
1c56e0d2d7 gdkglcontext.c: Re-create an OpenGL/ES 3.0 context if needed
Currently, we create an OpenGL/ES 2.0 context if GLES is requested or required,
but it may not support the needed extensions for it to work, such as
OES_vertex_half_float.  So, if that is the case, create an OpenGL/ES 3.0
context to replace the OpenGL/ES 2.0 context that we have created, so that we
have the needed OpenGL/ES features, in which the OpenGL/ES 2.0 context will
then be dropped.
2023-04-24 16:34:48 +08:00
Chun-wei Fan
bca38a66cc GDK: Allow forcing OpenGL/ES 3.0 contexts if needed
Allow setting the minimal OpenGL/ES API version to 3.0 if needed, such as when
the OpenGL/ES 2.0 context does not support required extensions such as
OES_vertex_half_float.

Update all callers--this currently does things in the exising way.
2023-04-24 16:34:48 +08:00
Chun-wei Fan
d523781ec1 gdkglcontext.c: Split out part creating the actual EGL context
...so that we can retry creating the EGL context to use an OpenGL/ES 3.0
context rather than an OpenGL/ES 2.0 context, when for instance, the
"OES_vertex_half_float" extension is not supported.
2023-04-24 16:34:48 +08:00
3 changed files with 134 additions and 19 deletions

View File

@@ -121,6 +121,7 @@ typedef struct {
#ifdef HAVE_EGL
EGLContext egl_context;
EGLBoolean (*eglSwapBuffersWithDamage) (EGLDisplay, EGLSurface, const EGLint *, EGLint);
guint use_es3 : 1;
#endif
} GdkGLContextPrivate;
@@ -274,12 +275,12 @@ gdk_api_to_egl_api (GdkGLAPI api)
}
}
static GdkGLAPI
gdk_gl_context_create_egl_context (GdkGLContext *context,
GdkGLAPI api,
gboolean legacy)
static EGLContext
gdk_gl_context_create_actual_egl_context (GdkGLContext *context,
GdkGLAPI api,
gboolean legacy,
gboolean use_es3)
{
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);
GdkGLContext *share = gdk_display_get_gl_context (display);
@@ -289,21 +290,18 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
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 (!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,
&min_major, &min_minor);
&min_major, &min_minor,
use_es3);
gdk_gl_context_get_clipped_version (context,
min_major, min_minor,
&major, &minor);
if (!eglBindAPI (gdk_api_to_egl_api (api)))
return 0;
return NULL;
debug_bit = gdk_gl_context_get_debug_enabled (context);
forward_bit = gdk_gl_context_get_forward_compatible (context);
@@ -353,12 +351,113 @@ gdk_gl_context_create_egl_context (GdkGLContext *context,
share ? share_priv->egl_context : EGL_NO_CONTEXT,
context_attribs);
return ctx;
}
static GdkGLAPI
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);
GdkGLContext *share = gdk_display_get_gl_context (display);
GdkGLContextPrivate *share_priv = gdk_gl_context_get_instance_private (share);
EGLContext ctx;
gboolean use_es3 = FALSE;
gboolean share_has_half_float = FALSE;
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
if (!gdk_gl_context_is_api_allowed (context, api, NULL))
return 0;
/*
* The new context must use an OpenGL/ES 3.0 context if the
* shared context is an OpenGL/ES 3.0 context
*/
use_es3 = share != NULL ? share_priv->use_es3 : FALSE;
share_has_half_float = share != NULL ? share_priv->has_half_float : FALSE;
ctx = gdk_gl_context_create_actual_egl_context (context,
api,
legacy,
use_es3);
/*
* If we are using an OpenGL/ES 2.0 context, check whether
* it supports the needed extension(s) if not already done so
*/
if (api == GDK_GL_API_GLES &&
!share_has_half_float &&
!use_es3 &&
ctx != NULL)
{
gboolean surfaceless = !gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context));
EGLContext ctx_es3 = NULL;
gboolean destroy_es2_ctx = FALSE;
EGLSurface egl_surface;
if (!surfaceless)
egl_surface = gdk_surface_get_egl_surface (gdk_gl_context_get_surface (context));
else
egl_surface = EGL_NO_SURFACE;
if (eglMakeCurrent (egl_display,
egl_surface,
egl_surface,
ctx))
{
/*
* If we don't support the needed extension(s) in the OpenGL/ES 2.0 context,
* destroy the context and re-create an OpenGL/ES 3.0 context, and use it
* if it is successfully created.
*/
if (epoxy_gl_version () < 30 &&
!epoxy_has_gl_extension ("OES_vertex_half_float"))
{
GDK_DISPLAY_DEBUG (display, OPENGL,
"No OES_vertex_half_float extension found.\n"
"Creating new OpenGL/ES 3.0 context to replace OpenGL/ES 2.0 context...");
ctx_es3 = gdk_gl_context_create_actual_egl_context (context,
api,
legacy,
TRUE);
if (ctx_es3 != NULL)
use_es3 = TRUE;
destroy_es2_ctx = TRUE;
}
else
priv->has_half_float = TRUE;
eglMakeCurrent (egl_display,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
EGL_NO_CONTEXT);
}
else
/* no point going on if the EGLContext isn't working */
destroy_es2_ctx = TRUE;
if (destroy_es2_ctx)
{
eglDestroyContext (egl_display, ctx);
ctx = NULL;
}
if (use_es3)
ctx = ctx_es3;
}
if (ctx == NULL)
return 0;
return 0;
GDK_DISPLAY_DEBUG (display, OPENGL, "Created EGL context[%p]", ctx);
priv->egl_context = ctx;
priv->use_es3 = use_es3;
gdk_gl_context_set_is_legacy (context, legacy);
if (epoxy_has_egl_extension (egl_display, "EGL_KHR_swap_buffers_with_damage"))
@@ -989,7 +1088,8 @@ void
gdk_gl_context_get_matching_version (GdkGLAPI api,
gboolean legacy,
int *major,
int *minor)
int *minor,
gboolean use_es3)
{
int maj, min;
@@ -1008,8 +1108,16 @@ gdk_gl_context_get_matching_version (GdkGLAPI api,
}
else
{
maj = GDK_GL_MIN_GLES_VERSION_MAJOR;
min = GDK_GL_MIN_GLES_VERSION_MINOR;
if (use_es3)
{
maj = GDK_GL_MIN_GLES3_VERSION_MAJOR;
min = GDK_GL_MIN_GLES3_VERSION_MINOR;
}
else
{
maj = GDK_GL_MIN_GLES_VERSION_MAJOR;
min = GDK_GL_MIN_GLES_VERSION_MINOR;
}
}
if (major != NULL)
@@ -1554,8 +1662,11 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
glGetIntegerv (GL_MAX_LABEL_LENGTH, &priv->max_debug_label_length);
}
priv->has_half_float = gdk_gl_context_check_version (context, 3, 0, 3, 0) ||
epoxy_has_gl_extension ("OES_vertex_half_float");
if (!priv->has_half_float)
{
priv->has_half_float = gdk_gl_context_check_version (context, 3, 0, 3, 0) ||
epoxy_has_gl_extension ("OES_vertex_half_float");
}
#ifdef G_ENABLE_DEBUG
{

View File

@@ -44,6 +44,8 @@ G_BEGIN_DECLS
#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_GLES3_VERSION_MAJOR (3)
#define GDK_GL_MIN_GLES3_VERSION_MINOR (0)
typedef enum {
GDK_GL_NONE = 0,
@@ -137,7 +139,8 @@ void gdk_gl_context_get_clipped_version (GdkGLContext
void gdk_gl_context_get_matching_version (GdkGLAPI api,
gboolean legacy,
int *major,
int *minor);
int *minor,
gboolean use_es3);
gboolean gdk_gl_context_has_unpack_subimage (GdkGLContext *context);
void gdk_gl_context_push_debug_group (GdkGLContext *context,

View File

@@ -489,7 +489,8 @@ gdk_x11_context_create_glx_context (GdkGLContext *context,
/* 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,
&min_major, &min_minor);
&min_major, &min_minor,
FALSE);
gdk_gl_context_get_clipped_version (context, min_major, min_minor,
&major, &minor);