[gtk+] tests/gears: Ensure we don't use unavailable GL resources



commit b274a2656d06ed7aa3e649e93988de86af048957
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Thu Jul 16 14:53:42 2015 +0100

    tests/gears: Ensure we don't use unavailable GL resources
    
    We need to check on realize if we have access to a GL context, before
    calling GL functions. We use gtk_gl_area_get_error() for that.
    
    We also need to tear down the resources during unrealization, instead
    of leaking them.

 tests/gtkgears.c |  122 ++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 87 insertions(+), 35 deletions(-)
---
diff --git a/tests/gtkgears.c b/tests/gtkgears.c
index 7a28071..a8e4fed 100644
--- a/tests/gtkgears.c
+++ b/tests/gtkgears.c
@@ -83,19 +83,26 @@ struct gear {
    struct vertex_strip *strips;
    /** The number of triangle strips comprising the gear */
    int nstrips;
-   /** The Vertex Buffer Object holding the vertices in the graphics card */
-   GLuint vbo;
 };
 
 typedef struct {
   /* The view rotation [x, y, z] */
   GLfloat view_rot[GTK_GEARS_N_AXIS];
 
+  /* The Vertex Array Object */
+  GLuint vao;
+
+  /* The shader program */
+  GLuint program;
+
   /* The gears */
   struct gear *gear1;
   struct gear *gear2;
   struct gear *gear3;
 
+  /** The Vertex Buffer Object holding the vertices in the graphics card */
+  GLuint gear_vbo[3];
+
   /** The location of the shader uniforms */
   GLuint ModelViewProjectionMatrix_location;
   GLuint NormalMatrix_location;
@@ -120,9 +127,11 @@ G_DEFINE_TYPE_WITH_PRIVATE (GtkGears, gtk_gears, GTK_TYPE_GL_AREA)
 
 static gboolean gtk_gears_render        (GtkGLArea     *area,
                                          GdkGLContext  *context);
-static void     gtk_gears_size_allocate (GtkWidget     *widget,
-                                         GtkAllocation *allocation);
+static void     gtk_gears_reshape       (GtkGLArea     *area,
+                                         int            width,
+                                         int            height);
 static void     gtk_gears_realize       (GtkWidget     *widget);
+static void     gtk_gears_unrealize     (GtkWidget     *widget);
 static gboolean gtk_gears_tick          (GtkWidget     *widget,
                                          GdkFrameClock *frame_clock,
                                          gpointer       user_data);
@@ -175,8 +184,11 @@ static void
 gtk_gears_class_init (GtkGearsClass *klass)
 {
   GTK_GL_AREA_CLASS (klass)->render = gtk_gears_render;
+  GTK_GL_AREA_CLASS (klass)->resize = gtk_gears_reshape;
+
   GTK_WIDGET_CLASS (klass)->realize = gtk_gears_realize;
-  GTK_WIDGET_CLASS (klass)->size_allocate = gtk_gears_size_allocate;
+  GTK_WIDGET_CLASS (klass)->unrealize = gtk_gears_unrealize;
+
   G_OBJECT_CLASS (klass)->finalize = gtk_gears_finalize;
 }
 
@@ -211,7 +223,7 @@ vert (GearVertex *v,
 static void
 destroy_gear (struct gear *g)
 {
-  g_clear_pointer (&g->strips, g_free);
+  g_free (g->strips);
   g_free (g);
 }
 
@@ -358,14 +370,6 @@ create_gear (GLfloat inner_radius,
 
   gear->nvertices = (v - gear->vertices);
 
-  /* Store the vertices in a vertex buffer object (VBO) */
-  glGenBuffers (1, &gear->vbo);
-  glBindBuffer (GL_ARRAY_BUFFER, gear->vbo);
-  glBufferData (GL_ARRAY_BUFFER,
-                gear->nvertices * sizeof(GearVertex),
-                gear->vertices,
-                GL_STATIC_DRAW);
-
   return gear;
 }
 
@@ -546,6 +550,7 @@ void perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloa
 static void
 draw_gear(GtkGears *self,
           struct gear *gear,
+          GLuint gear_vbo,
           GLfloat *transform,
           GLfloat x,
           GLfloat y,
@@ -583,7 +588,7 @@ draw_gear(GtkGears *self,
   glUniform4fv(priv->MaterialColor_location, 1, color);
 
   /* Set the vertex buffer object to use */
-  glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
+  glBindBuffer(GL_ARRAY_BUFFER, gear_vbo);
 
   /* Set up the position of the attributes in the vertex buffer object */
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), NULL);
@@ -605,9 +610,9 @@ draw_gear(GtkGears *self,
 
 /* new window size or exposure */
 static void
-reshape(GtkGears *gears, int width, int height)
+gtk_gears_reshape (GtkGLArea *area, int width, int height)
 {
-  GtkGearsPrivate *priv = gtk_gears_get_instance_private (gears);
+  GtkGearsPrivate *priv = gtk_gears_get_instance_private ((GtkGears *) area);
 
   /* Update the projection matrix */
   perspective (priv->ProjectionMatrix, 60.0, width / (float)height, 1.0, 1024.0);
@@ -640,28 +645,13 @@ gtk_gears_render (GtkGLArea    *area,
   rotate (transform, 2 * G_PI * priv->view_rot[2] / 360.0, 0, 0, 1);
 
   /* Draw the gears */
-  draw_gear (self, priv->gear1, transform, -3.0, -2.0,      priv->angle,        red);
-  draw_gear (self, priv->gear2, transform,  3.1, -2.0, -2 * priv->angle - 9.0,  green);
-  draw_gear (self, priv->gear3, transform, -3.1,  4.2, -2 * priv->angle - 25.0, blue);
+  draw_gear (self, priv->gear1, priv->gear_vbo[0], transform, -3.0, -2.0,      priv->angle,        red);
+  draw_gear (self, priv->gear2, priv->gear_vbo[1], transform,  3.1, -2.0, -2 * priv->angle - 9.0,  green);
+  draw_gear (self, priv->gear3, priv->gear_vbo[2], transform, -3.1,  4.2, -2 * priv->angle - 25.0, blue);
 
   return TRUE;
 }
 
-static void
-gtk_gears_size_allocate (GtkWidget     *widget,
-                         GtkAllocation *allocation)
-{
-  GtkGLArea *glarea = GTK_GL_AREA (widget);
-
-  GTK_WIDGET_CLASS (gtk_gears_parent_class)->size_allocate (widget, allocation);
-
-  if (gtk_widget_get_realized (widget))
-    {
-      gtk_gl_area_make_current (glarea);
-      reshape ((GtkGears *) glarea, allocation->width, allocation->height);
-    }
-}
-
 static const char vertex_shader[] =
 "#version 150\n"
 "\n"
@@ -715,6 +705,8 @@ gtk_gears_realize (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_gears_parent_class)->realize (widget);
 
   gtk_gl_area_make_current (glarea);
+  if (gtk_gl_area_get_error (glarea) != NULL)
+    return;
 
   glEnable (GL_CULL_FACE);
   glEnable (GL_DEPTH_TEST);
@@ -722,6 +714,7 @@ gtk_gears_realize (GtkWidget *widget)
   /* Create the VAO */
   glGenVertexArrays (1, &vao);
   glBindVertexArray (vao);
+  priv->vao = vao;
 
   /* Compile the vertex shader */
   p = vertex_shader;
@@ -749,9 +742,12 @@ gtk_gears_realize (GtkWidget *widget)
   glLinkProgram(program);
   glGetProgramInfoLog(program, sizeof msg, NULL, msg);
   g_print ("program info: %s\n", msg);
+  glDeleteShader (v);
+  glDeleteShader (f);
 
   /* Enable the shaders */
   glUseProgram(program);
+  priv->program = program;
 
   /* Get the locations of the uniforms so we can access them */
   priv->ModelViewProjectionMatrix_location = glGetUniformLocation(program, "ModelViewProjectionMatrix");
@@ -764,8 +760,64 @@ gtk_gears_realize (GtkWidget *widget)
 
   /* make the gears */
   priv->gear1 = create_gear(1.0, 4.0, 1.0, 20, 0.7);
+
+  /* Store the vertices in a vertex buffer object (VBO) */
+  glGenBuffers (1, &(priv->gear_vbo[0]));
+  glBindBuffer (GL_ARRAY_BUFFER, priv->gear_vbo[0]);
+  glBufferData (GL_ARRAY_BUFFER,
+                priv->gear1->nvertices * sizeof(GearVertex),
+                priv->gear1->vertices,
+                GL_STATIC_DRAW);
+
   priv->gear2 = create_gear(0.5, 2.0, 2.0, 10, 0.7);
+  glGenBuffers (1, &(priv->gear_vbo[1]));
+  glBindBuffer (GL_ARRAY_BUFFER, priv->gear_vbo[1]);
+  glBufferData (GL_ARRAY_BUFFER,
+                priv->gear2->nvertices * sizeof(GearVertex),
+                priv->gear2->vertices,
+                GL_STATIC_DRAW);
+
   priv->gear3 = create_gear(1.3, 2.0, 0.5, 10, 0.7);
+  glGenBuffers (1, &(priv->gear_vbo[2]));
+  glBindBuffer (GL_ARRAY_BUFFER, priv->gear_vbo[2]);
+  glBufferData (GL_ARRAY_BUFFER,
+                priv->gear3->nvertices * sizeof(GearVertex),
+                priv->gear3->vertices,
+                GL_STATIC_DRAW);
+}
+
+static void
+gtk_gears_unrealize (GtkWidget *widget)
+{
+  GtkGLArea *glarea = GTK_GL_AREA (widget);
+  GtkGearsPrivate *priv = gtk_gears_get_instance_private ((GtkGears *) widget);
+
+  gtk_gl_area_make_current (glarea);
+  if (gtk_gl_area_get_error (glarea) != NULL)
+    return;
+
+  /* Release the resources associated with OpenGL */
+  if (priv->gear_vbo[0] != 0)
+    glDeleteBuffers (1, &(priv->gear_vbo[0]));
+
+  if (priv->gear_vbo[1] != 0)
+    glDeleteBuffers (1, &(priv->gear_vbo[1]));
+
+  if (priv->gear_vbo[2] != 0)
+    glDeleteBuffers (1, &(priv->gear_vbo[2]));
+
+  if (priv->vao != 0)
+    glDeleteVertexArrays (1, &priv->vao);
+
+  if (priv->program != 0)
+    glDeleteProgram (priv->program);
+
+  priv->ModelViewProjectionMatrix_location = 0;
+  priv->NormalMatrix_location = 0;
+  priv->LightSourcePosition_location = 0;
+  priv->MaterialColor_location = 0;
+
+  GTK_WIDGET_CLASS (gtk_gears_parent_class)->unrealize (widget);
 }
 
 static gboolean


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