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