blob: 1656dc945073d5d4e48d3116c5edb23662a57db8 [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
32#include "glheader.h"
33#include "arbprogram.h"
Brian Paul8c41a142005-11-19 15:36:28 +000034#include "arbprogparse.h"
Michal Krol157ec8b2004-03-10 18:02:01 +000035#include "context.h"
36#include "imports.h"
37#include "macros.h"
38#include "mtypes.h"
Brian Paulf49c0d02006-11-02 16:20:29 +000039#include "program.h"
Michal Krol157ec8b2004-03-10 18:02:01 +000040
41
42void GLAPIENTRY
43_mesa_EnableVertexAttribArrayARB(GLuint index)
44{
45 GET_CURRENT_CONTEXT(ctx);
46 ASSERT_OUTSIDE_BEGIN_END(ctx);
47
Brian Paul05051032005-11-01 04:36:33 +000048 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
Michal Krol157ec8b2004-03-10 18:02:01 +000049 _mesa_error(ctx, GL_INVALID_VALUE,
50 "glEnableVertexAttribArrayARB(index)");
51 return;
52 }
53
54 FLUSH_VERTICES(ctx, _NEW_ARRAY);
Ian Romanickee34e6e2006-06-12 16:26:29 +000055 ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE;
56 ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index);
Michal Krol157ec8b2004-03-10 18:02:01 +000057 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
58}
59
60
61void GLAPIENTRY
62_mesa_DisableVertexAttribArrayARB(GLuint index)
63{
64 GET_CURRENT_CONTEXT(ctx);
65 ASSERT_OUTSIDE_BEGIN_END(ctx);
66
Brian Paul05051032005-11-01 04:36:33 +000067 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
Michal Krol157ec8b2004-03-10 18:02:01 +000068 _mesa_error(ctx, GL_INVALID_VALUE,
69 "glEnableVertexAttribArrayARB(index)");
70 return;
71 }
72
73 FLUSH_VERTICES(ctx, _NEW_ARRAY);
Ian Romanickee34e6e2006-06-12 16:26:29 +000074 ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE;
75 ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index);
Michal Krol157ec8b2004-03-10 18:02:01 +000076 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
77}
78
79
80void GLAPIENTRY
81_mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
82{
83 GLfloat fparams[4];
84 GET_CURRENT_CONTEXT(ctx);
85 ASSERT_OUTSIDE_BEGIN_END(ctx);
86
87 _mesa_GetVertexAttribfvARB(index, pname, fparams);
88 if (ctx->ErrorValue == GL_NO_ERROR) {
89 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
90 COPY_4V(params, fparams);
91 }
92 else {
93 params[0] = fparams[0];
94 }
95 }
96}
97
98
99void GLAPIENTRY
100_mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
101{
102 GET_CURRENT_CONTEXT(ctx);
103 ASSERT_OUTSIDE_BEGIN_END(ctx);
104
Brian Paul590b5572006-11-04 17:28:38 +0000105 if (index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000106 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribfvARB(index)");
107 return;
108 }
109
110 switch (pname) {
111 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000112 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Enabled;
Michal Krol157ec8b2004-03-10 18:02:01 +0000113 break;
114 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000115 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Size;
Michal Krol157ec8b2004-03-10 18:02:01 +0000116 break;
117 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000118 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Stride;
Michal Krol157ec8b2004-03-10 18:02:01 +0000119 break;
120 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000121 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].Type;
Michal Krol157ec8b2004-03-10 18:02:01 +0000122 break;
123 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
Ian Romanickee34e6e2006-06-12 16:26:29 +0000124 params[0] = ctx->Array.ArrayObj->VertexAttrib[index].Normalized;
Michal Krol157ec8b2004-03-10 18:02:01 +0000125 break;
126 case GL_CURRENT_VERTEX_ATTRIB_ARB:
Brian Paul590b5572006-11-04 17:28:38 +0000127 if (index == 0) {
128 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Pauladf3a642006-11-04 17:31:21 +0000129 "glGetVertexAttribfvARB(index==0)");
Brian Paul590b5572006-11-04 17:28:38 +0000130 return;
131 }
Michal Krolbb38cad2006-04-11 11:41:11 +0000132 FLUSH_CURRENT(ctx, 0);
133 COPY_4V(params, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index]);
Michal Krol157ec8b2004-03-10 18:02:01 +0000134 break;
135 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
136 if (!ctx->Extensions.ARB_vertex_buffer_object) {
137 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
138 return;
139 }
Ian Romanickee34e6e2006-06-12 16:26:29 +0000140 params[0] = (GLfloat) ctx->Array.ArrayObj->VertexAttrib[index].BufferObj->Name;
Tilman Sauerbeck6be81272006-05-30 16:57:52 +0000141 break;
Michal Krol157ec8b2004-03-10 18:02:01 +0000142 default:
143 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribfvARB(pname)");
144 return;
145 }
146}
147
148
149void GLAPIENTRY
150_mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
151{
152 GLfloat fparams[4];
153 GET_CURRENT_CONTEXT(ctx);
154 ASSERT_OUTSIDE_BEGIN_END(ctx);
155
156 _mesa_GetVertexAttribfvARB(index, pname, fparams);
157 if (ctx->ErrorValue == GL_NO_ERROR) {
158 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
159 COPY_4V_CAST(params, fparams, GLint); /* float to int */
160 }
161 else {
162 params[0] = (GLint) fparams[0];
163 }
164 }
165}
166
167
168void GLAPIENTRY
169_mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
170{
171 GET_CURRENT_CONTEXT(ctx);
172 ASSERT_OUTSIDE_BEGIN_END(ctx);
173
Brian Paul05051032005-11-01 04:36:33 +0000174 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000175 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
176 return;
177 }
178
179 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
180 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
181 return;
182 }
183
Ian Romanickee34e6e2006-06-12 16:26:29 +0000184 *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
Michal Krol157ec8b2004-03-10 18:02:01 +0000185}
186
187
Brian Paulf49c0d02006-11-02 16:20:29 +0000188/**
189 * Determine if id names a vertex or fragment program.
190 * \note Not compiled into display lists.
191 * \note Called from both glIsProgramNV and glIsProgramARB.
192 * \param id is the program identifier
193 * \return GL_TRUE if id is a program, else GL_FALSE.
194 */
195GLboolean GLAPIENTRY
196_mesa_IsProgramARB(GLuint id)
197{
Brian Paul308b85f2006-11-23 15:58:30 +0000198 struct gl_program *prog = NULL;
Brian Paulf49c0d02006-11-02 16:20:29 +0000199 GET_CURRENT_CONTEXT(ctx);
200 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
201
202 if (id == 0)
203 return GL_FALSE;
204
Brian Paul308b85f2006-11-23 15:58:30 +0000205 prog = _mesa_lookup_program(ctx, id);
206 if (prog && (prog != &_mesa_DummyProgram))
Brian Paulf49c0d02006-11-02 16:20:29 +0000207 return GL_TRUE;
208 else
209 return GL_FALSE;
210}
211
212
Michal Krol157ec8b2004-03-10 18:02:01 +0000213void GLAPIENTRY
214_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
215 const GLvoid *string)
216{
217 GET_CURRENT_CONTEXT(ctx);
218 ASSERT_OUTSIDE_BEGIN_END(ctx);
219
220 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
221
Brian Paul8c41a142005-11-19 15:36:28 +0000222 if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
223 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
224 return;
225 }
226
Michal Krol157ec8b2004-03-10 18:02:01 +0000227 if (target == GL_VERTEX_PROGRAM_ARB
228 && ctx->Extensions.ARB_vertex_program) {
Brian Paul122629f2006-07-20 16:49:57 +0000229 struct gl_vertex_program *prog = ctx->VertexProgram.Current;
Brian Paul8c41a142005-11-19 15:36:28 +0000230 _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
Michal Krol157ec8b2004-03-10 18:02:01 +0000231
Eric Anholt23db6282008-01-15 15:08:34 -0800232 if (ctx->Program.ErrorPos == -1 && ctx->Driver.ProgramStringNotify)
Michal Krol157ec8b2004-03-10 18:02:01 +0000233 ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
234 }
235 else if (target == GL_FRAGMENT_PROGRAM_ARB
236 && ctx->Extensions.ARB_fragment_program) {
Brian Paul122629f2006-07-20 16:49:57 +0000237 struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
Brian Paul8c41a142005-11-19 15:36:28 +0000238 _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
Michal Krol157ec8b2004-03-10 18:02:01 +0000239
Eric Anholt23db6282008-01-15 15:08:34 -0800240 if (ctx->Program.ErrorPos == -1 && ctx->Driver.ProgramStringNotify)
Michal Krol157ec8b2004-03-10 18:02:01 +0000241 ctx->Driver.ProgramStringNotify( ctx, target, &prog->Base );
242 }
243 else {
244 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
245 return;
246 }
247}
248
249
Brian Paulf9e1ef22008-05-18 15:21:28 -0600250/**
251 * Set a program env parameter register.
252 * \note Called from the GL API dispatcher.
253 * Note, this function is also used by the GL_NV_vertex_program extension
254 * (alias to ProgramParameterdNV)
255 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000256void GLAPIENTRY
257_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
258 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
259{
260 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
261 (GLfloat) z, (GLfloat) w);
262}
263
264
Brian Paulf9e1ef22008-05-18 15:21:28 -0600265/**
266 * Set a program env parameter register.
267 * \note Called from the GL API dispatcher.
268 * Note, this function is also used by the GL_NV_vertex_program extension
269 * (alias to ProgramParameterdvNV)
270 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000271void GLAPIENTRY
272_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
273 const GLdouble *params)
274{
275 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
276 (GLfloat) params[1], (GLfloat) params[2],
277 (GLfloat) params[3]);
278}
279
280
Brian Paulf9e1ef22008-05-18 15:21:28 -0600281/**
282 * Set a program env parameter register.
283 * \note Called from the GL API dispatcher.
284 * Note, this function is also used by the GL_NV_vertex_program extension
285 * (alias to ProgramParameterfNV)
286 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000287void GLAPIENTRY
288_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
289 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
290{
291 GET_CURRENT_CONTEXT(ctx);
292 ASSERT_OUTSIDE_BEGIN_END(ctx);
293
294 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
295
296 if (target == GL_FRAGMENT_PROGRAM_ARB
297 && ctx->Extensions.ARB_fragment_program) {
Brian Paul05051032005-11-01 04:36:33 +0000298 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000299 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
300 return;
301 }
302 ASSIGN_4V(ctx->FragmentProgram.Parameters[index], x, y, z, w);
303 }
Brian Paulf9e1ef22008-05-18 15:21:28 -0600304 else if (target == GL_VERTEX_PROGRAM_ARB /* == GL_VERTEX_PROGRAM_NV */
305 && (ctx->Extensions.ARB_vertex_program || ctx->Extensions.NV_vertex_program)) {
Brian Paul05051032005-11-01 04:36:33 +0000306 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000307 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
308 return;
309 }
310 ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
311 }
312 else {
313 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter(target)");
314 return;
315 }
316}
317
Brian Paulf9e1ef22008-05-18 15:21:28 -0600318/**
319 * Set a program env parameter register.
320 * \note Called from the GL API dispatcher.
321 * Note, this function is also used by the GL_NV_vertex_program extension
322 * (alias to ProgramParameterfvNV)
323 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000324void GLAPIENTRY
325_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
326 const GLfloat *params)
327{
328 _mesa_ProgramEnvParameter4fARB(target, index, params[0], params[1],
329 params[2], params[3]);
330}
331
332
333void GLAPIENTRY
Ian Romanick8c41c752006-08-15 16:47:34 +0000334_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
335 const GLfloat *params)
336{
337 GET_CURRENT_CONTEXT(ctx);
Brian223d7cb2007-01-23 16:37:51 -0700338 GLint i;
Ian Romanick8c41c752006-08-15 16:47:34 +0000339 GLfloat * dest;
340 ASSERT_OUTSIDE_BEGIN_END(ctx);
341
342 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
343
344 if (count <= 0) {
345 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
346 }
347
348 if (target == GL_FRAGMENT_PROGRAM_ARB
349 && ctx->Extensions.ARB_fragment_program) {
350 if ((index + count) > ctx->Const.FragmentProgram.MaxEnvParams) {
351 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
352 return;
353 }
354 dest = ctx->FragmentProgram.Parameters[index];
355 }
356 else if (target == GL_VERTEX_PROGRAM_ARB
357 && ctx->Extensions.ARB_vertex_program) {
358 if ((index + count) > ctx->Const.VertexProgram.MaxEnvParams) {
359 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
360 return;
361 }
362 dest = ctx->VertexProgram.Parameters[index];
363 }
364 else {
365 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
366 return;
367 }
368
369 for ( i = 0 ; i < count ; i++ ) {
370 COPY_4V(dest, params);
371 params += 4;
372 dest += 4;
373 }
374}
375
376
377void GLAPIENTRY
Michal Krol157ec8b2004-03-10 18:02:01 +0000378_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
379 GLdouble *params)
380{
381 GET_CURRENT_CONTEXT(ctx);
382 GLfloat fparams[4];
383
384 _mesa_GetProgramEnvParameterfvARB(target, index, fparams);
385 if (ctx->ErrorValue == GL_NO_ERROR) {
386 params[0] = fparams[0];
387 params[1] = fparams[1];
388 params[2] = fparams[2];
389 params[3] = fparams[3];
390 }
391}
392
393
394void GLAPIENTRY
395_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
396 GLfloat *params)
397{
398 GET_CURRENT_CONTEXT(ctx);
399
400 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
401
402 if (!ctx->_CurrentProgram)
403 ASSERT_OUTSIDE_BEGIN_END(ctx);
404
405 if (target == GL_FRAGMENT_PROGRAM_ARB
406 && ctx->Extensions.ARB_fragment_program) {
Brian Paul05051032005-11-01 04:36:33 +0000407 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000408 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
409 return;
410 }
411 COPY_4V(params, ctx->FragmentProgram.Parameters[index]);
412 }
Brian Paul83c74b72004-10-16 00:29:03 +0000413 else if (target == GL_VERTEX_PROGRAM_ARB
Michal Krol157ec8b2004-03-10 18:02:01 +0000414 && ctx->Extensions.ARB_vertex_program) {
Brian Paul05051032005-11-01 04:36:33 +0000415 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000416 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
417 return;
418 }
419 COPY_4V(params, ctx->VertexProgram.Parameters[index]);
420 }
421 else {
422 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramEnvParameter(target)");
423 return;
424 }
425}
426
427
428/**
429 * Note, this function is also used by the GL_NV_fragment_program extension.
430 */
431void GLAPIENTRY
432_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
433 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
434{
435 GET_CURRENT_CONTEXT(ctx);
Brian Paul122629f2006-07-20 16:49:57 +0000436 struct gl_program *prog;
Michal Krol157ec8b2004-03-10 18:02:01 +0000437 ASSERT_OUTSIDE_BEGIN_END(ctx);
438
439 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
440
441 if ((target == GL_FRAGMENT_PROGRAM_NV
442 && ctx->Extensions.NV_fragment_program) ||
443 (target == GL_FRAGMENT_PROGRAM_ARB
444 && ctx->Extensions.ARB_fragment_program)) {
Brian Paul05051032005-11-01 04:36:33 +0000445 if (index >= ctx->Const.FragmentProgram.MaxLocalParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000446 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
447 return;
448 }
449 prog = &(ctx->FragmentProgram.Current->Base);
450 }
451 else if (target == GL_VERTEX_PROGRAM_ARB
452 && ctx->Extensions.ARB_vertex_program) {
Brian Paul05051032005-11-01 04:36:33 +0000453 if (index >= ctx->Const.VertexProgram.MaxLocalParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000454 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
455 return;
456 }
457 prog = &(ctx->VertexProgram.Current->Base);
458 }
459 else {
460 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
461 return;
462 }
463
464 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
465 prog->LocalParams[index][0] = x;
466 prog->LocalParams[index][1] = y;
467 prog->LocalParams[index][2] = z;
468 prog->LocalParams[index][3] = w;
469}
470
471
472/**
473 * Note, this function is also used by the GL_NV_fragment_program extension.
474 */
475void GLAPIENTRY
476_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
477 const GLfloat *params)
478{
479 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
480 params[2], params[3]);
481}
482
483
Ian Romanick8c41c752006-08-15 16:47:34 +0000484void GLAPIENTRY
485_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
486 const GLfloat *params)
487{
488 GET_CURRENT_CONTEXT(ctx);
489 struct gl_program *prog;
Brian223d7cb2007-01-23 16:37:51 -0700490 GLint i;
Ian Romanick8c41c752006-08-15 16:47:34 +0000491 ASSERT_OUTSIDE_BEGIN_END(ctx);
492
493 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
494
495 if (count <= 0) {
496 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
497 }
498
499 if (target == GL_FRAGMENT_PROGRAM_ARB
500 && ctx->Extensions.ARB_fragment_program) {
501 if ((index + count) > ctx->Const.FragmentProgram.MaxLocalParams) {
502 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
503 return;
504 }
505 prog = &(ctx->FragmentProgram.Current->Base);
506 }
507 else if (target == GL_VERTEX_PROGRAM_ARB
508 && ctx->Extensions.ARB_vertex_program) {
509 if ((index + count) > ctx->Const.VertexProgram.MaxLocalParams) {
510 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
511 return;
512 }
513 prog = &(ctx->VertexProgram.Current->Base);
514 }
515 else {
516 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)");
517 return;
518 }
519
520 for (i = 0; i < count; i++) {
521 ASSERT((index + i) < MAX_PROGRAM_LOCAL_PARAMS);
522 COPY_4V(prog->LocalParams[index + i], params);
523 params += 4;
524 }
525}
526
527
Michal Krol157ec8b2004-03-10 18:02:01 +0000528/**
529 * Note, this function is also used by the GL_NV_fragment_program extension.
530 */
531void GLAPIENTRY
532_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
533 GLdouble x, GLdouble y,
534 GLdouble z, GLdouble w)
535{
536 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
537 (GLfloat) z, (GLfloat) w);
538}
539
540
541/**
542 * Note, this function is also used by the GL_NV_fragment_program extension.
543 */
544void GLAPIENTRY
545_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
546 const GLdouble *params)
547{
548 _mesa_ProgramLocalParameter4fARB(target, index,
549 (GLfloat) params[0], (GLfloat) params[1],
550 (GLfloat) params[2], (GLfloat) params[3]);
551}
552
553
554/**
555 * Note, this function is also used by the GL_NV_fragment_program extension.
556 */
557void GLAPIENTRY
558_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
559 GLfloat *params)
560{
Brian Paul122629f2006-07-20 16:49:57 +0000561 const struct gl_program *prog;
Michal Krol157ec8b2004-03-10 18:02:01 +0000562 GLuint maxParams;
563 GET_CURRENT_CONTEXT(ctx);
564 ASSERT_OUTSIDE_BEGIN_END(ctx);
565
566 if (target == GL_VERTEX_PROGRAM_ARB
567 && ctx->Extensions.ARB_vertex_program) {
568 prog = &(ctx->VertexProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000569 maxParams = ctx->Const.VertexProgram.MaxLocalParams;
Michal Krol157ec8b2004-03-10 18:02:01 +0000570 }
571 else if (target == GL_FRAGMENT_PROGRAM_ARB
572 && ctx->Extensions.ARB_fragment_program) {
573 prog = &(ctx->FragmentProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000574 maxParams = ctx->Const.FragmentProgram.MaxLocalParams;
Michal Krol157ec8b2004-03-10 18:02:01 +0000575 }
576 else if (target == GL_FRAGMENT_PROGRAM_NV
577 && ctx->Extensions.NV_fragment_program) {
578 prog = &(ctx->FragmentProgram.Current->Base);
579 maxParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
580 }
581 else {
582 _mesa_error(ctx, GL_INVALID_ENUM,
583 "glGetProgramLocalParameterARB(target)");
584 return;
585 }
586
587 if (index >= maxParams) {
588 _mesa_error(ctx, GL_INVALID_VALUE,
589 "glGetProgramLocalParameterARB(index)");
590 return;
591 }
592
593 ASSERT(prog);
594 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
595 COPY_4V(params, prog->LocalParams[index]);
596}
597
598
599/**
600 * Note, this function is also used by the GL_NV_fragment_program extension.
601 */
602void GLAPIENTRY
603_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
604 GLdouble *params)
605{
606 GET_CURRENT_CONTEXT(ctx);
607 GLfloat floatParams[4];
608 _mesa_GetProgramLocalParameterfvARB(target, index, floatParams);
609 if (ctx->ErrorValue == GL_NO_ERROR) {
610 COPY_4V(params, floatParams);
611 }
612}
613
614
615void GLAPIENTRY
616_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
617{
Brian Paul05051032005-11-01 04:36:33 +0000618 const struct gl_program_constants *limits;
Brian Paul122629f2006-07-20 16:49:57 +0000619 struct gl_program *prog;
Michal Krol157ec8b2004-03-10 18:02:01 +0000620 GET_CURRENT_CONTEXT(ctx);
621
622 if (!ctx->_CurrentProgram)
623 ASSERT_OUTSIDE_BEGIN_END(ctx);
624
625 if (target == GL_VERTEX_PROGRAM_ARB
626 && ctx->Extensions.ARB_vertex_program) {
627 prog = &(ctx->VertexProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000628 limits = &ctx->Const.VertexProgram;
Michal Krol157ec8b2004-03-10 18:02:01 +0000629 }
630 else if (target == GL_FRAGMENT_PROGRAM_ARB
631 && ctx->Extensions.ARB_fragment_program) {
632 prog = &(ctx->FragmentProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000633 limits = &ctx->Const.FragmentProgram;
Michal Krol157ec8b2004-03-10 18:02:01 +0000634 }
635 else {
636 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
637 return;
638 }
639
640 ASSERT(prog);
Brian Paul05051032005-11-01 04:36:33 +0000641 ASSERT(limits);
Michal Krol157ec8b2004-03-10 18:02:01 +0000642
Brian Paul05051032005-11-01 04:36:33 +0000643 /* Queries supported for both vertex and fragment programs */
Michal Krol157ec8b2004-03-10 18:02:01 +0000644 switch (pname) {
645 case GL_PROGRAM_LENGTH_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000646 *params
647 = prog->String ? (GLint) _mesa_strlen((char *) prog->String) : 0;
648 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000649 case GL_PROGRAM_FORMAT_ARB:
650 *params = prog->Format;
Brian Paul05051032005-11-01 04:36:33 +0000651 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000652 case GL_PROGRAM_BINDING_ARB:
653 *params = prog->Id;
Brian Paul05051032005-11-01 04:36:33 +0000654 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000655 case GL_PROGRAM_INSTRUCTIONS_ARB:
656 *params = prog->NumInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000657 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000658 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000659 *params = limits->MaxInstructions;
660 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000661 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000662 *params = prog->NumNativeInstructions;
663 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000664 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000665 *params = limits->MaxNativeInstructions;
666 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000667 case GL_PROGRAM_TEMPORARIES_ARB:
668 *params = prog->NumTemporaries;
Brian Paul05051032005-11-01 04:36:33 +0000669 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000670 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000671 *params = limits->MaxTemps;
672 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000673 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000674 *params = prog->NumNativeTemporaries;
675 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000676 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000677 *params = limits->MaxNativeTemps;
678 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000679 case GL_PROGRAM_PARAMETERS_ARB:
680 *params = prog->NumParameters;
Brian Paul05051032005-11-01 04:36:33 +0000681 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000682 case GL_MAX_PROGRAM_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000683 *params = limits->MaxParameters;
684 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000685 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000686 *params = prog->NumNativeParameters;
687 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000688 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000689 *params = limits->MaxNativeParameters;
690 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000691 case GL_PROGRAM_ATTRIBS_ARB:
692 *params = prog->NumAttributes;
Brian Paul05051032005-11-01 04:36:33 +0000693 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000694 case GL_MAX_PROGRAM_ATTRIBS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000695 *params = limits->MaxAttribs;
696 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000697 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000698 *params = prog->NumNativeAttributes;
699 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000700 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000701 *params = limits->MaxNativeAttribs;
702 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000703 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
704 *params = prog->NumAddressRegs;
Brian Paul05051032005-11-01 04:36:33 +0000705 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000706 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000707 *params = limits->MaxAddressRegs;
708 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000709 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000710 *params = prog->NumNativeAddressRegs;
711 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000712 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000713 *params = limits->MaxNativeAddressRegs;
714 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000715 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000716 *params = limits->MaxLocalParams;
717 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000718 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000719 *params = limits->MaxEnvParams;
720 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000721 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000722 /*
723 * XXX we may not really need a driver callback here.
724 * If the number of native instructions, registers, etc. used
725 * are all below the maximums, we could return true.
726 * The spec says that even if this query returns true, there's
727 * no guarantee that the program will run in hardware.
728 */
Brian4ca7c802007-04-28 08:01:18 -0600729 if (prog->Id == 0) {
730 /* default/null program */
731 *params = GL_FALSE;
732 }
733 else if (ctx->Driver.IsProgramNative) {
734 /* ask the driver */
Michal Krol157ec8b2004-03-10 18:02:01 +0000735 *params = ctx->Driver.IsProgramNative( ctx, target, prog );
Brian4ca7c802007-04-28 08:01:18 -0600736 }
737 else {
738 /* probably running in software */
Michal Krol157ec8b2004-03-10 18:02:01 +0000739 *params = GL_TRUE;
Brian4ca7c802007-04-28 08:01:18 -0600740 }
Michal Krol157ec8b2004-03-10 18:02:01 +0000741 return;
Brian Paul05051032005-11-01 04:36:33 +0000742 default:
743 /* continue with fragment-program only queries below */
744 break;
745 }
746
747 /*
748 * The following apply to fragment programs only (at this time)
749 */
750 if (target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul122629f2006-07-20 16:49:57 +0000751 const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
Brian Paul05051032005-11-01 04:36:33 +0000752 switch (pname) {
753 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700754 *params = fp->Base.NumNativeAluInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000755 return;
756 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700757 *params = fp->Base.NumAluInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000758 return;
759 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700760 *params = fp->Base.NumTexInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000761 return;
762 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700763 *params = fp->Base.NumNativeTexInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000764 return;
765 case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700766 *params = fp->Base.NumTexIndirections;
Brian Paul05051032005-11-01 04:36:33 +0000767 return;
768 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700769 *params = fp->Base.NumNativeTexIndirections;
Brian Paul05051032005-11-01 04:36:33 +0000770 return;
771 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
772 *params = limits->MaxAluInstructions;
773 return;
774 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
775 *params = limits->MaxNativeAluInstructions;
776 return;
777 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
778 *params = limits->MaxTexInstructions;
779 return;
780 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
781 *params = limits->MaxNativeTexInstructions;
782 return;
783 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
784 *params = limits->MaxTexIndirections;
785 return;
786 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
787 *params = limits->MaxNativeTexIndirections;
788 return;
789 default:
790 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
791 return;
792 }
Michal Krol157ec8b2004-03-10 18:02:01 +0000793 }
794}
795
796
797void GLAPIENTRY
798_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
799{
Brian Paul122629f2006-07-20 16:49:57 +0000800 const struct gl_program *prog;
Brian Paul308b85f2006-11-23 15:58:30 +0000801 char *dst = (char *) string;
Michal Krol157ec8b2004-03-10 18:02:01 +0000802 GET_CURRENT_CONTEXT(ctx);
803
804 if (!ctx->_CurrentProgram)
805 ASSERT_OUTSIDE_BEGIN_END(ctx);
806
807 if (target == GL_VERTEX_PROGRAM_ARB) {
808 prog = &(ctx->VertexProgram.Current->Base);
809 }
810 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
811 prog = &(ctx->FragmentProgram.Current->Base);
812 }
813 else {
814 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
815 return;
816 }
817
818 ASSERT(prog);
819
820 if (pname != GL_PROGRAM_STRING_ARB) {
821 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
822 return;
823 }
824
Brian Paul308b85f2006-11-23 15:58:30 +0000825 if (prog->String)
826 _mesa_memcpy(dst, prog->String, _mesa_strlen((char *) prog->String));
827 else
828 *dst = '\0';
Michal Krol157ec8b2004-03-10 18:02:01 +0000829}