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