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