[gtk+] gsk: Move resource handling inside GskGLDriver



commit 24a6f3c055e749bc077093c7fd90ce357695dd52
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Wed Jul 20 17:55:35 2016 +0100

    gsk: Move resource handling inside GskGLDriver
    
    We want the GL driver to cache as many resources as possible, so we can
    always ensure that we're in a consistent state, and we can handle state
    transitions more appropriately.

 gsk/gskgldriver.c        |  267 ++++++++++++++++++++++++++++++++++------------
 gsk/gskgldriverprivate.h |   13 ++-
 gsk/gskglrenderer.c      |  120 +++++++++------------
 gsk/gskshaderbuilder.c   |    6 +-
 4 files changed, 262 insertions(+), 144 deletions(-)
---
diff --git a/gsk/gskgldriver.c b/gsk/gskgldriver.c
index 634cb54..52d8631 100644
--- a/gsk/gskgldriver.c
+++ b/gsk/gskgldriver.c
@@ -23,21 +23,26 @@ typedef struct {
   GLuint uv_id;
 } Vao;
 
+typedef struct {
+  GLuint fbo_id;
+  GLuint depth_stencil_id;
+} Fbo;
+
 struct _GskGLDriver
 {
   GObject parent_instance;
 
   GdkGLContext *gl_context;
 
-  GLuint default_fbo;
+  Fbo default_fbo;
 
   GHashTable *textures;
-  GArray *vaos;
+  GHashTable *vaos;
 
   Texture *bound_source_texture;
   Texture *bound_mask_texture;
   Vao *bound_vao;
-  GLuint bound_fbo;
+  Fbo *bound_fbo;
 
   gboolean in_frame : 1;
 };
@@ -72,18 +77,28 @@ texture_free (gpointer data)
 static void
 fbo_clear (gpointer data)
 {
-  GLuint fbo_id = GPOINTER_TO_UINT (data);
+  Fbo *f = data;
+
+  if (f->depth_stencil_id != 0)
+    glDeleteRenderbuffers (1, &f->depth_stencil_id);
+
+  glDeleteFramebuffers (1, &f->fbo_id);
+}
 
-  glDeleteFramebuffers (1, &fbo_id);
+static Vao *
+vao_new (void)
+{
+  return g_slice_new0 (Vao);
 }
 
 static void
-vao_clear (gpointer data)
+vao_free (gpointer data)
 {
   Vao *v = data;
 
   glDeleteBuffers (1, &v->buffer_id);
   glDeleteVertexArrays (1, &v->vao_id);
+  g_slice_free (Vao, v);
 }
 
 static void
@@ -92,7 +107,7 @@ gsk_gl_driver_finalize (GObject *gobject)
   GskGLDriver *self = GSK_GL_DRIVER (gobject);
 
   g_clear_pointer (&self->textures, g_hash_table_unref);
-  g_clear_pointer (&self->vaos, g_array_unref);
+  g_clear_pointer (&self->vaos, g_hash_table_unref);
 
   g_clear_object (&self->gl_context);
 
@@ -158,9 +173,7 @@ static void
 gsk_gl_driver_init (GskGLDriver *self)
 {
   self->textures = g_hash_table_new_full (NULL, NULL, NULL, texture_free);
-
-  self->vaos = g_array_new (FALSE, FALSE, sizeof (Vao));
-  g_array_set_clear_func (self->vaos, vao_clear);
+  self->vaos = g_hash_table_new_full (NULL, NULL, NULL, vao_free);
 }
 
 GskGLDriver *
@@ -181,8 +194,8 @@ 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;
+  glGetIntegerv (GL_FRAMEBUFFER_BINDING, (GLint *) &(driver->default_fbo.fbo_id));
+  driver->bound_fbo = &driver->default_fbo;
 
   glActiveTexture (GL_TEXTURE0);
   glBindTexture (GL_TEXTURE_2D, 0);
@@ -209,10 +222,12 @@ 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;
+  driver->bound_fbo = NULL;
 
-  g_hash_table_remove_all (driver->textures);
-  g_array_set_size (driver->vaos, 0);
+  GSK_NOTE (OPENGL,
+            g_print ("*** Frame end: textures=%d, vaos=%d\n",
+                     g_hash_table_size (driver->textures),
+                     g_hash_table_size (driver->vaos)));
 
   driver->in_frame = FALSE;
 }
