xref: /third_party/mesa3d/src/mesa/main/arbprogram.c (revision bf215546)
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
48static void
49flush_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
65static struct gl_program*
66lookup_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 */
106void GLAPIENTRY
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 */
167void GLAPIENTRY
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 */
221void GLAPIENTRY
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 */
256GLboolean GLAPIENTRY
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
273static struct gl_program*
274get_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
291static GLboolean
292get_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
332static GLboolean
333get_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
359static void
360set_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
466void GLAPIENTRY
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
484void GLAPIENTRY
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 */
501void GLAPIENTRY
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 */
514void GLAPIENTRY
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 */
528void GLAPIENTRY
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 */
550void GLAPIENTRY
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
567void GLAPIENTRY
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
605void GLAPIENTRY
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
619void GLAPIENTRY
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
634void GLAPIENTRY
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
654void GLAPIENTRY
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
680void GLAPIENTRY
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
689void GLAPIENTRY
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
698static void
699program_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
716void GLAPIENTRY
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
731void GLAPIENTRY
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
747void GLAPIENTRY
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
757void GLAPIENTRY
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
767void GLAPIENTRY
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
777void GLAPIENTRY
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
787void GLAPIENTRY
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
805void GLAPIENTRY
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
824void GLAPIENTRY
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
842void GLAPIENTRY
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
861static void
862get_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
1032void GLAPIENTRY
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
1044void GLAPIENTRY
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
1062void GLAPIENTRY
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
1094void GLAPIENTRY
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