Skip to content

Latest commit

 

History

History
881 lines (720 loc) · 26.6 KB

mojoshader_opengl.c

File metadata and controls

881 lines (720 loc) · 26.6 KB
 
Apr 29, 2008
Apr 29, 2008
1
2
3
4
5
6
7
8
9
/**
* MojoShader; generate shader programs from bytecode of compiled
* Direct3D shaders.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
Apr 26, 2008
Apr 26, 2008
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
Apr 30, 2008
Apr 30, 2008
16
17
18
19
20
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h> // GL headers need this for WINGDIAPI definition.
#endif
Apr 26, 2008
Apr 26, 2008
21
#include "mojoshader.h"
Apr 27, 2008
Apr 27, 2008
22
#define GL_GLEXT_LEGACY 1
Apr 29, 2008
Apr 29, 2008
23
24
#include "GL/gl.h"
#include "GL/glext.h"
Apr 26, 2008
Apr 26, 2008
25
26
27
28
// Get basic wankery out of the way here...
typedef unsigned int uint; // this is a printf() helper. don't use for code.
Apr 30, 2008
Apr 30, 2008
29
30
31
32
33
34
35
36
#ifdef _MSC_VER
#define snprintf _snprintf
typedef unsigned __int8 uint8;
typedef unsigned __int32 uint32;
typedef unsigned __int32 int32;
#else
#include <stdint.h>
Apr 26, 2008
Apr 26, 2008
37
38
39
typedef uint8_t uint8;
typedef uint32_t uint32;
typedef int32_t int32;
Apr 30, 2008
Apr 30, 2008
40
41
42
#endif
#define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) )
Apr 26, 2008
Apr 26, 2008
43
Apr 30, 2008
Apr 30, 2008
44
45
46
47
#ifndef SUPPORT_PROFILE_GLSL
#define SUPPORT_PROFILE_GLSL 1
#endif
Apr 26, 2008
Apr 26, 2008
48
49
50
struct MOJOSHADER_glShader
{
const MOJOSHADER_parseData *parseData;
Apr 27, 2008
Apr 27, 2008
51
GLhandleARB handle;
Apr 26, 2008
Apr 26, 2008
52
53
54
uint32 refcount;
};
Apr 27, 2008
Apr 27, 2008
55
56
typedef struct
{
Apr 27, 2008
Apr 27, 2008
57
MOJOSHADER_shaderType shader_type;
Apr 27, 2008
Apr 27, 2008
58
const MOJOSHADER_uniform *uniform;
Apr 27, 2008
Apr 27, 2008
59
GLuint location;
Apr 27, 2008
Apr 27, 2008
60
61
} UniformMap;
Apr 27, 2008
Apr 27, 2008
62
63
typedef struct
{
Apr 27, 2008
Apr 27, 2008
64
const MOJOSHADER_attribute *attribute;
Apr 27, 2008
Apr 27, 2008
65
GLuint location;
Apr 27, 2008
Apr 27, 2008
66
67
} AttributeMap;
Apr 26, 2008
Apr 26, 2008
68
69
struct MOJOSHADER_glProgram
{
Apr 27, 2008
Apr 27, 2008
70
71
MOJOSHADER_glShader *vertex;
MOJOSHADER_glShader *fragment;
Apr 27, 2008
Apr 27, 2008
72
GLhandleARB handle;
Apr 27, 2008
Apr 27, 2008
73
uint32 uniform_count;
Apr 27, 2008
Apr 27, 2008
74
UniformMap *uniforms;
Apr 27, 2008
Apr 27, 2008
75
uint32 attribute_count;
Apr 27, 2008
Apr 27, 2008
76
AttributeMap *attributes;
Apr 26, 2008
Apr 26, 2008
77
78
79
uint32 refcount;
};
Apr 28, 2008
Apr 28, 2008
80
// Entry points in base OpenGL that lack function pointer prototypes...
Apr 29, 2008
Apr 29, 2008
81
typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
Apr 28, 2008
Apr 28, 2008
82
Apr 28, 2008
Apr 28, 2008
83
84
85
86
87
88
89
90
91
struct MOJOSHADER_glContext
{
// Allocators...
MOJOSHADER_malloc malloc_fn;
MOJOSHADER_free free_fn;
void *malloc_data;
// The constant register files...
// Man, it kills me how much memory this takes...
Apr 29, 2008
Apr 29, 2008
92
93
94
95
96
97
GLfloat vs_reg_file_f[8192 * 4];
GLint vs_reg_file_i[2047 * 4];
GLint vs_reg_file_b[2047];
GLfloat ps_reg_file_f[8192 * 4];
GLint ps_reg_file_i[2047 * 4];
GLint ps_reg_file_b[2047];
Apr 28, 2008
Apr 28, 2008
98
99
100
101
102
// GL stuff...
int opengl_major;
int opengl_minor;
MOJOSHADER_glProgram *bound_program;
Apr 30, 2008
Apr 30, 2008
103
char profile[16];
Apr 28, 2008
Apr 28, 2008
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
// Extensions...
int have_base_opengl;
int have_GL_ARB_shader_objects;
int have_GL_ARB_vertex_shader;
int have_GL_ARB_fragment_shader;
int have_GL_ARB_shading_language_100;
int have_GL_NV_half_float;
// Entry points...
PFNGLGETSTRINGPROC glGetString;
PFNGLDELETEOBJECTARBPROC glDeleteObject;
PFNGLATTACHOBJECTARBPROC glAttachObject;
PFNGLCOMPILESHADERARBPROC glCompileShader;
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObject;
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObject;
PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArray;
PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArray;
PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocation;
PFNGLGETINFOLOGARBPROC glGetInfoLog;
PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameteriv;
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocation;
PFNGLLINKPROGRAMARBPROC glLinkProgram;
PFNGLSHADERSOURCEARBPROC glShaderSource;
PFNGLUNIFORM1IARBPROC glUniform1i;
PFNGLUNIFORM4FVARBPROC glUniform4fv;
PFNGLUNIFORM4IVARBPROC glUniform4iv;
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObject;
PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointer;
};
static MOJOSHADER_glContext *ctx = NULL;
Apr 28, 2008
Apr 28, 2008
136
Apr 26, 2008
Apr 26, 2008
137
Apr 27, 2008
Apr 27, 2008
138
139
140
141
142
143
144
145
// Error state...
static char error_buffer[1024] = { '\0' };
static void set_error(const char *str)
{
snprintf(error_buffer, sizeof (error_buffer), "%s", str);
} // set_error
Apr 26, 2008
Apr 26, 2008
146
147
148
149
150
151
152
153
154
155
156
157
158
// #define this to force app to supply an allocator, so there's no reference
// to the C runtime's malloc() and free()...
#if MOJOSHADER_FORCE_ALLOCATOR
#define internal_malloc NULL
#define internal_free NULL
#else
static void *internal_malloc(int bytes, void *d) { return malloc(bytes); }
static void internal_free(void *ptr, void *d) { free(ptr); }
#endif
static inline void *Malloc(const size_t len)
{
Apr 28, 2008
Apr 28, 2008
159
void *retval = ctx->malloc_fn(len, ctx->malloc_data);
Apr 27, 2008
Apr 27, 2008
160
161
162
if (retval == NULL)
set_error("out of memory");
return retval;
Apr 26, 2008
Apr 26, 2008
163
164
165
166
} // Malloc
static inline void Free(void *ptr)
{
Apr 27, 2008
Apr 27, 2008
167
if (ptr != NULL)
Apr 28, 2008
Apr 28, 2008
168
ctx->free_fn(ptr, ctx->malloc_data);
Apr 26, 2008
Apr 26, 2008
169
170
171
} // Free
Apr 27, 2008
Apr 27, 2008
172
173
174
175
176
177
const char *MOJOSHADER_glGetError(void)
{
return error_buffer;
} // MOJOSHADER_glGetError
Apr 28, 2008
Apr 28, 2008
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
static void *loadsym(void *(*lookup)(const char *fn), const char *fn, int *ext)
{
void *retval = NULL;
if (lookup != NULL)
{
retval = lookup(fn);
if (retval == NULL)
{
char arbfn[64];
snprintf(arbfn, sizeof (arbfn), "%sARB", fn);
retval = lookup(arbfn);
} // if
} // if
if (retval == NULL)
*ext = 0;
return retval;
} // loadsym
static void lookup_entry_points(void *(*lookup)(const char *fnname))
{
Apr 28, 2008
Apr 28, 2008
200
#define DO_LOOKUP(ext, typ, fn) ctx->fn = (typ) loadsym(lookup, #fn, &ctx->have_##ext)
Apr 28, 2008
Apr 28, 2008
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
DO_LOOKUP(base_opengl, PFNGLGETSTRINGPROC, glGetString);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLDELETEOBJECTARBPROC, glDeleteObject);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLATTACHOBJECTARBPROC, glAttachObject);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLCOMPILESHADERARBPROC, glCompileShader);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLCREATEPROGRAMOBJECTARBPROC, glCreateProgramObject);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLCREATESHADEROBJECTARBPROC, glCreateShaderObject);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLGETINFOLOGARBPROC, glGetInfoLog);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLGETOBJECTPARAMETERIVARBPROC, glGetObjectParameteriv);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLGETUNIFORMLOCATIONARBPROC, glGetUniformLocation);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLLINKPROGRAMARBPROC, glLinkProgram);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLSHADERSOURCEARBPROC, glShaderSource);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM1IARBPROC, glUniform1i);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM4FVARBPROC, glUniform4fv);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLUNIFORM4IVARBPROC, glUniform4iv);
DO_LOOKUP(GL_ARB_shader_objects, PFNGLUSEPROGRAMOBJECTARBPROC, glUseProgramObject);
DO_LOOKUP(GL_ARB_vertex_shader, PFNGLDISABLEVERTEXATTRIBARRAYARBPROC, glDisableVertexAttribArray);
DO_LOOKUP(GL_ARB_vertex_shader, PFNGLENABLEVERTEXATTRIBARRAYARBPROC, glEnableVertexAttribArray);
DO_LOOKUP(GL_ARB_vertex_shader, PFNGLGETATTRIBLOCATIONARBPROC, glGetAttribLocation);
DO_LOOKUP(GL_ARB_vertex_shader, PFNGLVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointer);
#undef DO_LOOKUP
} // lookup_entry_points
static int verify_extension(const char *ext, int have, const char *extlist,
int major, int minor)
{
if (have == 0)
return 0; // don't bother checking, we're missing an entry point.
Apr 30, 2008
Apr 30, 2008
230
231
232
else if (!ctx->have_base_opengl)
return 0; // don't bother checking, we're missing basic functionality.
Apr 28, 2008
Apr 28, 2008
233
// See if it's in the spec for this GL implementation's version.
Apr 28, 2008
Apr 28, 2008
234
235
if (major >= 0)
{
Apr 28, 2008
Apr 28, 2008
236
if ( ((ctx->opengl_major << 16) | (ctx->opengl_minor & 0xFFFF)) >=
Apr 28, 2008
Apr 28, 2008
237
238
239
((major << 16) | (minor & 0xFFFF)) )
return 1;
} // if
Apr 28, 2008
Apr 28, 2008
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
// Not available in the GL version, check the extension list.
const char *ptr = strstr(extlist, ext);
if (ptr == NULL)
return 0;
const char endchar = ptr[strlen(ext)];
if ((endchar == '\0') || (endchar == ' '))
return 1; // extension is in the list.
return 0; // just not supported, fail.
} // verify_extension
static void parse_opengl_version(const char *verstr)
{
if (verstr == NULL)
Apr 28, 2008
Apr 28, 2008
257
ctx->opengl_major = ctx->opengl_minor = 0;
Apr 28, 2008
Apr 28, 2008
258
else
Apr 28, 2008
Apr 28, 2008
259
sscanf(verstr, "%d.%d", &ctx->opengl_major, &ctx->opengl_minor);
Apr 28, 2008
Apr 28, 2008
260
261
262
} // parse_opengl_version
Apr 30, 2008
Apr 30, 2008
263
static void load_extensions(void *(*lookup)(const char *fnname))
Apr 28, 2008
Apr 28, 2008
264
{
Apr 30, 2008
Apr 30, 2008
265
266
const char *extlist = NULL;
Apr 28, 2008
Apr 28, 2008
267
268
269
270
271
272
ctx->have_base_opengl = 1;
ctx->have_GL_ARB_shader_objects = 1;
ctx->have_GL_ARB_vertex_shader = 1;
ctx->have_GL_ARB_fragment_shader = 1;
ctx->have_GL_ARB_shading_language_100 = 1;
ctx->have_GL_NV_half_float = 1;
Apr 28, 2008
Apr 28, 2008
273
274
275
lookup_entry_points(lookup);
Apr 30, 2008
Apr 30, 2008
276
if (!ctx->have_base_opengl)
Apr 28, 2008
Apr 28, 2008
277
set_error("missing basic OpenGL entry points");
Apr 30, 2008
Apr 30, 2008
278
279
280
281
282
else
{
parse_opengl_version((const char *) ctx->glGetString(GL_VERSION));
extlist = (const char *) ctx->glGetString(GL_EXTENSIONS);
} // else
Apr 28, 2008
Apr 28, 2008
283
284
285
286
287
if (extlist == NULL)
extlist = ""; // just in case.
#define VERIFY_EXT(ext, major, minor) \
Apr 28, 2008
Apr 28, 2008
288
ctx->have_##ext = verify_extension(#ext, ctx->have_##ext, extlist, major, minor)
Apr 28, 2008
Apr 28, 2008
289
290
291
292
293
VERIFY_EXT(GL_ARB_shader_objects, 2, 0);
VERIFY_EXT(GL_ARB_vertex_shader, 2, 0);
VERIFY_EXT(GL_ARB_fragment_shader, 2, 0);
VERIFY_EXT(GL_ARB_shading_language_100, 2, 0);
Apr 28, 2008
Apr 28, 2008
294
VERIFY_EXT(GL_NV_half_float, -1, -1);
Apr 28, 2008
Apr 28, 2008
295
296
#undef VERIFY_EXT
Apr 30, 2008
Apr 30, 2008
297
298
299
300
301
302
303
} // load_extensions
static int valid_profile(const char *profile)
{
if (!ctx->have_base_opengl)
return 0;
Apr 28, 2008
Apr 28, 2008
304
Apr 30, 2008
Apr 30, 2008
305
306
#define MUST_HAVE(p, x) \
if (!ctx->have_##x) { set_error(#p " profile needs " #x); return 0; }
Apr 28, 2008
Apr 28, 2008
307
Apr 30, 2008
Apr 30, 2008
308
309
310
311
if (0) {}
#if SUPPORT_PROFILE_GLSL
else if (strcmp(profile, MOJOSHADER_PROFILE_GLSL) == 0)
Apr 28, 2008
Apr 28, 2008
312
{
Apr 30, 2008
Apr 30, 2008
313
314
315
316
317
318
MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_shader_objects);
MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_vertex_shader);
MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_fragment_shader);
MUST_HAVE(MOJOSHADER_PROFILE_GLSL, GL_ARB_shading_language_100);
} // else if
#endif
Apr 28, 2008
Apr 28, 2008
319
320
321
else
{
Apr 30, 2008
Apr 30, 2008
322
set_error("unknown or unsupported profile");
Apr 28, 2008
Apr 28, 2008
323
324
325
return 0;
} // else
Apr 30, 2008
Apr 30, 2008
326
#undef MUST_HAVE
Apr 28, 2008
Apr 28, 2008
327
328
return 1;
Apr 30, 2008
Apr 30, 2008
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
} // valid_profile
const char *MOJOSHADER_glBestProfile(void *(*lookup)(const char *fnname))
{
const char *retval = NULL;
MOJOSHADER_glContext _ctx;
MOJOSHADER_glContext *current_ctx = ctx;
ctx = &_ctx;
memset(ctx, '\0', sizeof (MOJOSHADER_glContext));
load_extensions(lookup);
if (ctx->have_base_opengl)
{
static const char *priority[] = {
MOJOSHADER_PROFILE_GLSL,
};
int i;
for (i = 0; i < STATICARRAYLEN(priority); i++)
{
if (valid_profile(priority[i]))
{
retval = priority[i];
break;
} // if
} // for
Apr 28, 2008
Apr 28, 2008
357
Apr 30, 2008
Apr 30, 2008
358
359
360
if (retval == NULL)
set_error("no profiles available");
} // if
Apr 28, 2008
Apr 28, 2008
361
Apr 30, 2008
Apr 30, 2008
362
363
364
365
366
367
ctx = current_ctx;
return retval;
} // MOJOSHADER_glBestProfile
MOJOSHADER_glContext *MOJOSHADER_glCreateContext(const char *profile,
Apr 28, 2008
Apr 28, 2008
368
369
370
void *(*lookup)(const char *fnname),
MOJOSHADER_malloc m, MOJOSHADER_free f,
void *d)
Apr 26, 2008
Apr 26, 2008
371
{
Apr 29, 2008
Apr 29, 2008
372
MOJOSHADER_glContext *retval = NULL;
Apr 28, 2008
Apr 28, 2008
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
MOJOSHADER_glContext *current_ctx = ctx;
ctx = NULL;
if (m == NULL) m = internal_malloc;
if (f == NULL) f = internal_free;
ctx = (MOJOSHADER_glContext *) m(sizeof (MOJOSHADER_glContext), d);
if (ctx == NULL)
{
set_error("out of memory");
goto init_fail;
} // if
memset(ctx, '\0', sizeof (MOJOSHADER_glContext));
ctx->malloc_fn = m;
ctx->free_fn = f;
ctx->malloc_data = d;
Apr 30, 2008
Apr 30, 2008
390
snprintf(ctx->profile, sizeof (ctx->profile), "%s", profile);
Apr 27, 2008
Apr 27, 2008
391
Apr 30, 2008
Apr 30, 2008
392
393
load_extensions(lookup);
if (!valid_profile(profile))
Apr 28, 2008
Apr 28, 2008
394
goto init_fail;
Apr 26, 2008
Apr 26, 2008
395
396
397
MOJOSHADER_glBindProgram(NULL);
Apr 29, 2008
Apr 29, 2008
398
retval = ctx;
Apr 28, 2008
Apr 28, 2008
399
400
ctx = current_ctx;
return retval;
Apr 28, 2008
Apr 28, 2008
401
402
init_fail:
Apr 28, 2008
Apr 28, 2008
403
404
405
406
if (ctx != NULL)
f(ctx, d);
ctx = current_ctx;
return NULL;
Apr 28, 2008
Apr 28, 2008
407
} // MOJOSHADER_glCreateContext
Apr 26, 2008
Apr 26, 2008
408
409
Apr 28, 2008
Apr 28, 2008
410
411
412
413
414
415
void MOJOSHADER_glMakeContextCurrent(MOJOSHADER_glContext *_ctx)
{
ctx = _ctx;
} // MOJOSHADER_glMakeContextCurrent
Apr 26, 2008
Apr 26, 2008
416
417
418
419
MOJOSHADER_glShader *MOJOSHADER_glCompileShader(const unsigned char *tokenbuf,
const unsigned int bufsize)
{
MOJOSHADER_glShader *retval = NULL;
Apr 27, 2008
Apr 27, 2008
420
GLhandleARB shader = 0;
Apr 28, 2008
Apr 28, 2008
421
422
423
424
const MOJOSHADER_parseData *pd = MOJOSHADER_parse(ctx->profile, tokenbuf,
bufsize, ctx->malloc_fn,
ctx->free_fn,
ctx->malloc_data);
Apr 29, 2008
Apr 29, 2008
425
426
427
428
GLint ok = 0;
const GLenum shader_type = (pd->shader_type == MOJOSHADER_TYPE_PIXEL) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER;
GLint shaderlen = (GLint) pd->output_len;
Apr 26, 2008
Apr 26, 2008
429
if (pd->error != NULL)
Apr 27, 2008
Apr 27, 2008
430
431
{
set_error(pd->error);
Apr 27, 2008
Apr 27, 2008
432
goto compile_shader_fail;
Apr 27, 2008
Apr 27, 2008
433
} // if
Apr 26, 2008
Apr 26, 2008
434
435
436
retval = (MOJOSHADER_glShader *) Malloc(sizeof (MOJOSHADER_glShader));
if (retval == NULL)
Apr 27, 2008
Apr 27, 2008
437
438
goto compile_shader_fail;
Apr 28, 2008
Apr 28, 2008
439
shader = ctx->glCreateShaderObject(shader_type);
Apr 26, 2008
Apr 26, 2008
440
Apr 28, 2008
Apr 28, 2008
441
442
443
ctx->glShaderSource(shader, 1, (const GLchar **) &pd->output, &shaderlen);
ctx->glCompileShader(shader);
ctx->glGetObjectParameteriv(shader, GL_OBJECT_COMPILE_STATUS_ARB, &ok);
Apr 26, 2008
Apr 26, 2008
444
445
446
447
if (!ok)
{
GLsizei len = 0;
Apr 28, 2008
Apr 28, 2008
448
ctx->glGetInfoLog(shader, sizeof (error_buffer), &len, (GLchar *) error_buffer);
Apr 27, 2008
Apr 27, 2008
449
goto compile_shader_fail;
Apr 26, 2008
Apr 26, 2008
450
451
452
453
454
455
} // if
retval->parseData = pd;
retval->handle = shader;
retval->refcount = 1;
return retval;
Apr 27, 2008
Apr 27, 2008
456
457
458
459
460
compile_shader_fail:
MOJOSHADER_freeParseData(pd);
Free(retval);
if (shader != 0)
Apr 28, 2008
Apr 28, 2008
461
ctx->glDeleteObject(shader);
Apr 27, 2008
Apr 27, 2008
462
return NULL;
Apr 26, 2008
Apr 26, 2008
463
464
465
} // MOJOSHADER_glCompileShader
Apr 29, 2008
Apr 29, 2008
466
467
468
469
470
471
472
const MOJOSHADER_parseData *MOJOSHADER_glGetShaderParseData(
MOJOSHADER_glShader *shader)
{
return (shader != NULL) ? shader->parseData : NULL;
} // MOJOSHADER_glGetShaderParseData
Apr 26, 2008
Apr 26, 2008
473
474
475
476
static void shader_unref(MOJOSHADER_glShader *shader)
{
if (shader != NULL)
{
Apr 27, 2008
Apr 27, 2008
477
const uint32 refcount = shader->refcount;
Apr 26, 2008
Apr 26, 2008
478
if (refcount > 1)
Apr 27, 2008
Apr 27, 2008
479
shader->refcount--;
Apr 26, 2008
Apr 26, 2008
480
481
else
{
Apr 28, 2008
Apr 28, 2008
482
ctx->glDeleteObject(shader->handle);
Apr 26, 2008
Apr 26, 2008
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
MOJOSHADER_freeParseData(shader->parseData);
Free(shader);
} // else
} // if
} // shader_unref
static void program_unref(MOJOSHADER_glProgram *program)
{
if (program != NULL)
{
const uint32 refcount = program->refcount;
if (refcount > 1)
program->refcount--;
else
{
Apr 28, 2008
Apr 28, 2008
499
ctx->glDeleteObject(program->handle);
Apr 26, 2008
Apr 26, 2008
500
501
shader_unref(program->vertex);
shader_unref(program->fragment);
Apr 27, 2008
Apr 27, 2008
502
Free(program->attributes);
Apr 27, 2008
Apr 27, 2008
503
Free(program->uniforms);
Apr 26, 2008
Apr 26, 2008
504
505
506
507
508
509
Free(program);
} // else
} // if
} // program_unref
Apr 27, 2008
Apr 27, 2008
510
511
512
513
514
static void lookup_uniforms(MOJOSHADER_glProgram *program,
MOJOSHADER_glShader *shader)
{
int i;
const MOJOSHADER_parseData *pd = shader->parseData;
Apr 27, 2008
Apr 27, 2008
515
const MOJOSHADER_uniform *u = pd->uniforms;
Apr 27, 2008
Apr 27, 2008
516
const MOJOSHADER_shaderType shader_type = pd->shader_type;
Apr 27, 2008
Apr 27, 2008
517
518
519
for (i = 0; i < pd->uniform_count; i++)
{
Apr 28, 2008
Apr 28, 2008
520
const GLint loc = ctx->glGetUniformLocation(program->handle, u[i].name);
Apr 27, 2008
Apr 27, 2008
521
522
523
if (loc != -1) // maybe the Uniform was optimized out?
{
UniformMap *map = &program->uniforms[program->uniform_count];
Apr 27, 2008
Apr 27, 2008
524
map->shader_type = shader_type;
Apr 27, 2008
Apr 27, 2008
525
map->uniform = &u[i];
Apr 27, 2008
Apr 27, 2008
526
map->location = (GLuint) loc;
Apr 27, 2008
Apr 27, 2008
527
528
529
530
531
532
program->uniform_count++;
} // if
} // for
} // lookup_uniforms
Apr 27, 2008
Apr 27, 2008
533
534
535
536
static void lookup_attributes(MOJOSHADER_glProgram *program)
{
int i;
const MOJOSHADER_parseData *pd = program->vertex->parseData;
Apr 27, 2008
Apr 27, 2008
537
const MOJOSHADER_attribute *a = pd->attributes;
Apr 27, 2008
Apr 27, 2008
538
539
540
for (i = 0; i < pd->attribute_count; i++)
{
Apr 28, 2008
Apr 28, 2008
541
const GLint loc = ctx->glGetAttribLocation(program->handle, a->name);
Apr 27, 2008
Apr 27, 2008
542
543
544
545
if (loc != -1) // maybe the Attribute was optimized out?
{
AttributeMap *map = &program->attributes[program->attribute_count];
map->attribute = &a[i];
Apr 27, 2008
Apr 27, 2008
546
map->location = (GLuint) loc;
Apr 27, 2008
Apr 27, 2008
547
548
549
550
551
552
program->attribute_count++;
} // if
} // for
} // lookup_attributes
Apr 26, 2008
Apr 26, 2008
553
554
555
MOJOSHADER_glProgram *MOJOSHADER_glLinkProgram(MOJOSHADER_glShader *vshader,
MOJOSHADER_glShader *pshader)
{
Apr 27, 2008
Apr 27, 2008
556
557
558
if ((vshader == NULL) && (pshader == NULL))
return NULL;
Apr 27, 2008
Apr 27, 2008
559
MOJOSHADER_glProgram *retval = NULL;
Apr 28, 2008
Apr 28, 2008
560
const GLhandleARB program = ctx->glCreateProgramObject();
Apr 29, 2008
Apr 29, 2008
561
int numregs = 0;
Apr 26, 2008
Apr 26, 2008
562
Apr 28, 2008
Apr 28, 2008
563
564
if (vshader != NULL) ctx->glAttachObject(program, vshader->handle);
if (pshader != NULL) ctx->glAttachObject(program, pshader->handle);
Apr 27, 2008
Apr 27, 2008
565
Apr 28, 2008
Apr 28, 2008
566
ctx->glLinkProgram(program);
Apr 27, 2008
Apr 27, 2008
567
568
GLint ok = 0;
Apr 28, 2008
Apr 28, 2008
569
ctx->glGetObjectParameteriv(program, GL_OBJECT_LINK_STATUS_ARB, &ok);
Apr 27, 2008
Apr 27, 2008
570
571
572
if (!ok)
{
GLsizei len = 0;
Apr 28, 2008
Apr 28, 2008
573
ctx->glGetInfoLog(program, sizeof (error_buffer), &len, (GLchar *) error_buffer);
Apr 27, 2008
Apr 27, 2008
574
575
goto link_program_fail;
} // if
Apr 26, 2008
Apr 26, 2008
576
Apr 27, 2008
Apr 27, 2008
577
578
retval = (MOJOSHADER_glProgram *) Malloc(sizeof (MOJOSHADER_glProgram));
if (retval == NULL)
Apr 27, 2008
Apr 27, 2008
579
580
goto link_program_fail;
memset(retval, '\0', sizeof (MOJOSHADER_glProgram));
Apr 27, 2008
Apr 27, 2008
581
582
583
if (vshader != NULL) numregs += vshader->parseData->uniform_count;
if (pshader != NULL) numregs += pshader->parseData->uniform_count;
Apr 27, 2008
Apr 27, 2008
584
585
586
retval->uniforms = (UniformMap *) Malloc(sizeof (UniformMap) * numregs);
if (retval->uniforms == NULL)
goto link_program_fail;
Apr 27, 2008
Apr 27, 2008
587
memset(retval->uniforms, '\0', sizeof (UniformMap) * numregs);
Apr 27, 2008
Apr 27, 2008
588
589
590
591
592
retval->handle = program;
retval->vertex = vshader;
retval->fragment = pshader;
retval->refcount = 1;
Apr 26, 2008
Apr 26, 2008
593
594
if (vshader != NULL)
Apr 27, 2008
Apr 27, 2008
595
{
Apr 27, 2008
Apr 27, 2008
596
597
598
599
600
601
retval->attributes = (AttributeMap *) Malloc(sizeof (AttributeMap) *
vshader->parseData->attribute_count);
if (retval->attributes == NULL)
goto link_program_fail;
lookup_attributes(retval);
Apr 27, 2008
Apr 27, 2008
602
lookup_uniforms(retval, vshader);
Apr 26, 2008
Apr 26, 2008
603
vshader->refcount++;
Apr 27, 2008
Apr 27, 2008
604
605
} // if
Apr 26, 2008
Apr 26, 2008
606
if (pshader != NULL)
Apr 27, 2008
Apr 27, 2008
607
608
{
lookup_uniforms(retval, pshader);
Apr 26, 2008
Apr 26, 2008
609
pshader->refcount++;
Apr 27, 2008
Apr 27, 2008
610
} // if
Apr 27, 2008
Apr 27, 2008
611
612
return retval;
Apr 27, 2008
Apr 27, 2008
613
614
615
616
link_program_fail:
if (retval != NULL)
{
Apr 27, 2008
Apr 27, 2008
617
618
Free(retval->uniforms);
Free(retval->attributes);
Apr 27, 2008
Apr 27, 2008
619
620
621
Free(retval);
} // if
Apr 28, 2008
Apr 28, 2008
622
ctx->glDeleteObject(program);
Apr 27, 2008
Apr 27, 2008
623
return NULL;
Apr 26, 2008
Apr 26, 2008
624
625
626
627
628
} // MOJOSHADER_glLinkProgram
void MOJOSHADER_glBindProgram(MOJOSHADER_glProgram *program)
{
Apr 27, 2008
Apr 27, 2008
629
GLhandleARB handle = 0;
Apr 27, 2008
Apr 27, 2008
630
int i;
Apr 27, 2008
Apr 27, 2008
631
Apr 28, 2008
Apr 28, 2008
632
if (program == ctx->bound_program)
Apr 27, 2008
Apr 27, 2008
633
634
635
return; // nothing to do.
// Disable any client-side arrays the current program could have used.
Apr 28, 2008
Apr 28, 2008
636
637
// !!! FIXME: don't disable yet...see which ones get reused, and disable
// !!! FIXME: only what we don't need in MOJOSHADER_glProgramReady().
Apr 28, 2008
Apr 28, 2008
638
if (ctx->bound_program != NULL)
Apr 27, 2008
Apr 27, 2008
639
{
Apr 28, 2008
Apr 28, 2008
640
641
const int count = ctx->bound_program->attribute_count;
for (i = 0; i < count; i++)
Apr 27, 2008
Apr 27, 2008
642
{
Apr 28, 2008
Apr 28, 2008
643
644
const AttributeMap *map = &ctx->bound_program->attributes[i];
ctx->glDisableVertexAttribArray(map->location);
Apr 27, 2008
Apr 27, 2008
645
646
647
} // if
} // for
Apr 26, 2008
Apr 26, 2008
648
649
650
651
652
653
if (program != NULL)
{
handle = program->handle;
program->refcount++;
} // if
Apr 28, 2008
Apr 28, 2008
654
655
656
ctx->glUseProgramObject(handle);
program_unref(ctx->bound_program);
ctx->bound_program = program;
Apr 26, 2008
Apr 26, 2008
657
658
659
} // MOJOSHADER_glBindProgram
Apr 30, 2008
Apr 30, 2008
660
static inline uint minuint(const uint a, const uint b)
Apr 27, 2008
Apr 27, 2008
661
{
Apr 30, 2008
Apr 30, 2008
662
663
return ((a < b) ? a : b);
} // minuint
Apr 27, 2008
Apr 27, 2008
664
665
Apr 26, 2008
Apr 26, 2008
666
void MOJOSHADER_glSetVertexShaderUniformF(unsigned int idx, const float *data,
Apr 27, 2008
Apr 27, 2008
667
unsigned int vec4n)
Apr 26, 2008
Apr 26, 2008
668
{
Apr 28, 2008
Apr 28, 2008
669
const uint maxregs = STATICARRAYLEN(ctx->vs_reg_file_f) / 4;
Apr 27, 2008
Apr 27, 2008
670
671
if (idx < maxregs)
{
Apr 29, 2008
Apr 29, 2008
672
assert(sizeof (GLfloat) == sizeof (float));
Apr 30, 2008
Apr 30, 2008
673
const uint cpy = (minuint(maxregs - idx, vec4n) * sizeof (*data)) * 4;
Apr 28, 2008
Apr 28, 2008
674
memcpy(ctx->vs_reg_file_f + (idx * 4), data, cpy);
Apr 27, 2008
Apr 27, 2008
675
} // if
Apr 26, 2008
Apr 26, 2008
676
677
678
679
} // MOJOSHADER_glSetVertexShaderUniformF
void MOJOSHADER_glSetVertexShaderUniformI(unsigned int idx, const int *data,
Apr 27, 2008
Apr 27, 2008
680
unsigned int ivec4n)
Apr 26, 2008
Apr 26, 2008
681
{
Apr 28, 2008
Apr 28, 2008
682
const uint maxregs = STATICARRAYLEN(ctx->vs_reg_file_i) / 4;
Apr 27, 2008
Apr 27, 2008
683
684
if (idx < maxregs)
{
Apr 29, 2008
Apr 29, 2008
685
assert(sizeof (GLint) == sizeof (int));
Apr 30, 2008
Apr 30, 2008
686
const uint cpy = (minuint(maxregs - idx, ivec4n) * sizeof (*data)) * 4;
Apr 28, 2008
Apr 28, 2008
687
memcpy(ctx->vs_reg_file_i + (idx * 4), data, cpy);
Apr 27, 2008
Apr 27, 2008
688
} // if
Apr 26, 2008
Apr 26, 2008
689
690
691
692
693
694
} // MOJOSHADER_glSetVertexShaderUniformI
void MOJOSHADER_glSetVertexShaderUniformB(unsigned int idx, const int *data,
unsigned int bcount)
{
Apr 28, 2008
Apr 28, 2008
695
const uint maxregs = STATICARRAYLEN(ctx->vs_reg_file_f) / 4;
Apr 27, 2008
Apr 27, 2008
696
697
if (idx < maxregs)
{
Apr 29, 2008
Apr 29, 2008
698
GLint *wptr = ctx->vs_reg_file_b + idx;
Apr 30, 2008
Apr 30, 2008
699
GLint *endptr = wptr + minuint(maxregs - idx, bcount);
Apr 27, 2008
Apr 27, 2008
700
701
702
while (wptr != endptr)
*(wptr++) = *(data++) ? 1 : 0;
} // if
Apr 26, 2008
Apr 26, 2008
703
704
705
706
} // MOJOSHADER_glSetVertexShaderUniformB
void MOJOSHADER_glSetPixelShaderUniformF(unsigned int idx, const float *data,
Apr 27, 2008
Apr 27, 2008
707
unsigned int vec4n)
Apr 26, 2008
Apr 26, 2008
708
{
Apr 28, 2008
Apr 28, 2008
709
const uint maxregs = STATICARRAYLEN(ctx->ps_reg_file_f) / 4;
Apr 27, 2008
Apr 27, 2008
710
711
if (idx < maxregs)
{
Apr 29, 2008
Apr 29, 2008
712
assert(sizeof (GLfloat) == sizeof (float));
Apr 30, 2008
Apr 30, 2008
713
const uint cpy = (minuint(maxregs - idx, vec4n) * sizeof (*data)) * 4;
Apr 28, 2008
Apr 28, 2008
714
memcpy(ctx->ps_reg_file_f + (idx * 4), data, cpy);
Apr 27, 2008
Apr 27, 2008
715
} // if
Apr 26, 2008
Apr 26, 2008
716
717
718
719
} // MOJOSHADER_glSetPixelShaderUniformF
void MOJOSHADER_glSetPixelShaderUniformI(unsigned int idx, const int *data,
Apr 27, 2008
Apr 27, 2008
720
unsigned int ivec4n)
Apr 26, 2008
Apr 26, 2008
721
{
Apr 28, 2008
Apr 28, 2008
722
const uint maxregs = STATICARRAYLEN(ctx->ps_reg_file_i) / 4;
Apr 27, 2008
Apr 27, 2008
723
724
if (idx < maxregs)
{
Apr 29, 2008
Apr 29, 2008
725
assert(sizeof (GLint) == sizeof (int));
Apr 30, 2008
Apr 30, 2008
726
const uint cpy = (minuint(maxregs - idx, ivec4n) * sizeof (*data)) * 4;
Apr 28, 2008
Apr 28, 2008
727
memcpy(ctx->ps_reg_file_i + (idx * 4), data, cpy);
Apr 27, 2008
Apr 27, 2008
728
} // if
Apr 26, 2008
Apr 26, 2008
729
730
731
732
} // MOJOSHADER_glSetPixelShaderUniformI
void MOJOSHADER_glSetPixelShaderUniformB(unsigned int idx, const int *data,
Apr 27, 2008
Apr 27, 2008
733
unsigned int bcount)
Apr 26, 2008
Apr 26, 2008
734
{
Apr 28, 2008
Apr 28, 2008
735
const uint maxregs = STATICARRAYLEN(ctx->ps_reg_file_f) / 4;
Apr 27, 2008
Apr 27, 2008
736
737
if (idx < maxregs)
{
Apr 29, 2008
Apr 29, 2008
738
GLint *wptr = ctx->ps_reg_file_b + idx;
Apr 30, 2008
Apr 30, 2008
739
GLint *endptr = wptr + minuint(maxregs - idx, bcount);
Apr 27, 2008
Apr 27, 2008
740
741
742
while (wptr != endptr)
*(wptr++) = *(data++) ? 1 : 0;
} // if
Apr 26, 2008
Apr 26, 2008
743
744
745
} // MOJOSHADER_glSetPixelShaderUniformB
Apr 27, 2008
Apr 27, 2008
746
747
748
749
static inline GLenum opengl_attr_type(const MOJOSHADER_attributeType type)
{
switch (type)
{
Apr 28, 2008
Apr 28, 2008
750
case MOJOSHADER_ATTRIBUTE_UNKNOWN: return GL_NONE; // oh well.
Apr 27, 2008
Apr 27, 2008
751
752
753
case MOJOSHADER_ATTRIBUTE_BYTE: return GL_BYTE;
case MOJOSHADER_ATTRIBUTE_UBYTE: return GL_UNSIGNED_BYTE;
case MOJOSHADER_ATTRIBUTE_SHORT: return GL_SHORT;
Apr 27, 2008
Apr 27, 2008
754
case MOJOSHADER_ATTRIBUTE_USHORT: return GL_UNSIGNED_SHORT;
Apr 27, 2008
Apr 27, 2008
755
756
757
758
case MOJOSHADER_ATTRIBUTE_INT: return GL_INT;
case MOJOSHADER_ATTRIBUTE_UINT: return GL_UNSIGNED_INT;
case MOJOSHADER_ATTRIBUTE_FLOAT: return GL_FLOAT;
case MOJOSHADER_ATTRIBUTE_DOUBLE: return GL_DOUBLE;
Apr 28, 2008
Apr 28, 2008
759
760
case MOJOSHADER_ATTRIBUTE_HALF_FLOAT:
Apr 28, 2008
Apr 28, 2008
761
if (ctx->have_GL_NV_half_float)
Apr 28, 2008
Apr 28, 2008
762
763
return GL_HALF_FLOAT_NV;
break;
Apr 27, 2008
Apr 27, 2008
764
765
766
767
768
769
} // switch
return GL_NONE; // oh well. Raises a GL error later.
} // opengl_attr_type
Apr 26, 2008
Apr 26, 2008
770
771
772
773
774
775
void MOJOSHADER_glSetVertexAttribute(MOJOSHADER_usage usage,
int index, unsigned int size,
MOJOSHADER_attributeType type,
int normalized, unsigned int stride,
const void *ptr)
{
Apr 28, 2008
Apr 28, 2008
776
if ((ctx->bound_program == NULL) || (ctx->bound_program->vertex == NULL))
Apr 27, 2008
Apr 27, 2008
777
778
return;
Apr 28, 2008
Apr 28, 2008
779
780
781
const GLenum gl_type = opengl_attr_type(type);
const GLboolean norm = (normalized) ? GL_TRUE : GL_FALSE;
GLuint gl_index = 0;
Apr 27, 2008
Apr 27, 2008
782
Apr 28, 2008
Apr 28, 2008
783
784
785
// We have to map POSITION0 to generic vertex attribute 0; the
// GL_ARB_vertex_shader spec says this is equivalent to using
// glVertexPointer(), but without the limitations of that entry point.
Apr 27, 2008
Apr 27, 2008
786
Apr 28, 2008
Apr 28, 2008
787
if ((usage != MOJOSHADER_USAGE_POSITION) || (index != 0))
Apr 27, 2008
Apr 27, 2008
788
{
Apr 28, 2008
Apr 28, 2008
789
790
791
792
793
794
int i;
const int count = ctx->bound_program->attribute_count;
for (i = 0; i < count; i++)
{
const AttributeMap *map = &ctx->bound_program->attributes[i];
const MOJOSHADER_attribute *a = map->attribute;
Apr 27, 2008
Apr 27, 2008
795
Apr 28, 2008
Apr 28, 2008
796
797
// !!! FIXME: is this array guaranteed to be sorted by usage?
// !!! FIXME: if so, we can break if a->usage > usage.
Apr 27, 2008
Apr 27, 2008
798
Apr 28, 2008
Apr 28, 2008
799
800
801
802
803
804
if ((a->usage == usage) && (a->index == index))
{
gl_index = map->location;
break;
} // if
} // for
Apr 27, 2008
Apr 27, 2008
805
Apr 28, 2008
Apr 28, 2008
806
807
if (gl_index == 0)
return; // nothing to do, this shader doesn't use this stream.
Apr 27, 2008
Apr 27, 2008
808
} // if
Apr 28, 2008
Apr 28, 2008
809
810
811
ctx->glVertexAttribPointer(gl_index, size, gl_type, norm, stride, ptr);
ctx->glEnableVertexAttribArray(gl_index);
Apr 26, 2008
Apr 26, 2008
812
813
814
815
816
} // MOJOSHADER_glSetVertexAttribute
void MOJOSHADER_glProgramReady(void)
{
Apr 27, 2008
Apr 27, 2008
817
818
int i;
Apr 28, 2008
Apr 28, 2008
819
if (ctx->bound_program == NULL)
Apr 27, 2008
Apr 27, 2008
820
821
822
823
824
return; // nothing to do.
// !!! FIXME: don't push Uniforms if we know they haven't changed.
// push Uniforms to the program from our register files...
Apr 28, 2008
Apr 28, 2008
825
826
const int count = ctx->bound_program->uniform_count;
for (i = 0; i < count; i++)
Apr 27, 2008
Apr 27, 2008
827
{
Apr 28, 2008
Apr 28, 2008
828
const UniformMap *map = &ctx->bound_program->uniforms[i];
Apr 27, 2008
Apr 27, 2008
829
830
831
832
833
834
835
836
837
const MOJOSHADER_uniform *u = map->uniform;
const MOJOSHADER_uniformType type = u->type;
const MOJOSHADER_shaderType shader_type = map->shader_type;
const int index = u->index;
const GLint location = map->location;
if (shader_type == MOJOSHADER_TYPE_VERTEX)
{
if (type == MOJOSHADER_UNIFORM_FLOAT)
Apr 28, 2008
Apr 28, 2008
838
ctx->glUniform4fv(location, 1, &ctx->vs_reg_file_f[index * 4]);
Apr 27, 2008
Apr 27, 2008
839
else if (type == MOJOSHADER_UNIFORM_INT)
Apr 28, 2008
Apr 28, 2008
840
ctx->glUniform4iv(location, 1, &ctx->vs_reg_file_i[index * 4]);
Apr 27, 2008
Apr 27, 2008
841
else if (type == MOJOSHADER_UNIFORM_BOOL)
Apr 28, 2008
Apr 28, 2008
842
ctx->glUniform1i(location, ctx->vs_reg_file_b[index]);
Apr 27, 2008
Apr 27, 2008
843
844
845
846
847
} // if
else if (shader_type == MOJOSHADER_TYPE_PIXEL)
{
if (type == MOJOSHADER_UNIFORM_FLOAT)
Apr 28, 2008
Apr 28, 2008
848
ctx->glUniform4fv(location, 1, &ctx->ps_reg_file_f[index * 4]);
Apr 27, 2008
Apr 27, 2008
849
else if (type == MOJOSHADER_UNIFORM_INT)
Apr 28, 2008
Apr 28, 2008
850
ctx->glUniform4iv(location, 1, &ctx->ps_reg_file_i[index * 4]);
Apr 27, 2008
Apr 27, 2008
851
else if (type == MOJOSHADER_UNIFORM_BOOL)
Apr 28, 2008
Apr 28, 2008
852
ctx->glUniform1i(location, ctx->ps_reg_file_b[index]);
Apr 27, 2008
Apr 27, 2008
853
854
} // else if
} // for
Apr 26, 2008
Apr 26, 2008
855
856
857
} // MOJOSHADER_glProgramReady
Apr 27, 2008
Apr 27, 2008
858
void MOJOSHADER_glDeleteProgram(MOJOSHADER_glProgram *program)
Apr 26, 2008
Apr 26, 2008
859
{
Apr 27, 2008
Apr 27, 2008
860
program_unref(program);
Apr 26, 2008
Apr 26, 2008
861
862
863
} // MOJOSHADER_glDeleteProgram
Apr 27, 2008
Apr 27, 2008
864
void MOJOSHADER_glDeleteShader(MOJOSHADER_glShader *shader)
Apr 26, 2008
Apr 26, 2008
865
866
867
868
869
{
shader_unref(shader);
} // MOJOSHADER_glDeleteShader
Apr 28, 2008
Apr 28, 2008
870
void MOJOSHADER_glDestroyContext(MOJOSHADER_glContext *_ctx)
Apr 26, 2008
Apr 26, 2008
871
{
Apr 28, 2008
Apr 28, 2008
872
873
MOJOSHADER_glContext *current_ctx = ctx;
ctx = _ctx;
Apr 26, 2008
Apr 26, 2008
874
MOJOSHADER_glBindProgram(NULL);
Apr 28, 2008
Apr 28, 2008
875
lookup_entry_points(NULL);
Apr 28, 2008
Apr 28, 2008
876
877
Free(ctx);
ctx = ((current_ctx == _ctx) ? NULL : current_ctx);
Apr 28, 2008
Apr 28, 2008
878
} // MOJOSHADER_glDestroyContext
Apr 26, 2008
Apr 26, 2008
879
880
// end of mojoshader_opengl.c ...