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