mesa/version: only enable GL4.1 with correct limits.
[mesa.git] / src / mesa / main / arbprogram.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file arbprogram.c
27 * ARB_vertex/fragment_program state management functions.
28 * \author Brian Paul
29 */
30
31
32 #include "main/glheader.h"
33 #include "main/context.h"
34 #include "main/hash.h"
35
36 #include "main/macros.h"
37 #include "main/mtypes.h"
38 #include "main/arbprogram.h"
39 #include "main/shaderapi.h"
40 #include "main/state.h"
41 #include "program/arbprogparse.h"
42 #include "program/program.h"
43 #include "program/prog_print.h"
44
45 static void
46 flush_vertices_for_program_constants(struct gl_context *ctx, GLenum target)
47 {
48 uint64_t new_driver_state;
49
50 if (target == GL_FRAGMENT_PROGRAM_ARB) {
51 new_driver_state =
52 ctx->DriverFlags.NewShaderConstants[MESA_SHADER_FRAGMENT];
53 } else {
54 new_driver_state =
55 ctx->DriverFlags.NewShaderConstants[MESA_SHADER_VERTEX];
56 }
57
58 FLUSH_VERTICES(ctx, new_driver_state ? 0 : _NEW_PROGRAM_CONSTANTS);
59 ctx->NewDriverState |= new_driver_state;
60 }
61
62 static struct gl_program*
63 lookup_or_create_program(GLuint id, GLenum target, const char* caller)
64 {
65 GET_CURRENT_CONTEXT(ctx);
66 struct gl_program* newProg;
67
68 if (id == 0) {
69 /* Bind a default program */
70 if (target == GL_VERTEX_PROGRAM_ARB)
71 newProg = ctx->Shared->DefaultVertexProgram;
72 else
73 newProg = ctx->Shared->DefaultFragmentProgram;
74 }
75 else {
76 /* Bind a user program */
77 newProg = _mesa_lookup_program(ctx, id);
78 if (!newProg || newProg == &_mesa_DummyProgram) {
79 /* allocate a new program now */
80 newProg = ctx->Driver.NewProgram(ctx, _mesa_program_enum_to_shader_stage(target),
81 id, true);
82 if (!newProg) {
83 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
84 return NULL;
85 }
86 _mesa_HashInsert(ctx->Shared->Programs, id, newProg);
87 }
88 else if (newProg->Target != target) {
89 _mesa_error(ctx, GL_INVALID_OPERATION,
90 "%s(target mismatch)", caller);
91 return NULL;
92 }
93 }
94 return newProg;
95 }
96
97 /**
98 * Bind a program (make it current)
99 * \note Called from the GL API dispatcher by both glBindProgramNV
100 * and glBindProgramARB.
101 */
102 void GLAPIENTRY
103 _mesa_BindProgramARB(GLenum target, GLuint id)
104 {
105 struct gl_program *curProg, *newProg;
106 GET_CURRENT_CONTEXT(ctx);
107
108 /* Error-check target and get curProg */
109 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
110 curProg = ctx->VertexProgram.Current;
111 }
112 else if (target == GL_FRAGMENT_PROGRAM_ARB
113 && ctx->Extensions.ARB_fragment_program) {
114 curProg = ctx->FragmentProgram.Current;
115 }
116 else {
117 _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramARB(target)");
118 return;
119 }
120
121 /*
122 * Get pointer to new program to bind.
123 * NOTE: binding to a non-existant program is not an error.
124 * That's supposed to be caught in glBegin.
125 */
126 newProg = lookup_or_create_program(id, target, "glBindProgram");
127 if (!newProg)
128 return;
129
130 /** All error checking is complete now **/
131
132 if (curProg->Id == id) {
133 /* binding same program - no change */
134 return;
135 }
136
137 /* signal new program (and its new constants) */
138 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
139 flush_vertices_for_program_constants(ctx, target);
140
141 /* bind newProg */
142 if (target == GL_VERTEX_PROGRAM_ARB) {
143 _mesa_reference_program(ctx, &ctx->VertexProgram.Current, newProg);
144 }
145 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
146 _mesa_reference_program(ctx, &ctx->FragmentProgram.Current, newProg);
147 }
148
149 _mesa_update_vertex_processing_mode(ctx);
150
151 /* Never null pointers */
152 assert(ctx->VertexProgram.Current);
153 assert(ctx->FragmentProgram.Current);
154 }
155
156
157 /**
158 * Delete a list of programs.
159 * \note Not compiled into display lists.
160 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
161 */
162 void GLAPIENTRY
163 _mesa_DeleteProgramsARB(GLsizei n, const GLuint *ids)
164 {
165 GLint i;
166 GET_CURRENT_CONTEXT(ctx);
167
168 FLUSH_VERTICES(ctx, 0);
169
170 if (n < 0) {
171 _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
172 return;
173 }
174
175 for (i = 0; i < n; i++) {
176 if (ids[i] != 0) {
177 struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
178 if (prog == &_mesa_DummyProgram) {
179 _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
180 }
181 else if (prog) {
182 /* Unbind program if necessary */
183 switch (prog->Target) {
184 case GL_VERTEX_PROGRAM_ARB:
185 if (ctx->VertexProgram.Current &&
186 ctx->VertexProgram.Current->Id == ids[i]) {
187 /* unbind this currently bound program */
188 _mesa_BindProgramARB(prog->Target, 0);
189 }
190 break;
191 case GL_FRAGMENT_PROGRAM_ARB:
192 if (ctx->FragmentProgram.Current &&
193 ctx->FragmentProgram.Current->Id == ids[i]) {
194 /* unbind this currently bound program */
195 _mesa_BindProgramARB(prog->Target, 0);
196 }
197 break;
198 default:
199 _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
200 return;
201 }
202 /* The ID is immediately available for re-use now */
203 _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
204 _mesa_reference_program(ctx, &prog, NULL);
205 }
206 }
207 }
208 }
209
210
211 /**
212 * Generate a list of new program identifiers.
213 * \note Not compiled into display lists.
214 * \note Called by both glGenProgramsNV and glGenProgramsARB.
215 */
216 void GLAPIENTRY
217 _mesa_GenProgramsARB(GLsizei n, GLuint *ids)
218 {
219 GLuint first;
220 GLuint i;
221 GET_CURRENT_CONTEXT(ctx);
222
223 if (n < 0) {
224 _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
225 return;
226 }
227
228 if (!ids)
229 return;
230
231 _mesa_HashLockMutex(ctx->Shared->Programs);
232
233 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
234
235 /* Insert pointer to dummy program as placeholder */
236 for (i = 0; i < (GLuint) n; i++) {
237 _mesa_HashInsertLocked(ctx->Shared->Programs, first + i,
238 &_mesa_DummyProgram);
239 }
240
241 _mesa_HashUnlockMutex(ctx->Shared->Programs);
242
243 /* Return the program names */
244 for (i = 0; i < (GLuint) n; i++) {
245 ids[i] = first + i;
246 }
247 }
248
249
250 /**
251 * Determine if id names a vertex or fragment program.
252 * \note Not compiled into display lists.
253 * \note Called from both glIsProgramNV and glIsProgramARB.
254 * \param id is the program identifier
255 * \return GL_TRUE if id is a program, else GL_FALSE.
256 */
257 GLboolean GLAPIENTRY
258 _mesa_IsProgramARB(GLuint id)
259 {
260 struct gl_program *prog = NULL;
261 GET_CURRENT_CONTEXT(ctx);
262 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
263
264 if (id == 0)
265 return GL_FALSE;
266
267 prog = _mesa_lookup_program(ctx, id);
268 if (prog && (prog != &_mesa_DummyProgram))
269 return GL_TRUE;
270 else
271 return GL_FALSE;
272 }
273
274 static struct gl_program*
275 get_current_program(struct gl_context* ctx, GLenum target, const char* caller)
276 {
277 if (target == GL_VERTEX_PROGRAM_ARB
278 && ctx->Extensions.ARB_vertex_program) {
279 return ctx->VertexProgram.Current;
280 }
281 else if (target == GL_FRAGMENT_PROGRAM_ARB
282 && ctx->Extensions.ARB_fragment_program) {
283 return ctx->FragmentProgram.Current;
284 }
285 else {
286 _mesa_error(ctx, GL_INVALID_ENUM,
287 "%s(target)", caller);
288 return NULL;
289 }
290 }
291
292 static GLboolean
293 get_local_param_pointer(struct gl_context *ctx, const char *func,
294 struct gl_program* prog, GLenum target,
295 GLuint index, GLfloat **param)
296 {
297 GLuint maxParams;
298
299 if (target == GL_VERTEX_PROGRAM_ARB) {
300 maxParams = ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams;
301 } else {
302 maxParams = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams;
303 }
304
305 if (index >= maxParams) {
306 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
307 return GL_FALSE;
308 }
309
310 if (!prog->arb.LocalParams) {
311 prog->arb.LocalParams = rzalloc_array_size(prog, sizeof(float[4]),
312 maxParams);
313 if (!prog->arb.LocalParams)
314 return GL_FALSE;
315 }
316
317 *param = prog->arb.LocalParams[index];
318 return GL_TRUE;
319 }
320
321
322 static GLboolean
323 get_env_param_pointer(struct gl_context *ctx, const char *func,
324 GLenum target, GLuint index, GLfloat **param)
325 {
326 if (target == GL_FRAGMENT_PROGRAM_ARB
327 && ctx->Extensions.ARB_fragment_program) {
328 if (index >= ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) {
329 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
330 return GL_FALSE;
331 }
332 *param = ctx->FragmentProgram.Parameters[index];
333 return GL_TRUE;
334 }
335 else if (target == GL_VERTEX_PROGRAM_ARB &&
336 ctx->Extensions.ARB_vertex_program) {
337 if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) {
338 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
339 return GL_FALSE;
340 }
341 *param = ctx->VertexProgram.Parameters[index];
342 return GL_TRUE;
343 } else {
344 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
345 return GL_FALSE;
346 }
347 }
348
349 static void
350 set_program_string(struct gl_program *prog, GLenum target, GLenum format, GLsizei len,
351 const GLvoid *string)
352 {
353 bool failed;
354 GET_CURRENT_CONTEXT(ctx);
355
356 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
357
358 if (!ctx->Extensions.ARB_vertex_program
359 && !ctx->Extensions.ARB_fragment_program) {
360 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()");
361 return;
362 }
363
364 if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
365 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
366 return;
367 }
368
369 #ifdef ENABLE_SHADER_CACHE
370 GLcharARB *replacement;
371
372 gl_shader_stage stage = _mesa_program_enum_to_shader_stage(target);
373
374 /* Dump original shader source to MESA_SHADER_DUMP_PATH and replace
375 * if corresponding entry found from MESA_SHADER_READ_PATH.
376 */
377 _mesa_dump_shader_source(stage, string);
378
379 replacement = _mesa_read_shader_source(stage, string);
380 if (replacement)
381 string = replacement;
382 #endif /* ENABLE_SHADER_CACHE */
383
384 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
385 _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
386 }
387 else if (target == GL_FRAGMENT_PROGRAM_ARB
388 && ctx->Extensions.ARB_fragment_program) {
389 _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
390 }
391 else {
392 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
393 return;
394 }
395
396 failed = ctx->Program.ErrorPos != -1;
397
398 if (!failed) {
399 /* finally, give the program to the driver for translation/checking */
400 if (!ctx->Driver.ProgramStringNotify(ctx, target, prog)) {
401 failed = true;
402 _mesa_error(ctx, GL_INVALID_OPERATION,
403 "glProgramStringARB(rejected by driver");
404 }
405 }
406
407 _mesa_update_vertex_processing_mode(ctx);
408
409 if (ctx->_Shader->Flags & GLSL_DUMP) {
410 const char *shader_type =
411 target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";
412
413 fprintf(stderr, "ARB_%s_program source for program %d:\n",
414 shader_type, prog->Id);
415 fprintf(stderr, "%s\n", (const char *) string);
416
417 if (failed) {
418 fprintf(stderr, "ARB_%s_program %d failed to compile.\n",
419 shader_type, prog->Id);
420 } else {
421 fprintf(stderr, "Mesa IR for ARB_%s_program %d:\n",
422 shader_type, prog->Id);
423 _mesa_print_program(prog);
424 fprintf(stderr, "\n");
425 }
426 fflush(stderr);
427 }
428
429 /* Capture vp-*.shader_test/fp-*.shader_test files. */
430 const char *capture_path = _mesa_get_shader_capture_path();
431 if (capture_path != NULL) {
432 FILE *file;
433 const char *shader_type =
434 target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";
435 char *filename =
436 ralloc_asprintf(NULL, "%s/%cp-%u.shader_test",
437 capture_path, shader_type[0], prog->Id);
438
439 file = fopen(filename, "w");
440 if (file) {
441 fprintf(file,
442 "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n",
443 shader_type, shader_type, (const char *) string);
444 fclose(file);
445 } else {
446 _mesa_warning(ctx, "Failed to open %s", filename);
447 }
448 ralloc_free(filename);
449 }
450 }
451
452 void GLAPIENTRY
453 _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
454 const GLvoid *string)
455 {
456 GET_CURRENT_CONTEXT(ctx);
457 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
458 set_program_string(ctx->VertexProgram.Current, target, format, len, string);
459 }
460 else if (target == GL_FRAGMENT_PROGRAM_ARB
461 && ctx->Extensions.ARB_fragment_program) {
462 set_program_string(ctx->FragmentProgram.Current, target, format, len, string);
463 }
464 else {
465 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
466 return;
467 }
468 }
469
470 void GLAPIENTRY
471 _mesa_NamedProgramStringEXT(GLuint program, GLenum target, GLenum format, GLsizei len,
472 const GLvoid *string)
473 {
474 struct gl_program* prog = lookup_or_create_program(program, target, "glNamedProgramStringEXT");
475
476 if (!prog) {
477 return;
478 }
479 set_program_string(prog, target, format, len, string);
480 }
481
482
483 /**
484 * Set a program env parameter register.
485 * \note Called from the GL API dispatcher.
486 */
487 void GLAPIENTRY
488 _mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
489 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
490 {
491 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
492 (GLfloat) z, (GLfloat) w);
493 }
494
495
496 /**
497 * Set a program env parameter register.
498 * \note Called from the GL API dispatcher.
499 */
500 void GLAPIENTRY
501 _mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
502 const GLdouble *params)
503 {
504 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
505 (GLfloat) params[1], (GLfloat) params[2],
506 (GLfloat) params[3]);
507 }
508
509
510 /**
511 * Set a program env parameter register.
512 * \note Called from the GL API dispatcher.
513 */
514 void GLAPIENTRY
515 _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
516 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
517 {
518 GLfloat *param;
519
520 GET_CURRENT_CONTEXT(ctx);
521
522 flush_vertices_for_program_constants(ctx, target);
523
524 if (get_env_param_pointer(ctx, "glProgramEnvParameter",
525 target, index, &param)) {
526 ASSIGN_4V(param, x, y, z, w);
527 }
528 }
529
530
531
532 /**
533 * Set a program env parameter register.
534 * \note Called from the GL API dispatcher.
535 */
536 void GLAPIENTRY
537 _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
538 const GLfloat *params)
539 {
540 GLfloat *param;
541
542 GET_CURRENT_CONTEXT(ctx);
543
544 flush_vertices_for_program_constants(ctx, target);
545
546 if (get_env_param_pointer(ctx, "glProgramEnvParameter4fv",
547 target, index, &param)) {
548 memcpy(param, params, 4 * sizeof(GLfloat));
549 }
550 }
551
552
553 void GLAPIENTRY
554 _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
555 const GLfloat *params)
556 {
557 GET_CURRENT_CONTEXT(ctx);
558 GLfloat * dest;
559
560 flush_vertices_for_program_constants(ctx, target);
561
562 if (count <= 0) {
563 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
564 }
565
566 if (target == GL_FRAGMENT_PROGRAM_ARB
567 && ctx->Extensions.ARB_fragment_program) {
568 if ((index + count) > ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) {
569 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
570 return;
571 }
572 dest = ctx->FragmentProgram.Parameters[index];
573 }
574 else if (target == GL_VERTEX_PROGRAM_ARB
575 && ctx->Extensions.ARB_vertex_program) {
576 if ((index + count) > ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) {
577 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
578 return;
579 }
580 dest = ctx->VertexProgram.Parameters[index];
581 }
582 else {
583 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
584 return;
585 }
586
587 memcpy(dest, params, count * 4 * sizeof(GLfloat));
588 }
589
590
591 void GLAPIENTRY
592 _mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
593 GLdouble *params)
594 {
595 GET_CURRENT_CONTEXT(ctx);
596 GLfloat *fparam;
597
598 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterdv",
599 target, index, &fparam)) {
600 COPY_4V(params, fparam);
601 }
602 }
603
604
605 void GLAPIENTRY
606 _mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
607 GLfloat *params)
608 {
609 GLfloat *param;
610
611 GET_CURRENT_CONTEXT(ctx);
612
613 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterfv",
614 target, index, &param)) {
615 COPY_4V(params, param);
616 }
617 }
618
619
620 void GLAPIENTRY
621 _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
622 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
623 {
624 GET_CURRENT_CONTEXT(ctx);
625 GLfloat *param;
626 struct gl_program* prog = get_current_program(ctx, target, "glProgramLocalParameterARB");
627 if (!prog) {
628 return;
629 }
630
631 flush_vertices_for_program_constants(ctx, target);
632
633 if (get_local_param_pointer(ctx, "glProgramLocalParameterARB",
634 prog, target, index, &param)) {
635 assert(index < MAX_PROGRAM_LOCAL_PARAMS);
636 ASSIGN_4V(param, x, y, z, w);
637 }
638 }
639
640 void GLAPIENTRY
641 _mesa_NamedProgramLocalParameter4fEXT(GLuint program, GLenum target, GLuint index,
642 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
643 {
644 GET_CURRENT_CONTEXT(ctx);
645 GLfloat *param;
646 struct gl_program* prog = lookup_or_create_program(program, target,
647 "glNamedProgramLocalParameter4fEXT");
648
649 if (!prog) {
650 return;
651 }
652
653 if ((target == GL_VERTEX_PROGRAM_ARB && prog == ctx->VertexProgram.Current) ||
654 (target == GL_FRAGMENT_PROGRAM_ARB && prog == ctx->FragmentProgram.Current)) {
655 flush_vertices_for_program_constants(ctx, target);
656 }
657
658 if (get_local_param_pointer(ctx, "glNamedProgramLocalParameter4fEXT",
659 prog, target, index, &param)) {
660 assert(index < MAX_PROGRAM_LOCAL_PARAMS);
661 ASSIGN_4V(param, x, y, z, w);
662 }
663 }
664
665
666 void GLAPIENTRY
667 _mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
668 const GLfloat *params)
669 {
670 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
671 params[2], params[3]);
672 }
673
674
675 void GLAPIENTRY
676 _mesa_NamedProgramLocalParameter4fvEXT(GLuint program, GLenum target, GLuint index,
677 const GLfloat *params)
678 {
679 _mesa_NamedProgramLocalParameter4fEXT(program, target, index, params[0],
680 params[1], params[2], params[3]);
681 }
682
683
684 static void
685 program_local_parameters4fv(struct gl_program* prog, GLuint index, GLsizei count,
686 const GLfloat *params, const char* caller)
687 {
688 GET_CURRENT_CONTEXT(ctx);
689 GLfloat *dest;
690 flush_vertices_for_program_constants(ctx, prog->Target);
691
692 if (count <= 0) {
693 _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", caller);
694 }
695
696 if (get_local_param_pointer(ctx, caller,
697 prog, prog->Target, index, &dest)) {
698 GLuint maxParams = prog->Target == GL_FRAGMENT_PROGRAM_ARB ?
699 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams :
700 ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams;
701
702 if ((index + count) > maxParams) {
703 _mesa_error(ctx, GL_INVALID_VALUE,
704 "%s(index + count)",
705 caller);
706 return;
707 }
708
709 memcpy(dest, params, count * 4 * sizeof(GLfloat));
710 }
711 }
712
713
714 void GLAPIENTRY
715 _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
716 const GLfloat *params)
717 {
718 GET_CURRENT_CONTEXT(ctx);
719 struct gl_program* prog = get_current_program(ctx, target,
720 "glProgramLocalParameters4fv");
721 if (!prog) {
722 return;
723 }
724
725 program_local_parameters4fv(prog, index, count, params,
726 "glProgramLocalParameters4fv");
727 }
728
729 void GLAPIENTRY
730 _mesa_NamedProgramLocalParameters4fvEXT(GLuint program, GLenum target, GLuint index,
731 GLsizei count, const GLfloat *params)
732 {
733 struct gl_program* prog =
734 lookup_or_create_program(program, target,
735 "glNamedProgramLocalParameters4fvEXT");
736 if (!prog) {
737 return;
738 }
739
740 program_local_parameters4fv(prog, index, count, params,
741 "glNamedProgramLocalParameters4fvEXT");
742 }
743
744
745 void GLAPIENTRY
746 _mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
747 GLdouble x, GLdouble y,
748 GLdouble z, GLdouble w)
749 {
750 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
751 (GLfloat) z, (GLfloat) w);
752 }
753
754
755 void GLAPIENTRY
756 _mesa_NamedProgramLocalParameter4dEXT(GLuint program, GLenum target, GLuint index,
757 GLdouble x, GLdouble y,
758 GLdouble z, GLdouble w)
759 {
760 _mesa_NamedProgramLocalParameter4fEXT(program, target, index, (GLfloat) x, (GLfloat) y,
761 (GLfloat) z, (GLfloat) w);
762 }
763
764
765 void GLAPIENTRY
766 _mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
767 const GLdouble *params)
768 {
769 _mesa_ProgramLocalParameter4fARB(target, index,
770 (GLfloat) params[0], (GLfloat) params[1],
771 (GLfloat) params[2], (GLfloat) params[3]);
772 }
773
774
775 void GLAPIENTRY
776 _mesa_NamedProgramLocalParameter4dvEXT(GLuint program, GLenum target, GLuint index,
777 const GLdouble *params)
778 {
779 _mesa_NamedProgramLocalParameter4fEXT(program, target, index,
780 (GLfloat) params[0], (GLfloat) params[1],
781 (GLfloat) params[2], (GLfloat) params[3]);
782 }
783
784
785 void GLAPIENTRY
786 _mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
787 GLfloat *params)
788 {
789 GLfloat *param;
790 GET_CURRENT_CONTEXT(ctx);
791 struct gl_program* prog = get_current_program(ctx, target, "glGetProgramLocalParameterfvARB");
792 if (!prog) {
793 return;
794 }
795
796 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
797 prog, target, index, &param)) {
798 COPY_4V(params, param);
799 }
800 }
801
802
803 void GLAPIENTRY
804 _mesa_GetNamedProgramLocalParameterfvEXT(GLuint program, GLenum target, GLuint index,
805 GLfloat *params)
806 {
807 GLfloat *param;
808 GET_CURRENT_CONTEXT(ctx);
809 struct gl_program* prog = lookup_or_create_program(program, target,
810 "glGetNamedProgramLocalParameterfvEXT");
811 if (!prog) {
812 return;
813 }
814
815 if (get_local_param_pointer(ctx, "glGetNamedProgramLocalParameterfvEXT",
816 prog, target, index, &param)) {
817 COPY_4V(params, param);
818 }
819 }
820
821
822 void GLAPIENTRY
823 _mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
824 GLdouble *params)
825 {
826 GLfloat *param;
827 GET_CURRENT_CONTEXT(ctx);
828 struct gl_program* prog = get_current_program(ctx, target, "glGetProgramLocalParameterdvARB");
829 if (!prog) {
830 return;
831 }
832
833 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
834 prog, target, index, &param)) {
835 COPY_4V(params, param);
836 }
837 }
838
839
840 void GLAPIENTRY
841 _mesa_GetNamedProgramLocalParameterdvEXT(GLuint program, GLenum target, GLuint index,
842 GLdouble *params)
843 {
844 GLfloat *param;
845 GET_CURRENT_CONTEXT(ctx);
846 struct gl_program* prog = lookup_or_create_program(program, target,
847 "glGetNamedProgramLocalParameterdvEXT");
848 if (!prog) {
849 return;
850 }
851
852 if (get_local_param_pointer(ctx, "glGetNamedProgramLocalParameterdvEXT",
853 prog, target, index, &param)) {
854 COPY_4V(params, param);
855 }
856 }
857
858
859 static void
860 get_program_iv(struct gl_program *prog, GLenum target, GLenum pname,
861 GLint *params)
862 {
863 const struct gl_program_constants *limits;
864
865 GET_CURRENT_CONTEXT(ctx);
866
867 if (target == GL_VERTEX_PROGRAM_ARB) {
868 limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
869 }
870 else {
871 limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
872 }
873
874 assert(prog);
875 assert(limits);
876
877 /* Queries supported for both vertex and fragment programs */
878 switch (pname) {
879 case GL_PROGRAM_LENGTH_ARB:
880 *params
881 = prog->String ? (GLint) strlen((char *) prog->String) : 0;
882 return;
883 case GL_PROGRAM_FORMAT_ARB:
884 *params = prog->Format;
885 return;
886 case GL_PROGRAM_BINDING_ARB:
887 *params = prog->Id;
888 return;
889 case GL_PROGRAM_INSTRUCTIONS_ARB:
890 *params = prog->arb.NumInstructions;
891 return;
892 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
893 *params = limits->MaxInstructions;
894 return;
895 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
896 *params = prog->arb.NumNativeInstructions;
897 return;
898 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
899 *params = limits->MaxNativeInstructions;
900 return;
901 case GL_PROGRAM_TEMPORARIES_ARB:
902 *params = prog->arb.NumTemporaries;
903 return;
904 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
905 *params = limits->MaxTemps;
906 return;
907 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
908 *params = prog->arb.NumNativeTemporaries;
909 return;
910 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
911 *params = limits->MaxNativeTemps;
912 return;
913 case GL_PROGRAM_PARAMETERS_ARB:
914 *params = prog->arb.NumParameters;
915 return;
916 case GL_MAX_PROGRAM_PARAMETERS_ARB:
917 *params = limits->MaxParameters;
918 return;
919 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
920 *params = prog->arb.NumNativeParameters;
921 return;
922 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
923 *params = limits->MaxNativeParameters;
924 return;
925 case GL_PROGRAM_ATTRIBS_ARB:
926 *params = prog->arb.NumAttributes;
927 return;
928 case GL_MAX_PROGRAM_ATTRIBS_ARB:
929 *params = limits->MaxAttribs;
930 return;
931 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
932 *params = prog->arb.NumNativeAttributes;
933 return;
934 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
935 *params = limits->MaxNativeAttribs;
936 return;
937 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
938 *params = prog->arb.NumAddressRegs;
939 return;
940 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
941 *params = limits->MaxAddressRegs;
942 return;
943 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
944 *params = prog->arb.NumNativeAddressRegs;
945 return;
946 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
947 *params = limits->MaxNativeAddressRegs;
948 return;
949 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
950 *params = limits->MaxLocalParams;
951 return;
952 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
953 *params = limits->MaxEnvParams;
954 return;
955 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
956 /*
957 * XXX we may not really need a driver callback here.
958 * If the number of native instructions, registers, etc. used
959 * are all below the maximums, we could return true.
960 * The spec says that even if this query returns true, there's
961 * no guarantee that the program will run in hardware.
962 */
963 if (prog->Id == 0) {
964 /* default/null program */
965 *params = GL_FALSE;
966 }
967 else if (ctx->Driver.IsProgramNative) {
968 /* ask the driver */
969 *params = ctx->Driver.IsProgramNative( ctx, target, prog );
970 }
971 else {
972 /* probably running in software */
973 *params = GL_TRUE;
974 }
975 return;
976 default:
977 /* continue with fragment-program only queries below */
978 break;
979 }
980
981 /*
982 * The following apply to fragment programs only (at this time)
983 */
984 if (target == GL_FRAGMENT_PROGRAM_ARB) {
985 const struct gl_program *fp = ctx->FragmentProgram.Current;
986 switch (pname) {
987 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
988 *params = fp->arb.NumNativeAluInstructions;
989 return;
990 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
991 *params = fp->arb.NumAluInstructions;
992 return;
993 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
994 *params = fp->arb.NumTexInstructions;
995 return;
996 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
997 *params = fp->arb.NumNativeTexInstructions;
998 return;
999 case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
1000 *params = fp->arb.NumTexIndirections;
1001 return;
1002 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
1003 *params = fp->arb.NumNativeTexIndirections;
1004 return;
1005 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
1006 *params = limits->MaxAluInstructions;
1007 return;
1008 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
1009 *params = limits->MaxNativeAluInstructions;
1010 return;
1011 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
1012 *params = limits->MaxTexInstructions;
1013 return;
1014 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
1015 *params = limits->MaxNativeTexInstructions;
1016 return;
1017 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
1018 *params = limits->MaxTexIndirections;
1019 return;
1020 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
1021 *params = limits->MaxNativeTexIndirections;
1022 return;
1023 default:
1024 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
1025 return;
1026 }
1027 } else {
1028 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
1029 return;
1030 }
1031 }
1032
1033
1034 void GLAPIENTRY
1035 _mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
1036 {
1037 GET_CURRENT_CONTEXT(ctx);
1038 struct gl_program* prog = get_current_program(ctx, target,
1039 "glGetProgramivARB");
1040 if (!prog) {
1041 return;
1042 }
1043 get_program_iv(prog, target, pname, params);
1044 }
1045
1046 void GLAPIENTRY
1047 _mesa_GetNamedProgramivEXT(GLuint program, GLenum target, GLenum pname,
1048 GLint *params)
1049 {
1050 struct gl_program* prog;
1051 if (pname == GL_PROGRAM_BINDING_ARB) {
1052 _mesa_GetProgramivARB(target, pname, params);
1053 return;
1054 }
1055 prog = lookup_or_create_program(program, target,
1056 "glGetNamedProgramivEXT");
1057 if (!prog) {
1058 return;
1059 }
1060 get_program_iv(prog, target, pname, params);
1061 }
1062
1063
1064 void GLAPIENTRY
1065 _mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
1066 {
1067 const struct gl_program *prog;
1068 char *dst = (char *) string;
1069 GET_CURRENT_CONTEXT(ctx);
1070
1071 if (target == GL_VERTEX_PROGRAM_ARB) {
1072 prog = ctx->VertexProgram.Current;
1073 }
1074 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
1075 prog = ctx->FragmentProgram.Current;
1076 }
1077 else {
1078 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
1079 return;
1080 }
1081
1082 assert(prog);
1083
1084 if (pname != GL_PROGRAM_STRING_ARB) {
1085 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
1086 return;
1087 }
1088
1089 if (prog->String)
1090 memcpy(dst, prog->String, strlen((char *) prog->String));
1091 else
1092 *dst = '\0';
1093 }
1094
1095
1096 void GLAPIENTRY
1097 _mesa_GetNamedProgramStringEXT(GLuint program, GLenum target,
1098 GLenum pname, GLvoid *string) {
1099 char *dst = (char *) string;
1100 GET_CURRENT_CONTEXT(ctx);
1101 struct gl_program* prog = lookup_or_create_program(program, target,
1102 "glGetNamedProgramStringEXT");
1103 if (!prog)
1104 return;
1105
1106 if (pname != GL_PROGRAM_STRING_ARB) {
1107 _mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedProgramStringEXT(pname)");
1108 return;
1109 }
1110
1111 if (prog->String)
1112 memcpy(dst, prog->String, strlen((char *) prog->String));
1113 else
1114 *dst = '\0';
1115 }