Graphics library for Mercury, including OpenGL bindings, TGA image reading, and X11, Win32, and SDL2 windowing and input.
リビジョン | 8a215ba90197900dd702c858e19a9984ed357516 (tree) |
---|---|
日時 | 2022-04-27 10:28:29 |
作者 | AlaskanEmily <emily@alas...> |
コミッター | AlaskanEmily |
Generate OpenGL extension and post-1.1 bindings automatically
@@ -11,6 +11,7 @@ PARALLEL_OPT=`if test ! -z '$(PARALLEL)' ; then echo ' -j $(PARALLEL)' ; fi` | ||
11 | 11 | SAFFRON_MMC_OPTS=$(MMC_OPTS) $(GRADE_OPT) $(PARALLEL_OPT) |
12 | 12 | SHARED_MMC_FLAGS=--linkage shared --lib-linkage shared |
13 | 13 | STATIC_MMC_FLAGS=--linkage static --lib-linkage static |
14 | +AWK?=awk | |
14 | 15 | |
15 | 16 | ALL=build_saffron |
16 | 17 | all: $(ALL) |
@@ -32,11 +33,20 @@ SAFFRON_TGA_LINK_FLAGS=--search-lib-files-dir "$$ROOT/util/tga" --init-file "$$R | ||
32 | 33 | SAFFRON_GLOW_LINK_FLAGS=--search-lib-files-dir "$$ROOT/util/glow" --init-file "$$ROOT/util/glow/saffron_glow.init" $(GLOW_INCLUDE_FLAGS) |
33 | 34 | SAFFRON_WINDOW_LINK_FLAGS=--search-lib-files-dir "$$ROOT/util/window" --init-file "$$ROOT/util/window/saffron_window.init" |
34 | 35 | |
36 | +# Generated source. | |
37 | +saffron.gl.buffer.inc: saffron.gl_gen.awk saffron.gl.buffer.csv | |
38 | + $(AWK) -F, -f saffron.gl_gen.awk < saffron.gl.buffer.csv > '$@' | |
39 | + @touch saffron.gl.buffer.m # Force the Mercury compiler to rebuild this... | |
40 | + | |
41 | +saffron.gl.shader.inc: saffron.gl_gen.awk saffron.gl.shader.csv | |
42 | + $(AWK) -F, -f saffron.gl_gen.awk < saffron.gl.shader.csv > '$@' | |
43 | + @touch saffron.gl.shader.m # Force the Mercury compiler to rebuild this... | |
44 | + | |
35 | 45 | # Primary libraries. |
36 | 46 | # Each is preceded by the shared object they create (if any, some like the TGA reader is only built static). |
37 | 47 | # This is used to copy the shared objects to target directories. |
38 | 48 | libsaffron.$(SO): build_saffron |
39 | -build_saffron: build_mmath | |
49 | +build_saffron: build_mmath saffron.gl.buffer.inc saffron.gl.shader.inc | |
40 | 50 | ROOT=`pwd` && $(MMC) $(SAFFRON_MMC_OPTS) $(MMATH_LINK_FLAGS) --make libsaffron $(STATIC_MMC_FLAGS) |
41 | 51 | ROOT=`pwd` && $(MMC) $(SAFFRON_MMC_OPTS) $(MMATH_LINK_FLAGS) --make libsaffron $(SHARED_MMC_FLAGS) -L "$$ROOT/mmath" -lmmath -lGL -lX11 |
42 | 52 | install libsaffron.$(SO) demo/ |
@@ -0,0 +1,22 @@ | ||
1 | +func,GenBuffers,GLsizei,GLuint* | |
2 | +func,DeleteBuffers,GLsizei,const GLuint* | |
3 | +func,BindBuffer,GLenum,GLuint | |
4 | +func,BufferData,GLenum,SaffronGLsizeiptr,const void*,GLenum | |
5 | +func,MapBuffer,GLenum,GLenum,=void* | |
6 | +func,UnmapBuffer,GLenum,=GLboolean | |
7 | + | |
8 | +struct,Buffer,GenBuffers,DeleteBuffers,BindBuffer,BufferData,MapBuffer,UnmapBuffer | |
9 | + | |
10 | +load,Buffer,core 2.0,ext GL_ARB_vertex_buffer_object ARB | |
11 | + | |
12 | +const,GL_ARRAY_BUFFER,0x8892 | |
13 | +const,GL_ELEMENT_ARRAY_BUFFER,0x8893 | |
14 | +const,GL_STREAM_DRAW,0x88E0 | |
15 | +const,GL_STREAM_READ,0x88E1 | |
16 | +const,GL_STREAM_COPY,0x88E2 | |
17 | +const,GL_STATIC_DRAW,0x88E4 | |
18 | +const,GL_STATIC_READ,0x88E5 | |
19 | +const,GL_STATIC_COPY,0x88E6 | |
20 | +const,GL_DYNAMIC_DRAW,0x88E8 | |
21 | +const,GL_DYNAMIC_READ,0x88E9 | |
22 | +const,GL_DYNAMIC_COPY,0x88EA |
@@ -0,0 +1,124 @@ | ||
1 | +#ifndef SAFFRON_GL_FUNC_VAR | |
2 | +#define SAFFRON_GL_FUNC_VAR(X) SaffronGL_ ## X ## _PROC X; | |
3 | +#endif | |
4 | +#ifndef SAFFRON_GL_FUNC_LOAD | |
5 | +#define SAFFRON_GL_FUNC_LOAD(X, EXT) \ | |
6 | + SaffronGL_LoadFunction(gl_ctx, (char*)("gl" #X EXT), &maybe_func); \ | |
7 | + if(!Saffron_GetCtxFunctionOK(maybe_func, &func)) break; \ | |
8 | + (ctx->X) = (SaffronGL_ ## X ## _PROC)func; | |
9 | + | |
10 | +#define SAFFRON_GL_LOAD_FUNC_CORE(X) SAFFRON_GL_FUNC_LOAD(X, "") | |
11 | +#endif | |
12 | + | |
13 | +#ifndef SAFFRON_GL_IMPL | |
14 | +typedef void(APIENTRY*SaffronGL_GenBuffers_PROC)( | |
15 | + GLsizei, | |
16 | + GLuint*); | |
17 | +#endif | |
18 | +#ifndef SAFFRON_GL_IMPL | |
19 | +typedef void(APIENTRY*SaffronGL_DeleteBuffers_PROC)( | |
20 | + GLsizei, | |
21 | + const GLuint*); | |
22 | +#endif | |
23 | +#ifndef SAFFRON_GL_IMPL | |
24 | +typedef void(APIENTRY*SaffronGL_BindBuffer_PROC)( | |
25 | + GLenum, | |
26 | + GLuint); | |
27 | +#endif | |
28 | +#ifndef SAFFRON_GL_IMPL | |
29 | +typedef void(APIENTRY*SaffronGL_BufferData_PROC)( | |
30 | + GLenum, | |
31 | + SaffronGLsizeiptr, | |
32 | + const void*, | |
33 | + GLenum); | |
34 | +#endif | |
35 | +#ifndef SAFFRON_GL_IMPL | |
36 | +typedef void*(APIENTRY*SaffronGL_MapBuffer_PROC)( | |
37 | + GLenum, | |
38 | + GLenum); | |
39 | +#endif | |
40 | +#ifndef SAFFRON_GL_IMPL | |
41 | +typedef GLboolean(APIENTRY*SaffronGL_UnmapBuffer_PROC)( | |
42 | + GLenum); | |
43 | +#endif | |
44 | +#ifndef SAFFRON_GL_IMPL | |
45 | +#define SAFFRON_GL_BUFFER_FUNCS(X) \ | |
46 | + X(GenBuffers) \ | |
47 | + X(DeleteBuffers) \ | |
48 | + X(BindBuffer) \ | |
49 | + X(BufferData) \ | |
50 | + X(MapBuffer) \ | |
51 | + X(UnmapBuffer) \ | |
52 | +/* */ | |
53 | +struct SaffronGL_BufferCtx{ | |
54 | + SAFFRON_GL_BUFFER_FUNCS(SAFFRON_GL_FUNC_VAR) | |
55 | +}; | |
56 | +#endif | |
57 | +#ifndef SAFFRON_GL_IMPL | |
58 | +#ifdef SAFFRON_GL_EXPECT_BUFFER | |
59 | +#define SAFFRON_GL_BUFFER_FUNC(CTX, X) (gl ## X) | |
60 | +#define SAFFRON_GL_BUFFER_CTX MR_Word | |
61 | +#define SAFFRON_GL_ALLOC_BUFFER_CTX() 0 | |
62 | +#define SAFFRON_GL_LOAD_BUFFER_CTX(GLCTX, CTX) (*(CTX) = 0) | |
63 | +#else | |
64 | +#define SAFFRON_GL_BUFFER_FUNC(CTX, X) ((CTX)->X) | |
65 | +#define SAFFRON_GL_BUFFER_CTX struct SaffronGL_BufferCtx | |
66 | +int SaffronGL_LoadBufferCtx(MR_Word gl_ctx, struct SaffronGL_BufferCtx **ctx_ptr); | |
67 | +#define SAFFRON_GL_LOAD_BUFFER_CTX SaffronGL_LoadBufferCtx | |
68 | +#endif | |
69 | +#else | |
70 | +#ifndef SAFFRON_GL_EXPECT_BUFFER | |
71 | +int SaffronGL_LoadBufferCtx(MR_Word gl_ctx, struct SaffronGL_BufferCtx **ctx_ptr){ | |
72 | + struct SaffronGL_BufferCtx *ctx = MR_GC_malloc_atomic(sizeof(struct SaffronGL_BufferCtx)); | |
73 | + MR_Word maybe_func, func; | |
74 | + MR_String err = NULL; | |
75 | + MR_Integer major, minor; | |
76 | + SaffronGL_Version(gl_ctx, &major, &minor); | |
77 | + if(major > 2 || (major == 2 && minor >= 0)) do{ | |
78 | + SAFFRON_GL_BUFFER_FUNCS(SAFFRON_GL_LOAD_FUNC_CORE) | |
79 | + *ctx_ptr = ctx; | |
80 | + return 0; | |
81 | + }while(0); | |
82 | +#define SAFFRON_GL_LOAD_FUNC_BUFFER_ARB(X) SAFFRON_GL_FUNC_LOAD(X, "ARB") | |
83 | + if(SaffronGL_SupportsExtension("GL_ARB_vertex_buffer_object")) do{ | |
84 | + SAFFRON_GL_BUFFER_FUNCS(SAFFRON_GL_LOAD_FUNC_BUFFER_ARB) | |
85 | + *ctx_ptr = ctx; | |
86 | + return 0; | |
87 | + }while(0); | |
88 | + return 1; | |
89 | +} | |
90 | +#endif | |
91 | +#endif | |
92 | +#ifndef GL_ARRAY_BUFFER | |
93 | +#define GL_ARRAY_BUFFER 0x8892 | |
94 | +#endif | |
95 | +#ifndef GL_ELEMENT_ARRAY_BUFFER | |
96 | +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 | |
97 | +#endif | |
98 | +#ifndef GL_STREAM_DRAW | |
99 | +#define GL_STREAM_DRAW 0x88E0 | |
100 | +#endif | |
101 | +#ifndef GL_STREAM_READ | |
102 | +#define GL_STREAM_READ 0x88E1 | |
103 | +#endif | |
104 | +#ifndef GL_STREAM_COPY | |
105 | +#define GL_STREAM_COPY 0x88E2 | |
106 | +#endif | |
107 | +#ifndef GL_STATIC_DRAW | |
108 | +#define GL_STATIC_DRAW 0x88E4 | |
109 | +#endif | |
110 | +#ifndef GL_STATIC_READ | |
111 | +#define GL_STATIC_READ 0x88E5 | |
112 | +#endif | |
113 | +#ifndef GL_STATIC_COPY | |
114 | +#define GL_STATIC_COPY 0x88E6 | |
115 | +#endif | |
116 | +#ifndef GL_DYNAMIC_DRAW | |
117 | +#define GL_DYNAMIC_DRAW 0x88E8 | |
118 | +#endif | |
119 | +#ifndef GL_DYNAMIC_READ | |
120 | +#define GL_DYNAMIC_READ 0x88E9 | |
121 | +#endif | |
122 | +#ifndef GL_DYNAMIC_COPY | |
123 | +#define GL_DYNAMIC_COPY 0x88EA | |
124 | +#endif |
@@ -110,112 +110,19 @@ | ||
110 | 110 | :- pragma foreign_import_module("C", saffron.gl). |
111 | 111 | :- pragma foreign_import_module("C", saffron.geometry). |
112 | 112 | |
113 | +%-----------------------------------------------------------------------------% | |
113 | 114 | % Define the native prototypes to handle buffers. |
114 | 115 | :- pragma foreign_decl("C", " |
116 | +#include ""saffron.gl.buffer.inc"" | |
117 | + "). | |
115 | 118 | |
116 | -#define SAFFRON_GL_BUFFER_FUNCS(X) \\ | |
117 | - X(GenBuffers) \\ | |
118 | - X(DeleteBuffers) \\ | |
119 | - X(BindBuffer) \\ | |
120 | - X(BufferData) \\ | |
121 | - X(MapBuffer) \\ | |
122 | - X(UnmapBuffer) | |
123 | - | |
124 | -typedef void(APIENTRY*SaffronGL_GenBuffers_PROC)(GLsizei, GLuint*); | |
125 | - | |
126 | -typedef void(APIENTRY*SaffronGL_DeleteBuffers_PROC)(GLsizei, const GLuint*); | |
127 | - | |
128 | -typedef void(APIENTRY*SaffronGL_BindBuffer_PROC)(GLenum, GLuint); | |
129 | - | |
130 | -typedef void(APIENTRY*SaffronGL_BufferData_PROC)( | |
131 | - GLenum, | |
132 | - SaffronGLsizeiptr, | |
133 | - const void *, | |
134 | - GLenum); | |
135 | - | |
136 | -typedef void*(APIENTRY*SaffronGL_MapBuffer_PROC)(GLenum, GLenum); | |
137 | - | |
138 | -typedef void(*APIENTRY*SaffronGL_UnmapBuffer_PROC)(GLenum); | |
139 | - | |
140 | -#ifdef SAFFRON_GL_EXPECT_BUFFERS | |
141 | - | |
142 | -/* TODO: Maybe we should be caching some info here? */ | |
143 | -# define SAFFRON_GL_BUFFER_CTX MR_Word | |
144 | -# define SAFFRON_GL_BUFFER_FUNC(CTX, FN) gl ## FN | |
145 | - | |
146 | -#else | |
147 | - | |
148 | -# define SAFFRON_GL_BUFFER_FUNC_VAR(X) \\ | |
149 | - SaffronGL_ ## X ## _PROC X; | |
150 | - | |
151 | -struct SaffronGL_BufferCtx{ | |
152 | - SAFFRON_GL_BUFFER_FUNCS(SAFFRON_GL_BUFFER_FUNC_VAR) | |
153 | -}; | |
154 | - | |
155 | -# undef SAFFRON_GL_BUFFER_FUNC_VAR | |
156 | - | |
157 | -# define SAFFRON_GL_BUFFER_CTX struct SaffronGL_BufferCtx* | |
158 | -# define SAFFRON_GL_BUFFER_FUNC(CTX, FN) ((CTX)->FN) | |
159 | - | |
160 | -#endif | |
161 | - | |
162 | -#ifndef GL_ARRAY_BUFFER | |
163 | -# define GL_ARRAY_BUFFER 0x8892 | |
164 | -#endif | |
165 | - | |
166 | -#ifndef GL_ELEMENT_ARRAY_BUFFER | |
167 | -# define GL_ELEMENT_ARRAY_BUFFER 0x8893 | |
168 | -#endif | |
169 | - | |
170 | -#ifndef GL_STREAM_DRAW | |
171 | -# define GL_STREAM_DRAW 0x88E0 | |
172 | -#endif | |
173 | - | |
174 | -#ifndef GL_STREAM_READ | |
175 | -# define GL_STREAM_READ 0x88E1 | |
176 | -#endif | |
177 | - | |
178 | -#ifndef GL_STREAM_COPY | |
179 | -# define GL_STREAM_COPY 0x88E2 | |
180 | -#endif | |
181 | - | |
182 | -#ifndef GL_STATIC_DRAW | |
183 | -# define GL_STATIC_DRAW 0x88E4 | |
184 | -#endif | |
185 | - | |
186 | -#ifndef GL_STATIC_READ | |
187 | -# define GL_STATIC_READ 0x88E5 | |
188 | -#endif | |
189 | - | |
190 | -#ifndef GL_STATIC_COPY | |
191 | -# define GL_STATIC_COPY 0x88E6 | |
192 | -#endif | |
193 | - | |
194 | -#ifndef GL_DYNAMIC_DRAW | |
195 | -# define GL_DYNAMIC_DRAW 0x88E8 | |
196 | -#endif | |
197 | - | |
198 | -#ifndef GL_DYNAMIC_READ | |
199 | -# define GL_DYNAMIC_READ 0x88E9 | |
200 | -#endif | |
201 | - | |
202 | -#ifndef GL_DYNAMIC_COPY | |
203 | -# define GL_DYNAMIC_COPY 0x88EA | |
204 | -#endif | |
205 | - | |
206 | -#ifndef GL_READ_ONLY | |
207 | -# define GL_READ_ONLY 0x88B8 | |
208 | -#endif | |
209 | - | |
210 | -#ifndef GL_WRITE_ONLY | |
211 | -# define GL_WRITE_ONLY 0x88B9 | |
212 | -#endif | |
213 | - | |
214 | -#ifndef GL_READ_WRITE | |
215 | -# define GL_READ_WRITE 0x88BA | |
216 | -#endif | |
119 | +%-----------------------------------------------------------------------------% | |
217 | 120 | |
218 | -"). | |
121 | +:- pragma foreign_code("C", " | |
122 | +#define SAFFRON_GL_IMPL | |
123 | +#include ""saffron.gl.buffer.inc"" | |
124 | +#undef SAFFRON_GL_IMPL | |
125 | + "). | |
219 | 126 | |
220 | 127 | %-----------------------------------------------------------------------------% |
221 | 128 |
@@ -252,89 +159,25 @@ create_buffer_ctx_error(E) = maybe.error(E). | ||
252 | 159 | |
253 | 160 | :- pred create_buffer_ctx_internal( |
254 | 161 | gl_load_func_ctx, |
255 | - bool.bool, | |
256 | 162 | maybe.maybe_error(buffer_ctx), |
257 | 163 | io.io, io.io). |
258 | 164 | :- mode create_buffer_ctx_internal( |
259 | 165 | in, |
260 | - in, | |
261 | 166 | out, |
262 | 167 | di, uo) is det. |
263 | 168 | |
264 | 169 | :- pragma foreign_proc("C", |
265 | - create_buffer_ctx_internal(Ctx::in, Old::in, MaybeBufferCtx::out, IOi::di, IOo::uo), | |
170 | + create_buffer_ctx_internal(Ctx::in, MaybeBufferCtx::out, IOi::di, IOo::uo), | |
266 | 171 | [may_call_mercury, promise_pure, thread_safe, will_not_throw_exception], |
267 | 172 | " |
268 | - | |
269 | -#ifndef SAFFRON_GL_EXPECT_BUFFERS | |
270 | - MR_Bool New = !Old; | |
271 | - | |
272 | - MR_Word maybe_func, func; | |
273 | - MR_String err = NULL; | |
274 | - struct SaffronGL_BufferCtx *buffer_ctx; | |
275 | - buffer_ctx = MR_GC_malloc_atomic(sizeof(struct SaffronGL_BufferCtx)); | |
276 | - | |
277 | -#ifdef _WIN32 | |
278 | - Old = MR_TRUE; | |
279 | -#endif | |
280 | - | |
281 | -# define SAFFRON_GL_BUFFER_FUNC_LOAD(ERR, X, NAME) { \\ | |
282 | - SaffronGL_LoadFunction(Ctx, (char*)(NAME), &maybe_func); \\ | |
283 | - err = NULL; \\ | |
284 | - if(Saffron_GetCtxFunctionOK(maybe_func, &func)) \\ | |
285 | - buffer_ctx->X = (SaffronGL_ ## X ## _PROC)func; \\ | |
286 | - else if(Saffron_GetCtxFunctionError(maybe_func, &err)) \\ | |
287 | - goto ERR; \\ | |
288 | - else \\ | |
289 | - MR_assert(0); \\ | |
290 | -} | |
291 | - | |
292 | -# define SAFFRON_GL_BUFFER_FUNC_LOAD_ARB(X) \\ | |
293 | - SAFFRON_GL_BUFFER_FUNC_LOAD( \\ | |
294 | - saffron_gl_create_buffer_ctx_internal_no_arb, \\ | |
295 | - X, \\ | |
296 | - ""gl"" #X ""ARB"") | |
297 | - | |
298 | -# define SAFFRON_GL_BUFFER_FUNC_LOAD_NEW(X) \\ | |
299 | - SAFFRON_GL_BUFFER_FUNC_LOAD( \\ | |
300 | - saffron_gl_create_buffer_ctx_internal, \\ | |
301 | - X, \\ | |
302 | - ""gl"" #X) | |
303 | - | |
304 | - /* For OpenGL versions before 2.1, only use the ARB version. */ | |
305 | - if(Old){ | |
306 | - /* Yes, this is slightly incorrect... */ | |
307 | - if(strstr( | |
308 | - (char*)glGetString(GL_EXTENSIONS), | |
309 | - ""GL_ARB_vertex_buffer_object"") != NULL){ | |
310 | - | |
311 | - SAFFRON_GL_BUFFER_FUNCS(SAFFRON_GL_BUFFER_FUNC_LOAD_ARB) | |
312 | - | |
313 | - /* If we made it this far, just go to the end. */ | |
314 | - goto saffron_gl_create_buffer_ctx_internal; | |
315 | - } | |
316 | - } | |
317 | -saffron_gl_create_buffer_ctx_internal_no_arb: | |
318 | - if(New){ | |
319 | - SAFFRON_GL_BUFFER_FUNCS(SAFFRON_GL_BUFFER_FUNC_LOAD_NEW) | |
320 | - } | |
321 | -saffron_gl_create_buffer_ctx_internal: | |
322 | - | |
323 | -#undef SAFFRON_GL_BUFFER_FUNC_LOAD_NEW | |
324 | -#undef SAFFRON_GL_BUFFER_FUNC_LOAD_ARB | |
325 | -#undef SAFFRON_GL_BUFFER_FUNC_LOAD | |
326 | - | |
327 | - if(err == NULL){ | |
328 | - MaybeBufferCtx = SaffronGL_CreateBufferCtxOK(buffer_ctx); | |
173 | + SAFFRON_GL_BUFFER_CTX ctx; | |
174 | + if(SAFFRON_GL_LOAD_BUFFER_CTX(Ctx, &ctx) == 0){ | |
175 | + MaybeBufferCtx = SaffronGL_CreateBufferCtxOK(ctx); | |
329 | 176 | } |
330 | 177 | else{ |
331 | - MR_GC_free(buffer_ctx); | |
332 | - MaybeBufferCtx = SaffronGL_CreateBufferCtxError(err); | |
178 | + MaybeBufferCtx = SaffronGL_CreateBufferCtxError( | |
179 | + (MR_String)""Could not create context""); | |
333 | 180 | } |
334 | -#else | |
335 | - MaybeBufferCtx = SaffronGL_CreateBufferCtxOK(0); | |
336 | -#endif | |
337 | - | |
338 | 181 | IOo = IOi; |
339 | 182 | "). |
340 | 183 |
@@ -342,27 +185,8 @@ saffron_gl_create_buffer_ctx_internal: | ||
342 | 185 | |
343 | 186 | create_buffer_ctx(Ctx, MaybeBufferCtx, !IO) :- |
344 | 187 | saffron.make_current(Ctx, !IO), |
345 | - saffron.gl.opengl_version(Ctx, MaybeSemVer, !IO), | |
346 | - ( | |
347 | - MaybeSemVer = maybe.ok(SemVer), | |
348 | - ( if | |
349 | - saffron.sem_ver_compare((<), SemVer, saffron.sem_ver(2, 1)) | |
350 | - then | |
351 | - Old = bool.yes | |
352 | - else | |
353 | - Old = bool.no | |
354 | - ) | |
355 | - ; | |
356 | - MaybeSemVer = maybe.error(Err), | |
357 | - trace [io(!XIO)] ( | |
358 | - io.write_string("Error reading OpenGL version: ", !XIO), | |
359 | - io.write_string(Err, !XIO), | |
360 | - io.nl(!XIO) | |
361 | - ), | |
362 | - Old = bool.yes | |
363 | - ), | |
364 | 188 | LoadFuncCtx = 'new gl_load_func_ctx'(Ctx), |
365 | - create_buffer_ctx_internal(LoadFuncCtx, Old, MaybeBufferCtx, !IO). | |
189 | + create_buffer_ctx_internal(LoadFuncCtx, MaybeBufferCtx, !IO). | |
366 | 190 | |
367 | 191 | %-----------------------------------------------------------------------------% |
368 | 192 |
@@ -129,16 +129,20 @@ typedef char SaffronGLchar; | ||
129 | 129 | * |
130 | 130 | * See: http://support.apple.com/kb/TA22513 |
131 | 131 | */ |
132 | -# define SAFFRON_GL_EXPECT_BUFFERS | |
132 | +# define SAFFRON_GL_EXPECT_BUFFER | |
133 | 133 | # define GL_GLEXT_PROTOTYPES |
134 | 134 | # include <OpenGL/gl.h> |
135 | 135 | # include <OpenGL/glext.h> |
136 | 136 | |
137 | +# ifndef APIENTRY | |
138 | +# define APIENTRY | |
139 | +# endif | |
140 | + | |
137 | 141 | #else |
138 | 142 | |
139 | 143 | # if (defined __linux__) || (defined __OpenBSD__) || (defined __FreeBSD__) |
140 | -# define SAFFRON_GL_EXPECT_BUFFERS | |
141 | -# define SAFFRON_GL_EXPECT_SHADERS | |
144 | +# define SAFFRON_GL_EXPECT_BUFFER | |
145 | +# define SAFFRON_GL_EXPECT_SHADER | |
142 | 146 | # define GL_GLEXT_PROTOTYPES |
143 | 147 | # endif |
144 | 148 |
@@ -165,16 +169,6 @@ typedef void(APIENTRY*SaffronGL_DrawTextureNV_PROC)( | ||
165 | 169 | GLfloat, |
166 | 170 | GLfloat); |
167 | 171 | |
168 | -struct SaffronGL_DrawTextureNV_ext{ | |
169 | - SaffronGL_DrawTextureNV_PROC draw_texture_nv; | |
170 | -}; | |
171 | - | |
172 | -# define SAFFRON_GL_DRAW_TEXTURE_NV_EXT ""GL_NV_draw_texture"" | |
173 | - | |
174 | -# define SAFFRON_GL_DRAW_TEXTURE_NV_INIT(TO, LOAD) do{ \\ | |
175 | - (TO)->draw_texture_nv = (LOAD(""glDrawTextureNV"")); \\ | |
176 | -}while(0) | |
177 | - | |
178 | 172 | #ifndef GL_SHADING_LANGUAGE_VERSION |
179 | 173 | # define GL_SHADING_LANGUAGE_VERSION 0x8B8C |
180 | 174 | #endif |
@@ -0,0 +1,26 @@ | ||
1 | +func,CreateShader,GLenum,=GLuint | |
2 | +func,DeleteShader,GLuint | |
3 | +func,ShaderSource,GLuint,GLsizei,const SaffronGLchar**,const GLint | |
4 | +func,CompileShader,GLuint | |
5 | +func,GetShaderiv,GLuint,GLenum,GLint* | |
6 | +func,GetShaderInfoLog,GLuint,GLsizei,GLsizei*,SaffronGLchar* | |
7 | +func,CreateProgram,void,=GLuint | |
8 | +func,DeleteProgram,GLuint | |
9 | +func,LinkProgram,GLuint | |
10 | +func,AttachShader,GLuint,GLuint | |
11 | +func,UseProgram,GLuint | |
12 | +func,GetProgramiv,GLuint,GLenum,GLint* | |
13 | + | |
14 | +struct,Shader,CreateShader,DeleteShader,ShaderSource,CompileShader,GetShaderiv,GetShaderInfoLog,CreateProgram,DeleteProgram,LinkProgram,AttachShader,UseProgram,GetProgramiv | |
15 | + | |
16 | +load,Shader,core 2.0 | |
17 | + | |
18 | +const,GL_SHADING_LANGUAGE_VERSION,0x8B8C | |
19 | +const,GL_VERTEX_SHADER,0x8B31 | |
20 | +const,GL_FRAGMENT_SHADER,0x8B30 | |
21 | +const,GL_GEOMETRY_SHADER,0x8DD9 | |
22 | +const,GL_COMPILE_STATUS,0x8B81 | |
23 | +const,GL_LINK_STATUS,0x8B82 | |
24 | +const,GL_VALIDATE_STATUS,0x8B83 | |
25 | +const,GL_INFO_LOG_LENGTH,0x8B84 | |
26 | + |
@@ -0,0 +1,143 @@ | ||
1 | +#ifndef SAFFRON_GL_FUNC_VAR | |
2 | +#define SAFFRON_GL_FUNC_VAR(X) SaffronGL_ ## X ## _PROC X; | |
3 | +#endif | |
4 | +#ifndef SAFFRON_GL_FUNC_LOAD | |
5 | +#define SAFFRON_GL_FUNC_LOAD(X, EXT) \ | |
6 | + SaffronGL_LoadFunction(gl_ctx, (char*)("gl" #X EXT), &maybe_func); \ | |
7 | + if(!Saffron_GetCtxFunctionOK(maybe_func, &func)) break; \ | |
8 | + (ctx->X) = (SaffronGL_ ## X ## _PROC)func; | |
9 | + | |
10 | +#define SAFFRON_GL_LOAD_FUNC_CORE(X) SAFFRON_GL_FUNC_LOAD(X, "") | |
11 | +#endif | |
12 | + | |
13 | +#ifndef SAFFRON_GL_IMPL | |
14 | +typedef GLuint(APIENTRY*SaffronGL_CreateShader_PROC)( | |
15 | + GLenum); | |
16 | +#endif | |
17 | +#ifndef SAFFRON_GL_IMPL | |
18 | +typedef void(APIENTRY*SaffronGL_DeleteShader_PROC)( | |
19 | + GLuint); | |
20 | +#endif | |
21 | +#ifndef SAFFRON_GL_IMPL | |
22 | +typedef void(APIENTRY*SaffronGL_ShaderSource_PROC)( | |
23 | + GLuint, | |
24 | + GLsizei, | |
25 | + const SaffronGLchar**, | |
26 | + const GLint); | |
27 | +#endif | |
28 | +#ifndef SAFFRON_GL_IMPL | |
29 | +typedef void(APIENTRY*SaffronGL_CompileShader_PROC)( | |
30 | + GLuint); | |
31 | +#endif | |
32 | +#ifndef SAFFRON_GL_IMPL | |
33 | +typedef void(APIENTRY*SaffronGL_GetShaderiv_PROC)( | |
34 | + GLuint, | |
35 | + GLenum, | |
36 | + GLint*); | |
37 | +#endif | |
38 | +#ifndef SAFFRON_GL_IMPL | |
39 | +typedef void(APIENTRY*SaffronGL_GetShaderInfoLog_PROC)( | |
40 | + GLuint, | |
41 | + GLsizei, | |
42 | + GLsizei*, | |
43 | + SaffronGLchar*); | |
44 | +#endif | |
45 | +#ifndef SAFFRON_GL_IMPL | |
46 | +typedef GLuint(APIENTRY*SaffronGL_CreateProgram_PROC)( | |
47 | + void); | |
48 | +#endif | |
49 | +#ifndef SAFFRON_GL_IMPL | |
50 | +typedef void(APIENTRY*SaffronGL_DeleteProgram_PROC)( | |
51 | + GLuint); | |
52 | +#endif | |
53 | +#ifndef SAFFRON_GL_IMPL | |
54 | +typedef void(APIENTRY*SaffronGL_LinkProgram_PROC)( | |
55 | + GLuint); | |
56 | +#endif | |
57 | +#ifndef SAFFRON_GL_IMPL | |
58 | +typedef void(APIENTRY*SaffronGL_AttachShader_PROC)( | |
59 | + GLuint, | |
60 | + GLuint); | |
61 | +#endif | |
62 | +#ifndef SAFFRON_GL_IMPL | |
63 | +typedef void(APIENTRY*SaffronGL_UseProgram_PROC)( | |
64 | + GLuint); | |
65 | +#endif | |
66 | +#ifndef SAFFRON_GL_IMPL | |
67 | +typedef void(APIENTRY*SaffronGL_GetProgramiv_PROC)( | |
68 | + GLuint, | |
69 | + GLenum, | |
70 | + GLint*); | |
71 | +#endif | |
72 | +#ifndef SAFFRON_GL_IMPL | |
73 | +#define SAFFRON_GL_SHADER_FUNCS(X) \ | |
74 | + X(CreateShader) \ | |
75 | + X(DeleteShader) \ | |
76 | + X(ShaderSource) \ | |
77 | + X(CompileShader) \ | |
78 | + X(GetShaderiv) \ | |
79 | + X(GetShaderInfoLog) \ | |
80 | + X(CreateProgram) \ | |
81 | + X(DeleteProgram) \ | |
82 | + X(LinkProgram) \ | |
83 | + X(AttachShader) \ | |
84 | + X(UseProgram) \ | |
85 | + X(GetProgramiv) \ | |
86 | +/* */ | |
87 | +struct SaffronGL_ShaderCtx{ | |
88 | + SAFFRON_GL_SHADER_FUNCS(SAFFRON_GL_FUNC_VAR) | |
89 | +}; | |
90 | +#endif | |
91 | +#ifndef SAFFRON_GL_IMPL | |
92 | +#ifdef SAFFRON_GL_EXPECT_SHADER | |
93 | +#define SAFFRON_GL_SHADER_FUNC(CTX, X) (gl ## X) | |
94 | +#define SAFFRON_GL_SHADER_CTX MR_Word | |
95 | +#define SAFFRON_GL_ALLOC_SHADER_CTX() 0 | |
96 | +#define SAFFRON_GL_LOAD_SHADER_CTX(GLCTX, CTX) (*(CTX) = 0) | |
97 | +#else | |
98 | +#define SAFFRON_GL_SHADER_FUNC(CTX, X) ((CTX)->X) | |
99 | +#define SAFFRON_GL_SHADER_CTX struct SaffronGL_ShaderCtx | |
100 | +int SaffronGL_LoadShaderCtx(MR_Word gl_ctx, struct SaffronGL_ShaderCtx **ctx_ptr); | |
101 | +#define SAFFRON_GL_LOAD_SHADER_CTX SaffronGL_LoadShaderCtx | |
102 | +#endif | |
103 | +#else | |
104 | +#ifndef SAFFRON_GL_EXPECT_SHADER | |
105 | +int SaffronGL_LoadShaderCtx(MR_Word gl_ctx, struct SaffronGL_ShaderCtx **ctx_ptr){ | |
106 | + struct SaffronGL_ShaderCtx *ctx = MR_GC_malloc_atomic(sizeof(struct SaffronGL_ShaderCtx)); | |
107 | + MR_Word maybe_func, func; | |
108 | + MR_String err = NULL; | |
109 | + MR_Integer major, minor; | |
110 | + SaffronGL_Version(gl_ctx, &major, &minor); | |
111 | + if(major > 2 || (major == 2 && minor >= 0)) do{ | |
112 | + SAFFRON_GL_SHADER_FUNCS(SAFFRON_GL_LOAD_FUNC_CORE) | |
113 | + *ctx_ptr = ctx; | |
114 | + return 0; | |
115 | + }while(0); | |
116 | + return 1; | |
117 | +} | |
118 | +#endif | |
119 | +#endif | |
120 | +#ifndef GL_SHADING_LANGUAGE_VERSION | |
121 | +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C | |
122 | +#endif | |
123 | +#ifndef GL_VERTEX_SHADER | |
124 | +#define GL_VERTEX_SHADER 0x8B31 | |
125 | +#endif | |
126 | +#ifndef GL_FRAGMENT_SHADER | |
127 | +#define GL_FRAGMENT_SHADER 0x8B30 | |
128 | +#endif | |
129 | +#ifndef GL_GEOMETRY_SHADER | |
130 | +#define GL_GEOMETRY_SHADER 0x8DD9 | |
131 | +#endif | |
132 | +#ifndef GL_COMPILE_STATUS | |
133 | +#define GL_COMPILE_STATUS 0x8B81 | |
134 | +#endif | |
135 | +#ifndef GL_LINK_STATUS | |
136 | +#define GL_LINK_STATUS 0x8B82 | |
137 | +#endif | |
138 | +#ifndef GL_VALIDATE_STATUS | |
139 | +#define GL_VALIDATE_STATUS 0x8B83 | |
140 | +#endif | |
141 | +#ifndef GL_INFO_LOG_LENGTH | |
142 | +#define GL_INFO_LOG_LENGTH 0x8B84 | |
143 | +#endif |
@@ -82,115 +82,13 @@ | ||
82 | 82 | |
83 | 83 | % Define the native prototypes to handle shaders. |
84 | 84 | :- pragma foreign_decl("C", " |
85 | +#include ""saffron.gl.shader.inc"" | |
86 | +"). | |
85 | 87 | |
86 | -#define SAFFRON_GL_SHADER_FUNCS(X) \\ | |
87 | - X(CreateShader) \\ | |
88 | - X(DeleteShader) \\ | |
89 | - X(ShaderSource) \\ | |
90 | - X(CompileShader) \\ | |
91 | - X(GetShaderiv) \\ | |
92 | - X(GetShaderInfoLog) \\ | |
93 | - X(CreateProgram) \\ | |
94 | - X(DeleteProgram) \\ | |
95 | - X(AttachShader) \\ | |
96 | - X(LinkProgram) \\ | |
97 | - X(UseProgram) \\ | |
98 | - X(GetProgramiv) | |
99 | - | |
100 | -/* Shader function types */ | |
101 | -typedef GLuint(APIENTRY*SaffronGL_CreateShader_PROC)(GLenum); | |
102 | - | |
103 | -typedef void(APIENTRY*SaffronGL_DeleteShader_PROC)(GLuint); | |
104 | - | |
105 | -typedef void(APIENTRY*SaffronGL_ShaderSource_PROC)( | |
106 | - GLuint, | |
107 | - GLsizei, | |
108 | - const SaffronGLchar**, | |
109 | - const GLint*); | |
110 | - | |
111 | -typedef void(APIENTRY*SaffronGL_CompileShader_PROC)(GLuint); | |
112 | - | |
113 | -typedef void(APIENTRY*SaffronGL_GetShaderiv_PROC)(GLuint, GLenum, GLint*); | |
114 | - | |
115 | -typedef void(APIENTRY*SaffronGL_GetShaderInfoLog_PROC)( | |
116 | - GLuint, | |
117 | - GLsizei, | |
118 | - GLsizei*, | |
119 | - SaffronGLchar*); | |
120 | - | |
121 | -typedef GLuint(APIENTRY*SaffronGL_CreateProgram_PROC)(void); | |
122 | - | |
123 | -typedef void(APIENTRY*SaffronGL_DeleteProgram_PROC)(GLuint); | |
124 | - | |
125 | -typedef void(APIENTRY*SaffronGL_LinkProgram_PROC)(GLuint); | |
126 | - | |
127 | -typedef void(APIENTRY*SaffronGL_AttachShader_PROC)(GLuint, GLuint); | |
128 | - | |
129 | -typedef void(APIENTRY*SaffronGL_UseProgram_PROC)(GLuint); | |
130 | - | |
131 | -typedef void(APIENTRY*SaffronGL_GetProgramiv_PROC)(GLuint, GLenum, GLint*); | |
132 | - | |
133 | -#ifdef SAFFRON_GL_EXPECT_SHADERS | |
134 | - | |
135 | -/* TODO: Maybe we should be caching some info here? */ | |
136 | -# define SAFFRON_GL_SHADER_CTX MR_Word | |
137 | -# define SAFFRON_GL_SHADER_FUNC(CTX, FN) gl ## FN | |
138 | - | |
139 | -#else | |
140 | - | |
141 | -# define SAFFRON_GL_SHADER_FUNC_VAR(X) \\ | |
142 | - SaffronGL_ ## X ## _PROC X; | |
143 | - | |
144 | -struct SaffronGL_ShaderCtx{ | |
145 | - SAFFRON_GL_SHADER_FUNCS(SAFFRON_GL_SHADER_FUNC_VAR) | |
146 | -}; | |
147 | - | |
148 | -# undef SAFFRON_GL_SHADER_FUNC_VAR | |
149 | - | |
150 | -# define SAFFRON_GL_SHADER_CTX struct SaffronGL_ShaderCtx* | |
151 | -# define SAFFRON_GL_SHADER_FUNC(CTX, FN) ((CTX)->FN) | |
152 | - | |
153 | -#endif | |
154 | - | |
155 | -/* OpenGL constants for use with shaders */ | |
156 | -#ifndef GL_SHADING_LANGUAGE_VERSION | |
157 | -# define GL_SHADING_LANGUAGE_VERSION 0x8B8C | |
158 | -#endif | |
159 | - | |
160 | -#ifndef GL_VERTEX_SHADER | |
161 | -# define GL_VERTEX_SHADER 0x8B31 | |
162 | -#endif | |
163 | - | |
164 | -#ifndef GL_FRAGMENT_SHADER | |
165 | -# define GL_FRAGMENT_SHADER 0x8B30 | |
166 | -#endif | |
167 | - | |
168 | -#ifndef GL_GEOMETRY_SHADER | |
169 | -# define GL_GEOMETRY_SHADER 0x8DD9 | |
170 | -#endif | |
171 | - | |
172 | -#ifndef GL_COMPILE_STATUS | |
173 | -# define GL_COMPILE_STATUS 0x8B81 | |
174 | -#endif | |
175 | - | |
176 | -#ifndef GL_LINK_STATUS | |
177 | -# define GL_LINK_STATUS 0x8B82 | |
178 | -#endif | |
179 | - | |
180 | -#ifndef GL_VALIDATE_STATUS | |
181 | -# define GL_VALIDATE_STATUS 0x8B83 | |
182 | -#endif | |
183 | - | |
184 | -#ifndef GL_INFO_LOG_LENGTH | |
185 | -# define GL_INFO_LOG_LENGTH 0x8B84 | |
186 | -#endif | |
187 | - | |
188 | -#ifdef MR_USE_SINGLE_PREC_FLOAT | |
189 | -# define SAFFRON_GL_FLOAT_FUNC(NAME) NAME ## f | |
190 | -#else | |
191 | -# define SAFFRON_GL_FLOAT_FUNC(NAME) NAME ## d | |
192 | -#endif | |
193 | - | |
88 | +:- pragma foreign_decl("C", " | |
89 | +#define SAFFRON_GL_IMPL | |
90 | +#include ""saffron.gl.shader.inc"" | |
91 | +#undef SAFFRON_GL_IMPL | |
194 | 92 | "). |
195 | 93 | |
196 | 94 | %-----------------------------------------------------------------------------% |
@@ -244,38 +142,14 @@ create_shader_ctx_error(E) = maybe.error(E). | ||
244 | 142 | create_shader_ctx_internal(Ctx::in, MaybeShaderCtx::out, IOi::di, IOo::uo), |
245 | 143 | [may_call_mercury, promise_pure, thread_safe, will_not_throw_exception], |
246 | 144 | " |
247 | -#ifndef SAFFRON_GL_EXPECT_SHADERS | |
248 | - MR_Word maybe_func, func; | |
249 | - MR_String err = NULL; | |
250 | - struct SaffronGL_ShaderCtx *shader_ctx; | |
251 | - shader_ctx = MR_GC_malloc_atomic(sizeof(struct SaffronGL_ShaderCtx)); | |
252 | - | |
253 | -# define SAFFRON_GL_SHADER_FUNC_LOAD(X) { \\ | |
254 | - SaffronGL_LoadFunction(Ctx, (char*)(""gl"" #X), &maybe_func); \\ | |
255 | - err = NULL; \\ | |
256 | - if(Saffron_GetCtxFunctionOK(maybe_func, &func)) \\ | |
257 | - shader_ctx->X = (SaffronGL_ ## X ## _PROC)func; \\ | |
258 | - else if(Saffron_GetCtxFunctionError(maybe_func, &err)) \\ | |
259 | - goto create_shader_ctx_internal_error; \\ | |
260 | - else \\ | |
261 | - MR_assert(0); \\ | |
262 | -} | |
263 | - | |
264 | - SAFFRON_GL_SHADER_FUNCS(SAFFRON_GL_SHADER_FUNC_LOAD) | |
265 | - | |
266 | -# undef SAFFRON_GL_SHADER_FUNC_LOAD | |
267 | - | |
268 | -create_shader_ctx_internal_error: | |
269 | - if(err == NULL){ | |
270 | - MaybeShaderCtx = SaffronGL_CreateShaderCtxOK(shader_ctx); | |
145 | + SAFFRON_GL_SHADER_CTX ctx; | |
146 | + if(SAFFRON_GL_LOAD_SHADER_CTX(Ctx, &ctx) == 0){ | |
147 | + MaybeShaderCtx = SaffronGL_CreateShaderCtxOK(ctx); | |
271 | 148 | } |
272 | 149 | else{ |
273 | - MR_GC_free(shader_ctx); | |
274 | - MaybeShaderCtx = SaffronGL_CreateShaderCtxError(err); | |
150 | + MaybeShaderCtx = SaffronGL_CreateShaderCtxError( | |
151 | + (MR_String)""Could not create context""); | |
275 | 152 | } |
276 | -#else | |
277 | - MaybeShaderCtx = SaffronGL_CreateShaderCtxOK(0); | |
278 | -#endif | |
279 | 153 | IOo = IOi; |
280 | 154 | "). |
281 | 155 |
@@ -0,0 +1,146 @@ | ||
1 | +BEGIN{ | |
2 | + print("\ | |
3 | +#ifndef SAFFRON_GL_FUNC_VAR\n\ | |
4 | +#define SAFFRON_GL_FUNC_VAR(X) SaffronGL_ ## X ## _PROC X;\n\ | |
5 | +#endif\n\ | |
6 | +#ifndef SAFFRON_GL_FUNC_LOAD\n\ | |
7 | +#define SAFFRON_GL_FUNC_LOAD(X, EXT) \\\n\ | |
8 | + SaffronGL_LoadFunction(gl_ctx, (char*)(\"gl\" #X EXT), &maybe_func); \\\n\ | |
9 | + if(!Saffron_GetCtxFunctionOK(maybe_func, &func)) break; \\\n\ | |
10 | + (ctx->X) = (SaffronGL_ ## X ## _PROC)func; \n\ | |
11 | +\n\ | |
12 | +#define SAFFRON_GL_LOAD_FUNC_CORE(X) SAFFRON_GL_FUNC_LOAD(X, \"\")\n\ | |
13 | +#endif\n\ | |
14 | +"); | |
15 | + | |
16 | +} | |
17 | + | |
18 | +$1 == "const" { | |
19 | + print("\ | |
20 | +#ifndef " $2 "\n\ | |
21 | +#define " $2 " " $3 "\n\ | |
22 | +#endif"); | |
23 | + next; | |
24 | +} | |
25 | + | |
26 | +$1 !~ /#/ && $0 != "" { | |
27 | + print("#ifndef SAFFRON_GL_IMPL"); | |
28 | + upper2 = toupper($2); | |
29 | +} | |
30 | + | |
31 | +$1 == "struct" || $1 == "load"{ | |
32 | + struct = "struct SaffronGL_" $2 "Ctx"; | |
33 | +} | |
34 | + | |
35 | +$1 == "func" { | |
36 | + if($NF ~ /^=/){ | |
37 | + last = NF - 1; | |
38 | + ret = substr($NF, 2); | |
39 | + } | |
40 | + else{ | |
41 | + last = NF; | |
42 | + ret = "void"; | |
43 | + } | |
44 | + sig = "typedef " ret "(APIENTRY*SaffronGL_" $2 "_PROC)("; | |
45 | + if(last < 3){ | |
46 | + print(sig "void);"); | |
47 | + } | |
48 | + else{ | |
49 | + print(sig); | |
50 | + for(i = 3; i < last; i++) | |
51 | + print(" " $i ","); | |
52 | + print(" " $last ");"); | |
53 | + } | |
54 | +} | |
55 | + | |
56 | +$1 == "struct" { | |
57 | + print("#define SAFFRON_GL_" upper2 "_FUNCS(X) \\"); | |
58 | + for(i = 3; i <= NF; i++){ | |
59 | + print(" X(" $i ") \\"); | |
60 | + } | |
61 | + print("/* */"); | |
62 | + print(struct "{"); | |
63 | + print(" SAFFRON_GL_" upper2 "_FUNCS(SAFFRON_GL_FUNC_VAR)"); | |
64 | + print("};"); | |
65 | +} | |
66 | + | |
67 | +$1 == "load" { | |
68 | + # Check for "core" spec, and if we find it we should generate an 'expect' | |
69 | + # C preprocessor check to avoid unnecessary indirection. | |
70 | + core = 0; | |
71 | + for(i = 3; i <= NF; i++){ | |
72 | + if($i ~ /^core [0-9]\.[0-9]$/){ | |
73 | + core = i; | |
74 | + break; | |
75 | + } | |
76 | + } | |
77 | + if(core != 0){ | |
78 | + print("\ | |
79 | +#ifdef SAFFRON_GL_EXPECT_" upper2 "\n\ | |
80 | +#define SAFFRON_GL_" upper2 "_FUNC(CTX, X) (gl ## X)\n\ | |
81 | +#define SAFFRON_GL_" upper2 "_CTX MR_Word\n\ | |
82 | +#define SAFFRON_GL_ALLOC_" upper2 "_CTX() 0\n\ | |
83 | +#define SAFFRON_GL_LOAD_" upper2 "_CTX(GLCTX, CTX) (*(CTX) = 0)\n\ | |
84 | +#else"); | |
85 | + } | |
86 | + # Write the default, loader implementation. | |
87 | + sig = "int SaffronGL_Load" $2 "Ctx(MR_Word gl_ctx, " struct " **ctx_ptr)"; | |
88 | + print("\ | |
89 | +#define SAFFRON_GL_" upper2 "_FUNC(CTX, X) ((CTX)->X)\n\ | |
90 | +#define SAFFRON_GL_" upper2 "_CTX " struct "\n\ | |
91 | +" sig ";\n\ | |
92 | +#define SAFFRON_GL_LOAD_" upper2 "_CTX SaffronGL_Load" $2 "Ctx"); | |
93 | + if(core != ""){ | |
94 | + print("#endif"); | |
95 | + } | |
96 | + | |
97 | + # Write the impl (we are in an #ifdef for the interface) | |
98 | + print("#else"); | |
99 | + print("#ifndef SAFFRON_GL_EXPECT_" upper2); | |
100 | + | |
101 | + # Write the loader function | |
102 | + print(sig "{\n\ | |
103 | + " struct " *ctx = MR_GC_malloc_atomic(sizeof(" struct "));\n\ | |
104 | + MR_Word maybe_func, func;\n\ | |
105 | + MR_String err = NULL;"); | |
106 | + if(core != 0){ | |
107 | + print("\ | |
108 | + MR_Integer major, minor;\n\ | |
109 | + SaffronGL_Version(gl_ctx, &major, &minor);"); | |
110 | + } | |
111 | + for(i = 3; i <= NF; i++){ | |
112 | + # Core has special handling. | |
113 | + if($i ~ /^core [0-9]\.[0-9]$/){ | |
114 | + major = substr($i, 6, 1); | |
115 | + minor = substr($i, 8, 1); | |
116 | + print("\ | |
117 | + if(major > " major " || (major == " major " && minor >= " minor ")) do{\n\ | |
118 | + SAFFRON_GL_" upper2 "_FUNCS(SAFFRON_GL_LOAD_FUNC_CORE)\n\ | |
119 | + *ctx_ptr = ctx;\n\ | |
120 | + return 0;\n\ | |
121 | + }while(0);"); | |
122 | + } | |
123 | + else if($i ~ /^ext GL_[A-Za-z0-9_]+ [A-Za-z0-9_]+$/){ | |
124 | + ext_i = match($i, / GL_/) + 1; | |
125 | + sfx_i = match($i, / [A-Za-z0-9_]+$/) + 1; | |
126 | + ext = substr($i, ext_i, sfx_i - ext_i - 1); | |
127 | + sfx = substr($i, sfx_i); | |
128 | + macro = "SAFFRON_GL_LOAD_FUNC_" upper2 "_" sfx; | |
129 | + print("\ | |
130 | +#define " macro "(X) SAFFRON_GL_FUNC_LOAD(X, \"" sfx "\")\n\ | |
131 | + if(SaffronGL_SupportsExtension(\"" ext "\")) do{ \n\ | |
132 | + SAFFRON_GL_" upper2 "_FUNCS(" macro ")\n\ | |
133 | + *ctx_ptr = ctx;\n\ | |
134 | + return 0;\n\ | |
135 | + }while(0);"); | |
136 | + } | |
137 | + } | |
138 | + print(" return 1;\n}"); | |
139 | + print("#endif"); # SAFFRON_GL_EXPECT_ | |
140 | +} | |
141 | + | |
142 | +$1 !~ /#/ && $0 != "" { | |
143 | + print("#endif"); | |
144 | +} | |
145 | + | |
146 | + |