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