mesa: Remove unnecessary header.
[mesa.git] / src / mesa / main / shaders.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.3
4 *
5 * Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include "glheader.h"
27 #include "context.h"
28 #include "shaders.h"
29 #include "shader/shader_api.h"
30
31
32 /** Define this to enable shader substitution (see below) */
33 #define SHADER_SUBST 0
34
35
36
37 /**
38 * These are basically just wrappers/adaptors for calling the
39 * ctx->Driver.foobar() GLSL-related functions.
40 *
41 * Things are biased toward the OpenGL 2.0 functions rather than the
42 * ARB extensions (i.e. the ARB functions are layered on the 2.0 functions).
43 *
44 * The general idea here is to allow enough modularity such that a
45 * completely different GLSL implemenation can be plugged in and co-exist
46 * with Mesa's native GLSL code.
47 */
48
49
50
51 void GLAPIENTRY
52 _mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader)
53 {
54 GET_CURRENT_CONTEXT(ctx);
55 ctx->Driver.AttachShader(ctx, program, shader);
56 }
57
58
59 void GLAPIENTRY
60 _mesa_AttachShader(GLuint program, GLuint shader)
61 {
62 GET_CURRENT_CONTEXT(ctx);
63 ctx->Driver.AttachShader(ctx, program, shader);
64 }
65
66
67 void GLAPIENTRY
68 _mesa_BindAttribLocationARB(GLhandleARB program, GLuint index,
69 const GLcharARB *name)
70 {
71 GET_CURRENT_CONTEXT(ctx);
72 ctx->Driver.BindAttribLocation(ctx, program, index, name);
73 }
74
75
76 void GLAPIENTRY
77 _mesa_CompileShaderARB(GLhandleARB shaderObj)
78 {
79 GET_CURRENT_CONTEXT(ctx);
80 ctx->Driver.CompileShader(ctx, shaderObj);
81 }
82
83
84 GLuint GLAPIENTRY
85 _mesa_CreateShader(GLenum type)
86 {
87 GET_CURRENT_CONTEXT(ctx);
88 return ctx->Driver.CreateShader(ctx, type);
89 }
90
91
92 GLhandleARB GLAPIENTRY
93 _mesa_CreateShaderObjectARB(GLenum type)
94 {
95 GET_CURRENT_CONTEXT(ctx);
96 return ctx->Driver.CreateShader(ctx, type);
97 }
98
99
100 GLuint GLAPIENTRY
101 _mesa_CreateProgram(void)
102 {
103 GET_CURRENT_CONTEXT(ctx);
104 return ctx->Driver.CreateProgram(ctx);
105 }
106
107
108 GLhandleARB GLAPIENTRY
109 _mesa_CreateProgramObjectARB(void)
110 {
111 GET_CURRENT_CONTEXT(ctx);
112 return ctx->Driver.CreateProgram(ctx);
113 }
114
115
116 void GLAPIENTRY
117 _mesa_DeleteObjectARB(GLhandleARB obj)
118 {
119 if (obj) {
120 GET_CURRENT_CONTEXT(ctx);
121 if (ctx->Driver.IsProgram(ctx, obj)) {
122 ctx->Driver.DeleteProgram2(ctx, obj);
123 }
124 else if (ctx->Driver.IsShader(ctx, obj)) {
125 ctx->Driver.DeleteShader(ctx, obj);
126 }
127 else {
128 /* error? */
129 }
130 }
131 }
132
133
134 void GLAPIENTRY
135 _mesa_DeleteProgram(GLuint name)
136 {
137 if (name) {
138 GET_CURRENT_CONTEXT(ctx);
139 ctx->Driver.DeleteProgram2(ctx, name);
140 }
141 }
142
143
144 void GLAPIENTRY
145 _mesa_DeleteShader(GLuint name)
146 {
147 if (name) {
148 GET_CURRENT_CONTEXT(ctx);
149 ctx->Driver.DeleteShader(ctx, name);
150 }
151 }
152
153
154 void GLAPIENTRY
155 _mesa_DetachObjectARB(GLhandleARB program, GLhandleARB shader)
156 {
157 GET_CURRENT_CONTEXT(ctx);
158 ctx->Driver.DetachShader(ctx, program, shader);
159 }
160
161
162 void GLAPIENTRY
163 _mesa_DetachShader(GLuint program, GLuint shader)
164 {
165 GET_CURRENT_CONTEXT(ctx);
166 ctx->Driver.DetachShader(ctx, program, shader);
167 }
168
169
170 void GLAPIENTRY
171 _mesa_GetActiveAttribARB(GLhandleARB program, GLuint index,
172 GLsizei maxLength, GLsizei * length, GLint * size,
173 GLenum * type, GLcharARB * name)
174 {
175 GET_CURRENT_CONTEXT(ctx);
176 ctx->Driver.GetActiveAttrib(ctx, program, index, maxLength, length, size,
177 type, name);
178 }
179
180
181 void GLAPIENTRY
182 _mesa_GetActiveUniformARB(GLhandleARB program, GLuint index,
183 GLsizei maxLength, GLsizei * length, GLint * size,
184 GLenum * type, GLcharARB * name)
185 {
186 GET_CURRENT_CONTEXT(ctx);
187 ctx->Driver.GetActiveUniform(ctx, program, index, maxLength, length, size,
188 type, name);
189 }
190
191
192 void GLAPIENTRY
193 _mesa_GetAttachedObjectsARB(GLhandleARB container, GLsizei maxCount,
194 GLsizei * count, GLhandleARB * obj)
195 {
196 GET_CURRENT_CONTEXT(ctx);
197 ctx->Driver.GetAttachedShaders(ctx, container, maxCount, count, obj);
198 }
199
200
201 void GLAPIENTRY
202 _mesa_GetAttachedShaders(GLuint program, GLsizei maxCount,
203 GLsizei *count, GLuint *obj)
204 {
205 GET_CURRENT_CONTEXT(ctx);
206 ctx->Driver.GetAttachedShaders(ctx, program, maxCount, count, obj);
207 }
208
209
210 GLint GLAPIENTRY
211 _mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name)
212 {
213 GET_CURRENT_CONTEXT(ctx);
214 return ctx->Driver.GetAttribLocation(ctx, program, name);
215 }
216
217
218 void GLAPIENTRY
219 _mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length,
220 GLcharARB * infoLog)
221 {
222 GET_CURRENT_CONTEXT(ctx);
223 /* Implement in terms of GetProgramInfoLog, GetShaderInfoLog */
224 if (ctx->Driver.IsProgram(ctx, object)) {
225 ctx->Driver.GetProgramInfoLog(ctx, object, maxLength, length, infoLog);
226 }
227 else if (ctx->Driver.IsShader(ctx, object)) {
228 ctx->Driver.GetShaderInfoLog(ctx, object, maxLength, length, infoLog);
229 }
230 else {
231 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInfoLogARB");
232 }
233 }
234
235
236 void GLAPIENTRY
237 _mesa_GetObjectParameterivARB(GLhandleARB object, GLenum pname, GLint *params)
238 {
239 GET_CURRENT_CONTEXT(ctx);
240 /* Implement in terms of GetProgramiv, GetShaderiv */
241 if (ctx->Driver.IsProgram(ctx, object)) {
242 if (pname == GL_OBJECT_TYPE_ARB) {
243 *params = GL_PROGRAM_OBJECT_ARB;
244 }
245 else {
246 ctx->Driver.GetProgramiv(ctx, object, pname, params);
247 }
248 }
249 else if (ctx->Driver.IsShader(ctx, object)) {
250 if (pname == GL_OBJECT_TYPE_ARB) {
251 *params = GL_SHADER_OBJECT_ARB;
252 }
253 else {
254 ctx->Driver.GetShaderiv(ctx, object, pname, params);
255 }
256 }
257 else {
258 _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameterivARB");
259 }
260 }
261
262
263 void GLAPIENTRY
264 _mesa_GetObjectParameterfvARB(GLhandleARB object, GLenum pname,
265 GLfloat *params)
266 {
267 GLint iparams[1]; /* XXX is one element enough? */
268 _mesa_GetObjectParameterivARB(object, pname, iparams);
269 params[0] = (GLfloat) iparams[0];
270 }
271
272
273 void GLAPIENTRY
274 _mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params)
275 {
276 GET_CURRENT_CONTEXT(ctx);
277 ctx->Driver.GetProgramiv(ctx, program, pname, params);
278 }
279
280
281 void GLAPIENTRY
282 _mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params)
283 {
284 GET_CURRENT_CONTEXT(ctx);
285 ctx->Driver.GetShaderiv(ctx, shader, pname, params);
286 }
287
288
289 void GLAPIENTRY
290 _mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize,
291 GLsizei *length, GLchar *infoLog)
292 {
293 GET_CURRENT_CONTEXT(ctx);
294 ctx->Driver.GetProgramInfoLog(ctx, program, bufSize, length, infoLog);
295 }
296
297
298 void GLAPIENTRY
299 _mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize,
300 GLsizei *length, GLchar *infoLog)
301 {
302 GET_CURRENT_CONTEXT(ctx);
303 ctx->Driver.GetShaderInfoLog(ctx, shader, bufSize, length, infoLog);
304 }
305
306
307 void GLAPIENTRY
308 _mesa_GetShaderSourceARB(GLhandleARB shader, GLsizei maxLength,
309 GLsizei *length, GLcharARB *sourceOut)
310 {
311 GET_CURRENT_CONTEXT(ctx);
312 ctx->Driver.GetShaderSource(ctx, shader, maxLength, length, sourceOut);
313 }
314
315
316 void GLAPIENTRY
317 _mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat * params)
318 {
319 GET_CURRENT_CONTEXT(ctx);
320 ctx->Driver.GetUniformfv(ctx, program, location, params);
321 }
322
323
324 void GLAPIENTRY
325 _mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint * params)
326 {
327 GET_CURRENT_CONTEXT(ctx);
328 ctx->Driver.GetUniformiv(ctx, program, location, params);
329 }
330
331
332
333 #if 0
334 GLint GLAPIENTRY
335 _mesa_GetUniformLocation(GLuint program, const GLcharARB *name)
336 {
337 GET_CURRENT_CONTEXT(ctx);
338 return ctx->Driver.GetUniformLocation(ctx, program, name);
339 }
340 #endif
341
342
343 GLhandleARB GLAPIENTRY
344 _mesa_GetHandleARB(GLenum pname)
345 {
346 GET_CURRENT_CONTEXT(ctx);
347 return ctx->Driver.GetHandle(ctx, pname);
348 }
349
350
351 GLint GLAPIENTRY
352 _mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
353 {
354 GET_CURRENT_CONTEXT(ctx);
355 return ctx->Driver.GetUniformLocation(ctx, programObj, name);
356 }
357
358
359 GLboolean GLAPIENTRY
360 _mesa_IsProgram(GLuint name)
361 {
362 GET_CURRENT_CONTEXT(ctx);
363 return ctx->Driver.IsProgram(ctx, name);
364 }
365
366
367 GLboolean GLAPIENTRY
368 _mesa_IsShader(GLuint name)
369 {
370 GET_CURRENT_CONTEXT(ctx);
371 return ctx->Driver.IsShader(ctx, name);
372 }
373
374
375 void GLAPIENTRY
376 _mesa_LinkProgramARB(GLhandleARB programObj)
377 {
378 GET_CURRENT_CONTEXT(ctx);
379 ctx->Driver.LinkProgram(ctx, programObj);
380 }
381
382
383
384 /**
385 * Read shader source code from a file.
386 * Useful for debugging to override an app's shader.
387 */
388 static GLcharARB *
389 _mesa_read_shader(const char *fname)
390 {
391 const int max = 50*1000;
392 FILE *f = fopen(fname, "r");
393 GLcharARB *buffer, *shader;
394 int len;
395
396 if (!f) {
397 return NULL;
398 }
399
400 buffer = (char *) malloc(max);
401 len = fread(buffer, 1, max, f);
402 buffer[len] = 0;
403
404 fclose(f);
405
406 shader = _mesa_strdup(buffer);
407 free(buffer);
408
409 return shader;
410 }
411
412
413 /**
414 * Called via glShaderSource() and glShaderSourceARB() API functions.
415 * Basically, concatenate the source code strings into one long string
416 * and pass it to ctx->Driver.ShaderSource().
417 */
418 void GLAPIENTRY
419 _mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count,
420 const GLcharARB ** string, const GLint * length)
421 {
422 GET_CURRENT_CONTEXT(ctx);
423 GLint *offsets;
424 GLsizei i, totalLength;
425 GLcharARB *source;
426 GLuint checksum;
427
428 if (!shaderObj || string == NULL) {
429 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB");
430 return;
431 }
432
433 /*
434 * This array holds offsets of where the appropriate string ends, thus the
435 * last element will be set to the total length of the source code.
436 */
437 offsets = (GLint *) malloc(count * sizeof(GLint));
438 if (offsets == NULL) {
439 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB");
440 return;
441 }
442
443 for (i = 0; i < count; i++) {
444 if (string[i] == NULL) {
445 free((GLvoid *) offsets);
446 _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderSourceARB(null string)");
447 return;
448 }
449 if (length == NULL || length[i] < 0)
450 offsets[i] = strlen(string[i]);
451 else
452 offsets[i] = length[i];
453 /* accumulate string lengths */
454 if (i > 0)
455 offsets[i] += offsets[i - 1];
456 }
457
458 /* Total length of source string is sum off all strings plus two.
459 * One extra byte for terminating zero, another extra byte to silence
460 * valgrind warnings in the parser/grammer code.
461 */
462 totalLength = offsets[count - 1] + 2;
463 source = (GLcharARB *) malloc(totalLength * sizeof(GLcharARB));
464 if (source == NULL) {
465 free((GLvoid *) offsets);
466 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB");
467 return;
468 }
469
470 for (i = 0; i < count; i++) {
471 GLint start = (i > 0) ? offsets[i - 1] : 0;
472 memcpy(source + start, string[i],
473 (offsets[i] - start) * sizeof(GLcharARB));
474 }
475 source[totalLength - 1] = '\0';
476 source[totalLength - 2] = '\0';
477
478 if (SHADER_SUBST) {
479 /* Compute the shader's source code checksum then try to open a file
480 * named newshader_<CHECKSUM>. If it exists, use it in place of the
481 * original shader source code. For debugging.
482 */
483 char filename[100];
484 GLcharARB *newSource;
485
486 checksum = _mesa_str_checksum(source);
487
488 sprintf(filename, "newshader_%d", checksum);
489
490 newSource = _mesa_read_shader(filename);
491 if (newSource) {
492 fprintf(stderr, "Mesa: Replacing shader %u chksum=%d with %s\n",
493 shaderObj, checksum, filename);
494 free(source);
495 source = newSource;
496 }
497 }
498
499 ctx->Driver.ShaderSource(ctx, shaderObj, source);
500
501 if (SHADER_SUBST) {
502 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
503 if (sh)
504 sh->SourceChecksum = checksum; /* save original checksum */
505 }
506
507 free(offsets);
508 }
509
510
511 void GLAPIENTRY
512 _mesa_Uniform1fARB(GLint location, GLfloat v0)
513 {
514 GET_CURRENT_CONTEXT(ctx);
515 ctx->Driver.Uniform(ctx, location, 1, &v0, GL_FLOAT);
516 }
517
518 void GLAPIENTRY
519 _mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
520 {
521 GET_CURRENT_CONTEXT(ctx);
522 GLfloat v[2];
523 v[0] = v0;
524 v[1] = v1;
525 ctx->Driver.Uniform(ctx, location, 1, v, GL_FLOAT_VEC2);
526 }
527
528 void GLAPIENTRY
529 _mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
530 {
531 GET_CURRENT_CONTEXT(ctx);
532 GLfloat v[3];
533 v[0] = v0;
534 v[1] = v1;
535 v[2] = v2;
536 ctx->Driver.Uniform(ctx, location, 1, v, GL_FLOAT_VEC3);
537 }
538
539 void GLAPIENTRY
540 _mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
541 GLfloat v3)
542 {
543 GET_CURRENT_CONTEXT(ctx);
544 GLfloat v[4];
545 v[0] = v0;
546 v[1] = v1;
547 v[2] = v2;
548 v[3] = v3;
549 ctx->Driver.Uniform(ctx, location, 1, v, GL_FLOAT_VEC4);
550 }
551
552 void GLAPIENTRY
553 _mesa_Uniform1iARB(GLint location, GLint v0)
554 {
555 GET_CURRENT_CONTEXT(ctx);
556 ctx->Driver.Uniform(ctx, location, 1, &v0, GL_INT);
557 }
558
559 void GLAPIENTRY
560 _mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
561 {
562 GET_CURRENT_CONTEXT(ctx);
563 GLint v[2];
564 v[0] = v0;
565 v[1] = v1;
566 ctx->Driver.Uniform(ctx, location, 1, v, GL_INT_VEC2);
567 }
568
569 void GLAPIENTRY
570 _mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
571 {
572 GET_CURRENT_CONTEXT(ctx);
573 GLint v[3];
574 v[0] = v0;
575 v[1] = v1;
576 v[2] = v2;
577 ctx->Driver.Uniform(ctx, location, 1, v, GL_INT_VEC3);
578 }
579
580 void GLAPIENTRY
581 _mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
582 {
583 GET_CURRENT_CONTEXT(ctx);
584 GLint v[4];
585 v[0] = v0;
586 v[1] = v1;
587 v[2] = v2;
588 v[3] = v3;
589 ctx->Driver.Uniform(ctx, location, 1, v, GL_INT_VEC4);
590 }
591
592 void GLAPIENTRY
593 _mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
594 {
595 GET_CURRENT_CONTEXT(ctx);
596 ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT);
597 }
598
599 void GLAPIENTRY
600 _mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
601 {
602 GET_CURRENT_CONTEXT(ctx);
603 ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT_VEC2);
604 }
605
606 void GLAPIENTRY
607 _mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
608 {
609 GET_CURRENT_CONTEXT(ctx);
610 ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT_VEC3);
611 }
612
613 void GLAPIENTRY
614 _mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
615 {
616 GET_CURRENT_CONTEXT(ctx);
617 ctx->Driver.Uniform(ctx, location, count, value, GL_FLOAT_VEC4);
618 }
619
620 void GLAPIENTRY
621 _mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
622 {
623 GET_CURRENT_CONTEXT(ctx);
624 ctx->Driver.Uniform(ctx, location, count, value, GL_INT);
625 }
626
627 void GLAPIENTRY
628 _mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
629 {
630 GET_CURRENT_CONTEXT(ctx);
631 ctx->Driver.Uniform(ctx, location, count, value, GL_INT_VEC2);
632 }
633
634 void GLAPIENTRY
635 _mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
636 {
637 GET_CURRENT_CONTEXT(ctx);
638 ctx->Driver.Uniform(ctx, location, count, value, GL_INT_VEC3);
639 }
640
641 void GLAPIENTRY
642 _mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
643 {
644 GET_CURRENT_CONTEXT(ctx);
645 ctx->Driver.Uniform(ctx, location, count, value, GL_INT_VEC4);
646 }
647
648
649 void GLAPIENTRY
650 _mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
651 const GLfloat * value)
652 {
653 GET_CURRENT_CONTEXT(ctx);
654 ctx->Driver.UniformMatrix(ctx, 2, 2, location, count, transpose, value);
655 }
656
657 void GLAPIENTRY
658 _mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
659 const GLfloat * value)
660 {
661 GET_CURRENT_CONTEXT(ctx);
662 ctx->Driver.UniformMatrix(ctx, 3, 3, location, count, transpose, value);
663 }
664
665 void GLAPIENTRY
666 _mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
667 const GLfloat * value)
668 {
669 GET_CURRENT_CONTEXT(ctx);
670 ctx->Driver.UniformMatrix(ctx, 4, 4, location, count, transpose, value);
671 }
672
673
674 /**
675 * Non-square UniformMatrix are OpenGL 2.1
676 */
677 void GLAPIENTRY
678 _mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose,
679 const GLfloat *value)
680 {
681 GET_CURRENT_CONTEXT(ctx);
682 ctx->Driver.UniformMatrix(ctx, 2, 3, location, count, transpose, value);
683 }
684
685 void GLAPIENTRY
686 _mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose,
687 const GLfloat *value)
688 {
689 GET_CURRENT_CONTEXT(ctx);
690 ctx->Driver.UniformMatrix(ctx, 3, 2, location, count, transpose, value);
691 }
692
693 void GLAPIENTRY
694 _mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose,
695 const GLfloat *value)
696 {
697 GET_CURRENT_CONTEXT(ctx);
698 ctx->Driver.UniformMatrix(ctx, 2, 4, location, count, transpose, value);
699 }
700
701 void GLAPIENTRY
702 _mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose,
703 const GLfloat *value)
704 {
705 GET_CURRENT_CONTEXT(ctx);
706 ctx->Driver.UniformMatrix(ctx, 4, 2, location, count, transpose, value);
707 }
708
709 void GLAPIENTRY
710 _mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose,
711 const GLfloat *value)
712 {
713 GET_CURRENT_CONTEXT(ctx);
714 ctx->Driver.UniformMatrix(ctx, 3, 4, location, count, transpose, value);
715 }
716
717 void GLAPIENTRY
718 _mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose,
719 const GLfloat *value)
720 {
721 GET_CURRENT_CONTEXT(ctx);
722 ctx->Driver.UniformMatrix(ctx, 4, 3, location, count, transpose, value);
723 }
724
725
726 void GLAPIENTRY
727 _mesa_UseProgramObjectARB(GLhandleARB program)
728 {
729 GET_CURRENT_CONTEXT(ctx);
730 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
731 ctx->Driver.UseProgram(ctx, program);
732 }
733
734
735 void GLAPIENTRY
736 _mesa_ValidateProgramARB(GLhandleARB program)
737 {
738 GET_CURRENT_CONTEXT(ctx);
739 ctx->Driver.ValidateProgram(ctx, program);
740 }
741