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