1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
#pragma once
static void (*_glFlush)(void);
static GLenum (*_glGetError)(void);
static void (*_glGetIntegerv)(GLenum, GLint*);
static void (*_glGetFloatv)(GLenum, GLfloat*);
static void (*_glGetBooleanv)(GLenum, GLboolean*);
static const char* (*_glGetString)(GLenum);
static GLboolean (*_glIsBuffer)(GLuint);
static void (*_glGenBuffers)(GLsizei, GLuint*);
static void (*_glDeleteBuffers)(GLsizei, GLuint*);
static void (*_glBindBuffer)(GLenum, GLuint);
static void (*_glBufferData)(GLenum, GLsizeiptr, const GLvoid*, GLenum);
static void* (*_glMapBufferRange)(GLenum, GLintptr, GLsizeiptr, GLbitfield);
static void (*_glUnmapBuffer)(GLenum);
static void (*_glPixelStorei)(GLenum, GLint);
static void (*_glReadPixels)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid*);
static void (*_glEnable)(GLenum);
static void (*_glDisable)(GLenum);
static void (*_glScissor)(GLint, GLint, GLsizei, GLsizei);
static void (*_glClearColor)(GLclampf, GLclampf, GLclampf, GLclampf);
static void (*_glClear)(GLbitfield);
static void (*_glDebugMessageCallback)(GLDEBUGPROC, const void*);
enum gl_variant {
OPENGL_ES,
OPENGL,
};
struct gl_version {
uint32_t major, minor;
};
static enum gl_variant OPENGL_VARIANT;
static struct gl_version OPENGL_VERSION;
#define glFlush _glFlush
#define glGetError _glGetError
#define glGetIntegerv _glGetIntegerv
#define glGetFloatv _glGetFloatv
#define glGetBooleanv _glGetBooleanv
#define glGetString _glGetString
#define glIsBuffer _glIsBuffer
#define glGenBuffers _glGenBuffers
#define glDeleteBuffers _glDeleteBuffers
#define glBindBuffer _glBindBuffer
#define glBufferData _glBufferData
#define glMapBufferRange _glMapBufferRange
#define glUnmapBuffer _glUnmapBuffer
#define glPixelStorei _glPixelStorei
#define glReadPixels _glReadPixels
#define glEnable _glEnable
#define glDisable _glDisable
#define glScissor _glScissor
#define glClearColor _glClearColor
#define glClear _glClear
#define glDebugMessageCallback _glDebugMessageCallback
static void
debug_cb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *data)
{
(void)source, (void)type, (void)id, (void)severity, (void)length, (void)message, (void)data;
WARNX("%s", message);
}
static void*
dlsym_proc(const char *procname)
{
void *ptr = NULL;
hook_function(&ptr, procname, false, (const char*[]){ GL_LIBS, NULL });
return ptr;
}
static void
load_gl_function_pointers(void* (*procs[])(const char*), const size_t memb)
{
static bool loaded;
if (loaded)
return;
void* (*proc)(const char*);
for (size_t i = 0; i < memb; ++i) {
if ((proc = procs[i]))
break;
}
if (!proc)
proc = dlsym_proc;
#define GL_REQUIRED(x) do { if (!(_##x = proc(#x))) { ERRX(EXIT_FAILURE, "Failed to load %s", #x); } } while (0)
#define GL_OPTIONAL(x) do { _##x = proc(#x); } while (0)
GL_REQUIRED(glFlush);
GL_REQUIRED(glGetError);
GL_REQUIRED(glGetIntegerv);
GL_REQUIRED(glGetFloatv);
GL_REQUIRED(glGetBooleanv);
GL_REQUIRED(glGetString);
GL_REQUIRED(glIsBuffer);
GL_REQUIRED(glGenBuffers);
GL_REQUIRED(glDeleteBuffers);
GL_REQUIRED(glBindBuffer);
GL_REQUIRED(glBufferData);
GL_REQUIRED(glMapBufferRange);
GL_REQUIRED(glUnmapBuffer);
GL_REQUIRED(glPixelStorei);
GL_REQUIRED(glReadPixels);
GL_REQUIRED(glEnable);
GL_REQUIRED(glDisable);
GL_REQUIRED(glScissor);
GL_REQUIRED(glClearColor);
GL_REQUIRED(glClear);
GL_OPTIONAL(glDebugMessageCallback);
#undef GL
if (glDebugMessageCallback) {
glDebugMessageCallback(debug_cb, NULL);
}
const struct { const char *p; enum gl_variant v; } variants[] = {
{ .p = "OpenGL ES-CM ", .v = OPENGL_ES },
{ .p = "OpenGL ES-CL ", .v = OPENGL_ES },
{ .p = "OpenGL ES ", .v = OPENGL_ES },
{ .p = "OpenGL ", .v = OPENGL },
};
const char *version = glGetString(GL_VERSION);
WARNX("%s", version);
for (size_t i = 0; i < ARRAY_SIZE(variants); ++i) {
const size_t len = strlen(variants[i].p);
if (strncmp(version, variants[i].p, len))
continue;
OPENGL_VARIANT = variants[i].v;
version += len;
break;
}
sscanf(version, "%u.%u", &OPENGL_VERSION.major, &OPENGL_VERSION.minor);
loaded = true;
}
|