blob: eb537cd1b99bc1e9a3987c7f9063e5a5052ac40f [file] [log] [blame]
Michal Krol157ec8b2004-03-10 18:02:01 +00001/*
2 * Mesa 3-D graphics library
Brian4ca7c802007-04-28 08:01:18 -06003 * Version: 7.0
Michal Krol157ec8b2004-03-10 18:02:01 +00004 *
Brian4ca7c802007-04-28 08:01:18 -06005 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
Michal Krol157ec8b2004-03-10 18:02:01 +00006 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR 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
Brian Paulbbd28712008-09-18 12:26:54 -060032#include "main/glheader.h"
33#include "main/context.h"
34#include "main/hash.h"
35#include "main/imports.h"
36#include "main/macros.h"
37#include "main/mtypes.h"
Michal Krol157ec8b2004-03-10 18:02:01 +000038#include "arbprogram.h"
Brian Paul8c41a142005-11-19 15:36:28 +000039#include "arbprogparse.h"
Ian Romanick74528772009-11-02 13:37:47 -080040#include "nvfragparse.h"
Ian Romanick6d2ceda2009-11-02 14:08:51 -080041#include "nvvertparse.h"
Brian Paulf49c0d02006-11-02 16:20:29 +000042#include "program.h"
Michal Krol157ec8b2004-03-10 18:02:01 +000043
44
Brian Paulb7eea9a2008-07-29 17:19:25 -060045
46/**
47 * Mixing ARB and NV vertex/fragment programs can be tricky.
48 * Note: GL_VERTEX_PROGRAM_ARB == GL_VERTEX_PROGRAM_NV
49 * but, GL_FRAGMENT_PROGRAM_ARB != GL_FRAGMENT_PROGRAM_NV
50 * The two different fragment program targets are supposed to be compatible
51 * to some extent (see GL_ARB_fragment_program spec).
52 * This function does the compatibility check.
53 */
54static GLboolean
55compatible_program_targets(GLenum t1, GLenum t2)
56{
57 if (t1 == t2)
58 return GL_TRUE;
59 if (t1 == GL_FRAGMENT_PROGRAM_ARB && t2 == GL_FRAGMENT_PROGRAM_NV)
60 return GL_TRUE;
61 if (t1 == GL_FRAGMENT_PROGRAM_NV && t2 == GL_FRAGMENT_PROGRAM_ARB)
62 return GL_TRUE;
63 return GL_FALSE;
64}
65
66
67/**
68 * Bind a program (make it current)
69 * \note Called from the GL API dispatcher by both glBindProgramNV
70 * and glBindProgramARB.
71 */
72void GLAPIENTRY
73_mesa_BindProgram(GLenum target, GLuint id)
74{
75 struct gl_program *curProg, *newProg;
76 GET_CURRENT_CONTEXT(ctx);
77 ASSERT_OUTSIDE_BEGIN_END(ctx);
78
Brian Paulb7eea9a2008-07-29 17:19:25 -060079 /* Error-check target and get curProg */
80 if ((target == GL_VERTEX_PROGRAM_ARB) && /* == GL_VERTEX_PROGRAM_NV */
81 (ctx->Extensions.NV_vertex_program ||
82 ctx->Extensions.ARB_vertex_program)) {
83 curProg = &ctx->VertexProgram.Current->Base;
84 }
85 else if ((target == GL_FRAGMENT_PROGRAM_NV
86 && ctx->Extensions.NV_fragment_program) ||
87 (target == GL_FRAGMENT_PROGRAM_ARB
88 && ctx->Extensions.ARB_fragment_program)) {
89 curProg = &ctx->FragmentProgram.Current->Base;
90 }
91 else {
92 _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV/ARB(target)");
93 return;
94 }
95
96 /*
97 * Get pointer to new program to bind.
98 * NOTE: binding to a non-existant program is not an error.
99 * That's supposed to be caught in glBegin.
100 */
101 if (id == 0) {
102 /* Bind a default program */
103 newProg = NULL;
104 if (target == GL_VERTEX_PROGRAM_ARB) /* == GL_VERTEX_PROGRAM_NV */
105 newProg = &ctx->Shared->DefaultVertexProgram->Base;
106 else
107 newProg = &ctx->Shared->DefaultFragmentProgram->Base;
108 }
109 else {
110 /* Bind a user program */
111 newProg = _mesa_lookup_program(ctx, id);
112 if (!newProg || newProg == &_mesa_DummyProgram) {
113 /* allocate a new program now */
114 newProg = ctx->Driver.NewProgram(ctx, target, id);
115 if (!newProg) {
116 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV/ARB");
117 return;
118 }
119 _mesa_HashInsert(ctx->Shared->Programs, id, newProg);
120 }
121 else if (!compatible_program_targets(newProg->Target, target)) {
122 _mesa_error(ctx, GL_INVALID_OPERATION,
123 "glBindProgramNV/ARB(target mismatch)");
124 return;
125 }
126 }
127
128 /** All error checking is complete now **/
129
130 if (curProg->Id == id) {
131 /* binding same program - no change */
132 return;
133 }
134
Brian Paul027ed1b2009-04-24 09:43:44 -0600135 /* signal new program (and its new constants) */
136 FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
137
Brian Paulb7eea9a2008-07-29 17:19:25 -0600138 /* bind newProg */
139 if (target == GL_VERTEX_PROGRAM_ARB) { /* == GL_VERTEX_PROGRAM_NV */
140 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
141 (struct gl_vertex_program *) newProg);
142 }
143 else if (target == GL_FRAGMENT_PROGRAM_NV ||
144 target == GL_FRAGMENT_PROGRAM_ARB) {
145 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
146 (struct gl_fragment_program *) newProg);
147 }
148
149 /* Never null pointers */
150 ASSERT(ctx->VertexProgram.Current);
151 ASSERT(ctx->FragmentProgram.Current);
152
153 if (ctx->Driver.BindProgram)
154 ctx->Driver.BindProgram(ctx, target, newProg);
155}
156
157
158/**
159 * Delete a list of programs.
160 * \note Not compiled into display lists.
161 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
162 */
163void GLAPIENTRY
164_mesa_DeletePrograms(GLsizei n, const GLuint *ids)
165{
166 GLint i;
167 GET_CURRENT_CONTEXT(ctx);
168 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
169
170 if (n < 0) {
171 _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
172 return;
173 }
174
175 for (i = 0; i < n; i++) {
176 if (ids[i] != 0) {
177 struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
178 if (prog == &_mesa_DummyProgram) {
179 _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
180 }
181 else if (prog) {
182 /* Unbind program if necessary */
183 if (prog->Target == GL_VERTEX_PROGRAM_ARB || /* == GL_VERTEX_PROGRAM_NV */
184 prog->Target == GL_VERTEX_STATE_PROGRAM_NV) {
185 if (ctx->VertexProgram.Current &&
186 ctx->VertexProgram.Current->Base.Id == ids[i]) {
187 /* unbind this currently bound program */
188 _mesa_BindProgram(prog->Target, 0);
189 }
190 }
191 else if (prog->Target == GL_FRAGMENT_PROGRAM_NV ||
192 prog->Target == GL_FRAGMENT_PROGRAM_ARB) {
193 if (ctx->FragmentProgram.Current &&
194 ctx->FragmentProgram.Current->Base.Id == ids[i]) {
195 /* unbind this currently bound program */
196 _mesa_BindProgram(prog->Target, 0);
197 }
198 }
199 else {
200 _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
201 return;
202 }
203 /* The ID is immediately available for re-use now */
204 _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
205 _mesa_reference_program(ctx, &prog, NULL);
206 }
207 }
208 }
209}
210
211
212/**
213 * Generate a list of new program identifiers.
214 * \note Not compiled into display lists.
215 * \note Called by both glGenProgramsNV and glGenProgramsARB.
216 */
217void GLAPIENTRY
218_mesa_GenPrograms(GLsizei n, GLuint *ids)
219{
220 GLuint first;
221 GLuint i;
222 GET_CURRENT_CONTEXT(ctx);
223 ASSERT_OUTSIDE_BEGIN_END(ctx);
224
225 if (n < 0) {
226 _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
227 return;
228 }
229
230 if (!ids)
231 return;
232
233 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
234
235 /* Insert pointer to dummy program as placeholder */
236 for (i = 0; i < (GLuint) n; i++) {
237 _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
238 }
239
240 /* Return the program names */
241 for (i = 0; i < (GLuint) n; i++) {
242 ids[i] = first + i;
243 }
244}
245
246
Michal Krol157ec8b2004-03-10 18:02:01 +0000247void GLAPIENTRY
248_mesa_EnableVertexAttribArrayARB(GLuint index)
249{
250 GET_CURRENT_CONTEXT(ctx);
251 ASSERT_OUTSIDE_BEGIN_END(ctx);
252
Brian Paul05051032005-11-01 04:36:33 +0000253 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000254 _mesa_error(ctx, GL_INVALID_VALUE,
255 "glEnableVertexAttribArrayARB(index)");
256 return;
257 }
258
Brian Paula545f1a2009-05-22 07:51:35 -0600259 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
260
Michal Krol157ec8b2004-03-10 18:02:01 +0000261 FLUSH_VERTICES(ctx, _NEW_ARRAY);
Ian Romanickee34e6e2006-06-12 16:26:29 +0000262 ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE;
263 ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index);
Michal Krol157ec8b2004-03-10 18:02:01 +0000264 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
265}
266
267
268void GLAPIENTRY
269_mesa_DisableVertexAttribArrayARB(GLuint index)
270{
271 GET_CURRENT_CONTEXT(ctx);
272 ASSERT_OUTSIDE_BEGIN_END(ctx);
273
Brian Paul05051032005-11-01 04:36:33 +0000274 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000275 _mesa_error(ctx, GL_INVALID_VALUE,
276 "glEnableVertexAttribArrayARB(index)");
277 return;
278 }
279
Brian Paula545f1a2009-05-22 07:51:35 -0600280 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
281
Michal Krol157ec8b2004-03-10 18:02:01 +0000282 FLUSH_VERTICES(ctx, _NEW_ARRAY);
Ian Romanickee34e6e2006-06-12 16:26:29 +0000283 ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE;
284 ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index);
Michal Krol157ec8b2004-03-10 18:02:01 +0000285 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
286}
287
288
289void GLAPIENTRY
290_mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
291{
292 GLfloat fparams[4];
293 GET_CURRENT_CONTEXT(ctx);
294 ASSERT_OUTSIDE_BEGIN_END(ctx);
295
296 _mesa_GetVertexAttribfvARB(index, pname, fparams);
297 if (ctx->ErrorValue == GL_NO_ERROR) {
298 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
299 COPY_4V(params, fparams);
300 }
301 else {
302 params[0] = fparams[0];
303 }
304 }
305}
306
307
Brian Paul024de602009-05-21 16:02:50 -0600308/**
309 * Return info for a generic vertex attribute array (no alias with
310 * legacy vertex attributes (pos, normal, color, etc)).
311 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000312void GLAPIENTRY
313_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
314{
Brian Paul254845f2009-05-21 15:57:29 -0600315 const struct gl_client_array *array;
Michal Krol157ec8b2004-03-10 18:02:01 +0000316 GET_CURRENT_CONTEXT(ctx);
317 ASSERT_OUTSIDE_BEGIN_END(ctx);
318
Brian Paul882cd6c2009-05-22 07:30:05 -0600319 if (index >= MAX_VERTEX_GENERIC_ATTRIBS) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000320 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribfvARB(index)");
321 return;
322 }
323
Brian Paula545f1a2009-05-22 07:51:35 -0600324 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
325
Brian Paul254845f2009-05-21 15:57:29 -0600326 array = &ctx->Array.ArrayObj->VertexAttrib[index];
327
Michal Krol157ec8b2004-03-10 18:02:01 +0000328 switch (pname) {
329 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
Brian Paul254845f2009-05-21 15:57:29 -0600330 params[0] = (GLfloat) array->Enabled;
Michal Krol157ec8b2004-03-10 18:02:01 +0000331 break;
332 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
Brian Paul254845f2009-05-21 15:57:29 -0600333 params[0] = (GLfloat) array->Size;
Michal Krol157ec8b2004-03-10 18:02:01 +0000334 break;
335 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
Brian Paul254845f2009-05-21 15:57:29 -0600336 params[0] = (GLfloat) array->Stride;
Michal Krol157ec8b2004-03-10 18:02:01 +0000337 break;
338 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
Brian Paul254845f2009-05-21 15:57:29 -0600339 params[0] = (GLfloat) array->Type;
Michal Krol157ec8b2004-03-10 18:02:01 +0000340 break;
341 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
Brian Paul254845f2009-05-21 15:57:29 -0600342 params[0] = array->Normalized;
Michal Krol157ec8b2004-03-10 18:02:01 +0000343 break;
344 case GL_CURRENT_VERTEX_ATTRIB_ARB:
Brian Paul590b5572006-11-04 17:28:38 +0000345 if (index == 0) {
346 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Pauladf3a642006-11-04 17:31:21 +0000347 "glGetVertexAttribfvARB(index==0)");
Brian Paul590b5572006-11-04 17:28:38 +0000348 return;
349 }
Michal Krolbb38cad2006-04-11 11:41:11 +0000350 FLUSH_CURRENT(ctx, 0);
351 COPY_4V(params, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]);
Michal Krol157ec8b2004-03-10 18:02:01 +0000352 break;
353 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
Brian Paul254845f2009-05-21 15:57:29 -0600354 params[0] = (GLfloat) array->BufferObj->Name;
Tilman Sauerbeck6be81272006-05-30 16:57:52 +0000355 break;
Michal Krol157ec8b2004-03-10 18:02:01 +0000356 default:
357 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
358 return;
359 }
360}
361
362
363void GLAPIENTRY
364_mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
365{
366 GLfloat fparams[4];
367 GET_CURRENT_CONTEXT(ctx);
368 ASSERT_OUTSIDE_BEGIN_END(ctx);
369
370 _mesa_GetVertexAttribfvARB(index, pname, fparams);
371 if (ctx->ErrorValue == GL_NO_ERROR) {
372 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
373 COPY_4V_CAST(params, fparams, GLint); /* float to int */
374 }
375 else {
376 params[0] = (GLint) fparams[0];
377 }
378 }
379}
380
381
382void GLAPIENTRY
383_mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
384{
385 GET_CURRENT_CONTEXT(ctx);
386 ASSERT_OUTSIDE_BEGIN_END(ctx);
387
Brian Paul05051032005-11-01 04:36:33 +0000388 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000389 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
390 return;
391 }
392
393 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
394 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
395 return;
396 }
397
Brian Paula545f1a2009-05-22 07:51:35 -0600398 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
399
Ian Romanickee34e6e2006-06-12 16:26:29 +0000400 *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
Michal Krol157ec8b2004-03-10 18:02:01 +0000401}
402
403
Brian Paulf49c0d02006-11-02 16:20:29 +0000404/**
405 * Determine if id names a vertex or fragment program.
406 * \note Not compiled into display lists.
407 * \note Called from both glIsProgramNV and glIsProgramARB.
408 * \param id is the program identifier
409 * \return GL_TRUE if id is a program, else GL_FALSE.
410 */
411GLboolean GLAPIENTRY
412_mesa_IsProgramARB(GLuint id)
413{
Brian Paul308b85f2006-11-23 15:58:30 +0000414 struct gl_program *prog = NULL;
Brian Paulf49c0d02006-11-02 16:20:29 +0000415 GET_CURRENT_CONTEXT(ctx);
416 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
417
418 if (id == 0)
419 return GL_FALSE;
420
Brian Paul308b85f2006-11-23 15:58:30 +0000421 prog = _mesa_lookup_program(ctx, id);
422 if (prog && (prog != &_mesa_DummyProgram))
Brian Paulf49c0d02006-11-02 16:20:29 +0000423 return GL_TRUE;
424 else
425 return GL_FALSE;
426}
427
428
Michal Krol157ec8b2004-03-10 18:02:01 +0000429void GLAPIENTRY
430_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
431 const GLvoid *string)
432{
Ian Romanick74528772009-11-02 13:37:47 -0800433 struct gl_program *base;
Michal Krol157ec8b2004-03-10 18:02:01 +0000434 GET_CURRENT_CONTEXT(ctx);
435 ASSERT_OUTSIDE_BEGIN_END(ctx);
436
437 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
438
Ian Romanick6d2ceda2009-11-02 14:08:51 -0800439 if (!ctx->Extensions.ARB_vertex_program
440 && !ctx->Extensions.ARB_fragment_program) {
441 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()");
442 return;
443 }
444
Brian Paul8c41a142005-11-19 15:36:28 +0000445 if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
446 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
447 return;
448 }
449
Ian Romanick6d2ceda2009-11-02 14:08:51 -0800450 /* The first couple cases are complicated. The same enum value is used for
451 * ARB and NV vertex programs. If the target is a vertex program, parse it
452 * using the ARB grammar if the string starts with "!!ARB" or if
453 * NV_vertex_program is not supported.
454 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000455 if (target == GL_VERTEX_PROGRAM_ARB
Ian Romanick6d2ceda2009-11-02 14:08:51 -0800456 && ctx->Extensions.ARB_vertex_program
457 && ((strncmp(string, "!!ARB", 5) == 0)
458 || !ctx->Extensions.NV_vertex_program)) {
Brian Paul122629f2006-07-20 16:49:57 +0000459 struct gl_vertex_program *prog = ctx->VertexProgram.Current;
Brian Paul8c41a142005-11-19 15:36:28 +0000460 _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
Ian Romanick74528772009-11-02 13:37:47 -0800461
462 base = & prog->Base;
Michal Krol157ec8b2004-03-10 18:02:01 +0000463 }
Ian Romanick6d2ceda2009-11-02 14:08:51 -0800464 else if ((target == GL_VERTEX_PROGRAM_ARB
465 || target == GL_VERTEX_STATE_PROGRAM_NV)
466 && ctx->Extensions.NV_vertex_program) {
467 struct gl_vertex_program *prog = ctx->VertexProgram.Current;
468 _mesa_parse_nv_vertex_program(ctx, target, string, len, prog);
469
470 base = & prog->Base;
471 }
Michal Krol157ec8b2004-03-10 18:02:01 +0000472 else if (target == GL_FRAGMENT_PROGRAM_ARB
473 && ctx->Extensions.ARB_fragment_program) {
Brian Paul122629f2006-07-20 16:49:57 +0000474 struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
Brian Paul8c41a142005-11-19 15:36:28 +0000475 _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
Michal Krol157ec8b2004-03-10 18:02:01 +0000476
Ian Romanick74528772009-11-02 13:37:47 -0800477 base = & prog->Base;
478 }
479 else if (target == GL_FRAGMENT_PROGRAM_NV
480 && ctx->Extensions.NV_fragment_program) {
481 struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
482 _mesa_parse_nv_fragment_program(ctx, target, string, len, prog);
483
484 base = & prog->Base;
Michal Krol157ec8b2004-03-10 18:02:01 +0000485 }
486 else {
487 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
488 return;
489 }
Ian Romanick74528772009-11-02 13:37:47 -0800490
491 if (ctx->Program.ErrorPos == -1 && ctx->Driver.ProgramStringNotify)
492 ctx->Driver.ProgramStringNotify( ctx, target, base );
Michal Krol157ec8b2004-03-10 18:02:01 +0000493}
494
495
Roland Scheidegger86a48102007-11-09 14:46:59 +0100496/**
497 * Set a program env parameter register.
498 * \note Called from the GL API dispatcher.
499 * Note, this function is also used by the GL_NV_vertex_program extension
500 * (alias to ProgramParameterdNV)
501 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000502void GLAPIENTRY
503_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
504 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
505{
506 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
507 (GLfloat) z, (GLfloat) w);
508}
509
510
Roland Scheidegger86a48102007-11-09 14:46:59 +0100511/**
512 * Set a program env parameter register.
513 * \note Called from the GL API dispatcher.
514 * Note, this function is also used by the GL_NV_vertex_program extension
515 * (alias to ProgramParameterdvNV)
516 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000517void GLAPIENTRY
518_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
519 const GLdouble *params)
520{
521 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
522 (GLfloat) params[1], (GLfloat) params[2],
523 (GLfloat) params[3]);
524}
525
526
Roland Scheidegger86a48102007-11-09 14:46:59 +0100527/**
528 * Set a program env parameter register.
529 * \note Called from the GL API dispatcher.
530 * Note, this function is also used by the GL_NV_vertex_program extension
531 * (alias to ProgramParameterfNV)
532 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000533void GLAPIENTRY
534_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
535 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
536{
537 GET_CURRENT_CONTEXT(ctx);
538 ASSERT_OUTSIDE_BEGIN_END(ctx);
539
Brian Paul027ed1b2009-04-24 09:43:44 -0600540 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
Michal Krol157ec8b2004-03-10 18:02:01 +0000541
542 if (target == GL_FRAGMENT_PROGRAM_ARB
543 && ctx->Extensions.ARB_fragment_program) {
Brian Paul05051032005-11-01 04:36:33 +0000544 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000545 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
546 return;
547 }
548 ASSIGN_4V(ctx->FragmentProgram.Parameters[index], x, y, z, w);
549 }
Roland Scheidegger86a48102007-11-09 14:46:59 +0100550 else if (target == GL_VERTEX_PROGRAM_ARB /* == GL_VERTEX_PROGRAM_NV */
551 && (ctx->Extensions.ARB_vertex_program || ctx->Extensions.NV_vertex_program)) {
Brian Paul05051032005-11-01 04:36:33 +0000552 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000553 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
554 return;
555 }
556 ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
557 }
558 else {
559 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter(target)");
560 return;
561 }
562}
563
Roland Scheidegger86a48102007-11-09 14:46:59 +0100564/**
565 * Set a program env parameter register.
566 * \note Called from the GL API dispatcher.
567 * Note, this function is also used by the GL_NV_vertex_program extension
568 * (alias to ProgramParameterfvNV)
569 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000570void GLAPIENTRY
571_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
572 const GLfloat *params)
573{
574 _mesa_ProgramEnvParameter4fARB(target, index, params[0], params[1],
575 params[2], params[3]);
576}
577
578
579void GLAPIENTRY
Ian Romanick8c41c752006-08-15 16:47:34 +0000580_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
581 const GLfloat *params)
582{
583 GET_CURRENT_CONTEXT(ctx);
Brian223d7cb2007-01-23 16:37:51 -0700584 GLint i;
Ian Romanick8c41c752006-08-15 16:47:34 +0000585 GLfloat * dest;
586 ASSERT_OUTSIDE_BEGIN_END(ctx);
587
Brian Paul027ed1b2009-04-24 09:43:44 -0600588 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
Ian Romanick8c41c752006-08-15 16:47:34 +0000589
590 if (count <= 0) {
591 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
592 }
593
594 if (target == GL_FRAGMENT_PROGRAM_ARB
595 && ctx->Extensions.ARB_fragment_program) {
596 if ((index + count) > ctx->Const.FragmentProgram.MaxEnvParams) {
597 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
598 return;
599 }
600 dest = ctx->FragmentProgram.Parameters[index];
601 }
602 else if (target == GL_VERTEX_PROGRAM_ARB
603 && ctx->Extensions.ARB_vertex_program) {
604 if ((index + count) > ctx->Const.VertexProgram.MaxEnvParams) {
605 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
606 return;
607 }
608 dest = ctx->VertexProgram.Parameters[index];
609 }
610 else {
611 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
612 return;
613 }
614
615 for ( i = 0 ; i < count ; i++ ) {
616 COPY_4V(dest, params);
617 params += 4;
618 dest += 4;
619 }
620}
621
622
623void GLAPIENTRY
Michal Krol157ec8b2004-03-10 18:02:01 +0000624_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
625 GLdouble *params)
626{
627 GET_CURRENT_CONTEXT(ctx);
628 GLfloat fparams[4];
629
630 _mesa_GetProgramEnvParameterfvARB(target, index, fparams);
631 if (ctx->ErrorValue == GL_NO_ERROR) {
632 params[0] = fparams[0];
633 params[1] = fparams[1];
634 params[2] = fparams[2];
635 params[3] = fparams[3];
636 }
637}
638
639
640void GLAPIENTRY
641_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
642 GLfloat *params)
643{
644 GET_CURRENT_CONTEXT(ctx);
645
Brian Paul548be382009-03-11 20:08:37 -0600646 ASSERT_OUTSIDE_BEGIN_END(ctx);
Michal Krol157ec8b2004-03-10 18:02:01 +0000647
648 if (target == GL_FRAGMENT_PROGRAM_ARB
649 && ctx->Extensions.ARB_fragment_program) {
Brian Paul05051032005-11-01 04:36:33 +0000650 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000651 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
652 return;
653 }
654 COPY_4V(params, ctx->FragmentProgram.Parameters[index]);
655 }
Brian Paul83c74b72004-10-16 00:29:03 +0000656 else if (target == GL_VERTEX_PROGRAM_ARB
Michal Krol157ec8b2004-03-10 18:02:01 +0000657 && ctx->Extensions.ARB_vertex_program) {
Brian Paul05051032005-11-01 04:36:33 +0000658 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000659 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
660 return;
661 }
662 COPY_4V(params, ctx->VertexProgram.Parameters[index]);
663 }
664 else {
665 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramEnvParameter(target)");
666 return;
667 }
668}
669
670
671/**
672 * Note, this function is also used by the GL_NV_fragment_program extension.
673 */
674void GLAPIENTRY
675_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
676 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
677{
678 GET_CURRENT_CONTEXT(ctx);
Brian Paul122629f2006-07-20 16:49:57 +0000679 struct gl_program *prog;
Michal Krol157ec8b2004-03-10 18:02:01 +0000680 ASSERT_OUTSIDE_BEGIN_END(ctx);
681
Brian Paul027ed1b2009-04-24 09:43:44 -0600682 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
Michal Krol157ec8b2004-03-10 18:02:01 +0000683
684 if ((target == GL_FRAGMENT_PROGRAM_NV
685 && ctx->Extensions.NV_fragment_program) ||
686 (target == GL_FRAGMENT_PROGRAM_ARB
687 && ctx->Extensions.ARB_fragment_program)) {
Brian Paul05051032005-11-01 04:36:33 +0000688 if (index >= ctx->Const.FragmentProgram.MaxLocalParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000689 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
690 return;
691 }
692 prog = &(ctx->FragmentProgram.Current->Base);
693 }
694 else if (target == GL_VERTEX_PROGRAM_ARB
695 && ctx->Extensions.ARB_vertex_program) {
Brian Paul05051032005-11-01 04:36:33 +0000696 if (index >= ctx->Const.VertexProgram.MaxLocalParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000697 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
698 return;
699 }
700 prog = &(ctx->VertexProgram.Current->Base);
701 }
702 else {
703 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
704 return;
705 }
706
707 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
708 prog->LocalParams[index][0] = x;
709 prog->LocalParams[index][1] = y;
710 prog->LocalParams[index][2] = z;
711 prog->LocalParams[index][3] = w;
712}
713
714
715/**
716 * Note, this function is also used by the GL_NV_fragment_program extension.
717 */
718void GLAPIENTRY
719_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
720 const GLfloat *params)
721{
722 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
723 params[2], params[3]);
724}
725
726
Ian Romanick8c41c752006-08-15 16:47:34 +0000727void GLAPIENTRY
728_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
729 const GLfloat *params)
730{
731 GET_CURRENT_CONTEXT(ctx);
732 struct gl_program *prog;
Brian223d7cb2007-01-23 16:37:51 -0700733 GLint i;
Ian Romanick8c41c752006-08-15 16:47:34 +0000734 ASSERT_OUTSIDE_BEGIN_END(ctx);
735
Brian Paul027ed1b2009-04-24 09:43:44 -0600736 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
Ian Romanick8c41c752006-08-15 16:47:34 +0000737
738 if (count <= 0) {
739 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
740 }
741
742 if (target == GL_FRAGMENT_PROGRAM_ARB
743 && ctx->Extensions.ARB_fragment_program) {
744 if ((index + count) > ctx->Const.FragmentProgram.MaxLocalParams) {
745 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
746 return;
747 }
748 prog = &(ctx->FragmentProgram.Current->Base);
749 }
750 else if (target == GL_VERTEX_PROGRAM_ARB
751 && ctx->Extensions.ARB_vertex_program) {
752 if ((index + count) > ctx->Const.VertexProgram.MaxLocalParams) {
753 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
754 return;
755 }
756 prog = &(ctx->VertexProgram.Current->Base);
757 }
758 else {
759 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)");
760 return;
761 }
762
763 for (i = 0; i < count; i++) {
764 ASSERT((index + i) < MAX_PROGRAM_LOCAL_PARAMS);
765 COPY_4V(prog->LocalParams[index + i], params);
766 params += 4;
767 }
768}
769
770
Michal Krol157ec8b2004-03-10 18:02:01 +0000771/**
772 * Note, this function is also used by the GL_NV_fragment_program extension.
773 */
774void GLAPIENTRY
775_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
776 GLdouble x, GLdouble y,
777 GLdouble z, GLdouble w)
778{
779 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
780 (GLfloat) z, (GLfloat) w);
781}
782
783
784/**
785 * Note, this function is also used by the GL_NV_fragment_program extension.
786 */
787void GLAPIENTRY
788_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
789 const GLdouble *params)
790{
791 _mesa_ProgramLocalParameter4fARB(target, index,
792 (GLfloat) params[0], (GLfloat) params[1],
793 (GLfloat) params[2], (GLfloat) params[3]);
794}
795
796
797/**
798 * Note, this function is also used by the GL_NV_fragment_program extension.
799 */
800void GLAPIENTRY
801_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
802 GLfloat *params)
803{
Brian Paul122629f2006-07-20 16:49:57 +0000804 const struct gl_program *prog;
Michal Krol157ec8b2004-03-10 18:02:01 +0000805 GLuint maxParams;
806 GET_CURRENT_CONTEXT(ctx);
807 ASSERT_OUTSIDE_BEGIN_END(ctx);
808
809 if (target == GL_VERTEX_PROGRAM_ARB
810 && ctx->Extensions.ARB_vertex_program) {
811 prog = &(ctx->VertexProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000812 maxParams = ctx->Const.VertexProgram.MaxLocalParams;
Michal Krol157ec8b2004-03-10 18:02:01 +0000813 }
814 else if (target == GL_FRAGMENT_PROGRAM_ARB
815 && ctx->Extensions.ARB_fragment_program) {
816 prog = &(ctx->FragmentProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000817 maxParams = ctx->Const.FragmentProgram.MaxLocalParams;
Michal Krol157ec8b2004-03-10 18:02:01 +0000818 }
819 else if (target == GL_FRAGMENT_PROGRAM_NV
820 && ctx->Extensions.NV_fragment_program) {
821 prog = &(ctx->FragmentProgram.Current->Base);
822 maxParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
823 }
824 else {
825 _mesa_error(ctx, GL_INVALID_ENUM,
826 "glGetProgramLocalParameterARB(target)");
827 return;
828 }
829
830 if (index >= maxParams) {
831 _mesa_error(ctx, GL_INVALID_VALUE,
832 "glGetProgramLocalParameterARB(index)");
833 return;
834 }
835
836 ASSERT(prog);
837 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
838 COPY_4V(params, prog->LocalParams[index]);
839}
840
841
842/**
843 * Note, this function is also used by the GL_NV_fragment_program extension.
844 */
845void GLAPIENTRY
846_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
847 GLdouble *params)
848{
849 GET_CURRENT_CONTEXT(ctx);
850 GLfloat floatParams[4];
Brian Pauleb26cc62009-01-20 09:17:12 -0700851 ASSIGN_4V(floatParams, 0.0F, 0.0F, 0.0F, 0.0F);
Michal Krol157ec8b2004-03-10 18:02:01 +0000852 _mesa_GetProgramLocalParameterfvARB(target, index, floatParams);
853 if (ctx->ErrorValue == GL_NO_ERROR) {
854 COPY_4V(params, floatParams);
855 }
856}
857
858
859void GLAPIENTRY
860_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
861{
Brian Paul05051032005-11-01 04:36:33 +0000862 const struct gl_program_constants *limits;
Brian Paul122629f2006-07-20 16:49:57 +0000863 struct gl_program *prog;
Michal Krol157ec8b2004-03-10 18:02:01 +0000864 GET_CURRENT_CONTEXT(ctx);
865
Brian Paul548be382009-03-11 20:08:37 -0600866 ASSERT_OUTSIDE_BEGIN_END(ctx);
Michal Krol157ec8b2004-03-10 18:02:01 +0000867
868 if (target == GL_VERTEX_PROGRAM_ARB
869 && ctx->Extensions.ARB_vertex_program) {
870 prog = &(ctx->VertexProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000871 limits = &ctx->Const.VertexProgram;
Michal Krol157ec8b2004-03-10 18:02:01 +0000872 }
873 else if (target == GL_FRAGMENT_PROGRAM_ARB
874 && ctx->Extensions.ARB_fragment_program) {
875 prog = &(ctx->FragmentProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000876 limits = &ctx->Const.FragmentProgram;
Michal Krol157ec8b2004-03-10 18:02:01 +0000877 }
878 else {
879 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
880 return;
881 }
882
883 ASSERT(prog);
Brian Paul05051032005-11-01 04:36:33 +0000884 ASSERT(limits);
Michal Krol157ec8b2004-03-10 18:02:01 +0000885
Brian Paul05051032005-11-01 04:36:33 +0000886 /* Queries supported for both vertex and fragment programs */
Michal Krol157ec8b2004-03-10 18:02:01 +0000887 switch (pname) {
888 case GL_PROGRAM_LENGTH_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000889 *params
890 = prog->String ? (GLint) _mesa_strlen((char *) prog->String) : 0;
891 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000892 case GL_PROGRAM_FORMAT_ARB:
893 *params = prog->Format;
Brian Paul05051032005-11-01 04:36:33 +0000894 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000895 case GL_PROGRAM_BINDING_ARB:
896 *params = prog->Id;
Brian Paul05051032005-11-01 04:36:33 +0000897 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000898 case GL_PROGRAM_INSTRUCTIONS_ARB:
899 *params = prog->NumInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000900 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000901 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000902 *params = limits->MaxInstructions;
903 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000904 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000905 *params = prog->NumNativeInstructions;
906 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000907 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000908 *params = limits->MaxNativeInstructions;
909 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000910 case GL_PROGRAM_TEMPORARIES_ARB:
911 *params = prog->NumTemporaries;
Brian Paul05051032005-11-01 04:36:33 +0000912 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000913 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000914 *params = limits->MaxTemps;
915 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000916 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000917 *params = prog->NumNativeTemporaries;
918 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000919 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000920 *params = limits->MaxNativeTemps;
921 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000922 case GL_PROGRAM_PARAMETERS_ARB:
923 *params = prog->NumParameters;
Brian Paul05051032005-11-01 04:36:33 +0000924 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000925 case GL_MAX_PROGRAM_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000926 *params = limits->MaxParameters;
927 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000928 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000929 *params = prog->NumNativeParameters;
930 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000931 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000932 *params = limits->MaxNativeParameters;
933 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000934 case GL_PROGRAM_ATTRIBS_ARB:
935 *params = prog->NumAttributes;
Brian Paul05051032005-11-01 04:36:33 +0000936 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000937 case GL_MAX_PROGRAM_ATTRIBS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000938 *params = limits->MaxAttribs;
939 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000940 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000941 *params = prog->NumNativeAttributes;
942 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000943 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000944 *params = limits->MaxNativeAttribs;
945 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000946 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
947 *params = prog->NumAddressRegs;
Brian Paul05051032005-11-01 04:36:33 +0000948 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000949 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000950 *params = limits->MaxAddressRegs;
951 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000952 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000953 *params = prog->NumNativeAddressRegs;
954 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000955 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000956 *params = limits->MaxNativeAddressRegs;
957 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000958 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000959 *params = limits->MaxLocalParams;
960 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000961 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000962 *params = limits->MaxEnvParams;
963 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000964 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000965 /*
966 * XXX we may not really need a driver callback here.
967 * If the number of native instructions, registers, etc. used
968 * are all below the maximums, we could return true.
969 * The spec says that even if this query returns true, there's
970 * no guarantee that the program will run in hardware.
971 */
Brian4ca7c802007-04-28 08:01:18 -0600972 if (prog->Id == 0) {
973 /* default/null program */
974 *params = GL_FALSE;
975 }
976 else if (ctx->Driver.IsProgramNative) {
977 /* ask the driver */
Michal Krol157ec8b2004-03-10 18:02:01 +0000978 *params = ctx->Driver.IsProgramNative( ctx, target, prog );
Brian4ca7c802007-04-28 08:01:18 -0600979 }
980 else {
981 /* probably running in software */
Michal Krol157ec8b2004-03-10 18:02:01 +0000982 *params = GL_TRUE;
Brian4ca7c802007-04-28 08:01:18 -0600983 }
Michal Krol157ec8b2004-03-10 18:02:01 +0000984 return;
Brian Paul05051032005-11-01 04:36:33 +0000985 default:
986 /* continue with fragment-program only queries below */
987 break;
988 }
989
990 /*
991 * The following apply to fragment programs only (at this time)
992 */
993 if (target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul122629f2006-07-20 16:49:57 +0000994 const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
Brian Paul05051032005-11-01 04:36:33 +0000995 switch (pname) {
996 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700997 *params = fp->Base.NumNativeAluInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000998 return;
999 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -07001000 *params = fp->Base.NumAluInstructions;
Brian Paul05051032005-11-01 04:36:33 +00001001 return;
1002 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -07001003 *params = fp->Base.NumTexInstructions;
Brian Paul05051032005-11-01 04:36:33 +00001004 return;
1005 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -07001006 *params = fp->Base.NumNativeTexInstructions;
Brian Paul05051032005-11-01 04:36:33 +00001007 return;
1008 case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -07001009 *params = fp->Base.NumTexIndirections;
Brian Paul05051032005-11-01 04:36:33 +00001010 return;
1011 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -07001012 *params = fp->Base.NumNativeTexIndirections;
Brian Paul05051032005-11-01 04:36:33 +00001013 return;
1014 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
1015 *params = limits->MaxAluInstructions;
1016 return;
1017 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
1018 *params = limits->MaxNativeAluInstructions;
1019 return;
1020 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
1021 *params = limits->MaxTexInstructions;
1022 return;
1023 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
1024 *params = limits->MaxNativeTexInstructions;
1025 return;
1026 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
1027 *params = limits->MaxTexIndirections;
1028 return;
1029 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
1030 *params = limits->MaxNativeTexIndirections;
1031 return;
1032 default:
1033 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
1034 return;
1035 }
Ian Romanick4bccd692009-08-24 12:48:01 -07001036 } else {
1037 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
1038 return;
Michal Krol157ec8b2004-03-10 18:02:01 +00001039 }
1040}
1041
1042
1043void GLAPIENTRY
1044_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
1045{
Brian Paul122629f2006-07-20 16:49:57 +00001046 const struct gl_program *prog;
Brian Paul308b85f2006-11-23 15:58:30 +00001047 char *dst = (char *) string;
Michal Krol157ec8b2004-03-10 18:02:01 +00001048 GET_CURRENT_CONTEXT(ctx);
1049
Brian Paul548be382009-03-11 20:08:37 -06001050 ASSERT_OUTSIDE_BEGIN_END(ctx);
Michal Krol157ec8b2004-03-10 18:02:01 +00001051
1052 if (target == GL_VERTEX_PROGRAM_ARB) {
1053 prog = &(ctx->VertexProgram.Current->Base);
1054 }
1055 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
1056 prog = &(ctx->FragmentProgram.Current->Base);
1057 }
1058 else {
1059 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
1060 return;
1061 }
1062
1063 ASSERT(prog);
1064
1065 if (pname != GL_PROGRAM_STRING_ARB) {
1066 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
1067 return;
1068 }
1069
Brian Paul308b85f2006-11-23 15:58:30 +00001070 if (prog->String)
1071 _mesa_memcpy(dst, prog->String, _mesa_strlen((char *) prog->String));
1072 else
1073 *dst = '\0';
Michal Krol157ec8b2004-03-10 18:02:01 +00001074}