aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-03-09 21:50:01 +0100
committerDavid Robillard <d@drobilla.net>2020-03-09 22:17:44 +0100
commitdd903f46e74d4a5a99eb7d34a9d2f9ba34e8b706 (patch)
tree743ee85918196ce9578b43c190e70a90ab46b7cb
parent0444a408dd6667fb69fd6395b9b911bf61d21f76 (diff)
GL3 Demo: Factor out GL setup and teardown
-rw-r--r--examples/pugl_gl3_demo.c171
1 files changed, 102 insertions, 69 deletions
diff --git a/examples/pugl_gl3_demo.c b/examples/pugl_gl3_demo.c
index 9efe185..c999e5a 100644
--- a/examples/pugl_gl3_demo.c
+++ b/examples/pugl_gl3_demo.c
@@ -47,7 +47,6 @@
#include "pugl/pugl_gl.h"
#include <math.h>
-#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -224,69 +223,63 @@ loadShader(const char* const path)
return source;
}
-int
-main(int argc, char** argv)
+static int
+parseOptions(PuglTestApp* app, int argc, char** argv)
{
- PuglTestApp app;
- memset(&app, 0, sizeof(app));
-
- const PuglRect frame = {0, 0, defaultWidth, defaultHeight};
-
// Parse command line options
- app.numRects = 1024;
- app.opts = puglParseTestOptions(&argc, &argv);
- if (app.opts.help) {
- puglPrintTestUsage("pugl_gl3_test", "[NUM_RECTS]");
+ app->numRects = 1024;
+ app->opts = puglParseTestOptions(&argc, &argv);
+ if (app->opts.help) {
return 1;
}
// Parse number of rectangles argument, if given
if (argc == 1) {
char* endptr = NULL;
- app.numRects = (size_t)strtol(argv[0], &endptr, 10);
+
+ app->numRects = (size_t)strtol(argv[0], &endptr, 10);
if (endptr != argv[0] + strlen(argv[0])) {
- puglPrintTestUsage("pugl_gl3_test", "[NUM_RECTS]");
return 1;
}
}
+ return 0;
+}
+
+static void
+setupPugl(PuglTestApp* app, const PuglRect frame)
+{
// Create world, view, and rect data
- app.world = puglNewWorld();
- app.view = puglNewView(app.world);
- app.rects = makeRects(app.numRects);
+ app->world = puglNewWorld();
+ app->view = puglNewView(app->world);
+ app->rects = makeRects(app->numRects);
// Set up world and view
- puglSetClassName(app.world, "PuglGL3Test");
- puglSetFrame(app.view, frame);
- puglSetMinSize(app.view, defaultWidth / 4, defaultHeight / 4);
- puglSetAspectRatio(app.view, 1, 1, 16, 9);
- puglSetBackend(app.view, puglGlBackend());
- puglSetViewHint(app.view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE);
- puglSetViewHint(app.view, PUGL_USE_DEBUG_CONTEXT, app.opts.errorChecking);
- puglSetViewHint(app.view, PUGL_CONTEXT_VERSION_MAJOR, 3);
- puglSetViewHint(app.view, PUGL_CONTEXT_VERSION_MINOR, 3);
- puglSetViewHint(app.view, PUGL_RESIZABLE, app.opts.resizable);
- puglSetViewHint(app.view, PUGL_SAMPLES, app.opts.samples);
- puglSetViewHint(app.view, PUGL_DOUBLE_BUFFER, app.opts.doubleBuffer);
- puglSetViewHint(app.view, PUGL_SWAP_INTERVAL, app.opts.sync);
- puglSetViewHint(app.view, PUGL_IGNORE_KEY_REPEAT, PUGL_TRUE);
- puglSetHandle(app.view, &app);
- puglSetEventFunc(app.view, onEvent);
-
- const PuglStatus st = puglCreateWindow(app.view, "Pugl OpenGL 3");
- if (st) {
- return logError("Failed to create window (%s)\n", puglStrerror(st));
- }
-
- // Enter context to set up GL stuff
- puglEnterContext(app.view, false);
+ puglSetClassName(app->world, "PuglGL3Demo");
+ puglSetFrame(app->view, frame);
+ puglSetMinSize(app->view, defaultWidth / 4, defaultHeight / 4);
+ puglSetAspectRatio(app->view, 1, 1, 16, 9);
+ puglSetBackend(app->view, puglGlBackend());
+ puglSetViewHint(app->view, PUGL_USE_COMPAT_PROFILE, PUGL_FALSE);
+ puglSetViewHint(app->view, PUGL_USE_DEBUG_CONTEXT, app->opts.errorChecking);
+ puglSetViewHint(app->view, PUGL_CONTEXT_VERSION_MAJOR, 3);
+ puglSetViewHint(app->view, PUGL_CONTEXT_VERSION_MINOR, 3);
+ puglSetViewHint(app->view, PUGL_RESIZABLE, app->opts.resizable);
+ puglSetViewHint(app->view, PUGL_SAMPLES, app->opts.samples);
+ puglSetViewHint(app->view, PUGL_DOUBLE_BUFFER, app->opts.doubleBuffer);
+ puglSetViewHint(app->view, PUGL_SWAP_INTERVAL, app->opts.sync);
+ puglSetViewHint(app->view, PUGL_IGNORE_KEY_REPEAT, PUGL_TRUE);
+ puglSetHandle(app->view, app);
+ puglSetEventFunc(app->view, onEvent);
+}
+static PuglStatus
+setupGl(PuglTestApp* app)
+{
// Load GL functions via GLAD
if (!gladLoadGLLoader((GLADloadproc)&puglGetProcAddress)) {
logError("Failed to load GL\n");
- puglFreeView(app.view);
- puglFreeWorld(app.world);
- return 1;
+ return PUGL_FAILURE;
}
// Load shader sources
@@ -294,32 +287,28 @@ main(int argc, char** argv)
char* const fragmentSource = loadShader("shaders/rect.frag");
if (!vertexSource || !fragmentSource) {
logError("Failed to load shader sources\n");
- puglFreeView(app.view);
- puglFreeWorld(app.world);
- return 1;
+ return PUGL_FAILURE;
}
// Compile rectangle shaders and program
- app.drawRect = compileProgram(vertexSource, fragmentSource);
+ app->drawRect = compileProgram(vertexSource, fragmentSource);
free(fragmentSource);
free(vertexSource);
- if (!app.drawRect.program) {
- puglFreeView(app.view);
- puglFreeWorld(app.world);
- return 1;
+ if (!app->drawRect.program) {
+ return PUGL_FAILURE;
}
// Get location of rectangle shader uniforms
- app.u_projection =
- glGetUniformLocation(app.drawRect.program, "u_projection");
+ app->u_projection =
+ glGetUniformLocation(app->drawRect.program, "u_projection");
// Generate/bind a VAO to track state
- glGenVertexArrays(1, &app.vao);
- glBindVertexArray(app.vao);
+ glGenVertexArrays(1, &app->vao);
+ glBindVertexArray(app->vao);
// Generate/bind a VBO to store vertex position data
- glGenBuffers(1, &app.vbo);
- glBindBuffer(GL_ARRAY_BUFFER, app.vbo);
+ glGenBuffers(1, &app->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, app->vbo);
glBufferData(GL_ARRAY_BUFFER,
sizeof(rectVertices),
rectVertices,
@@ -330,11 +319,11 @@ main(int argc, char** argv)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
// Generate/bind a VBO to store instance attribute data
- glGenBuffers(1, &app.instanceVbo);
- glBindBuffer(GL_ARRAY_BUFFER, app.instanceVbo);
+ glGenBuffers(1, &app->instanceVbo);
+ glBindBuffer(GL_ARRAY_BUFFER, app->instanceVbo);
glBufferData(GL_ARRAY_BUFFER,
- (GLsizeiptr)(app.numRects * sizeof(Rect)),
- app.rects,
+ (GLsizeiptr)(app->numRects * sizeof(Rect)),
+ app->rects,
GL_STREAM_DRAW);
// Attribute 1 is Rect::position
@@ -363,13 +352,59 @@ main(int argc, char** argv)
(const void*)offsetof(Rect, fillColor));
// Set up the IBO to index into the VBO
- glGenBuffers(1, &app.ibo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, app.ibo);
+ glGenBuffers(1, &app->ibo);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, app->ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof(rectIndices),
rectIndices,
GL_STATIC_DRAW);
+ return PUGL_SUCCESS;
+}
+
+static void
+teardownGl(PuglTestApp* app)
+{
+ glDeleteBuffers(1, &app->ibo);
+ glDeleteBuffers(1, &app->vbo);
+ glDeleteBuffers(1, &app->instanceVbo);
+ glDeleteVertexArrays(1, &app->vao);
+ deleteProgram(app->drawRect);
+}
+
+int
+main(int argc, char** argv)
+{
+ PuglTestApp app;
+ memset(&app, 0, sizeof(app));
+
+ const PuglRect frame = {0, 0, defaultWidth, defaultHeight};
+
+ // Parse command line options
+ if (parseOptions(&app, argc, argv)) {
+ puglPrintTestUsage("pugl_gl3_demo", "[NUM_RECTS]");
+ return 1;
+ }
+
+ // Create and configure world and view
+ setupPugl(&app, frame);
+
+ // Create window
+ const PuglStatus st = puglCreateWindow(app.view, "Pugl OpenGL 3");
+ if (st) {
+ return logError("Failed to create window (%s)\n", puglStrerror(st));
+ }
+
+ // Enter context to set up GL stuff
+ puglEnterContext(app.view, false);
+
+ // Set up OpenGL
+ if (setupGl(&app)) {
+ puglFreeView(app.view);
+ puglFreeWorld(app.world);
+ return 1;
+ }
+
// Finally ready to go, leave GL context and show the window
puglLeaveContext(app.view, false);
puglShowWindow(app.view);
@@ -384,15 +419,13 @@ main(int argc, char** argv)
// Delete GL stuff
puglEnterContext(app.view, false);
- glDeleteBuffers(1, &app.ibo);
- glDeleteBuffers(1, &app.vbo);
- glDeleteBuffers(1, &app.instanceVbo);
- glDeleteVertexArrays(1, &app.vao);
- deleteProgram(app.drawRect);
+ teardownGl(&app);
puglLeaveContext(app.view, false);
// Tear down view and world
puglFreeView(app.view);
puglFreeWorld(app.world);
+ free(app.rects);
+
return 0;
}