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