From e2a43a8701a10eccb0bef30d23c8c2329e2c2866 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 12 Jul 2016 15:41:31 +0100 Subject: [PATCH] gsk: Add GL driver API to create render targets It's going to be used by the GL renderer to safely create and bind FBOs when needed. --- gsk/gskgldriver.c | 104 +++++++++++++++++++++++++++++++++------ gsk/gskgldriverprivate.h | 2 + 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/gsk/gskgldriver.c b/gsk/gskgldriver.c index 1a2a289320..01caa00050 100644 --- a/gsk/gskgldriver.c +++ b/gsk/gskgldriver.c @@ -13,6 +13,7 @@ typedef struct { int height; GLuint min_filter; GLuint mag_filter; + GArray *fbos; } Texture; typedef struct { @@ -28,12 +29,15 @@ struct _GskGLDriver GdkGLContext *gl_context; + GLuint default_fbo; + GHashTable *textures; GArray *vaos; Texture *bound_source_texture; Texture *bound_mask_texture; Vao *bound_vao; + GLuint bound_fbo; gboolean in_frame : 1; }; @@ -60,10 +64,19 @@ texture_free (gpointer data) { Texture *t = data; + g_clear_pointer (&t->fbos, g_array_unref); glDeleteTextures (1, &t->texture_id); g_slice_free (Texture, t); } +static void +fbo_clear (gpointer data) +{ + GLuint fbo_id = GPOINTER_TO_UINT (data); + + glDeleteFramebuffers (1, &fbo_id); +} + static void vao_clear (gpointer data) { @@ -168,6 +181,9 @@ gsk_gl_driver_begin_frame (GskGLDriver *driver) driver->in_frame = TRUE; + glGetIntegerv (GL_FRAMEBUFFER_BINDING, (GLint *) &driver->default_fbo); + driver->bound_fbo = driver->default_fbo; + glActiveTexture (GL_TEXTURE0); glBindTexture (GL_TEXTURE_2D, 0); @@ -193,6 +209,7 @@ gsk_gl_driver_end_frame (GskGLDriver *driver) driver->bound_source_texture = NULL; driver->bound_mask_texture = NULL; driver->bound_vao = NULL; + driver->bound_fbo = driver->default_fbo; g_hash_table_remove_all (driver->textures); g_array_set_size (driver->vaos, 0); @@ -200,6 +217,29 @@ gsk_gl_driver_end_frame (GskGLDriver *driver) driver->in_frame = FALSE; } +static Texture * +gsk_gl_driver_get_texture (GskGLDriver *driver, + int texture_id) +{ + return g_hash_table_lookup (driver->textures, GINT_TO_POINTER (texture_id)); +} + +static Vao * +gsk_gl_driver_get_vao (GskGLDriver *driver, + int vao_id) +{ + int i; + + for (i = 0; i < driver->vaos->len; i++) + { + Vao *v = &g_array_index (driver->vaos, Vao, i); + if (v->vao_id == vao_id) + return v; + } + + return NULL; +} + int gsk_gl_driver_create_texture (GskGLDriver *driver, int width, @@ -273,27 +313,34 @@ gsk_gl_driver_create_vao_for_quad (GskGLDriver *driver, return vao_id; } -static Texture * -gsk_gl_driver_get_texture (GskGLDriver *driver, - int texture_id) +int +gsk_gl_driver_create_render_target (GskGLDriver *driver, + int texture_id) { - return g_hash_table_lookup (driver->textures, GINT_TO_POINTER (texture_id)); -} + Texture *t; + GLuint fbo_id; -static Vao * -gsk_gl_driver_get_vao (GskGLDriver *driver, - int vao_id) -{ - int i; + g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1); - for (i = 0; i < driver->vaos->len; i++) + t = gsk_gl_driver_get_texture (driver, texture_id); + if (t == NULL) + return -1; + + if (t->fbos == NULL) { - Vao *v = &g_array_index (driver->vaos, Vao, i); - if (v->vao_id == vao_id) - return v; + t->fbos = g_array_new (FALSE, FALSE, sizeof (GLuint)); + g_array_set_clear_func (t->fbos, fbo_clear); } - return NULL; + glGenFramebuffers (1, &fbo_id); + glBindFramebuffer (GL_FRAMEBUFFER, fbo_id); + glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, t->texture_id, 0); + + g_array_append_val (t->fbos, fbo_id); + + glBindFramebuffer (GL_FRAMEBUFFER, driver->default_fbo); + + return fbo_id; } void @@ -366,6 +413,33 @@ gsk_gl_driver_bind_vao (GskGLDriver *driver, } } +void +gsk_gl_driver_bind_render_target (GskGLDriver *driver, + int texture_id) +{ + GLuint fbo_id; + Texture *t; + + g_return_if_fail (GSK_IS_GL_DRIVER (driver)); + g_return_if_fail (driver->in_frame); + + t = gsk_gl_driver_get_texture (driver, texture_id); + if (t == NULL) + return; + + if (t->fbos == NULL) + fbo_id = driver->default_fbo; + else + fbo_id = g_array_index (t->fbos, GLuint, 0); + + if (fbo_id != driver->bound_fbo) + { + glBindFramebuffer (GL_FRAMEBUFFER, fbo_id); + + driver->bound_fbo = fbo_id; + } +} + void gsk_gl_driver_render_surface_to_texture (GskGLDriver *driver, cairo_surface_t *surface, diff --git a/gsk/gskgldriverprivate.h b/gsk/gskgldriverprivate.h index 9fc1d8ad3b..d5ddf46f20 100644 --- a/gsk/gskgldriverprivate.h +++ b/gsk/gskgldriverprivate.h @@ -31,6 +31,8 @@ int gsk_gl_driver_create_vao_for_quad (GskGLDriver *driver int uv_id, int n_vertices, GskQuadVertex *vertices); +int gsk_gl_driver_create_render_target (GskGLDriver *driver, + int texture_id); void gsk_gl_driver_bind_source_texture (GskGLDriver *driver, int texture_id);