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