/
mojoshader_opengl.c
3086 lines (2624 loc) · 103 KB
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.
*/
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
16
#ifdef _WIN32
17
18
19
20
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h> // GL headers need this for WINGDIAPI definition.
#endif
21
#if (defined(__APPLE__) && defined(__MACH__))
22
23
#include "TargetConditionals.h"
#if !TARGET_OS_IPHONE && !TARGET_OS_TV
24
#define PLATFORM_MACOSX 1
25
26
#endif /* !TARGET_OS_IPHONE && !TARGET_OS_TV */
#endif /* (defined(__APPLE__) && defined(__MACH__)) */
27
28
29
30
31
#if PLATFORM_MACOSX
#include <Carbon/Carbon.h>
#endif
32
33
34
#define __MOJOSHADER_INTERNAL__ 1
#include "mojoshader_internal.h"
35
#define GL_GLEXT_LEGACY 1
36
37
#include "GL/gl.h"
#include "GL/glext.h"
38
39
40
41
42
43
44
#ifndef GL_HALF_FLOAT_NV
#define GL_HALF_FLOAT_NV 0x140B
#endif
#ifndef GL_HALF_FLOAT_ARB
#define GL_HALF_FLOAT_ARB 0x140B
45
46
47
48
49
50
#endif
#ifndef GL_HALF_FLOAT_OES
#define GL_HALF_FLOAT_OES 0x8D61
#endif
51
52
53
54
// this happens to be the same value for ARB1 and GLSL.
#ifndef GL_PROGRAM_POINT_SIZE
#define GL_PROGRAM_POINT_SIZE 0x8642
#endif
55
56
57
58
struct MOJOSHADER_glShader
{
const MOJOSHADER_parseData *parseData;
59
GLuint handle;
60
61
62
uint32 refcount;
};
63
64
typedef struct
{
65
MOJOSHADER_shaderType shader_type;
66
const MOJOSHADER_uniform *uniform;
67
GLint location;
68
69
} UniformMap;
70
71
typedef struct
{
72
const MOJOSHADER_attribute *attribute;
73
GLint location;
74
75
} AttributeMap;
76
77
struct MOJOSHADER_glProgram
{
78
79
MOJOSHADER_glShader *vertex;
MOJOSHADER_glShader *fragment;
80
GLuint handle;
81
uint32 generation;
82
uint32 uniform_count;
83
uint32 texbem_count;
84
UniformMap *uniforms;
85
uint32 attribute_count;
86
AttributeMap *attributes;
87
88
89
90
91
92
93
94
95
96
97
98
size_t vs_uniforms_float4_count;
GLfloat *vs_uniforms_float4;
size_t vs_uniforms_int4_count;
GLint *vs_uniforms_int4;
size_t vs_uniforms_bool_count;
GLint *vs_uniforms_bool;
size_t ps_uniforms_float4_count;
GLfloat *ps_uniforms_float4;
size_t ps_uniforms_int4_count;
GLint *ps_uniforms_int4;
size_t ps_uniforms_bool_count;
GLint *ps_uniforms_bool;
99
100
uint32 refcount;
101
102
103
int uses_pointsize;
104
105
106
// 10 is apparently the resource limit according to SM3 -flibit
GLint vertex_attrib_loc[MOJOSHADER_USAGE_TOTAL][10];
107
// GLSL uses these...location of uniform arrays.
108
109
110
111
112
113
GLint vs_float4_loc;
GLint vs_int4_loc;
GLint vs_bool_loc;
GLint ps_float4_loc;
GLint ps_int4_loc;
GLint ps_bool_loc;
114
115
116
117
// Numerous fixes for coordinate system mismatches
GLint ps_vpos_flip_loc;
int current_vpos_flip[2];
118
119
120
121
#ifdef MOJOSHADER_FLIP_RENDERTARGET
GLint vs_flip_loc;
int current_flip;
#endif
122
123
};
124
125
126
127
#ifndef WINGDIAPI
#define WINGDIAPI
#endif
128
// Entry points in base OpenGL that lack function pointer prototypes...
129
130
typedef WINGDIAPI void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
typedef WINGDIAPI const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
131
typedef WINGDIAPI GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
132
133
typedef WINGDIAPI void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
typedef WINGDIAPI void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
134
135
136
137
138
// Max entries for each register file type...
#define MAX_REG_FILE_F 8192
#define MAX_REG_FILE_I 2047
#define MAX_REG_FILE_B 2047
139
#define MAX_TEXBEMS 3 // ps_1_1 allows 4 texture stages, texbem can't use t0.
140
141
142
143
144
145
146
147
148
struct MOJOSHADER_glContext
{
// Allocators...
MOJOSHADER_malloc malloc_fn;
MOJOSHADER_free free_fn;
void *malloc_data;
// The constant register files...
149
150
// !!! FIXME: Man, it kills me how much memory this takes...
// !!! FIXME: ... make this dynamically allocated on demand.
151
152
153
154
155
156
GLfloat vs_reg_file_f[MAX_REG_FILE_F * 4];
GLint vs_reg_file_i[MAX_REG_FILE_I * 4];
uint8 vs_reg_file_b[MAX_REG_FILE_B];
GLfloat ps_reg_file_f[MAX_REG_FILE_F * 4];
GLint ps_reg_file_i[MAX_REG_FILE_I * 4];
uint8 ps_reg_file_b[MAX_REG_FILE_B];
157
GLuint sampler_reg_file[16];
158
GLfloat texbem_state[MAX_TEXBEMS * 6];
159
160
161
162
// This increments every time we change the register files.
uint32 generation;
163
164
165
// This keeps track of implicitly linked programs.
HashTable *linker_cache;
166
// This tells us which vertex attribute arrays we have enabled.
167
GLint max_attrs;
168
169
170
uint8 want_attr[32];
uint8 have_attr[32];
171
172
173
// This shadows vertex attribute and divisor states.
GLuint attr_divisor[32];
174
175
176
// rarely used, so we don't touch when we don't have to.
int pointsize_enabled;
177
178
179
// GL stuff...
int opengl_major;
int opengl_minor;
180
181
int glsl_major;
int glsl_minor;
182
MOJOSHADER_glProgram *bound_program;
183
char profile[16];
184
185
186
187
188
189
#ifdef MOJOSHADER_XNA4_VERTEX_TEXTURES
// Vertex texture sampler offset...
int vertex_sampler_offset;
#endif
190
// Extensions...
191
192
int have_core_opengl;
int have_opengl_2; // different entry points than ARB extensions.
193
int have_opengl_3; // different extension query.
194
int have_opengl_es; // different extension requirements
195
196
197
198
199
200
201
202
203
204
205
206
207
int have_GL_ARB_vertex_program;
int have_GL_ARB_fragment_program;
int have_GL_NV_vertex_program2_option;
int have_GL_NV_fragment_program2;
int have_GL_NV_vertex_program3;
int have_GL_NV_gpu_program4;
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;
int have_GL_ARB_half_float_vertex;
int have_GL_OES_vertex_half_float;
208
int have_GL_ARB_instanced_arrays;
209
210
211
// Entry points...
PFNGLGETSTRINGPROC glGetString;
212
PFNGLGETSTRINGIPROC glGetStringi;
213
PFNGLGETERRORPROC glGetError;
214
PFNGLGETINTEGERVPROC glGetIntegerv;
215
216
PFNGLENABLEPROC glEnable;
PFNGLDISABLEPROC glDisable;
217
218
219
220
221
222
223
224
225
226
PFNGLDELETESHADERPROC glDeleteShader;
PFNGLDELETEPROGRAMPROC glDeleteProgram;
PFNGLATTACHSHADERPROC glAttachShader;
PFNGLCOMPILESHADERPROC glCompileShader;
PFNGLCREATESHADERPROC glCreateShader;
PFNGLCREATEPROGRAMPROC glCreateProgram;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
227
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
228
229
230
231
232
233
234
PFNGLGETSHADERIVPROC glGetShaderiv;
PFNGLGETPROGRAMIVPROC glGetProgramiv;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
PFNGLLINKPROGRAMPROC glLinkProgram;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLUNIFORM1IPROC glUniform1i;
PFNGLUNIFORM1IVPROC glUniform1iv;
235
PFNGLUNIFORM2FPROC glUniform2f;
236
237
238
#ifdef MOJOSHADER_FLIP_RENDERTARGET
PFNGLUNIFORM1FPROC glUniform1f;
#endif
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
PFNGLUNIFORM4FVPROC glUniform4fv;
PFNGLUNIFORM4IVPROC glUniform4iv;
PFNGLUSEPROGRAMPROC glUseProgram;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
PFNGLUNIFORM1IARBPROC glUniform1iARB;
PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
262
PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
263
PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
264
PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC glProgramLocalParameterI4ivNV;
265
266
267
268
PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
PFNGLBINDPROGRAMARBPROC glBindProgramARB;
PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
269
PFNGLVERTEXATTRIBDIVISORARBPROC glVertexAttribDivisorARB;
270
271
272
// interface for profile-specific things.
int (*profileMaxUniforms)(MOJOSHADER_shaderType shader_type);
273
int (*profileCompileShader)(const MOJOSHADER_parseData *pd, GLuint *s);
274
275
void (*profileDeleteShader)(const GLuint shader);
void (*profileDeleteProgram)(const GLuint program);
276
GLint (*profileGetAttribLocation)(MOJOSHADER_glProgram *program, int idx);
277
GLint (*profileGetUniformLocation)(MOJOSHADER_glProgram *program, MOJOSHADER_glShader *shader, int idx);
278
GLint (*profileGetSamplerLocation)(MOJOSHADER_glProgram *, MOJOSHADER_glShader *, int);
279
GLuint (*profileLinkProgram)(MOJOSHADER_glShader *, MOJOSHADER_glShader *);
280
void (*profileFinalInitProgram)(MOJOSHADER_glProgram *program);
281
void (*profileUseProgram)(MOJOSHADER_glProgram *program);
282
283
284
void (*profilePushConstantArray)(MOJOSHADER_glProgram *, const MOJOSHADER_uniform *, const GLfloat *);
void (*profilePushUniforms)(void);
void (*profilePushSampler)(GLint loc, GLuint sampler);
285
286
int (*profileMustPushConstantArrays)(void);
int (*profileMustPushSamplers)(void);
287
void (*profileToggleProgramPointSize)(int enable);
288
289
};
290
291
static MOJOSHADER_glContext *ctx = NULL;
292
293
294
295
296
297
298
299
300
// 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
301
302
303
304
305
306
307
308
#if PLATFORM_MACOSX
static inline int macosx_version_atleast(int x, int y, int z)
{
static int checked = 0;
static int combined = 0;
if (!checked)
{
309
310
311
312
SInt32 ver = 0;
SInt32 major = 0;
SInt32 minor = 0;
SInt32 patch = 0;
313
314
315
int convert = 0;
if (Gestalt(gestaltSystemVersion, &ver) != noErr)
316
{
317
ver = 0x1000; // oh well.
318
319
convert = 1; // split (ver) into (major),(minor),(patch).
}
320
else if (ver < 0x1030)
321
{
322
convert = 1; // split (ver) into (major),(minor),(patch).
323
}
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
else
{
// presumably this won't fail. But if it does, we'll just use the
// original version value. This might cut the value--10.12.11 will
// come out to 10.9.9, for example--but it's better than nothing.
if (Gestalt(gestaltSystemVersionMajor, &major) != noErr)
convert = 1;
else if (Gestalt(gestaltSystemVersionMinor, &minor) != noErr)
convert = 1;
else if (Gestalt(gestaltSystemVersionBugFix, &patch) != noErr)
convert = 1;
} // else
if (convert)
{
major = ((ver & 0xFF00) >> 8);
major = (((major / 16) * 10) + (major % 16));
minor = ((ver & 0xF0) >> 4);
patch = (ver & 0xF);
343
} // if
344
345
346
347
348
combined = (major << 16) | (minor << 8) | patch;
checked = 1;
} // if
349
return (combined >= ((x << 16) | (y << 8) | z));
350
351
352
} // macosx_version_atleast
#endif
353
354
355
356
static inline void out_of_memory(void)
{
set_error("out of memory");
} // out_of_memory
357
358
359
static inline void *Malloc(const size_t len)
{
360
void *retval = ctx->malloc_fn((int) len, ctx->malloc_data);
361
if (retval == NULL)
362
out_of_memory();
363
return retval;
364
365
366
367
} // Malloc
static inline void Free(void *ptr)
{
368
if (ptr != NULL)
369
ctx->free_fn(ptr, ctx->malloc_data);
370
371
372
} // Free
373
374
375
376
377
378
379
380
381
static inline void toggle_gl_state(GLenum state, int val)
{
if (val)
ctx->glEnable(state);
else
ctx->glDisable(state);
} // toggle_gl_state
382
383
384
385
386
// profile-specific implementations...
#if SUPPORT_PROFILE_GLSL
static inline GLenum glsl_shader_type(const MOJOSHADER_shaderType t)
{
387
// these enums match between core 2.0 and the ARB extensions.
388
389
390
391
392
393
if (t == MOJOSHADER_TYPE_VERTEX)
return GL_VERTEX_SHADER;
else if (t == MOJOSHADER_TYPE_PIXEL)
return GL_FRAGMENT_SHADER;
// !!! FIXME: geometry shaders?
394
assert(0 && "Unknown GLSL shader type!");
395
396
397
398
return GL_NONE;
} // glsl_shader_type
399
400
static int impl_GLSL_MustPushConstantArrays(void) { return 1; }
static int impl_GLSL_MustPushSamplers(void) { return 1; }
401
402
403
static int impl_GLSL_MaxUniforms(MOJOSHADER_shaderType shader_type)
{
404
// these enums match between core 2.0 and the ARB extensions.
405
406
407
GLenum pname = GL_NONE;
GLint val = 0;
if (shader_type == MOJOSHADER_TYPE_VERTEX)
408
pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
409
else if (shader_type == MOJOSHADER_TYPE_PIXEL)
410
pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
411
412
413
414
415
416
417
418
419
420
421
else
return -1;
ctx->glGetIntegerv(pname, &val);
return (int) val;
} // impl_GLSL_MaxUniforms
static int impl_GLSL_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s)
{
GLint ok = 0;
422
const GLint codelen = (GLint) pd->output_len;
423
424
const GLenum shader_type = glsl_shader_type(pd->shader_type);
425
if (ctx->have_opengl_2)
426
{
427
428
429
430
431
432
433
const GLuint shader = ctx->glCreateShader(shader_type);
ctx->glShaderSource(shader, 1, (const GLchar**) &pd->output, &codelen);
ctx->glCompileShader(shader);
ctx->glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
if (!ok)
{
GLsizei len = 0;
434
ctx->glGetShaderInfoLog(shader, sizeof (error_buffer), &len,
435
(GLchar *) error_buffer);
436
ctx->glDeleteShader(shader);
437
438
439
440
441
*s = 0;
return 0;
} // if
*s = shader;
442
} // if
443
444
445
446
447
448
449
450
451
452
453
454
455
else
{
const GLhandleARB shader = ctx->glCreateShaderObjectARB(shader_type);
assert(sizeof (shader) == sizeof (*s)); // not always true on OS X!
ctx->glShaderSourceARB(shader, 1,
(const GLcharARB **) &pd->output, &codelen);
ctx->glCompileShaderARB(shader);
ctx->glGetObjectParameterivARB(shader,GL_OBJECT_COMPILE_STATUS_ARB,&ok);
if (!ok)
{
GLsizei len = 0;
ctx->glGetInfoLogARB(shader, sizeof (error_buffer), &len,
(GLcharARB *) error_buffer);
456
ctx->glDeleteObjectARB(shader);
457
458
459
460
461
462
*s = 0;
return 0;
} // if
*s = (GLuint) shader;
} // else
463
464
465
466
467
468
469
return 1;
} // impl_GLSL_CompileShader
static void impl_GLSL_DeleteShader(const GLuint shader)
{
470
471
472
473
if (ctx->have_opengl_2)
ctx->glDeleteShader(shader);
else
ctx->glDeleteObjectARB((GLhandleARB) shader);
474
475
476
477
478
} // impl_GLSL_DeleteShader
static void impl_GLSL_DeleteProgram(const GLuint program)
{
479
480
481
482
if (ctx->have_opengl_2)
ctx->glDeleteProgram(program);
else
ctx->glDeleteObjectARB((GLhandleARB) program);
483
484
485
486
487
488
} // impl_GLSL_DeleteProgram
static GLint impl_GLSL_GetUniformLocation(MOJOSHADER_glProgram *program,
MOJOSHADER_glShader *shader, int idx)
{
489
return 0; // no-op, we push this as one big-ass array now.
490
491
492
} // impl_GLSL_GetUniformLocation
493
494
495
496
497
498
499
500
501
static inline GLint glsl_uniform_loc(MOJOSHADER_glProgram *program,
const char *name)
{
return ctx->have_opengl_2 ?
ctx->glGetUniformLocation(program->handle, name) :
ctx->glGetUniformLocationARB((GLhandleARB) program->handle, name);
} // glsl_uniform_loc
502
503
504
static GLint impl_GLSL_GetSamplerLocation(MOJOSHADER_glProgram *program,
MOJOSHADER_glShader *shader, int idx)
{
505
return glsl_uniform_loc(program, shader->parseData->samplers[idx].name);
506
507
508
509
510
511
512
} // impl_GLSL_GetSamplerLocation
static GLint impl_GLSL_GetAttribLocation(MOJOSHADER_glProgram *program, int idx)
{
const MOJOSHADER_parseData *pd = program->vertex->parseData;
const MOJOSHADER_attribute *a = pd->attributes;
513
514
515
516
517
518
519
520
521
if (ctx->have_opengl_2)
{
return ctx->glGetAttribLocation(program->handle,
(const GLchar *) a[idx].name);
} // if
return ctx->glGetAttribLocationARB((GLhandleARB) program->handle,
(const GLcharARB *) a[idx].name);
522
523
524
525
526
527
} // impl_GLSL_GetAttribLocation
static GLuint impl_GLSL_LinkProgram(MOJOSHADER_glShader *vshader,
MOJOSHADER_glShader *pshader)
{
528
GLint ok = 0;
529
530
531
532
if (ctx->have_opengl_2)
{
const GLuint program = ctx->glCreateProgram();
533
534
535
if (vshader != NULL) ctx->glAttachShader(program, vshader->handle);
if (pshader != NULL) ctx->glAttachShader(program, pshader->handle);
536
537
538
539
540
541
542
543
544
545
546
547
548
549
ctx->glLinkProgram(program);
ctx->glGetProgramiv(program, GL_LINK_STATUS, &ok);
if (!ok)
{
GLsizei len = 0;
ctx->glGetProgramInfoLog(program, sizeof (error_buffer),
&len, (GLchar *) error_buffer);
ctx->glDeleteProgram(program);
return 0;
} // if
return program;
550
} // if
551
552
553
554
else
{
const GLhandleARB program = ctx->glCreateProgramObjectARB();
assert(sizeof(program) == sizeof(GLuint)); // not always true on OS X!
555
556
557
if (vshader != NULL)
ctx->glAttachObjectARB(program, (GLhandleARB) vshader->handle);
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
if (pshader != NULL)
ctx->glAttachObjectARB(program, (GLhandleARB) pshader->handle);
ctx->glLinkProgramARB(program);
ctx->glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &ok);
if (!ok)
{
GLsizei len = 0;
ctx->glGetInfoLogARB(program, sizeof (error_buffer),
&len, (GLcharARB *) error_buffer);
ctx->glDeleteObjectARB(program);
return 0;
} // if
return (GLuint) program;
} // else
} // impl_GLSL_LinkProgram
577
578
static void impl_GLSL_FinalInitProgram(MOJOSHADER_glProgram *program)
579
{
580
581
582
583
584
585
program->vs_float4_loc = glsl_uniform_loc(program, "vs_uniforms_vec4");
program->vs_int4_loc = glsl_uniform_loc(program, "vs_uniforms_ivec4");
program->vs_bool_loc = glsl_uniform_loc(program, "vs_uniforms_bool");
program->ps_float4_loc = glsl_uniform_loc(program, "ps_uniforms_vec4");
program->ps_int4_loc = glsl_uniform_loc(program, "ps_uniforms_ivec4");
program->ps_bool_loc = glsl_uniform_loc(program, "ps_uniforms_bool");
586
program->ps_vpos_flip_loc = glsl_uniform_loc(program, "vposFlip");
587
588
589
#ifdef MOJOSHADER_FLIP_RENDERTARGET
program->vs_flip_loc = glsl_uniform_loc(program, "vpFlip");
#endif
590
} // impl_GLSL_FinalInitProgram
591
592
593
static void impl_GLSL_UseProgram(MOJOSHADER_glProgram *program)
594
{
595
596
597
598
599
if (ctx->have_opengl_2)
ctx->glUseProgram(program ? program->handle : 0);
else
ctx->glUseProgramObjectARB((GLhandleARB) (program ? program->handle : 0));
} // impl_GLSL_UseProgram
600
601
602
603
604
static void impl_GLSL_PushConstantArray(MOJOSHADER_glProgram *program,
const MOJOSHADER_uniform *u,
const GLfloat *f)
605
{
606
const GLint loc = glsl_uniform_loc(program, u->name);
607
if (loc >= 0) // not optimized out?
608
609
ctx->glUniform4fv(loc, u->array_count, f);
} // impl_GLSL_PushConstantArray
610
611
612
static void impl_GLSL_PushUniforms(void)
613
{
614
const MOJOSHADER_glProgram *program = ctx->bound_program;
615
616
617
assert(program->uniform_count > 0); // don't call with nothing to do!
618
619
620
621
622
623
if (program->vs_float4_loc != -1)
{
ctx->glUniform4fv(program->vs_float4_loc,
program->vs_uniforms_float4_count,
program->vs_uniforms_float4);
} // if
624
625
626
627
628
629
630
if (program->vs_int4_loc != -1)
{
ctx->glUniform4iv(program->vs_int4_loc,
program->vs_uniforms_int4_count,
program->vs_uniforms_int4);
} // if
631
632
633
634
635
636
637
if (program->vs_bool_loc != -1)
{
ctx->glUniform1iv(program->vs_bool_loc,
program->vs_uniforms_bool_count,
program->vs_uniforms_bool);
} // if
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
if (program->ps_float4_loc != -1)
{
ctx->glUniform4fv(program->ps_float4_loc,
program->ps_uniforms_float4_count,
program->ps_uniforms_float4);
} // if
if (program->ps_int4_loc != -1)
{
ctx->glUniform4iv(program->ps_int4_loc,
program->ps_uniforms_int4_count,
program->ps_uniforms_int4);
} // if
if (program->ps_bool_loc != -1)
{
ctx->glUniform1iv(program->ps_bool_loc,
program->ps_uniforms_bool_count,
program->ps_uniforms_bool);
} // if
} // impl_GLSL_PushUniforms
static void impl_GLSL_PushSampler(GLint loc, GLuint sampler)
663
664
{
ctx->glUniform1i(loc, sampler);
665
} // impl_GLSL_PushSampler
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
#endif // SUPPORT_PROFILE_GLSL
#if SUPPORT_PROFILE_ARB1
static inline GLenum arb1_shader_type(const MOJOSHADER_shaderType t)
{
if (t == MOJOSHADER_TYPE_VERTEX)
return GL_VERTEX_PROGRAM_ARB;
else if (t == MOJOSHADER_TYPE_PIXEL)
return GL_FRAGMENT_PROGRAM_ARB;
// !!! FIXME: geometry shaders?
return GL_NONE;
} // arb1_shader_type
682
683
static int impl_ARB1_MustPushConstantArrays(void) { return 0; }
static int impl_ARB1_MustPushSamplers(void) { return 0; }
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
static int impl_ARB1_MaxUniforms(MOJOSHADER_shaderType shader_type)
{
GLint retval = 0;
const GLenum program_type = arb1_shader_type(shader_type);
if (program_type == GL_NONE)
return -1;
ctx->glGetProgramivARB(program_type, GL_MAX_PROGRAM_PARAMETERS_ARB, &retval);
return (int) retval; // !!! FIXME: times four?
} // impl_ARB1_MaxUniforms
static int impl_ARB1_CompileShader(const MOJOSHADER_parseData *pd, GLuint *s)
{
GLint shaderlen = (GLint) pd->output_len;
const GLenum shader_type = arb1_shader_type(pd->shader_type);
GLuint shader = 0;
ctx->glGenProgramsARB(1, &shader);
ctx->glGetError(); // flush any existing error state.
ctx->glBindProgramARB(shader_type, shader);
ctx->glProgramStringARB(shader_type, GL_PROGRAM_FORMAT_ASCII_ARB,
shaderlen, pd->output);
if (ctx->glGetError() == GL_INVALID_OPERATION)
710
{
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
GLint pos = 0;
ctx->glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
const GLubyte *errstr = ctx->glGetString(GL_PROGRAM_ERROR_STRING_ARB);
snprintf(error_buffer, sizeof (error_buffer),
"ARB1 compile error at position %d: %s",
(int) pos, (const char *) errstr);
ctx->glBindProgramARB(shader_type, 0);
ctx->glDeleteProgramsARB(1, &shader);
*s = 0;
return 0;
} // if
*s = shader;
return 1;
} // impl_ARB1_CompileShader
static void impl_ARB1_DeleteShader(const GLuint _shader)
{
GLuint shader = _shader; // const removal.
ctx->glDeleteProgramsARB(1, &shader);
} // impl_ARB1_DeleteShader
static void impl_ARB1_DeleteProgram(const GLuint program)
{
// no-op. ARB1 doesn't have real linked programs.
738
} // impl_ARB1_DeleteProgram
739
740
741
742
static GLint impl_ARB1_GetUniformLocation(MOJOSHADER_glProgram *program,
MOJOSHADER_glShader *shader, int idx)
{
743
return 0; // no-op, we push this as one big-ass array now.
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
} // impl_ARB1_GetUniformLocation
static GLint impl_ARB1_GetSamplerLocation(MOJOSHADER_glProgram *program,
MOJOSHADER_glShader *shader, int idx)
{
return shader->parseData->samplers[idx].index;
} // impl_ARB1_GetSamplerLocation
static GLint impl_ARB1_GetAttribLocation(MOJOSHADER_glProgram *program, int idx)
{
return idx; // map to vertex arrays in the same order as the parseData.
} // impl_ARB1_GetAttribLocation
static GLuint impl_ARB1_LinkProgram(MOJOSHADER_glShader *vshader,
MOJOSHADER_glShader *pshader)
{
// there is no formal linking in ARB1...just return a unique value.
static GLuint retval = 1;
return retval++;
} // impl_ARB1_LinkProgram
768
static void impl_ARB1_FinalInitProgram(MOJOSHADER_glProgram *program)
769
770
{
// no-op.
771
} // impl_ARB1_FinalInitProgram
772
773
774
static void impl_ARB1_UseProgram(MOJOSHADER_glProgram *program)
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
{
GLuint vhandle = 0;
GLuint phandle = 0;
if (program != NULL)
{
if (program->vertex != NULL)
vhandle = program->vertex->handle;
if (program->fragment != NULL)
phandle = program->fragment->handle;
} // if
toggle_gl_state(GL_VERTEX_PROGRAM_ARB, vhandle != 0);
toggle_gl_state(GL_FRAGMENT_PROGRAM_ARB, phandle != 0);
ctx->glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vhandle);
ctx->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, phandle);
791
} // impl_ARB1_UseProgram
792
793
794
795
796
static void impl_ARB1_PushConstantArray(MOJOSHADER_glProgram *program,
const MOJOSHADER_uniform *u,
const GLfloat *f)
797
{
798
799
// no-op. Constant arrays are defined in source code for arb1.
} // impl_ARB1_PushConstantArray
800
801
802
static void impl_ARB1_PushUniforms(void)
803
{
804
805
806
// vertex shader uniforms come first in program->uniforms array.
MOJOSHADER_shaderType shader_type = MOJOSHADER_TYPE_VERTEX;
GLenum arb_shader_type = arb1_shader_type(shader_type);
807
const MOJOSHADER_glProgram *program = ctx->bound_program;
808
809
810
811
812
const uint32 count = program->uniform_count;
const GLfloat *srcf = program->vs_uniforms_float4;
const GLint *srci = program->vs_uniforms_int4;
const GLint *srcb = program->vs_uniforms_bool;
GLint loc = 0;
813
GLint texbem_loc = 0;
814
uint32 i;
815
816
817
assert(count > 0); // shouldn't call this with nothing to do!
818
819
for (i = 0; i < count; i++)
{
820
UniformMap *map = &program->uniforms[i];
821
const MOJOSHADER_shaderType uniform_shader_type = map->shader_type;
822
823
824
const MOJOSHADER_uniform *u = map->uniform;
const MOJOSHADER_uniformType type = u->type;
const int size = u->array_count ? u->array_count : 1;
825
826
assert(!u->constant);
827
828
// Did we switch from vertex to pixel (to geometry, etc)?
829
if (shader_type != uniform_shader_type)
830
{
831
832
833
if (shader_type == MOJOSHADER_TYPE_PIXEL)
texbem_loc = loc;
834
835
// we start with vertex, move to pixel, then to geometry, etc.
// The array should always be sorted as such.
836
if (uniform_shader_type == MOJOSHADER_TYPE_PIXEL)
837
{
838
assert(shader_type == MOJOSHADER_TYPE_VERTEX);
839
840
841
842
843
844
845
srcf = program->ps_uniforms_float4;
srci = program->ps_uniforms_int4;
srcb = program->ps_uniforms_bool;
loc = 0;
} // if
else
{
846
// These should be ordered vertex, then pixel, then geometry.
847
848
assert(0 && "Unexpected shader type");
} // else
849
850
851
shader_type = uniform_shader_type;
arb_shader_type = arb1_shader_type(uniform_shader_type);
852
} // if
853
854
855
856
if (type == MOJOSHADER_UNIFORM_FLOAT)
{
int i;
857
858
for (i = 0; i < size; i++, srcf += 4, loc++)
ctx->glProgramLocalParameter4fvARB(arb_shader_type, loc, srcf);
859
860
861
862
} // if
else if (type == MOJOSHADER_UNIFORM_INT)
{
int i;
863
if (ctx->have_GL_NV_gpu_program4)
864
865
{
// GL_NV_gpu_program4 has integer uniform loading support.
866
867
for (i = 0; i < size; i++, srci += 4, loc++)
ctx->glProgramLocalParameterI4ivNV(arb_shader_type, loc, srci);
868
869
870
} // if
else
{
871
for (i = 0; i < size; i++, srci += 4, loc++)
872
{
873
874
875
876
877
const GLfloat fv[4] = {
(GLfloat) srci[0], (GLfloat) srci[1],
(GLfloat) srci[2], (GLfloat) srci[3]
};
ctx->glProgramLocalParameter4fvARB(arb_shader_type, loc, fv);
878
879
880
881
882
883
} // for
} // else
} // else if
else if (type == MOJOSHADER_UNIFORM_BOOL)
{
int i;
884
if (ctx->have_GL_NV_gpu_program4)
885
886
{
// GL_NV_gpu_program4 has integer uniform loading support.
887
for (i = 0; i < size; i++, srcb++, loc++)
888
{
889
const GLint ib = (GLint) ((*srcb) ? 1 : 0);
890
const GLint iv[4] = { ib, ib, ib, ib };
891
ctx->glProgramLocalParameterI4ivNV(arb_shader_type, loc, iv);
892
893
894
895
} // for
} // if
else
{
896
for (i = 0; i < size; i++, srcb++, loc++)
897
{
898
const GLfloat fb = (GLfloat) ((*srcb) ? 1.0f : 0.0f);
899
const GLfloat fv[4] = { fb, fb, fb, fb };
900
ctx->glProgramLocalParameter4fvARB(arb_shader_type, loc, fv);
901
902
903
904
} // for
} // else
} // else if
} // for
905
906
907
908
909
910
911
912
913
914
915
916
917
918
if (program->texbem_count)
{
const GLenum target = GL_FRAGMENT_PROGRAM_ARB;
GLfloat *srcf = program->ps_uniforms_float4;
srcf += (program->ps_uniforms_float4_count * 4) -
(program->texbem_count * 8);
loc = texbem_loc;
for (i = 0; i < program->texbem_count; i++, srcf += 8)
{
ctx->glProgramLocalParameter4fvARB(target, loc++, srcf);
ctx->glProgramLocalParameter4fvARB(target, loc++, srcf + 4);
} // for
} // if
919
} // impl_ARB1_PushUniforms
920
921
static void impl_ARB1_PushSampler(GLint loc, GLuint sampler)
922
923
924
{
// no-op in this profile...arb1 uses the texture units as-is.
assert(loc == (GLint) sampler);
925
} // impl_ARB1_PushSampler
926
927
928
#endif // SUPPORT_PROFILE_ARB1
929
930
931
932
933
934
935
936
937
938
939
940
941
942
#if SUPPORT_PROFILE_GLSL || SUPPORT_PROFILE_ARB1
static void impl_REAL_ToggleProgramPointSize(int enable)
{
toggle_gl_state(GL_PROGRAM_POINT_SIZE, enable);
} // impl_REAL_ToggleProgramPointSize
static void impl_NOOP_ToggleProgramPointSize(int enable)
{
// No-op, this profile's GL context forces this to always be on
} // impl_NOOP_ToggleProgramPointSize
#endif // SUPPORT_PROFILE_GLSL || SUPPORT_PROFILE_ARB1
943
944
945
946
947
948
949
const char *MOJOSHADER_glGetError(void)
{
return error_buffer;
} // MOJOSHADER_glGetError
950
951
static void *loadsym(MOJOSHADER_glGetProcAddress lookup, void *d,
const char *fn, int *ext)
952
953
954
{
void *retval = NULL;
if (lookup != NULL)
955
retval = lookup(fn, d);
956
957
958
959
960
961
962
if (retval == NULL)
*ext = 0;
return retval;
} // loadsym
963
static void lookup_entry_points(MOJOSHADER_glGetProcAddress lookup, void *d)
964
{
965
#define DO_LOOKUP(ext, typ, fn) { \
966
ctx->fn = (typ) loadsym(lookup, d, #fn, &ctx->have_##ext); \
967
968
}
969
970
971
972
973
DO_LOOKUP(core_opengl, PFNGLGETSTRINGPROC, glGetString);
DO_LOOKUP(core_opengl, PFNGLGETERRORPROC, glGetError);
DO_LOOKUP(core_opengl, PFNGLGETINTEGERVPROC, glGetIntegerv);
DO_LOOKUP(core_opengl, PFNGLENABLEPROC, glEnable);
DO_LOOKUP(core_opengl, PFNGLDISABLEPROC, glDisable);
974
DO_LOOKUP(opengl_3, PFNGLGETSTRINGIPROC, glGetStringi);
975
976
977
978
979
980
981
982
983
984
DO_LOOKUP(opengl_2, PFNGLDELETESHADERPROC, glDeleteShader);
DO_LOOKUP(opengl_2, PFNGLDELETEPROGRAMPROC, glDeleteProgram);
DO_LOOKUP(opengl_2, PFNGLATTACHSHADERPROC, glAttachShader);
DO_LOOKUP(opengl_2, PFNGLCOMPILESHADERPROC, glCompileShader);
DO_LOOKUP(opengl_2, PFNGLCREATESHADERPROC, glCreateShader);
DO_LOOKUP(opengl_2, PFNGLCREATEPROGRAMPROC, glCreateProgram);
DO_LOOKUP(opengl_2, PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray);
DO_LOOKUP(opengl_2, PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray);
DO_LOOKUP(opengl_2, PFNGLGETATTRIBLOCATIONPROC, glGetAttribLocation);
DO_LOOKUP(opengl_2, PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog);
985
DO_LOOKUP(opengl_2, PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog);
986
987
988
989
990
991
992
DO_LOOKUP(opengl_2, PFNGLGETSHADERIVPROC, glGetShaderiv);
DO_LOOKUP(opengl_2, PFNGLGETPROGRAMIVPROC, glGetProgramiv);
DO_LOOKUP(opengl_2, PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation);
DO_LOOKUP(opengl_2, PFNGLLINKPROGRAMPROC, glLinkProgram);
DO_LOOKUP(opengl_2, PFNGLSHADERSOURCEPROC, glShaderSource);
DO_LOOKUP(opengl_2, PFNGLUNIFORM1IPROC, glUniform1i);
DO_LOOKUP(opengl_2, PFNGLUNIFORM1IVPROC, glUniform1iv);
993
DO_LOOKUP(opengl_2, PFNGLUNIFORM2FPROC, glUniform2f);
994
995
996
#ifdef MOJOSHADER_FLIP_RENDERTARGET
DO_LOOKUP(opengl_2, PFNGLUNIFORM1FPROC, glUniform1f);
#endif
997
998
999
1000
DO_LOOKUP(opengl_2, PFNGLUNIFORM4FVPROC, glUniform4fv);
DO_LOOKUP(opengl_2, PFNGLUNIFORM4IVPROC, glUniform4iv);
DO_LOOKUP(opengl_2, PFNGLUSEPROGRAMPROC, glUseProgram);
DO_LOOKUP(opengl_2, PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer);