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