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