blob: 5583f16ce8d3224f011ebd0392736c35ed081f58 [file] [log] [blame]
Michal Krol157ec8b2004-03-10 18:02:01 +00001/*
2 * Mesa 3-D graphics library
Brian Paulf49c0d02006-11-02 16:20:29 +00003 * Version: 6.5.2
Michal Krol157ec8b2004-03-10 18:02:01 +00004 *
Michal Krolbb38cad2006-04-11 11:41:11 +00005 * Copyright (C) 1999-2006 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
232 if (ctx->Driver.ProgramStringNotify)
233 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
240 if (ctx->Driver.ProgramStringNotify)
241 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
250void GLAPIENTRY
251_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
252 GLdouble x, GLdouble y, GLdouble z, GLdouble w)
253{
254 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
255 (GLfloat) z, (GLfloat) w);
256}
257
258
259void GLAPIENTRY
260_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
261 const GLdouble *params)
262{
263 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
264 (GLfloat) params[1], (GLfloat) params[2],
265 (GLfloat) params[3]);
266}
267
268
269void GLAPIENTRY
270_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
271 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
272{
273 GET_CURRENT_CONTEXT(ctx);
274 ASSERT_OUTSIDE_BEGIN_END(ctx);
275
276 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
277
278 if (target == GL_FRAGMENT_PROGRAM_ARB
279 && ctx->Extensions.ARB_fragment_program) {
Brian Paul05051032005-11-01 04:36:33 +0000280 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000281 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
282 return;
283 }
284 ASSIGN_4V(ctx->FragmentProgram.Parameters[index], x, y, z, w);
285 }
Brian Paul83c74b72004-10-16 00:29:03 +0000286 else if (target == GL_VERTEX_PROGRAM_ARB
Michal Krol157ec8b2004-03-10 18:02:01 +0000287 && ctx->Extensions.ARB_vertex_program) {
Brian Paul05051032005-11-01 04:36:33 +0000288 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000289 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameter(index)");
290 return;
291 }
292 ASSIGN_4V(ctx->VertexProgram.Parameters[index], x, y, z, w);
293 }
294 else {
295 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameter(target)");
296 return;
297 }
298}
299
300
301void GLAPIENTRY
302_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
303 const GLfloat *params)
304{
305 _mesa_ProgramEnvParameter4fARB(target, index, params[0], params[1],
306 params[2], params[3]);
307}
308
309
310void GLAPIENTRY
Ian Romanick8c41c752006-08-15 16:47:34 +0000311_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
312 const GLfloat *params)
313{
314 GET_CURRENT_CONTEXT(ctx);
Brian223d7cb2007-01-23 16:37:51 -0700315 GLint i;
Ian Romanick8c41c752006-08-15 16:47:34 +0000316 GLfloat * dest;
317 ASSERT_OUTSIDE_BEGIN_END(ctx);
318
319 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
320
321 if (count <= 0) {
322 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
323 }
324
325 if (target == GL_FRAGMENT_PROGRAM_ARB
326 && ctx->Extensions.ARB_fragment_program) {
327 if ((index + count) > ctx->Const.FragmentProgram.MaxEnvParams) {
328 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
329 return;
330 }
331 dest = ctx->FragmentProgram.Parameters[index];
332 }
333 else if (target == GL_VERTEX_PROGRAM_ARB
334 && ctx->Extensions.ARB_vertex_program) {
335 if ((index + count) > ctx->Const.VertexProgram.MaxEnvParams) {
336 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
337 return;
338 }
339 dest = ctx->VertexProgram.Parameters[index];
340 }
341 else {
342 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
343 return;
344 }
345
346 for ( i = 0 ; i < count ; i++ ) {
347 COPY_4V(dest, params);
348 params += 4;
349 dest += 4;
350 }
351}
352
353
354void GLAPIENTRY
Michal Krol157ec8b2004-03-10 18:02:01 +0000355_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
356 GLdouble *params)
357{
358 GET_CURRENT_CONTEXT(ctx);
359 GLfloat fparams[4];
360
361 _mesa_GetProgramEnvParameterfvARB(target, index, fparams);
362 if (ctx->ErrorValue == GL_NO_ERROR) {
363 params[0] = fparams[0];
364 params[1] = fparams[1];
365 params[2] = fparams[2];
366 params[3] = fparams[3];
367 }
368}
369
370
371void GLAPIENTRY
372_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
373 GLfloat *params)
374{
375 GET_CURRENT_CONTEXT(ctx);
376
377 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
378
379 if (!ctx->_CurrentProgram)
380 ASSERT_OUTSIDE_BEGIN_END(ctx);
381
382 if (target == GL_FRAGMENT_PROGRAM_ARB
383 && ctx->Extensions.ARB_fragment_program) {
Brian Paul05051032005-11-01 04:36:33 +0000384 if (index >= ctx->Const.FragmentProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000385 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
386 return;
387 }
388 COPY_4V(params, ctx->FragmentProgram.Parameters[index]);
389 }
Brian Paul83c74b72004-10-16 00:29:03 +0000390 else if (target == GL_VERTEX_PROGRAM_ARB
Michal Krol157ec8b2004-03-10 18:02:01 +0000391 && ctx->Extensions.ARB_vertex_program) {
Brian Paul05051032005-11-01 04:36:33 +0000392 if (index >= ctx->Const.VertexProgram.MaxEnvParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000393 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramEnvParameter(index)");
394 return;
395 }
396 COPY_4V(params, ctx->VertexProgram.Parameters[index]);
397 }
398 else {
399 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramEnvParameter(target)");
400 return;
401 }
402}
403
404
405/**
406 * Note, this function is also used by the GL_NV_fragment_program extension.
407 */
408void GLAPIENTRY
409_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
410 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
411{
412 GET_CURRENT_CONTEXT(ctx);
Brian Paul122629f2006-07-20 16:49:57 +0000413 struct gl_program *prog;
Michal Krol157ec8b2004-03-10 18:02:01 +0000414 ASSERT_OUTSIDE_BEGIN_END(ctx);
415
416 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
417
418 if ((target == GL_FRAGMENT_PROGRAM_NV
419 && ctx->Extensions.NV_fragment_program) ||
420 (target == GL_FRAGMENT_PROGRAM_ARB
421 && ctx->Extensions.ARB_fragment_program)) {
Brian Paul05051032005-11-01 04:36:33 +0000422 if (index >= ctx->Const.FragmentProgram.MaxLocalParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000423 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
424 return;
425 }
426 prog = &(ctx->FragmentProgram.Current->Base);
427 }
428 else if (target == GL_VERTEX_PROGRAM_ARB
429 && ctx->Extensions.ARB_vertex_program) {
Brian Paul05051032005-11-01 04:36:33 +0000430 if (index >= ctx->Const.VertexProgram.MaxLocalParams) {
Michal Krol157ec8b2004-03-10 18:02:01 +0000431 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameterARB");
432 return;
433 }
434 prog = &(ctx->VertexProgram.Current->Base);
435 }
436 else {
437 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameterARB");
438 return;
439 }
440
441 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
442 prog->LocalParams[index][0] = x;
443 prog->LocalParams[index][1] = y;
444 prog->LocalParams[index][2] = z;
445 prog->LocalParams[index][3] = w;
446}
447
448
449/**
450 * Note, this function is also used by the GL_NV_fragment_program extension.
451 */
452void GLAPIENTRY
453_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
454 const GLfloat *params)
455{
456 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
457 params[2], params[3]);
458}
459
460
Ian Romanick8c41c752006-08-15 16:47:34 +0000461void GLAPIENTRY
462_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
463 const GLfloat *params)
464{
465 GET_CURRENT_CONTEXT(ctx);
466 struct gl_program *prog;
Brian223d7cb2007-01-23 16:37:51 -0700467 GLint i;
Ian Romanick8c41c752006-08-15 16:47:34 +0000468 ASSERT_OUTSIDE_BEGIN_END(ctx);
469
470 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
471
472 if (count <= 0) {
473 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
474 }
475
476 if (target == GL_FRAGMENT_PROGRAM_ARB
477 && ctx->Extensions.ARB_fragment_program) {
478 if ((index + count) > ctx->Const.FragmentProgram.MaxLocalParams) {
479 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
480 return;
481 }
482 prog = &(ctx->FragmentProgram.Current->Base);
483 }
484 else if (target == GL_VERTEX_PROGRAM_ARB
485 && ctx->Extensions.ARB_vertex_program) {
486 if ((index + count) > ctx->Const.VertexProgram.MaxLocalParams) {
487 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fvEXT(index + count)");
488 return;
489 }
490 prog = &(ctx->VertexProgram.Current->Base);
491 }
492 else {
493 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramLocalParameters4fvEXT(target)");
494 return;
495 }
496
497 for (i = 0; i < count; i++) {
498 ASSERT((index + i) < MAX_PROGRAM_LOCAL_PARAMS);
499 COPY_4V(prog->LocalParams[index + i], params);
500 params += 4;
501 }
502}
503
504
Michal Krol157ec8b2004-03-10 18:02:01 +0000505/**
506 * Note, this function is also used by the GL_NV_fragment_program extension.
507 */
508void GLAPIENTRY
509_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
510 GLdouble x, GLdouble y,
511 GLdouble z, GLdouble w)
512{
513 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
514 (GLfloat) z, (GLfloat) w);
515}
516
517
518/**
519 * Note, this function is also used by the GL_NV_fragment_program extension.
520 */
521void GLAPIENTRY
522_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
523 const GLdouble *params)
524{
525 _mesa_ProgramLocalParameter4fARB(target, index,
526 (GLfloat) params[0], (GLfloat) params[1],
527 (GLfloat) params[2], (GLfloat) params[3]);
528}
529
530
531/**
532 * Note, this function is also used by the GL_NV_fragment_program extension.
533 */
534void GLAPIENTRY
535_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
536 GLfloat *params)
537{
Brian Paul122629f2006-07-20 16:49:57 +0000538 const struct gl_program *prog;
Michal Krol157ec8b2004-03-10 18:02:01 +0000539 GLuint maxParams;
540 GET_CURRENT_CONTEXT(ctx);
541 ASSERT_OUTSIDE_BEGIN_END(ctx);
542
543 if (target == GL_VERTEX_PROGRAM_ARB
544 && ctx->Extensions.ARB_vertex_program) {
545 prog = &(ctx->VertexProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000546 maxParams = ctx->Const.VertexProgram.MaxLocalParams;
Michal Krol157ec8b2004-03-10 18:02:01 +0000547 }
548 else if (target == GL_FRAGMENT_PROGRAM_ARB
549 && ctx->Extensions.ARB_fragment_program) {
550 prog = &(ctx->FragmentProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000551 maxParams = ctx->Const.FragmentProgram.MaxLocalParams;
Michal Krol157ec8b2004-03-10 18:02:01 +0000552 }
553 else if (target == GL_FRAGMENT_PROGRAM_NV
554 && ctx->Extensions.NV_fragment_program) {
555 prog = &(ctx->FragmentProgram.Current->Base);
556 maxParams = MAX_NV_FRAGMENT_PROGRAM_PARAMS;
557 }
558 else {
559 _mesa_error(ctx, GL_INVALID_ENUM,
560 "glGetProgramLocalParameterARB(target)");
561 return;
562 }
563
564 if (index >= maxParams) {
565 _mesa_error(ctx, GL_INVALID_VALUE,
566 "glGetProgramLocalParameterARB(index)");
567 return;
568 }
569
570 ASSERT(prog);
571 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS);
572 COPY_4V(params, prog->LocalParams[index]);
573}
574
575
576/**
577 * Note, this function is also used by the GL_NV_fragment_program extension.
578 */
579void GLAPIENTRY
580_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
581 GLdouble *params)
582{
583 GET_CURRENT_CONTEXT(ctx);
584 GLfloat floatParams[4];
585 _mesa_GetProgramLocalParameterfvARB(target, index, floatParams);
586 if (ctx->ErrorValue == GL_NO_ERROR) {
587 COPY_4V(params, floatParams);
588 }
589}
590
591
592void GLAPIENTRY
593_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
594{
Brian Paul05051032005-11-01 04:36:33 +0000595 const struct gl_program_constants *limits;
Brian Paul122629f2006-07-20 16:49:57 +0000596 struct gl_program *prog;
Michal Krol157ec8b2004-03-10 18:02:01 +0000597 GET_CURRENT_CONTEXT(ctx);
598
599 if (!ctx->_CurrentProgram)
600 ASSERT_OUTSIDE_BEGIN_END(ctx);
601
602 if (target == GL_VERTEX_PROGRAM_ARB
603 && ctx->Extensions.ARB_vertex_program) {
604 prog = &(ctx->VertexProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000605 limits = &ctx->Const.VertexProgram;
Michal Krol157ec8b2004-03-10 18:02:01 +0000606 }
607 else if (target == GL_FRAGMENT_PROGRAM_ARB
608 && ctx->Extensions.ARB_fragment_program) {
609 prog = &(ctx->FragmentProgram.Current->Base);
Brian Paul05051032005-11-01 04:36:33 +0000610 limits = &ctx->Const.FragmentProgram;
Michal Krol157ec8b2004-03-10 18:02:01 +0000611 }
612 else {
613 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
614 return;
615 }
616
617 ASSERT(prog);
Brian Paul05051032005-11-01 04:36:33 +0000618 ASSERT(limits);
Michal Krol157ec8b2004-03-10 18:02:01 +0000619
Brian Paul05051032005-11-01 04:36:33 +0000620 /* Queries supported for both vertex and fragment programs */
Michal Krol157ec8b2004-03-10 18:02:01 +0000621 switch (pname) {
622 case GL_PROGRAM_LENGTH_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000623 *params
624 = prog->String ? (GLint) _mesa_strlen((char *) prog->String) : 0;
625 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000626 case GL_PROGRAM_FORMAT_ARB:
627 *params = prog->Format;
Brian Paul05051032005-11-01 04:36:33 +0000628 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000629 case GL_PROGRAM_BINDING_ARB:
630 *params = prog->Id;
Brian Paul05051032005-11-01 04:36:33 +0000631 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000632 case GL_PROGRAM_INSTRUCTIONS_ARB:
633 *params = prog->NumInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000634 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000635 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000636 *params = limits->MaxInstructions;
637 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000638 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000639 *params = prog->NumNativeInstructions;
640 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000641 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000642 *params = limits->MaxNativeInstructions;
643 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000644 case GL_PROGRAM_TEMPORARIES_ARB:
645 *params = prog->NumTemporaries;
Brian Paul05051032005-11-01 04:36:33 +0000646 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000647 case GL_MAX_PROGRAM_TEMPORARIES_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000648 *params = limits->MaxTemps;
649 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000650 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000651 *params = prog->NumNativeTemporaries;
652 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000653 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000654 *params = limits->MaxNativeTemps;
655 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000656 case GL_PROGRAM_PARAMETERS_ARB:
657 *params = prog->NumParameters;
Brian Paul05051032005-11-01 04:36:33 +0000658 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000659 case GL_MAX_PROGRAM_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000660 *params = limits->MaxParameters;
661 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000662 case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000663 *params = prog->NumNativeParameters;
664 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000665 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000666 *params = limits->MaxNativeParameters;
667 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000668 case GL_PROGRAM_ATTRIBS_ARB:
669 *params = prog->NumAttributes;
Brian Paul05051032005-11-01 04:36:33 +0000670 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000671 case GL_MAX_PROGRAM_ATTRIBS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000672 *params = limits->MaxAttribs;
673 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000674 case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000675 *params = prog->NumNativeAttributes;
676 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000677 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000678 *params = limits->MaxNativeAttribs;
679 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000680 case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
681 *params = prog->NumAddressRegs;
Brian Paul05051032005-11-01 04:36:33 +0000682 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000683 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000684 *params = limits->MaxAddressRegs;
685 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000686 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000687 *params = prog->NumNativeAddressRegs;
688 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000689 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000690 *params = limits->MaxNativeAddressRegs;
691 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000692 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000693 *params = limits->MaxLocalParams;
694 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000695 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000696 *params = limits->MaxEnvParams;
697 return;
Michal Krol157ec8b2004-03-10 18:02:01 +0000698 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
Brian Paul05051032005-11-01 04:36:33 +0000699 /*
700 * XXX we may not really need a driver callback here.
701 * If the number of native instructions, registers, etc. used
702 * are all below the maximums, we could return true.
703 * The spec says that even if this query returns true, there's
704 * no guarantee that the program will run in hardware.
705 */
Michal Krol157ec8b2004-03-10 18:02:01 +0000706 if (ctx->Driver.IsProgramNative)
707 *params = ctx->Driver.IsProgramNative( ctx, target, prog );
708 else
709 *params = GL_TRUE;
Michal Krol157ec8b2004-03-10 18:02:01 +0000710 return;
Brian Paul05051032005-11-01 04:36:33 +0000711 default:
712 /* continue with fragment-program only queries below */
713 break;
714 }
715
716 /*
717 * The following apply to fragment programs only (at this time)
718 */
719 if (target == GL_FRAGMENT_PROGRAM_ARB) {
Brian Paul122629f2006-07-20 16:49:57 +0000720 const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
Brian Paul05051032005-11-01 04:36:33 +0000721 switch (pname) {
722 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700723 *params = fp->Base.NumNativeAluInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000724 return;
725 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700726 *params = fp->Base.NumAluInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000727 return;
728 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700729 *params = fp->Base.NumTexInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000730 return;
731 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700732 *params = fp->Base.NumNativeTexInstructions;
Brian Paul05051032005-11-01 04:36:33 +0000733 return;
734 case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700735 *params = fp->Base.NumTexIndirections;
Brian Paul05051032005-11-01 04:36:33 +0000736 return;
737 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
Brian21f99792007-01-09 11:00:21 -0700738 *params = fp->Base.NumNativeTexIndirections;
Brian Paul05051032005-11-01 04:36:33 +0000739 return;
740 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
741 *params = limits->MaxAluInstructions;
742 return;
743 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
744 *params = limits->MaxNativeAluInstructions;
745 return;
746 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
747 *params = limits->MaxTexInstructions;
748 return;
749 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
750 *params = limits->MaxNativeTexInstructions;
751 return;
752 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
753 *params = limits->MaxTexIndirections;
754 return;
755 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
756 *params = limits->MaxNativeTexIndirections;
757 return;
758 default:
759 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
760 return;
761 }
Michal Krol157ec8b2004-03-10 18:02:01 +0000762 }
763}
764
765
766void GLAPIENTRY
767_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
768{
Brian Paul122629f2006-07-20 16:49:57 +0000769 const struct gl_program *prog;
Brian Paul308b85f2006-11-23 15:58:30 +0000770 char *dst = (char *) string;
Michal Krol157ec8b2004-03-10 18:02:01 +0000771 GET_CURRENT_CONTEXT(ctx);
772
773 if (!ctx->_CurrentProgram)
774 ASSERT_OUTSIDE_BEGIN_END(ctx);
775
776 if (target == GL_VERTEX_PROGRAM_ARB) {
777 prog = &(ctx->VertexProgram.Current->Base);
778 }
779 else if (target == GL_FRAGMENT_PROGRAM_ARB) {
780 prog = &(ctx->FragmentProgram.Current->Base);
781 }
782 else {
783 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
784 return;
785 }
786
787 ASSERT(prog);
788
789 if (pname != GL_PROGRAM_STRING_ARB) {
790 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
791 return;
792 }
793
Brian Paul308b85f2006-11-23 15:58:30 +0000794 if (prog->String)
795 _mesa_memcpy(dst, prog->String, _mesa_strlen((char *) prog->String));
796 else
797 *dst = '\0';
Michal Krol157ec8b2004-03-10 18:02:01 +0000798}