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 uint8_t sha1[SHA1_DIGEST_LENGTH];
384 _mesa_sha1_compute(string, len, sha1);
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, sha1);
390
391 replacement = _mesa_read_shader_source(stage, string, sha1);
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 return;
406 }
407
408 failed = ctx->Program.ErrorPos != -1;
409
410 if (!failed) {
411 /* finally, give the program to the driver for translation/checking */
412 if (!st_program_string_notify(ctx, target, prog)) {
413 failed = true;
414 _mesa_error(ctx, GL_INVALID_OPERATION,
415 "glProgramStringARB(rejected by driver");
416 }
417 }
418
419 _mesa_update_vertex_processing_mode(ctx);
420 _mesa_update_valid_to_render_state(ctx);
421
422 if (ctx->_Shader->Flags & GLSL_DUMP) {
423 const char *shader_type =
424 target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";
425
426 fprintf(stderr, "ARB_%s_program source for program %d:\n",
427 shader_type, prog->Id);
428 fprintf(stderr, "%s\n", (const char *) string);
429
430 if (failed) {
431 fprintf(stderr, "ARB_%s_program %d failed to compile.\n",
432 shader_type, prog->Id);
433 } else {
434 fprintf(stderr, "Mesa IR for ARB_%s_program %d:\n",
435 shader_type, prog->Id);
436 _mesa_print_program(prog);
437 fprintf(stderr, "\n");
438 }
439 fflush(stderr);
440 }
441
442 /* Capture vp-*.shader_test/fp-*.shader_test files. */
443 const char *capture_path = _mesa_get_shader_capture_path();
444 if (capture_path != NULL) {
445 FILE *file;
446 const char *shader_type =
447 target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";
448 char *filename =
449 ralloc_asprintf(NULL, "%s/%cp-%u.shader_test",
450 capture_path, shader_type[0], prog->Id);
451
452 file = fopen(filename, "w");
453 if (file) {
454 fprintf(file,
455 "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n",
456 shader_type, shader_type, (const char *) string);
457 fclose(file);
458 } else {
459 _mesa_warning(ctx, "Failed to open %s", filename);
460 }
461 ralloc_free(filename);
462 }
463 }
464
465 void GLAPIENTRY
_mesa_ProgramStringARB(GLenum target,GLenum format,GLsizei len,const GLvoid * string)466 _mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
467 const GLvoid *string)
468 {
469 GET_CURRENT_CONTEXT(ctx);
470 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
471 set_program_string(ctx->VertexProgram.Current, target, format, len, string);
472 }
473 else if (target == GL_FRAGMENT_PROGRAM_ARB
474 && ctx->Extensions.ARB_fragment_program) {
475 set_program_string(ctx->FragmentProgram.Current, target, format, len, string);
476 }
477 else {
478 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
479 return;
480 }
481 }
482
483 void GLAPIENTRY
_mesa_NamedProgramStringEXT(GLuint program,GLenum target,GLenum format,GLsizei len,const GLvoid * string)484 _mesa_NamedProgramStringEXT(GLuint program, GLenum target, GLenum format, GLsizei len,
485 const GLvoid *string)
486 {
487 struct gl_program* prog = lookup_or_create_program(program, target, "glNamedProgramStringEXT");
488
489 if (!prog) {
490 return;
491 }
492 set_program_string(prog, target, format, len, string);
493 }
494
495
496 /**
497 * Set a program env parameter register.
498 * \note Called from the GL API dispatcher.
499 */
500 void GLAPIENTRY
_mesa_ProgramEnvParameter4dARB(GLenum target,GLuint index,GLdouble x,GLdouble y,GLdouble z,GLdouble w)501 _mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
502 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
503 {
504 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
505 (GLfloat) z, (GLfloat) w);
506 }
507
508
509 /**
510 * Set a program env parameter register.
511 * \note Called from the GL API dispatcher.
512 */
513 void GLAPIENTRY
_mesa_ProgramEnvParameter4dvARB(GLenum target,GLuint index,const GLdouble * params)514 _mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
515 const GLdouble *params)
516 {
517 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
518 (GLfloat) params[1], (GLfloat) params[2],
519 (GLfloat) params[3]);
520 }
521
522
523 /**
524 * Set a program env parameter register.
525 * \note Called from the GL API dispatcher.
526 */
527 void GLAPIENTRY
_mesa_ProgramEnvParameter4fARB(GLenum target,GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)528 _mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
529 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
530 {
531 GLfloat *param;
532
533 GET_CURRENT_CONTEXT(ctx);
534
535 flush_vertices_for_program_constants(ctx, target);
536
537 if (get_env_param_pointer(ctx, "glProgramEnvParameter",
538 target, index, ¶m)) {
539 ASSIGN_4V(param, x, y, z, w);
540 }
541 }
542
543
544
545 /**
546 * Set a program env parameter register.
547 * \note Called from the GL API dispatcher.
548 */
549 void GLAPIENTRY
_mesa_ProgramEnvParameter4fvARB(GLenum target,GLuint index,const GLfloat * params)550 _mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
551 const GLfloat *params)
552 {
553 GLfloat *param;
554
555 GET_CURRENT_CONTEXT(ctx);
556
557 flush_vertices_for_program_constants(ctx, target);
558
559 if (get_env_param_pointer(ctx, "glProgramEnvParameter4fv",
560 target, index, ¶m)) {
561 memcpy(param, params, 4 * sizeof(GLfloat));
562 }
563 }
564
565
566 void GLAPIENTRY
_mesa_ProgramEnvParameters4fvEXT(GLenum target,GLuint index,GLsizei count,const GLfloat * params)567 _mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
568 const GLfloat *params)
569 {
570 GET_CURRENT_CONTEXT(ctx);
571 GLfloat * dest;
572
573 flush_vertices_for_program_constants(ctx, target);
574
575 if (count <= 0) {
576 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
577 }
578
579 if (target == GL_FRAGMENT_PROGRAM_ARB
580 && ctx->Extensions.ARB_fragment_program) {
581 if ((index + count) > ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) {
582 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
583 return;
584 }
585 dest = ctx->FragmentProgram.Parameters[index];
586 }
587 else if (target == GL_VERTEX_PROGRAM_ARB
588 && ctx->Extensions.ARB_vertex_program) {
589 if ((index + count) > ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) {
590 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
591 return;
592 }
593 dest = ctx->VertexProgram.Parameters[index];
594 }
595 else {
596 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
597 return;
598 }
599
600 memcpy(dest, params, count * 4 * sizeof(GLfloat));
601 }
602
603
604 void GLAPIENTRY
_mesa_GetProgramEnvParameterdvARB(GLenum target,GLuint index,GLdouble * params)605 _mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
606 GLdouble *params)
607 {
608 GET_CURRENT_CONTEXT(ctx);
609 GLfloat *fparam;
610
611 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterdv",
612 target, index, &fparam)) {
613 COPY_4V(params, fparam);
614 }
615 }
616
617
618 void GLAPIENTRY
_mesa_GetProgramEnvParameterfvARB(GLenum target,GLuint index,GLfloat * params)619 _mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
620 GLfloat *params)
621 {
622 GLfloat *param;
623
624 GET_CURRENT_CONTEXT(ctx);
625
626 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterfv",
627 target, index, ¶m)) {
628 COPY_4V(params, param);
629 }
630 }
631
632
633 void GLAPIENTRY
_mesa_ProgramLocalParameter4fARB(GLenum target,GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)634 _mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
635 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
636 {
637 GET_CURRENT_CONTEXT(ctx);
638 GLfloat *param;
639 struct gl_program* prog = get_current_program(ctx, target, "glProgramLocalParameterARB");
640 if (!prog) {
641 return;
642 }
643
644 flush_vertices_for_program_constants(ctx, target);
645
646 if (get_local_param_pointer(ctx, "glProgramLocalParameterARB",
647 prog, target, index, 1, ¶m)) {
648 assert(index < MAX_PROGRAM_LOCAL_PARAMS);
649 ASSIGN_4V(param, x, y, z, w);
650 }
651 }
652
653 void GLAPIENTRY
_mesa_NamedProgramLocalParameter4fEXT(GLuint program,GLenum target,GLuint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)654 _mesa_NamedProgramLocalParameter4fEXT(GLuint program, GLenum target, GLuint index,
655 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
656 {
657 GET_CURRENT_CONTEXT(ctx);
658 GLfloat *param;
659 struct gl_program* prog = lookup_or_create_program(program, target,
660 "glNamedProgramLocalParameter4fEXT");
661
662 if (!prog) {
663 return;
664 }
665
666 if ((target == GL_VERTEX_PROGRAM_ARB && prog == ctx->VertexProgram.Current) ||
667 (target == GL_FRAGMENT_PROGRAM_ARB && prog == ctx->FragmentProgram.Current)) {
668 flush_vertices_for_program_constants(ctx, target);
669 }
670
671 if (get_local_param_pointer(ctx, "glNamedProgramLocalParameter4fEXT",
672 prog, target, index, 1, ¶m)) {
673 assert(index < MAX_PROGRAM_LOCAL_PARAMS);
674 ASSIGN_4V(param, x, y, z, w);
675 }
676 }
677
678
679 void GLAPIENTRY
_mesa_ProgramLocalParameter4fvARB(GLenum target,GLuint index,const GLfloat * params)680 _mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
681 const GLfloat *params)
682 {
683 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
684 params[2], params[3]);
685 }
686
687
688 void GLAPIENTRY
_mesa_NamedProgramLocalParameter4fvEXT(GLuint program,GLenum target,GLuint index,const GLfloat * params)689 _mesa_NamedProgramLocalParameter4fvEXT(GLuint program, GLenum target, GLuint index,
690 const GLfloat *params)
691 {
692 _mesa_NamedProgramLocalParameter4fEXT(program, target, index, params[0],
693 params[1], params[2], params[3]);
694 }
695
696
697 static void
program_local_parameters4fv(struct gl_program * prog,GLuint index,GLsizei count,const GLfloat * params,const char * caller)698 program_local_parameters4fv(struct gl_program* prog, GLuint index, GLsizei count,
699 const GLfloat *params, const char* caller)
700 {
701 GET_CURRENT_CONTEXT(ctx);
702 GLfloat *dest;
703 flush_vertices_for_program_constants(ctx, prog->Target);
704
705 if (count <= 0) {
706 _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", caller);
707 }
708
709 if (get_local_param_pointer(ctx, caller,
710 prog, prog->Target, index, count, &dest))
711 memcpy(dest, params, count * 4 * sizeof(GLfloat));
712 }
713
714
715 void GLAPIENTRY
_mesa_ProgramLocalParameters4fvEXT(GLenum target,GLuint index,GLsizei count,const GLfloat * params)716 _mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
717 const GLfloat *params)
718 {
719 GET_CURRENT_CONTEXT(ctx);
720 struct gl_program* prog = get_current_program(ctx, target,
721 "glProgramLocalParameters4fv");
722 if (!prog) {
723 return;
724 }
725
726 program_local_parameters4fv(prog, index, count, params,
727 "glProgramLocalParameters4fv");
728 }
729
730 void GLAPIENTRY
_mesa_NamedProgramLocalParameters4fvEXT(GLuint program,GLenum target,GLuint index,GLsizei count,const GLfloat * params)731 _mesa_NamedProgramLocalParameters4fvEXT(GLuint program, GLenum target, GLuint index,
732 GLsizei count, const GLfloat *params)
733 {
734 struct gl_program* prog =
735 lookup_or_create_program(program, target,
736 "glNamedProgramLocalParameters4fvEXT");
737 if (!prog) {
738 return;
739 }
740
741 program_local_parameters4fv(prog, index, count, params,
742 "glNamedProgramLocalParameters4fvEXT");
743 }
744
745
746 void GLAPIENTRY
_mesa_ProgramLocalParameter4dARB(GLenum target,GLuint index,GLdouble x,GLdouble y,GLdouble z,GLdouble w)747 _mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
748 GLdouble x, GLdouble y,
749 GLdouble z, GLdouble w)
750 {
751 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
752 (GLfloat) z, (GLfloat) w);
753 }
754
755
756 void GLAPIENTRY
_mesa_NamedProgramLocalParameter4dEXT(GLuint program,GLenum target,GLuint index,GLdouble x,GLdouble y,GLdouble z,GLdouble w)757 _mesa_NamedProgramLocalParameter4dEXT(GLuint program, GLenum target, GLuint index,
758 GLdouble x, GLdouble y,
759 GLdouble z, GLdouble w)
760 {
761 _mesa_NamedProgramLocalParameter4fEXT(program, target, index, (GLfloat) x, (GLfloat) y,
762 (GLfloat) z, (GLfloat) w);
763 }
764
765
766 void GLAPIENTRY
_mesa_ProgramLocalParameter4dvARB(GLenum target,GLuint index,const GLdouble * params)767 _mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
768 const GLdouble *params)
769 {
770 _mesa_ProgramLocalParameter4fARB(target, index,
771 (GLfloat) params[0], (GLfloat) params[1],
772 (GLfloat) params[2], (GLfloat) params[3]);
773 }
774
775
776 void GLAPIENTRY
_mesa_NamedProgramLocalParameter4dvEXT(GLuint program,GLenum target,GLuint index,const GLdouble * params)777 _mesa_NamedProgramLocalParameter4dvEXT(GLuint program, GLenum target, GLuint index,
778 const GLdouble *params)
779 {
780 _mesa_NamedProgramLocalParameter4fEXT(program, target, index,
781 (GLfloat) params[0], (GLfloat) params[1],
782 (GLfloat) params[2], (GLfloat) params[3]);
783 }
784
785
786 void GLAPIENTRY
_mesa_GetProgramLocalParameterfvARB(GLenum target,GLuint index,GLfloat * params)787 _mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
788 GLfloat *params)
789 {
790 GLfloat *param;
791 GET_CURRENT_CONTEXT(ctx);
792 struct gl_program* prog = get_current_program(ctx, target, "glGetProgramLocalParameterfvARB");
793 if (!prog) {
794 return;
795 }
796
797 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
798 prog, target, index, 1, ¶m)) {
799 COPY_4V(params, param);
800 }
801 }
802
803
804 void GLAPIENTRY
_mesa_GetNamedProgramLocalParameterfvEXT(GLuint program,GLenum target,GLuint index,GLfloat * params)805 _mesa_GetNamedProgramLocalParameterfvEXT(GLuint program, GLenum target, GLuint index,
806 GLfloat *params)
807 {
808 GLfloat *param;
809 GET_CURRENT_CONTEXT(ctx);
810 struct gl_program* prog = lookup_or_create_program(program, target,
811 "glGetNamedProgramLocalParameterfvEXT");
812 if (!prog) {
813 return;
814 }
815
816 if (get_local_param_pointer(ctx, "glGetNamedProgramLocalParameterfvEXT",
817 prog, target, index, 1, ¶m)) {
818 COPY_4V(params, param);
819 }
820 }
821
822
823 void GLAPIENTRY
_mesa_GetProgramLocalParameterdvARB(GLenum target,GLuint index,GLdouble * params)824 _mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
825 GLdouble *params)
826 {
827 GLfloat *param;
828 GET_CURRENT_CONTEXT(ctx);
829 struct gl_program* prog = get_current_program(ctx, target, "glGetProgramLocalParameterdvARB");
830 if (!prog) {
831 return;
832 }
833
834 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
835 prog, target, index, 1, ¶m)) {
836 COPY_4V(params, param);
837 }
838 }
839
840
841 void GLAPIENTRY
_mesa_GetNamedProgramLocalParameterdvEXT(GLuint program,GLenum target,GLuint index,GLdouble * params)842 _mesa_GetNamedProgramLocalParameterdvEXT(GLuint program, GLenum target, GLuint index,
843 GLdouble *params)
844 {
845 GLfloat *param;
846 GET_CURRENT_CONTEXT(ctx);
847 struct gl_program* prog = lookup_or_create_program(program, target,
848 "glGetNamedProgramLocalParameterdvEXT");
849 if (!prog) {
850 return;
851 }
852
853 if (get_local_param_pointer(ctx, "glGetNamedProgramLocalParameterdvEXT",
854 prog, target, index, 1, ¶m)) {
855 COPY_4V(params, param);
856 }
857 }
858
859
860 static void
get_program_iv(struct gl_program * prog,GLenum target,GLenum pname,GLint * params)861 get_program_iv(struct gl_program *prog, GLenum target, GLenum pname,
862 GLint *params)
863 {
864 const struct gl_program_constants *limits;
865
866 GET_CURRENT_CONTEXT(ctx);
867
868 if (target == GL_VERTEX_PROGRAM_ARB) {
869 limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
870 }
871 else {
872 limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
873 }
874
875 assert(prog);
876 assert(limits);
877
878 /* Queries supported for both vertex and fragment programs */
879 switch (pname) {
880 case GL_PROGRAM_LENGTH_ARB:
881 *params
882 = prog->String ? (GLint) strlen((char *) prog->String) : 0;
883 return;
884 case GL_PROGRAM_FORMAT_ARB:
885 *params = prog->Format;
886 return;
887 case GL_PROGRAM_BINDING_ARB:
888 *params = prog->Id;
889 return;
890 case GL_PROGRAM_INSTRUCTIONS_ARB:
891 *params = prog->arb.NumInstructions;
892 return;
893 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
894 *params = limits->MaxInstructions;
895 return;
896 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
897 *params = prog->arb.NumNativeInstructions;
898 return;
899 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
900 *params = limits->MaxNativeInstructions;
901 return;
902 case GL_PROGRAM_TEMPORARIES_ARB:
903 *params = prog->arb.NumTemporaries;
904 return;
905 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
906 *params = limits->MaxTemps;
907 return;
908 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
909 *params = prog->arb.NumNativeTemporaries;
910 return;
911 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
912 *params = limits->MaxNativeTemps;
913 return;
914 case GL_PROGRAM_PARAMETERS_ARB:
915 *params = prog->arb.NumParameters;
916 return;
917 case GL_MAX_PROGRAM_PARAMETERS_ARB:
918 *params = limits->MaxParameters;
919 return;
920 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
921 *params = prog->arb.NumNativeParameters;
922 return;
923 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
924 *params = limits->MaxNativeParameters;
925 return;
926 case GL_PROGRAM_ATTRIBS_ARB:
927 *params = prog->arb.NumAttributes;
928 return;
929 case GL_MAX_PROGRAM_ATTRIBS_ARB:
930 *params = limits->MaxAttribs;
931 return;
932 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
933 *params = prog->arb.NumNativeAttributes;
934 return;
935 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
936 *params = limits->MaxNativeAttribs;
937 return;
938 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
939 *params = prog->arb.NumAddressRegs;
940 return;
941 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
942 *params = limits->MaxAddressRegs;
943 return;
944 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
945 *params = prog->arb.NumNativeAddressRegs;
946 return;
947 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
948 *params = limits->MaxNativeAddressRegs;
949 return;
950 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
951 *params = limits->MaxLocalParams;
952 return;
953 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
954 *params = limits->MaxEnvParams;
955 return;
956 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
957 /*
958 * XXX we may not really need a driver callback here.
959 * If the number of native instructions, registers, etc. used
960 * are all below the maximums, we could return true.
961 * The spec says that even if this query returns true, there's
962 * no guarantee that the program will run in hardware.
963 */
964 if (prog->Id == 0) {
965 /* default/null program */
966 *params = GL_FALSE;
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