diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2015-07-16 14:53:42 +0100 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2015-07-16 14:55:25 +0100 |
commit | b274a2656d06ed7aa3e649e93988de86af048957 (patch) | |
tree | 4d651f90841e5629f1e895cca8e9c386a71f2759 /tests | |
parent | a39b8f67ba914cd2d6c2df50ce8b1659d9714d30 (diff) | |
download | gtk+-b274a2656d06ed7aa3e649e93988de86af048957.tar.gz |
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.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/gtkgears.c | 122 |
1 files changed, 87 insertions, 35 deletions
diff --git a/tests/gtkgears.c b/tests/gtkgears.c index 7a28071727..a8e4fed812 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 |