gl: Track if mipmap generation is allowed

... and if it isn't, switch to a format that does allow mipmaps.
This commit is contained in:
Benjamin Otte 2024-01-03 16:03:24 +01:00
parent b830ca8fab
commit 96a71d515b
4 changed files with 48 additions and 14 deletions

View File

@ -1477,12 +1477,14 @@ gsk_gl_command_queue_create_framebuffer (GskGLCommandQueue *self)
static GdkMemoryFormat
memory_format_gl_format (GskGLCommandQueue *self,
GdkMemoryFormat data_format,
gboolean ensure_mipmap,
gboolean *out_can_mipmap,
GLint *gl_internalformat,
GLenum *gl_format,
GLenum *gl_type,
GLint gl_swizzle[4])
{
GdkGLMemoryFlags flags;
GdkGLMemoryFlags flags, required_flags;
GdkMemoryFormat alt_format;
const GdkMemoryFormat *fallbacks;
gsize i;
@ -1491,15 +1493,20 @@ memory_format_gl_format (GskGLCommandQueue *self,
if (gdk_memory_format_alpha (data_format) == GDK_MEMORY_ALPHA_STRAIGHT)
data_format = gdk_memory_format_get_premultiplied (data_format);
required_flags = GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE;
if (ensure_mipmap)
required_flags |= GDK_GL_FORMAT_RENDERABLE;
/* First, try the format itself */
flags = gdk_gl_context_get_format_flags (self->context, data_format);
if ((flags & (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE)) == (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE))
if ((flags & required_flags) == required_flags)
{
gdk_memory_format_gl_format (data_format,
gl_internalformat,
gl_format,
gl_type,
gl_swizzle);
*out_can_mipmap = (flags & GDK_GL_FORMAT_RENDERABLE) ? TRUE : FALSE;
return data_format;
}
@ -1512,8 +1519,10 @@ memory_format_gl_format (GskGLCommandQueue *self,
gl_swizzle))
{
flags = gdk_gl_context_get_format_flags (self->context, alt_format);
if ((flags & (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE)) == (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE))
if ((flags & required_flags) == required_flags)
{
*out_can_mipmap = (flags & GDK_GL_FORMAT_RENDERABLE) ? TRUE : FALSE;
if (self->can_swizzle)
return data_format;
@ -1532,13 +1541,15 @@ memory_format_gl_format (GskGLCommandQueue *self,
for (i = 0; fallbacks[i] != -1; i++)
{
flags = gdk_gl_context_get_format_flags (self->context, fallbacks[i]);
if (((flags & (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE)) == (GDK_GL_FORMAT_USABLE | GDK_GL_FORMAT_FILTERABLE)))
if (((flags & required_flags) == required_flags))
{
gdk_memory_format_gl_format (fallbacks[i],
gl_internalformat,
gl_format,
gl_type,
gl_swizzle);
*out_can_mipmap = (flags & GDK_GL_FORMAT_RENDERABLE) ? TRUE : FALSE;
return fallbacks[i];
}
}
@ -1644,8 +1655,10 @@ gsk_gl_command_queue_do_upload_texture_chunk (GskGLCommandQueue *self,
int
gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
gboolean ensure_mipmap,
unsigned int n_chunks,
GskGLTextureChunk *chunks)
GskGLTextureChunk *chunks,
gboolean *out_can_mipmap)
{
G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME;
int width, height;
@ -1690,6 +1703,8 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
data_format = gdk_texture_get_format (chunks[0].texture);
data_format = memory_format_gl_format (self,
data_format,
ensure_mipmap,
out_can_mipmap,
&gl_internalformat,
&gl_format,
&gl_type,
@ -1718,9 +1733,15 @@ gsk_gl_command_queue_upload_texture_chunks (GskGLCommandQueue *self,
int
gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
GdkTexture *texture)
GdkTexture *texture,
gboolean ensure_mipmap,
gboolean *out_can_mipmap)
{
return gsk_gl_command_queue_upload_texture_chunks (self, 1, &(GskGLTextureChunk){ texture, 0, 0});
return gsk_gl_command_queue_upload_texture_chunks (self,
ensure_mipmap,
1,
&(GskGLTextureChunk){ texture, 0, 0},
out_can_mipmap);
}
void

View File

@ -313,7 +313,9 @@ void gsk_gl_command_queue_execute (GskGLCommandQueue
const cairo_region_t *scissor,
guint default_framebuffer);
int gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
GdkTexture *texture);
GdkTexture *texture,
gboolean ensure_mipmap,
gboolean *out_can_mipmap);
int gsk_gl_command_queue_create_texture (GskGLCommandQueue *self,
int width,
int height,
@ -327,8 +329,10 @@ typedef struct {
} GskGLTextureChunk;
int gsk_gl_command_queue_upload_texture_chunks(GskGLCommandQueue *self,
gboolean ensure_mipmap,
unsigned int n_chunks,
GskGLTextureChunk *chunks);
GskGLTextureChunk *chunks,
gboolean *out_can_mipmap);
guint gsk_gl_command_queue_create_framebuffer (GskGLCommandQueue *self);
gboolean gsk_gl_command_queue_create_render_target (GskGLCommandQueue *self,

View File

@ -925,6 +925,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
guint texture_id;
int height;
int width;
gboolean can_mipmap = FALSE;
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), 0);
g_return_val_if_fail (GDK_IS_TEXTURE (texture), 0);
@ -938,7 +939,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
t = gdk_texture_get_render_data (texture, self);
if (t && t->texture_id)
{
if (ensure_mipmap && !t->has_mipmap)
if (ensure_mipmap && t->can_mipmap && !t->has_mipmap)
{
glBindTexture (GL_TEXTURE_2D, t->texture_id);
glGenerateMipmap (GL_TEXTURE_2D);
@ -948,7 +949,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
return t->texture_id;
}
if (GDK_IS_DMABUF_TEXTURE (texture))
if (GDK_IS_DMABUF_TEXTURE (texture) && !ensure_mipmap)
{
texture_id = gsk_gl_driver_import_dmabuf_texture (self, GDK_DMABUF_TEXTURE (texture));
}
@ -975,7 +976,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
*/
gdk_gl_context_make_current (context);
texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, GDK_TEXTURE (downloaded_texture));
texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, GDK_TEXTURE (downloaded_texture), ensure_mipmap, &can_mipmap);
}
width = gdk_texture_get_width (texture);
@ -984,8 +985,10 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
t = gsk_gl_texture_new (texture_id,
width, height,
self->current_frame_id);
t->can_mipmap = can_mipmap;
if (ensure_mipmap)
{
g_assert (can_mipmap);
glBindTexture (GL_TEXTURE_2D, t->texture_id);
glGenerateMipmap (GL_TEXTURE_2D);
t->has_mipmap = TRUE;
@ -1433,6 +1436,7 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
GdkMemoryTexture *memtex2 = NULL;
GdkMemoryTexture *memtex3 = NULL;
GdkMemoryTexture *memtex4 = NULL;
gboolean can_mipmap = TRUE, slice_can_mipmap;
g_assert (GSK_IS_GL_DRIVER (self));
g_assert (GDK_IS_TEXTURE (texture));
@ -1694,7 +1698,7 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
n_chunks++;
}
texture_id = gsk_gl_command_queue_upload_texture_chunks (self->command_queue, n_chunks, chunks);
texture_id = gsk_gl_command_queue_upload_texture_chunks (self->command_queue, TRUE, n_chunks, chunks, &slice_can_mipmap);
glBindTexture (GL_TEXTURE_2D, texture_id);
glGenerateMipmap (GL_TEXTURE_2D);
@ -1707,10 +1711,12 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
GdkTexture *subtex;
subtex = gdk_memory_texture_new_subtexture (memtex, x, y, slice_width, slice_height);
texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, subtex);
texture_id = gsk_gl_command_queue_upload_texture (self->command_queue, subtex, FALSE, &slice_can_mipmap);
g_object_unref (subtex);
}
can_mipmap &= slice_can_mipmap;
slices[slice_index].rect.x = x;
slices[slice_index].rect.y = y;
slices[slice_index].rect.width = slice_width;
@ -1737,6 +1743,7 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
t = gsk_gl_texture_new (0,
tex_width, tex_height,
self->current_frame_id);
t->can_mipmap = can_mipmap;
t->has_mipmap = ensure_mipmap;
/* Use gsk_gl_texture_free() as destroy notify here since we are

View File

@ -73,6 +73,8 @@ struct _GskGLTexture
/* Set when used by an atlas so we don't drop the texture */
guint permanent : 1;
/* we are allowed to call glGenerateMipmap() for this texture */
guint can_mipmap : 1;
/* we called glGenerateMipmap() for this texture */
guint has_mipmap : 1;
};