AtlatestRepositorysigil-graphics
sigil-graphics / tree / scriptsgen-gl-loader.sh
1
#!/bin/sh2
# gen-gl-loader.sh - regenerate src/c/gl_native_loader.h from vendor/sokol/sokol_gfx.h3
#4
# sokol_gfx's GL backend either includes the system GL headers (and links5
# libGL) or, on Win32, carries its own loader: GL types, constants and an6
# X-macro list of every GL function it calls. This script lifts those two7
# blocks out of the vendored header and emits a loader that fills the same8
# function pointers through a caller-supplied proc loader9
# (sigil_desktop_gl_get_proc_address, i.e. glfwGetProcAddress). The result10
# is what SOKOL_EXTERNAL_GL_LOADER expects on every native target, so no11
# GL header is needed to build and no libGL is linked.12
#13
# Run after every sokol_gfx.h bump; the counts below refuse a header whose14
# shape moved. Anchors are patterns, and each extraction is guarded by a15
# line count so a silent no-match cannot produce an empty header.16
set -eu17
cd "$(dirname "$0")/.."18
SRC=vendor/sokol/sokol_gfx.h19
OUT=src/c/gl_native_loader.h20
T=$(mktemp -d); trap 'rm -rf "$T"' EXIT22
# 1. the types + constants block: from the first GL typedef after23
# "#define GL_APIENTRY APIENTRY" to the "#endif" that closes the24
# win32-loader-definitions block25
awk '26
/#define GL_APIENTRY APIENTRY/ { armed = 1; next }27
armed && !started && /typedef unsigned int GLenum;/ { started = 1 }28
started && /^ #endif/ { exit }29
started { sub(/^ /, ""); print }30
' "$SRC" > "$T/defs.h"31
N1=$(wc -l < "$T/defs.h")32
[ "$N1" -gt 200 ] && [ "$N1" -lt 400 ] || { echo "REFUSING: types+constants block is $N1 lines (expected 200..400)"; exit 1; }33
grep -q '^typedef unsigned int GLenum;' "$T/defs.h" || { echo "REFUSING: no GLenum typedef"; exit 1; }34
tail -1 "$T/defs.h" | grep -q "^#define GL_MAX_IMAGE_UNITS " || { echo "REFUSING: constants block does not end on GL_MAX_IMAGE_UNITS (got: $(tail -1 "$T/defs.h"))"; exit 1; }36
# 2. the X-macro list: the body of _SG_GL_FUNCS, minus the SG_GL_FUNCS_EXT hook37
awk '38
/^#define _SG_GL_FUNCS \\$/ { started = 1; next }39
started && /SG_GL_FUNCS_EXT/ { next }40
started { print; if ($0 !~ /\\$/) exit }41
' "$SRC" | sed 's/_SG_XMACRO(/SIGIL_GL_XMACRO(/' > "$T/funcs.h"42
N2=$(grep -c 'SIGIL_GL_XMACRO(' "$T/funcs.h")43
[ "$N2" -gt 100 ] && [ "$N2" -lt 200 ] || { echo "REFUSING: function list has $N2 entries (expected 100..200)"; exit 1; }44
grep -q 'SIGIL_GL_XMACRO(glGenBuffers,' "$T/funcs.h" || { echo "REFUSING: glGenBuffers not in the function list"; exit 1; }45
# the last line must not end in a backslash (the macro closes there)46
tail -1 "$T/funcs.h" | grep -q '\\$' && { echo "REFUSING: function list did not close"; exit 1; }48
{49
cat <<HDR50
/*51
* gl_native_loader.h - GL types, constants and entry points for sokol_gfx52
* without a system GL header or a libGL link.53
*54
* GENERATED by scripts/gen-gl-loader.sh from vendor/sokol/sokol_gfx.h55
* (sokol's own Win32 loader block); do not edit, regenerate after a sokol56
* bump. Included once, by sokol-graphics.c, ahead of sokol_gfx.h with57
* SOKOL_EXTERNAL_GL_LOADER defined. Every gl* sokol_gfx calls is a static58
* function pointer here, filled by sigil_gl_load() through a proc loader59
* (sigil_desktop_gl_get_proc_address, GLFW's glfwGetProcAddress) once the60
* window's GL context is current. $N2 functions, $N1 lines of definitions.61
*/62
#ifndef SIGIL_GL_NATIVE_LOADER_H63
#define SIGIL_GL_NATIVE_LOADER_H65
#include <stddef.h>66
#include <stdint.h>68
/* sokol_gfx picks its Apple feature set from TargetConditionals.h, which it69
* includes itself only when it also includes the system GL headers; with70
* an external loader that is this header's job, or macOS would be read as71
* iOS (no base-vertex draws). */72
#if defined(__APPLE__)73
#include <TargetConditionals.h>74
#endif76
#if defined(_WIN32) && !defined(_WIN64)77
#define GL_APIENTRY __stdcall78
#else79
#define GL_APIENTRY80
#endif82
/* The guards the system GL headers use, so a later include of any of them83
* (glfw3.h without GLFW_INCLUDE_NONE, say) defines nothing twice. */84
#define __gl_h_ 185
#define __gl32_h_ 186
#define __gl31_h_ 187
#define __GL_H__ 188
#define __glext_h_ 189
#define __GLEXT_H_ 190
#define __gltypes_h_ 191
#define __glcorearb_h_ 192
#define __gl_glcorearb_h_ 194
/* sokol_gfx enables its 3.2 / 4.2 / 4.3 code paths on these, as the system95
* headers (Mesa's glext.h) defined them before; the runtime check on the96
* context's reported version still gates their use. */97
#define GL_VERSION_3_2 198
#define GL_VERSION_4_2 199
#define GL_VERSION_4_3 1101
/* ---- types and constants (from sokol_gfx.h) ---- */102
HDR103
cat "$T/defs.h"104
cat <<MID106
/* ---- the entry points sokol_gfx calls (from sokol_gfx.h) ---- */107
#define SIGIL_GL_FUNCS \\108
MID109
cat "$T/funcs.h"110
cat <<'FTR'112
#define SIGIL_GL_XMACRO(name, ret, args) typedef ret (GL_APIENTRY* PFN_ ## name) args;113
SIGIL_GL_FUNCS114
#undef SIGIL_GL_XMACRO116
#define SIGIL_GL_XMACRO(name, ret, args) static PFN_ ## name name;117
SIGIL_GL_FUNCS118
#undef SIGIL_GL_XMACRO120
typedef void *(*sigil_gl_proc_loader)(const char *name);122
/* Fill every pointer through `load`. Returns the number left NULL: entry123
* points newer than the context (glTextureView on a 4.1 context, the124
* base-instance draws before 4.2) are expected to be missing and sokol_gfx125
* only calls them behind its feature checks; glGenBuffers or glGetIntegerv126
* missing means there is no usable context, and sigil_gl_ready() says so. */127
static int sigil_gl_load(sigil_gl_proc_loader load)128
{129
int missing = 0;130
#define SIGIL_GL_XMACRO(name, ret, args) \131
name = (PFN_ ## name)load(#name); if (!name) missing++;132
SIGIL_GL_FUNCS133
#undef SIGIL_GL_XMACRO134
return missing;135
}137
static int sigil_gl_ready(void)138
{139
return glGetIntegerv != NULL && glClearBufferfv != NULL && glGenBuffers != NULL140
&& glCreateShader != NULL && glBindFramebuffer != NULL;141
}143
#endif /* SIGIL_GL_NATIVE_LOADER_H */144
FTR145
} > "$OUT"146
echo "wrote $OUT: $N1 definition lines, $N2 functions, $(wc -l < "$OUT") lines total"