glcontext: Add gdk_gl_context_get_memory_flags()

Checks which features of a given memory format are supported by
the current GL implementation.

We check:
 * usable: Can be used as a texture with NEAREST filter
 * renderable: Can be used as a render target
 * filterable: Can be used with GL_LINEAR

In normal GL, all formats are all of these things, but GLES is a lot
more picky.

So far nobody uses this.
This commit is contained in:
Benjamin Otte 2023-12-07 05:45:59 +01:00
parent 6e7c499408
commit 5485d806c5
2 changed files with 157 additions and 2 deletions

View File

@ -104,10 +104,15 @@
#define DEFAULT_ALLOWED_APIS GDK_GL_API_GL | GDK_GL_API_GLES
typedef struct {
typedef struct _GdkGLContextPrivate GdkGLContextPrivate;
struct _GdkGLContextPrivate
{
GdkGLVersion required;
GdkGLVersion gl_version;
GdkGLMemoryFlags memory_flags[GDK_MEMORY_N_FORMATS];
guint has_khr_debug : 1;
guint use_khr_debug : 1;
guint has_half_float : 1;
@ -129,7 +134,7 @@ typedef struct {
EGLContext egl_context;
EGLBoolean (*eglSwapBuffersWithDamage) (EGLDisplay, EGLSurface, const EGLint *, EGLint);
#endif
} GdkGLContextPrivate;
};
enum {
PROP_0,
@ -1524,6 +1529,132 @@ gdk_gl_context_realize (GdkGLContext *context,
return priv->api;
}
static void
gdk_gl_context_init_memory_flags (GdkGLContext *self)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
gsize i;
if (!gdk_gl_context_get_use_es (self))
{
for (i = 0; i < G_N_ELEMENTS (priv->memory_flags); i++)
{
priv->memory_flags[i] = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
}
return;
}
/* GLES 2.0 spec, tables 3.2 and 3.3 */
priv->memory_flags[GDK_MEMORY_R8G8B8] = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8A8] = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
#if 0
/* GLES2 can do these, but GTK can't */
priv->memory_flags[GDK_MEMORY_A8] = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G8] = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G8A8_PREMULTIPLIED] = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G8A8] = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
#endif
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
{
/* GLES 3.0.6 spec, table 3.13 */
priv->memory_flags[GDK_MEMORY_G8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8X8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32_FLOAT] |= GDK_GL_FORMAT_USABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= GDK_GL_FORMAT_USABLE;
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= GDK_GL_FORMAT_USABLE;
/* no changes in GLES 3.1 spec, table 8.13 */
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 2)))
{
/* GLES 3.2 spec, table 8.10 */
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= GDK_GL_FORMAT_FILTERABLE;
}
}
if (epoxy_has_gl_extension ("GL_OES_rgb8_rgba8"))
{
priv->memory_flags[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R8G8B8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
priv->memory_flags[GDK_MEMORY_R8G8B8X8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
}
if (epoxy_has_gl_extension ("GL_EXT_abgr"))
{
priv->memory_flags[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A8B8G8R8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
priv->memory_flags[GDK_MEMORY_X8B8G8R8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
}
if (epoxy_has_gl_extension ("GL_EXT_texture_format_BGRA8888"))
{
priv->memory_flags[GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_B8G8R8A8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
priv->memory_flags[GDK_MEMORY_B8G8R8X8] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
}
/* Technically, those extensions are supported on GLES2.
* However, GTK uses the wrong format/type pairs with them, so we don't enable them.
*/
if (gdk_gl_version_greater_equal (&priv->gl_version, &GDK_GL_VERSION_INIT (3, 0)))
{
if (epoxy_has_gl_extension ("GL_EXT_texture_norm16"))
{
priv->memory_flags[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G16A16_PREMULTIPLIED] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G16A16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_G16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_A16] |= GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_RENDERABLE | GDK_GL_FORMAT_FILTERABLE;
}
if (epoxy_has_gl_extension ("GL_OES_texture_half_float"))
{
GdkGLMemoryFlags flags = GDK_GL_FORMAT_USABLE;
if (epoxy_has_gl_extension ("GL_EXT_color_buffer_half_float"))
flags |= GDK_GL_FORMAT_RENDERABLE;
if (epoxy_has_gl_extension ("GL_OES_texture_half_float_linear"))
flags |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] |= flags;
priv->memory_flags[GDK_MEMORY_R16G16B16A16_FLOAT] |= flags;
priv->memory_flags[GDK_MEMORY_R16G16B16_FLOAT] |= flags;
priv->memory_flags[GDK_MEMORY_A16_FLOAT] |= flags;
}
if (epoxy_has_gl_extension ("GL_OES_texture_float"))
{
GdkGLMemoryFlags flags = GDK_GL_FORMAT_USABLE;
if (epoxy_has_gl_extension ("GL_EXT_color_buffer_float"))
flags |= GDK_GL_FORMAT_RENDERABLE;
if (epoxy_has_gl_extension ("GL_OES_texture_float_linear"))
flags |= GDK_GL_FORMAT_FILTERABLE;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] |= flags;
priv->memory_flags[GDK_MEMORY_R32G32B32A32_FLOAT] |= flags;
priv->memory_flags[GDK_MEMORY_R32G32B32_FLOAT] |= flags;
priv->memory_flags[GDK_MEMORY_A32_FLOAT] |= flags;
}
}
}
void
gdk_gl_version_init_epoxy (GdkGLVersion *version)
{
@ -1590,6 +1721,8 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
epoxy_has_gl_extension ("GL_ARB_sync") ||
epoxy_has_gl_extension ("GL_APPLE_sync");
gdk_gl_context_init_memory_flags (context);
{
int max_texture_size;
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_texture_size);
@ -1873,6 +2006,15 @@ gdk_gl_context_get_current (void)
return context;
}
GdkGLMemoryFlags
gdk_gl_context_get_format_flags (GdkGLContext *self,
GdkMemoryFormat format)
{
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->memory_flags[format];
}
gboolean
gdk_gl_context_has_debug (GdkGLContext *self)
{

View File

@ -35,6 +35,17 @@ typedef enum {
GDK_GL_CGL
} GdkGLBackend;
typedef enum {
/* The format is supported for glTexImage2D() */
GDK_GL_FORMAT_USABLE = 1 << 0,
/* The format can be rendered to.
* GL/GLES spec term: "color-renderable" */
GDK_GL_FORMAT_RENDERABLE = 1 << 1,
/* GL_LINEAR/GL_MIPMAP_LINEAR can be used for textures in this format.
* GLES spec term: "texture-filterable" */
GDK_GL_FORMAT_FILTERABLE = 1 << 2
} GdkGLMemoryFlags;
/* The maximum amount of buffers we track update regions for.
* Note that this is equal to the max buffer age value we
* can provide a damage region for */
@ -150,6 +161,8 @@ void gdk_gl_context_label_object_printf (GdkGLContext
const char * gdk_gl_context_get_glsl_version_string (GdkGLContext *self);
GdkGLMemoryFlags gdk_gl_context_get_format_flags (GdkGLContext *self,
GdkMemoryFormat format) G_GNUC_PURE;
gboolean gdk_gl_context_has_debug (GdkGLContext *self) G_GNUC_PURE;
gboolean gdk_gl_context_use_es_bgra (GdkGLContext *context);