summaryrefslogtreecommitdiff
path: root/gsk
diff options
context:
space:
mode:
authorBenjamin Otte <otte.benjamin@googlemail.com>2023-04-28 15:58:10 +0000
committerBenjamin Otte <otte.benjamin@googlemail.com>2023-04-28 15:58:10 +0000
commit76777cdd1801b450a0ba5fb6d8147045d888c866 (patch)
treefd198c14e9ecf01f8f4ed0124065ffefea331438 /gsk
parentbdec7782b4d30da8482f9d1f6a330e3fd1af2e8d (diff)
parent92a9f8cd7edb029a18f0897c173adba7c6213a18 (diff)
downloadgtk+-76777cdd1801b450a0ba5fb6d8147045d888c866.tar.gz
Merge branch 'wip/otte/texturebuilder' into 'main'
Add GdkGLTextureBuilder See merge request GNOME/gtk!5862
Diffstat (limited to 'gsk')
-rw-r--r--gsk/gl/gskglcommandqueue.c13
-rw-r--r--gsk/gl/gskglcommandqueueprivate.h41
-rw-r--r--gsk/gl/gskgldriver.c42
-rw-r--r--gsk/gl/gskglprogramprivate.h16
-rw-r--r--gsk/gl/gskglrenderjob.c42
5 files changed, 126 insertions, 28 deletions
diff --git a/gsk/gl/gskglcommandqueue.c b/gsk/gl/gskglcommandqueue.c
index d286c001ba..774b957785 100644
--- a/gsk/gl/gskglcommandqueue.c
+++ b/gsk/gl/gskglcommandqueue.c
@@ -427,6 +427,7 @@ gsk_gl_command_queue_dispose (GObject *object)
gsk_gl_command_batches_clear (&self->batches);
gsk_gl_command_binds_clear (&self->batch_binds);
gsk_gl_command_uniforms_clear (&self->batch_uniforms);
+ gsk_gl_syncs_clear (&self->syncs);
gsk_gl_buffer_destroy (&self->vertices);
@@ -449,6 +450,7 @@ gsk_gl_command_queue_init (GskGLCommandQueue *self)
gsk_gl_command_batches_init (&self->batches, 128);
gsk_gl_command_binds_init (&self->batch_binds, 1024);
gsk_gl_command_uniforms_init (&self->batch_uniforms, 2048);
+ gsk_gl_syncs_init (&self->syncs, 10);
gsk_gl_buffer_init (&self->vertices, GL_ARRAY_BUFFER, sizeof (GskGLDrawVertex));
}
@@ -1159,17 +1161,25 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
if G_UNLIKELY (batch->draw.bind_count > 0)
{
const GskGLCommandBind *bind = &self->batch_binds.items[batch->draw.bind_offset];
-
for (guint i = 0; i < batch->draw.bind_count; i++)
{
if (textures[bind->texture] != bind->id)
{
+ GskGLSync *s;
+
if (active != bind->texture)
{
active = bind->texture;
glActiveTexture (GL_TEXTURE0 + bind->texture);
}
+ s = gsk_gl_syncs_get_sync (&self->syncs, bind->id);
+ if (s && s->sync)
+ {
+ glWaitSync ((GLsync) s->sync, 0, GL_TIMEOUT_IGNORED);
+ s->sync = NULL;
+ }
+
glBindTexture (GL_TEXTURE_2D, bind->id);
textures[bind->texture] = bind->id;
if (!self->has_samplers)
@@ -1315,6 +1325,7 @@ gsk_gl_command_queue_end_frame (GskGLCommandQueue *self)
self->batches.len = 0;
self->batch_binds.len = 0;
self->batch_uniforms.len = 0;
+ self->syncs.len = 0;
self->n_uploads = 0;
self->tail_batch_index = -1;
self->in_frame = FALSE;
diff --git a/gsk/gl/gskglcommandqueueprivate.h b/gsk/gl/gskglcommandqueueprivate.h
index fd72f68aff..df3afb1eea 100644
--- a/gsk/gl/gskglcommandqueueprivate.h
+++ b/gsk/gl/gskglcommandqueueprivate.h
@@ -168,9 +168,15 @@ typedef union _GskGLCommandBatch
G_STATIC_ASSERT (sizeof (GskGLCommandBatch) == 32);
+typedef struct _GskGLSync {
+ guint id;
+ gpointer sync;
+} GskGLSync;
+
DEFINE_INLINE_ARRAY (GskGLCommandBatches, gsk_gl_command_batches, GskGLCommandBatch)
DEFINE_INLINE_ARRAY (GskGLCommandBinds, gsk_gl_command_binds, GskGLCommandBind)
DEFINE_INLINE_ARRAY (GskGLCommandUniforms, gsk_gl_command_uniforms, GskGLCommandUniform)
+DEFINE_INLINE_ARRAY (GskGLSyncs, gsk_gl_syncs, GskGLSync)
struct _GskGLCommandQueue
{
@@ -233,6 +239,10 @@ struct _GskGLCommandQueue
*/
GLuint samplers[GSK_GL_N_FILTERS * GSK_GL_N_FILTERS];
+ /* Array of sync objects to wait on.
+ */
+ GskGLSyncs syncs;
+
/* Discovered max texture size when loading the command queue so that we
* can either scale down or slice textures to fit within this size. Assumed
* to be both height and width.
@@ -371,5 +381,36 @@ gsk_gl_command_queue_bind_framebuffer (GskGLCommandQueue *self,
return ret;
}
+static inline GskGLSync *
+gsk_gl_syncs_get_sync (GskGLSyncs *syncs,
+ guint id)
+{
+ for (unsigned int i = 0; i < syncs->len; i++)
+ {
+ GskGLSync *sync = &syncs->items[i];
+ if (sync->id == id)
+ return sync;
+ }
+ return NULL;
+}
+
+static inline void
+gsk_gl_syncs_add_sync (GskGLSyncs *syncs,
+ guint id,
+ gpointer sync)
+{
+ GskGLSync *s;
+
+ s = gsk_gl_syncs_get_sync (syncs, id);
+ if (s)
+ g_assert (s->sync == sync);
+ else
+ {
+ s = gsk_gl_syncs_append (syncs);
+ s->id = id;
+ s->sync = sync;
+ }
+}
+
G_END_DECLS
diff --git a/gsk/gl/gskgldriver.c b/gsk/gl/gskgldriver.c
index 672f44a5ee..d0af5e76da 100644
--- a/gsk/gl/gskgldriver.c
+++ b/gsk/gl/gskgldriver.c
@@ -1126,14 +1126,20 @@ write_atlas_to_png (GskGLDriver *driver,
GskGLTextureAtlas *atlas,
const char *filename)
{
+ GdkGLTextureBuilder *builder;
GdkTexture *texture;
- texture = gdk_gl_texture_new (gsk_gl_driver_get_context (driver),
- atlas->texture_id,
- atlas->width, atlas->height,
- NULL, NULL);
+ builder = gdk_gl_texture_builder_new ();
+ gdk_gl_texture_builder_set_context (builder, gsk_gl_driver_get_context (driver));
+ gdk_gl_texture_builder_set_id (builder, atlas->texture_id);
+ gdk_gl_texture_builder_set_width (builder, atlas->width);
+ gdk_gl_texture_builder_set_height (builder, atlas->height);
+
+ texture = gdk_gl_texture_builder_build (builder, NULL, NULL);
gdk_texture_save_to_png (texture, filename);
+
g_object_unref (texture);
+ g_object_unref (builder);
}
void
@@ -1557,6 +1563,7 @@ typedef struct _GskGLTextureState
{
GdkGLContext *context;
GLuint texture_id;
+ GLsync sync;
} GskGLTextureState;
static void
@@ -1569,6 +1576,8 @@ create_texture_from_texture_destroy (gpointer data)
gdk_gl_context_make_current (state->context);
glDeleteTextures (1, &state->texture_id);
+ if (state->sync)
+ glDeleteSync (state->sync);
g_clear_object (&state->context);
g_free (state);
}
@@ -1578,8 +1587,9 @@ gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
guint texture_id)
{
GskGLTextureState *state;
+ GdkGLTextureBuilder *builder;
GskGLTexture *texture;
- int width, height;
+ GdkTexture *result;
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), NULL);
g_return_val_if_fail (self->command_queue != NULL, NULL);
@@ -1594,19 +1604,25 @@ gsk_gl_driver_create_gdk_texture (GskGLDriver *self,
state = g_new0 (GskGLTextureState, 1);
state->texture_id = texture_id;
state->context = g_object_ref (self->command_queue->context);
+ if (gdk_gl_context_has_sync (self->command_queue->context))
+ state->sync = glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
g_hash_table_steal (self->textures, GUINT_TO_POINTER (texture_id));
- width = texture->width;
- height = texture->height;
+ builder = gdk_gl_texture_builder_new ();
+ gdk_gl_texture_builder_set_context (builder, self->command_queue->context);
+ gdk_gl_texture_builder_set_id (builder, texture_id);
+ gdk_gl_texture_builder_set_width (builder, texture->width);
+ gdk_gl_texture_builder_set_height (builder, texture->height);
+ gdk_gl_texture_builder_set_sync (builder, state->sync);
+
+ result = gdk_gl_texture_builder_build (builder,
+ create_texture_from_texture_destroy,
+ state);
texture->texture_id = 0;
gsk_gl_texture_free (texture);
+ g_object_unref (builder);
- return gdk_gl_texture_new (self->command_queue->context,
- texture_id,
- width,
- height,
- create_texture_from_texture_destroy,
- state);
+ return result;
}
diff --git a/gsk/gl/gskglprogramprivate.h b/gsk/gl/gskglprogramprivate.h
index 50c191eb4b..6bfbe48f02 100644
--- a/gsk/gl/gskglprogramprivate.h
+++ b/gsk/gl/gskglprogramprivate.h
@@ -286,6 +286,22 @@ gsk_gl_program_set_uniform_texture (GskGLProgram *self,
}
static inline void
+gsk_gl_program_set_uniform_texture_with_sync (GskGLProgram *self,
+ guint key,
+ guint stamp,
+ GLenum texture_target,
+ GLenum texture_slot,
+ guint texture_id,
+ GLint min_filter,
+ GLint max_filter,
+ gpointer sync)
+{
+ gsk_gl_program_set_uniform_texture_with_filter (self, key, stamp, texture_target, texture_slot, texture_id,
+ min_filter, max_filter);
+ gsk_gl_syncs_add_sync (&self->driver->command_queue->syncs, texture_id, sync);
+}
+
+static inline void
gsk_gl_program_set_uniform_matrix (GskGLProgram *self,
guint key,
guint stamp,
diff --git a/gsk/gl/gskglrenderjob.c b/gsk/gl/gskglrenderjob.c
index 1eb82e80da..051619528c 100644
--- a/gsk/gl/gskglrenderjob.c
+++ b/gsk/gl/gskglrenderjob.c
@@ -191,6 +191,7 @@ typedef struct _GskGLRenderOffscreen
/* Return location for texture ID */
guint texture_id;
+ gpointer sync;
/* Whether to force creating a new texture, even if the
* input already is a texture
@@ -3570,6 +3571,9 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
offscreen->texture_id = gsk_gl_driver_load_texture (job->driver, texture, ensure_mipmap);
init_full_texture_region (offscreen);
offscreen->has_mipmap = ensure_mipmap;
+
+ if (gl_texture && offscreen->texture_id == gdk_gl_texture_get_id (gl_texture))
+ offscreen->sync = gdk_gl_texture_get_sync (gl_texture);
}
}
@@ -3597,13 +3601,15 @@ gsk_gl_render_job_visit_texture (GskGLRenderJob *job,
g_assert (offscreen.was_offscreen == FALSE);
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
- gsk_gl_program_set_uniform_texture_with_filter (job->current_program,
- UNIFORM_SHARED_SOURCE, 0,
- GL_TEXTURE_2D,
- GL_TEXTURE0,
- offscreen.texture_id,
- offscreen.has_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR,
- GL_LINEAR);
+
+ gsk_gl_program_set_uniform_texture_with_sync (job->current_program,
+ UNIFORM_SHARED_SOURCE, 0,
+ GL_TEXTURE_2D,
+ GL_TEXTURE0,
+ offscreen.texture_id,
+ offscreen.has_mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR,
+ GL_LINEAR,
+ offscreen.sync);
gsk_gl_render_job_draw_offscreen (job, bounds, &offscreen);
gsk_gl_render_job_end_draw (job);
}
@@ -3733,21 +3739,29 @@ gsk_gl_render_job_visit_texture_scale_node (GskGLRenderJob *job,
if G_LIKELY (texture->width <= max_texture_size &&
texture->height <= max_texture_size)
{
+ gpointer sync;
+
texture_id = gsk_gl_driver_load_texture (job->driver, texture, filter == GSK_SCALING_FILTER_TRILINEAR);
+ if (GDK_IS_GL_TEXTURE (texture) && texture_id == gdk_gl_texture_get_id (GDK_GL_TEXTURE (texture)))
+ sync = gdk_gl_texture_get_sync (GDK_GL_TEXTURE (texture));
+ else
+ sync = NULL;
+
u0 = (clip_rect.origin.x - bounds->origin.x) / bounds->size.width;
v0 = (clip_rect.origin.y - bounds->origin.y) / bounds->size.height;
u1 = (clip_rect.origin.x + clip_rect.size.width - bounds->origin.x) / bounds->size.width;
v1 = (clip_rect.origin.y + clip_rect.size.height - bounds->origin.y) / bounds->size.height;
gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, blit));
- gsk_gl_program_set_uniform_texture_with_filter (job->current_program,
- UNIFORM_SHARED_SOURCE, 0,
- GL_TEXTURE_2D,
- GL_TEXTURE0,
- texture_id,
- min_filter,
- mag_filter);
+ gsk_gl_program_set_uniform_texture_with_sync (job->current_program,
+ UNIFORM_SHARED_SOURCE, 0,
+ GL_TEXTURE_2D,
+ GL_TEXTURE0,
+ texture_id,
+ min_filter,
+ mag_filter,
+ sync);
gsk_gl_render_job_draw_coords (job,
0, 0, clip_rect.size.width, clip_rect.size.height,
u0, v0, u1, v1,