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