@@ -221,29 +236,42 @@ static Texture *
 gsk_gl_driver_get_texture (GskGLDriver *driver,
                            int          texture_id)
 {
-  return g_hash_table_lookup (driver->textures, GINT_TO_POINTER (texture_id));
+  Texture *t;
+
+  if (g_hash_table_lookup_extended (driver->textures, GINT_TO_POINTER (texture_id), NULL, (gpointer *) &t))
+    return t;
+
+  return NULL;
 }
 
 static Vao *
 gsk_gl_driver_get_vao (GskGLDriver *driver,
                        int          vao_id)
 {
-  int i;
+  Vao *v;
 
-  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;
-    }
+  if (g_hash_table_lookup_extended (driver->vaos, GINT_TO_POINTER (vao_id), NULL, (gpointer *) &v))
+    return v;
 
   return NULL;
 }
 
+static Fbo *
+gsk_gl_driver_get_fbo (GskGLDriver *driver,
+                       int          texture_id)
+{
+  Texture *t = gsk_gl_driver_get_texture (driver, texture_id);
+
+  if (t->fbos == NULL)
+    return &driver->default_fbo;
+
+  return &g_array_index (t->fbos, Fbo, 0);
+}
+
 int
-gsk_gl_driver_create_texture (GskGLDriver     *driver,
-                              int              width,
-                              int              height)
+gsk_gl_driver_create_texture (GskGLDriver *driver,
+                              int          width,
+                              int          height)
 {
   guint texture_id;
   Texture *t;
@@ -251,12 +279,6 @@ gsk_gl_driver_create_texture (GskGLDriver     *driver,
   g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
 
   glGenTextures (1, &texture_id);
-  glBindTexture (GL_TEXTURE_2D, texture_id);
-
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
   t = texture_new ();
   t->texture_id = texture_id;
@@ -264,9 +286,9 @@ gsk_gl_driver_create_texture (GskGLDriver     *driver,
   t->height = height;
   t->min_filter = GL_NEAREST;
   t->mag_filter = GL_NEAREST;
-  g_hash_table_insert (driver->textures, GUINT_TO_POINTER (texture_id), t);
+  g_hash_table_insert (driver->textures, GINT_TO_POINTER (texture_id), t);
 
-  return texture_id;
+  return t->texture_id;
 }
 
 int
@@ -278,9 +300,10 @@ gsk_gl_driver_create_vao_for_quad (GskGLDriver   *driver,
 
 {
   GLuint vao_id, buffer_id;
-  Vao v;
+  Vao *v;
 
   g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
+  g_return_val_if_fail (driver->in_frame, -1);
 
   glGenVertexArrays (1, &vao_id);
   glBindVertexArray (vao_id);
@@ -302,23 +325,28 @@ gsk_gl_driver_create_vao_for_quad (GskGLDriver   *driver,
   glBindBuffer (GL_ARRAY_BUFFER, 0);
   glBindVertexArray (0);
 
-  v.vao_id = vao_id;
-  v.buffer_id =  buffer_id;
-  v.position_id = position_id;
-  v.uv_id = uv_id;
-  g_array_append_val (driver->vaos, v);
+  v = vao_new ();
+  v->vao_id = vao_id;
+  v->buffer_id =  buffer_id;
+  v->position_id = position_id;
+  v->uv_id = uv_id;
+  g_hash_table_insert (driver->vaos, GINT_TO_POINTER (vao_id), v);
 
   return vao_id;
 }
 
 int
 gsk_gl_driver_create_render_target (GskGLDriver *driver,
-                                    int          texture_id)
+                                    int          texture_id,
+                                    gboolean     add_depth_buffer,
+                                    gboolean     add_stencil_buffer)
 {
+  GLuint fbo_id, depth_stencil_buffer_id;
   Texture *t;
-  GLuint fbo_id;
+  Fbo f;
 
   g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
+  g_return_val_if_fail (driver->in_frame, -1);
 
   t = gsk_gl_driver_get_texture (driver, texture_id);
   if (t == NULL)
@@ -326,7 +354,7 @@ gsk_gl_driver_create_render_target (GskGLDriver *driver,
 
   if (t->fbos == NULL)
     {
-      t->fbos = g_array_new (FALSE, FALSE, sizeof (GLuint));
+      t->fbos = g_array_new (FALSE, FALSE, sizeof (Fbo));
       g_array_set_clear_func (t->fbos, fbo_clear);
     }
 
@@ -334,9 +362,35 @@ gsk_gl_driver_create_render_target (GskGLDriver *driver,
   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);
+  if (add_depth_buffer || add_stencil_buffer)
+    glGenRenderbuffersEXT (1, &depth_stencil_buffer_id);
+  else
+    depth_stencil_buffer_id = 0;
+
+  glBindRenderbuffer (GL_RENDERBUFFER, depth_stencil_buffer_id);
+
+  if (add_depth_buffer || add_stencil_buffer)
+    {
+      if (add_stencil_buffer)
+        glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, t->width, t->height);
+      else
+        glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, t->width, t->height);
+
+      if (add_depth_buffer)
+        glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                                   GL_RENDERBUFFER, depth_stencil_buffer_id);
+
+      if (add_stencil_buffer)
+        glFramebufferRenderbufferEXT (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                      GL_RENDERBUFFER, depth_stencil_buffer_id);
+    }
+
+  f.fbo_id = fbo_id;
+  f.depth_stencil_id = depth_stencil_buffer_id;
 
-  glBindFramebuffer (GL_FRAMEBUFFER, driver->default_fbo);
+  g_array_append_val (t->fbos, f);
+
+  glBindFramebuffer (GL_FRAMEBUFFER, driver->default_fbo.fbo_id);
 
   return fbo_id;
 }
@@ -352,7 +406,10 @@ gsk_gl_driver_bind_source_texture (GskGLDriver *driver,
 
   t = gsk_gl_driver_get_texture (driver, texture_id);
   if (t == NULL)
-    return;
+    {
+      g_critical ("No texture %d found.", texture_id);
+      return;
+    }
 
   if (driver->bound_source_texture != t)
     {
@@ -374,7 +431,10 @@ gsk_gl_driver_bind_mask_texture (GskGLDriver *driver,
 
   t = gsk_gl_driver_get_texture (driver, texture_id);
   if (t == NULL)
-    return;
+    {
+      g_critical ("No texture %d found.", texture_id);
+      return;
+    }
 
   if (driver->bound_mask_texture != t)
     {
@@ -398,7 +458,10 @@ gsk_gl_driver_bind_vao (GskGLDriver *driver,
 
   v = gsk_gl_driver_get_vao (driver, vao_id);
   if (v == NULL)
-    return;
+    {
+      g_critical ("No VAO %d found.", vao_id);
+      return;
+    }
 
   if (driver->bound_vao != v)
     {
@@ -411,31 +474,94 @@ gsk_gl_driver_bind_vao (GskGLDriver *driver,
     }
 }
 
-void
+gboolean
 gsk_gl_driver_bind_render_target (GskGLDriver *driver,
                                   int          texture_id)
 {
-  GLuint fbo_id;
+  int status;
+  Fbo *f;
+
+  g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), FALSE);
+  g_return_val_if_fail (driver->in_frame, FALSE);
+
+  f = gsk_gl_driver_get_fbo (driver, texture_id);
+  if (f == NULL)
+    {
+      g_critical ("No render target associated to texture %d found.", texture_id);
+      return FALSE;
+    }
+
+  if (f != driver->bound_fbo)
+    {
+      glBindFramebuffer (GL_FRAMEBUFFER, f->fbo_id);
+
+      driver->bound_fbo = f;
+    }
+
+  status = glCheckFramebufferStatus (GL_FRAMEBUFFER);
+
+  return status == GL_FRAMEBUFFER_COMPLETE;
+}
+
+void
+gsk_gl_driver_destroy_texture (GskGLDriver *driver,
+                               int          texture_id)
+{
+  g_return_if_fail (GSK_IS_GL_DRIVER (driver));
+
+  g_hash_table_remove (driver->textures, GINT_TO_POINTER (texture_id));
+}
+
+void
+gsk_gl_driver_destroy_vao (GskGLDriver *driver,
+                           int          vao_id)
+{
+  g_return_if_fail (GSK_IS_GL_DRIVER (driver));
+
+  g_hash_table_remove (driver->vaos, GINT_TO_POINTER (vao_id));
+}
+
+static void
+gsk_gl_driver_set_texture_parameters (GskGLDriver *driver,
+                                      int          min_filter,
+                                      int          mag_filter)
+{
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
+
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+void
+gsk_gl_driver_init_texture_empty (GskGLDriver *driver,
+                                  int          texture_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);
+      g_critical ("No texture %d found.", texture_id);
+      return;
+    }
 
-      driver->bound_fbo = fbo_id;
+  if (!(driver->bound_source_texture == t || driver->bound_mask_texture == t))
+    {
+      g_critical ("You must bind the texture before initializing it.");
+      return;
     }
+
+  gsk_gl_driver_set_texture_parameters (driver, t->min_filter, t->mag_filter);
+
+  if (gdk_gl_context_get_use_es (driver->gl_context))
+    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, t->width, t->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+  else
+    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, t->width, t->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+  glBindTexture (GL_TEXTURE_2D, 0);
 }
 
 void
@@ -451,15 +577,18 @@ gsk_gl_driver_init_texture_with_surface (GskGLDriver     *driver,
 
   t = gsk_gl_driver_get_texture (driver, texture_id);
   if (t == NULL)
-    return;
-
-  glBindTexture (GL_TEXTURE_2D, t->texture_id);
+    {
+      g_critical ("No texture %d found.", texture_id);
+      return;
+    }
 
-  if (min_filter != t->min_filter)
-    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
+  if (!(driver->bound_source_texture == t || driver->bound_mask_texture == t))
+    {
+      g_critical ("You must bind the texture before initializing it.");
+      return;
+    }
 
-  if (mag_filter != t->mag_filter)
-    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
+  gsk_gl_driver_set_texture_parameters (driver, min_filter, mag_filter);
 
   gdk_cairo_surface_upload_to_gl (surface, GL_TEXTURE_2D, t->width, t->height, NULL);
 
@@ -468,4 +597,6 @@ gsk_gl_driver_init_texture_with_surface (GskGLDriver     *driver,
 
   if (t->min_filter != GL_NEAREST)
     glGenerateMipmap (GL_TEXTURE_2D);
+
+  glBindTexture (GL_TEXTURE_2D, 0);
 }
diff --git a/gsk/gskgldriverprivate.h b/gsk/gskgldriverprivate.h
index 27d7966..30eaffa 100644
--- a/gsk/gskgldriverprivate.h
+++ b/gsk/gskgldriverprivate.h
@@ -30,7 +30,9 @@ int             gsk_gl_driver_create_vao_for_quad       (GskGLDriver     *driver
                                                          int              n_vertices,
                                                          GskQuadVertex   *vertices);
 int             gsk_gl_driver_create_render_target      (GskGLDriver     *driver,
-                                                         int              texture_id);
+                                                         int              texture_id,
+                                                         gboolean         add_depth_buffer,
+                                                         gboolean         add_stencil_buffer);
 
 void            gsk_gl_driver_bind_source_texture       (GskGLDriver     *driver,
                                                          int              texture_id);
@@ -38,13 +40,22 @@ void            gsk_gl_driver_bind_mask_texture         (GskGLDriver     *driver
                                                          int              texture_id);
 void            gsk_gl_driver_bind_vao                  (GskGLDriver     *driver,
                                                          int              vao_id);
+gboolean        gsk_gl_driver_bind_render_target        (GskGLDriver     *driver,
+                                                         int              texture_id);
 
+void            gsk_gl_driver_init_texture_empty        (GskGLDriver     *driver,
+                                                         int              texture_id);
 void            gsk_gl_driver_init_texture_with_surface (GskGLDriver     *driver,
                                                          int              texture_id,
                                                          cairo_surface_t *surface,
                                                          int              min_filter,
                                                          int              mag_filter);
 
+void            gsk_gl_driver_destroy_texture           (GskGLDriver     *driver,
+                                                         int              texture_id);
+void            gsk_gl_driver_destroy_vao               (GskGLDriver     *driver,
+                                                         int              vao_id);
+
 G_END_DECLS
 
 #endif /* __GSK_GL_DRIVER_PRIVATE_H__ */
diff --git a/gsk/gskglrenderer.c b/gsk/gskglrenderer.c
index 15f32fb..ac156ca 100644
--- a/gsk/gskglrenderer.c
+++ b/gsk/gskglrenderer.c
@@ -20,18 +20,18 @@
 #define SHADER_VERSION_GL3              150
 
 typedef struct {
-  guint vao_id;
-  guint buffer_id;
-  guint texture_id;
-  guint program_id;
-
-  guint mvp_location;
-  guint map_location;
-  guint parentMap_location;
-  guint uv_location;
-  guint position_location;
-  guint alpha_location;
-  guint blendMode_location;
+  int vao_id;
+  int buffer_id;
+  int texture_id;
+  int program_id;
+
+  int mvp_location;
+  int map_location;
+  int parentMap_location;
+  int uv_location;
+  int position_location;
+  int alpha_location;
+  int blendMode_location;
 } RenderData;
 
 typedef struct {
@@ -131,54 +131,19 @@ gsk_gl_renderer_create_buffers (GskGLRenderer *self,
 
   GSK_NOTE (OPENGL, g_print ("Creating buffers\n"));
 
-  glGenFramebuffersEXT (1, &self->frame_buffer);
-
   if (self->texture_id == 0)
     {
-      glGenTextures (1, &self->texture_id);
-
-      glBindTexture (GL_TEXTURE_2D, self->texture_id);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-      if (gdk_gl_context_get_use_es (self->context))
-        glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-      else
-        glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+      self->texture_id = gsk_gl_driver_create_texture (self->gl_driver, width, height);
+      gsk_gl_driver_bind_source_texture (self->gl_driver, self->texture_id);
+      gsk_gl_driver_init_texture_empty (self->gl_driver, self->texture_id);
     }
 
-  if (self->depth_stencil_buffer == 0)
-    glGenRenderbuffersEXT (1, &self->depth_stencil_buffer);
-
-  glBindRenderbuffer (GL_RENDERBUFFER, self->depth_stencil_buffer);
-  glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
+  gsk_gl_driver_create_render_target (self->gl_driver, self->texture_id, TRUE, TRUE);
 
   self->has_buffers = TRUE;
 }
 
 static void
-gsk_gl_renderer_attach_buffers (GskGLRenderer *self)
-{
-  GSK_NOTE (OPENGL, g_print ("Attaching buffers\n"));
-
-  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, self->frame_buffer);
-
-  if (self->texture_id != 0)
-    {
-      glFramebufferTexture2D (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-                              GL_TEXTURE_2D, self->texture_id, 0);
-    }
-
-  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
-                                GL_RENDERBUFFER_EXT, self->depth_stencil_buffer);
-
-  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
-                                GL_RENDERBUFFER_EXT, self->depth_stencil_buffer);
-}
-
-static void
 gsk_gl_renderer_destroy_buffers (GskGLRenderer *self)
 {
   if (self->context == NULL)
@@ -191,25 +156,12 @@ gsk_gl_renderer_destroy_buffers (GskGLRenderer *self)
 
   gdk_gl_context_make_current (self->context);
 
-  if (self->depth_stencil_buffer != 0)
-    {
-      glDeleteRenderbuffersEXT (1, &self->depth_stencil_buffer);
-      self->depth_stencil_buffer = 0;
-    }
-
   if (self->texture_id != 0)
     {
-      glDeleteTextures (1, &self->texture_id);
+      gsk_gl_driver_destroy_texture (self->gl_driver, self->texture_id);
       self->texture_id = 0;
     }
 
-  if (self->frame_buffer != 0)
-    {
-      glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
-      glDeleteFramebuffersEXT (1, &self->frame_buffer);
-      self->frame_buffer = 0;
-    }
-
   self->has_buffers = FALSE;
 }
 
@@ -355,6 +307,9 @@ gsk_gl_renderer_unrealize (GskRenderer *renderer)
 
   gdk_gl_context_make_current (self->context);
 
+  /* We don't need to iterate to destroy the associated GL resources,
+   * as they will be dropped when we finalize the GskGLDriver
+   */
   g_clear_pointer (&self->opaque_render_items, g_array_unref);
   g_clear_pointer (&self->transparent_render_items, g_array_unref);
 
@@ -633,6 +588,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
   item.render_data.texture_id = gsk_gl_driver_create_texture (self->gl_driver,
                                                               bounds.size.width,
                                                               bounds.size.height);
+  gsk_gl_driver_bind_source_texture (self->gl_driver, item.render_data.texture_id);
   gsk_gl_driver_init_texture_with_surface (self->gl_driver,
                                            item.render_data.texture_id,
                                            surface,
@@ -682,6 +638,8 @@ gsk_gl_renderer_validate_tree (GskGLRenderer *self,
   self->opaque_render_items = g_array_sized_new (FALSE, FALSE, sizeof (RenderItem), n_nodes);
   self->transparent_render_items = g_array_sized_new (FALSE, FALSE, sizeof (RenderItem), n_nodes);
 
+  gsk_gl_driver_begin_frame (self->gl_driver);
+
   GSK_NOTE (OPENGL, g_print ("RenderNode -> RenderItem\n"));
   gsk_gl_renderer_add_render_item (self, root, NULL);
 
@@ -691,15 +649,37 @@ gsk_gl_renderer_validate_tree (GskGLRenderer *self,
                              self->opaque_render_items->len,
                              self->transparent_render_items->len));
 
+  gsk_gl_driver_end_frame (self->gl_driver);
+
   return TRUE;
 }
 
 static void
 gsk_gl_renderer_clear_tree (GskGLRenderer *self)
 {
+  int i;
+
   if (self->context == NULL)
     return;
 
+  gdk_gl_context_make_current (self->context);
+
+  for (i = 0; i < self->opaque_render_items->len; i++)
+    {
+      RenderItem *item = &g_array_index (self->opaque_render_items, RenderItem, i);
+
+      gsk_gl_driver_destroy_texture (self->gl_driver, item->render_data.texture_id);
+      gsk_gl_driver_destroy_vao (self->gl_driver, item->render_data.vao_id);
+    }
+
+  for (i = 0; i < self->transparent_render_items->len; i++)
+    {
+      RenderItem *item = &g_array_index (self->transparent_render_items, RenderItem, i);
+
+      gsk_gl_driver_destroy_texture (self->gl_driver, item->render_data.texture_id);
+      gsk_gl_driver_destroy_vao (self->gl_driver, item->render_data.vao_id);
+    }
+
   g_clear_pointer (&self->opaque_render_items, g_array_unref);
   g_clear_pointer (&self->transparent_render_items, g_array_unref);
 }
@@ -720,7 +700,6 @@ gsk_gl_renderer_render (GskRenderer *renderer,
   GskGLRenderer *self = GSK_GL_RENDERER (renderer);
   graphene_matrix_t modelview, projection;
   graphene_rect_t viewport;
-  int status;
   guint i;
   guint64 gpu_time;
 
@@ -731,8 +710,9 @@ gsk_gl_renderer_render (GskRenderer *renderer,
 
   gsk_renderer_get_viewport (renderer, &viewport);
 
+  gsk_gl_driver_begin_frame (self->gl_driver);
   gsk_gl_renderer_create_buffers (self, viewport.size.width, viewport.size.height);
-  gsk_gl_renderer_attach_buffers (self);
+  gsk_gl_driver_end_frame (self->gl_driver);
 
   gsk_renderer_get_modelview (renderer, &modelview);
   gsk_renderer_get_projection (renderer, &projection);
@@ -744,13 +724,11 @@ gsk_gl_renderer_render (GskRenderer *renderer,
   if (!gsk_gl_renderer_validate_tree (self, root))
     goto out;
 
-  gsk_gl_profiler_begin_gpu_region (self->gl_profiler);
-
   gsk_gl_driver_begin_frame (self->gl_driver);
+  gsk_gl_profiler_begin_gpu_region (self->gl_profiler);
 
   /* Ensure that the viewport is up to date */
-  status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
-  if (status == GL_FRAMEBUFFER_COMPLETE_EXT)
+  if (gsk_gl_driver_bind_render_target (self->gl_driver, self->texture_id))
     gsk_gl_renderer_resize_viewport (self, &viewport);
 
   gsk_gl_renderer_clear (self);
diff --git a/gsk/gskshaderbuilder.c b/gsk/gskshaderbuilder.c
index c37a203..f5a66a9 100644
--- a/gsk/gskshaderbuilder.c
+++ b/gsk/gskshaderbuilder.c
@@ -449,8 +449,7 @@ gsk_shader_builder_get_uniform_location (GskShaderBuilder *builder,
   if (builder->uniforms->len == 0)
     return -1;
 
-  p = g_hash_table_lookup (builder->programs, GINT_TO_POINTER (program_id));
-  if (p == NULL)
+  if (!g_hash_table_lookup_extended (builder->programs, GINT_TO_POINTER (program_id), NULL, (gpointer *) &p))
     return -1;
 
   if (g_hash_table_lookup_extended (p->uniform_locations, GINT_TO_POINTER (uniform_quark), NULL, &loc_p))
@@ -473,8 +472,7 @@ gsk_shader_builder_get_attribute_location (GskShaderBuilder *builder,
   if (builder->attributes->len == 0)
     return -1;
 
-  p = g_hash_table_lookup (builder->programs, GINT_TO_POINTER (program_id));
-  if (p == NULL)
+  if (!g_hash_table_lookup_extended (builder->programs, GINT_TO_POINTER (program_id), NULL, (gpointer *) &p))
     return -1;
 
   if (g_hash_table_lookup_extended (p->attribute_locations, GINT_TO_POINTER (attribute_quark), NULL, &loc_p))


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]