• 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 "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, &param)) {
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, &param)) {
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, &param)) {
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, &param)) {
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, &param)) {
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, &param)) {
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, &param)) {
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, &param)) {
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, &param)) {
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