From 5ee8c8f69338870e8062782dfcc08f60d455eb35 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 8 Jan 2023 20:13:12 -0500 Subject: Add support for OpenGL ES 3.2 in pugl_shader_demo --- .../pugl_shader_demo.app/Resources/meson.build | 1 + examples/pugl_shader_demo.app/meson.build | 1 + examples/pugl_shader_demo.c | 70 ++++++++++++---------- examples/shaders/header_320_es.glsl | 8 +++ examples/shaders/header_330.glsl | 3 +- examples/shaders/header_420.glsl | 3 +- examples/shaders/meson.build | 1 + examples/shaders/rect.frag | 8 ++- examples/shaders/rect.vert | 8 ++- test/test_utils.h | 24 +++++++- 10 files changed, 88 insertions(+), 39 deletions(-) create mode 100644 examples/shaders/header_320_es.glsl diff --git a/examples/pugl_shader_demo.app/Resources/meson.build b/examples/pugl_shader_demo.app/Resources/meson.build index ddbdcbe..7659daa 100644 --- a/examples/pugl_shader_demo.app/Resources/meson.build +++ b/examples/pugl_shader_demo.app/Resources/meson.build @@ -2,6 +2,7 @@ # SPDX-License-Identifier: 0BSD OR ISC shaders = [ + 'header_320_es.glsl', 'header_330.glsl', 'header_420.glsl', 'rect.vert', diff --git a/examples/pugl_shader_demo.app/meson.build b/examples/pugl_shader_demo.app/meson.build index 6885920..d7347b5 100644 --- a/examples/pugl_shader_demo.app/meson.build +++ b/examples/pugl_shader_demo.app/meson.build @@ -9,6 +9,7 @@ info_plist = configure_file(configuration: config, output: 'Info.plist') shaders = [ + 'header_320_es.glsl', 'header_330.glsl', 'header_420.glsl', 'rect.vert', diff --git a/examples/pugl_shader_demo.c b/examples/pugl_shader_demo.c index f273e31..02290da 100644 --- a/examples/pugl_shader_demo.c +++ b/examples/pugl_shader_demo.c @@ -63,8 +63,6 @@ typedef struct { double lastDrawDuration; double lastFrameEndTime; unsigned framesDrawn; - int glMajorVersion; - int glMinorVersion; int quit; } PuglTestApp; @@ -235,22 +233,6 @@ parseOptions(PuglTestApp* app, int argc, char** argv) } } - // Parse OpenGL major version argument, if given - if (argc >= 2) { - app->glMajorVersion = (int)strtol(argv[1], &endptr, 10); - if (endptr != argv[1] + strlen(argv[1])) { - logError("Invalid GL major version: %s\n", argv[1]); - return 1; - } - - if (app->glMajorVersion == 4) { - app->glMinorVersion = 2; - } else if (app->glMajorVersion != 3) { - logError("Unsupported GL major version %d\n", app->glMajorVersion); - return 1; - } - } - return 0; } @@ -271,9 +253,11 @@ setupPugl(PuglTestApp* app) puglSetSizeHint(app->view, PUGL_MIN_ASPECT, 1, 1); puglSetSizeHint(app->view, PUGL_MAX_ASPECT, 16, 9); puglSetBackend(app->view, puglGlBackend()); - puglSetViewHint(app->view, PUGL_CONTEXT_API, PUGL_OPENGL_API); - puglSetViewHint(app->view, PUGL_CONTEXT_VERSION_MAJOR, app->glMajorVersion); - puglSetViewHint(app->view, PUGL_CONTEXT_VERSION_MINOR, app->glMinorVersion); + puglSetViewHint(app->view, PUGL_CONTEXT_API, app->opts.glApi); + puglSetViewHint( + app->view, PUGL_CONTEXT_VERSION_MAJOR, app->opts.glMajorVersion); + puglSetViewHint( + app->view, PUGL_CONTEXT_VERSION_MINOR, app->opts.glMinorVersion); puglSetViewHint(app->view, PUGL_CONTEXT_PROFILE, PUGL_OPENGL_CORE_PROFILE); puglSetViewHint(app->view, PUGL_CONTEXT_DEBUG, app->opts.errorChecking); puglSetViewHint(app->view, PUGL_RESIZABLE, app->opts.resizable); @@ -288,15 +272,41 @@ setupPugl(PuglTestApp* app) static PuglStatus setupGl(PuglTestApp* app) { - // Load GL functions via GLAD - if (!gladLoadGLLoader((GLADloadproc)&puglGetProcAddress)) { - logError("Failed to load GL\n"); + // Load GL and determine the shader header to load + const char* headerFile = NULL; + if (app->opts.glApi == PUGL_OPENGL_API) { + if (!gladLoadGLLoader((GLADloadproc)&puglGetProcAddress)) { + logError("Failed to load OpenGL\n"); + return PUGL_FAILURE; + } + + headerFile = + (app->opts.glMajorVersion == 3 && app->opts.glMinorVersion == 3) + ? (SHADER_DIR "header_330.glsl") + : (app->opts.glMajorVersion == 4 && app->opts.glMinorVersion == 2) + ? (SHADER_DIR "header_420.glsl") + : NULL; + + } else if (app->opts.glApi == PUGL_OPENGL_ES_API) { + if (!gladLoadGLES2Loader((GLADloadproc)&puglGetProcAddress)) { + logError("Failed to load OpenGL ES\n"); + return PUGL_FAILURE; + } + + headerFile = + (app->opts.glMajorVersion == 3 && app->opts.glMinorVersion == 2) + ? (SHADER_DIR "header_320_es.glsl") + : NULL; + + } else { + logError("Unsupported API\n"); return PUGL_FAILURE; } - const char* const headerFile = - (app->glMajorVersion == 3 ? SHADER_DIR "header_330.glsl" - : SHADER_DIR "header_420.glsl"); + if (!headerFile) { + logError("Unsupported OpenGL version\n"); + return PUGL_FAILURE; + } // Load shader sources char* const headerSource = loadShader(app->programPath, headerFile); @@ -433,9 +443,9 @@ main(int argc, char** argv) { PuglTestApp app = {0}; - app.programPath = argv[0]; - app.glMajorVersion = 3; - app.glMinorVersion = 3; + app.programPath = argv[0]; + app.opts.glMajorVersion = 3; + app.opts.glMinorVersion = 3; // Parse command line options if (parseOptions(&app, argc, argv)) { diff --git a/examples/shaders/header_320_es.glsl b/examples/shaders/header_320_es.glsl new file mode 100644 index 0000000..ce5fe68 --- /dev/null +++ b/examples/shaders/header_320_es.glsl @@ -0,0 +1,8 @@ +// Copyright 2020-2023 David Robillard +// SPDX-License-Identifier: ISC + +#version 320 es + +#define NOPERSPECTIVE +#define INTER(qualifiers) +#define UBO(qualifiers) layout(std140) diff --git a/examples/shaders/header_330.glsl b/examples/shaders/header_330.glsl index 1de3301..11bdc53 100644 --- a/examples/shaders/header_330.glsl +++ b/examples/shaders/header_330.glsl @@ -1,7 +1,8 @@ -// Copyright 2020 David Robillard +// Copyright 2020-2023 David Robillard // SPDX-License-Identifier: ISC #version 330 core +#define NOPERSPECTIVE #define INTER(qualifiers) #define UBO(qualifiers) layout(std140) diff --git a/examples/shaders/header_420.glsl b/examples/shaders/header_420.glsl index 95fe1a1..cd226c9 100644 --- a/examples/shaders/header_420.glsl +++ b/examples/shaders/header_420.glsl @@ -1,7 +1,8 @@ -// Copyright 2020 David Robillard +// Copyright 2020-2023 David Robillard // SPDX-License-Identifier: ISC #version 420 core +#define NOPERSPECTIVE noperspective #define INTER(qualifiers) layout(qualifiers) #define UBO(qualifiers) layout(std140, qualifiers) diff --git a/examples/shaders/meson.build b/examples/shaders/meson.build index 54e9235..479f162 100644 --- a/examples/shaders/meson.build +++ b/examples/shaders/meson.build @@ -2,6 +2,7 @@ # SPDX-License-Identifier: 0BSD OR ISC shader_files = [ + 'header_320_es.glsl', 'header_330.glsl', 'header_420.glsl', 'rect.frag', diff --git a/examples/shaders/rect.frag b/examples/shaders/rect.frag index 9cee53b..17290bd 100644 --- a/examples/shaders/rect.frag +++ b/examples/shaders/rect.frag @@ -11,9 +11,11 @@ specified precisely in pixels to draw sharp lines. The border width is just hardcoded, but could be made a uniform or vertex attribute easily enough. */ -INTER(location = 0) noperspective in vec2 f_uv; -INTER(location = 1) noperspective in vec2 f_size; -INTER(location = 2) noperspective in vec4 f_fillColor; +precision mediump float; + +INTER(location = 0) NOPERSPECTIVE in vec2 f_uv; +INTER(location = 1) NOPERSPECTIVE in vec2 f_size; +INTER(location = 2) NOPERSPECTIVE in vec4 f_fillColor; layout(location = 0) out vec4 FragColor; diff --git a/examples/shaders/rect.vert b/examples/shaders/rect.vert index 0fa4dbc..ebdbec5 100644 --- a/examples/shaders/rect.vert +++ b/examples/shaders/rect.vert @@ -4,6 +4,8 @@ /* The vertex shader is trivial, but forwards scaled UV coordinates (in pixels) to the fragment shader for drawing the border. */ +precision mediump float; + UBO(binding = 0) uniform UniformBufferObject { mat4 projection; @@ -15,9 +17,9 @@ layout(location = 1) in vec2 v_origin; layout(location = 2) in vec2 v_size; layout(location = 3) in vec4 v_fillColor; -INTER(location = 0) noperspective out vec2 f_uv; -INTER(location = 1) noperspective out vec2 f_size; -INTER(location = 2) noperspective out vec4 f_fillColor; +INTER(location = 0) NOPERSPECTIVE out vec2 f_uv; +INTER(location = 1) NOPERSPECTIVE out vec2 f_size; +INTER(location = 2) NOPERSPECTIVE out vec4 f_fillColor; void main() diff --git a/test/test_utils.h b/test/test_utils.h index 8e21d97..e26e970 100644 --- a/test/test_utils.h +++ b/test/test_utils.h @@ -22,6 +22,9 @@ typedef struct { int samples; int doubleBuffer; int sync; + int glApi; + int glMajorVersion; + int glMinorVersion; bool continuous; bool help; bool ignoreKeyRepeat; @@ -314,6 +317,8 @@ static inline void puglPrintTestUsage(const char* prog, const char* posHelp) { printf("Usage: %s [OPTION]... %s\n\n" + " -E Use OpenGL ES\n" + " -G OpenGL context version\n" " -a Enable anti-aliasing\n" " -c Continuously animate and draw\n" " -d Directly draw to window (no double-buffering)\n" @@ -335,6 +340,9 @@ puglParseTestOptions(int* pargc, char*** pargv) 0, PUGL_TRUE, PUGL_DONT_CARE, + PUGL_OPENGL_API, + 3, + 3, false, false, false, @@ -346,7 +354,21 @@ puglParseTestOptions(int* pargc, char*** pargv) char** const argv = *pargv; int i = 1; for (; i < *pargc; ++i) { - if (!strcmp(argv[i], "-a")) { + if (!strcmp(argv[i], "-E")) { + opts.glApi = PUGL_OPENGL_ES_API; + } else if (!strcmp(argv[i], "-G")) { + if (++i == *pargc) { + fprintf(stderr, "error: Missing OpenGL version argument\n"); + return opts; + } + + const int matches = + sscanf(argv[i], "%u.%u", &opts.glMajorVersion, &opts.glMinorVersion); + if (matches != 2) { + fprintf(stderr, "error: Invalid OpenGL version argument\n"); + return opts; + } + } else if (!strcmp(argv[i], "-a")) { opts.samples = 4; } else if (!strcmp(argv[i], "-c")) { opts.continuous = true; -- cgit v1.2.1