Subversion Repositories shark

Rev

Rev 55 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
55 pj 1
/* $Id: vpstate.c,v 1.1 2003-02-28 11:42:06 pj Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  4.1
6
 *
7
 * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included
17
 * in all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26
 
27
/*
28
 * -------- Regarding NV_vertex_program --------
29
 * Redistribution and use in source and binary forms, with or without
30
 * modification, are permitted provided that the following conditions are met:
31
 *
32
 * o Redistribution of the source code must contain a copyright notice
33
 *   and this list of conditions;
34
 *
35
 * o Redistribution in binary and source code form must contain the
36
 *   following Notice in the software and any documentation and/or other
37
 *   materials provided with the distribution; and
38
 *
39
 * o The name of Nvidia may not be used to promote or endorse software
40
 *   derived from the software.
41
 *
42
 * NOTICE: Nvidia hereby grants to each recipient a non-exclusive worldwide
43
 * royalty free patent license under patent claims that are licensable by
44
 * Nvidia and which are necessarily required and for which no commercially
45
 * viable non infringing alternative exists to make, use, sell, offer to sell,
46
 * import and otherwise transfer the vertex extension for the Mesa 3D Graphics
47
 * Library as distributed in source code and object code form.  No hardware or
48
 * hardware implementation (including a semiconductor implementation and chips)
49
 * are licensed hereunder. If a recipient makes a patent claim or institutes
50
 * patent litigation against Nvidia or Nvidia's customers for use or sale of
51
 * Nvidia products, then this license grant as to such recipient shall
52
 * immediately terminate and recipient immediately agrees to cease use and
53
 * distribution of the Mesa Program and derivatives thereof.
54
 *
55
 * THE MESA 3D GRAPHICS LIBRARY IS PROVIDED ON AN "AS IS BASIS, WITHOUT
56
 * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
57
 * WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-NFRINGEMENT
58
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
59
 *
60
 * NVIDIA SHALL NOT HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
61
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
62
 * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64
 * ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE MESA 3D GRAPHICS
65
 * LIBRARY OR EVIDENCE OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDR, EVEN
66
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67
 *
68
 * If you do not comply with this agreement, then Nvidia may cancel the license
69
 * and rights granted herein.
70
 * ---------------------------------------------
71
 */
72
 
73
/**
74
 * \file vpstate.c
75
 * \brief Vertex program state management functions (most map to API functions)
76
 * \author Brian Paul
77
 */
78
 
79
 
80
#include "glheader.h"
81
#include "context.h"
82
#include "hash.h"
83
#include "imports.h"
84
#include "macros.h"
85
#include "mtypes.h"
86
#include "vpexec.h"
87
#include "vpparse.h"
88
#include "vpstate.h"
89
 
90
 
91
/**
92
 * Delete a program and remove it from the hash table, ignoring the
93
 * reference count.
94
 * \note Called from the GL API dispatcher.
95
 */
96
void _mesa_delete_program(GLcontext *ctx, GLuint id)
97
{
98
   struct vp_program *vprog = (struct vp_program *)
99
      _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
100
 
101
   if (vprog) {
102
      if (vprog->String)
103
         FREE(vprog->String);
104
      if (vprog->Instructions)
105
         FREE(vprog->Instructions);
106
      _mesa_HashRemove(ctx->Shared->VertexPrograms, id);
107
      FREE(vprog);
108
   }
109
}
110
 
111
 
112
/**
113
 * Bind a program (make it current)
114
 * \note Called from the GL API dispatcher.
115
 */
116
void _mesa_BindProgramNV(GLenum target, GLuint id)
117
{
118
   struct vp_program *vprog;
119
   GET_CURRENT_CONTEXT(ctx);
120
   ASSERT_OUTSIDE_BEGIN_END(ctx);
121
 
122
   if (target != GL_VERTEX_PROGRAM_NV) {
123
      _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramNV");
124
      return;
125
   }
126
 
127
   if (id == ctx->VertexProgram.CurrentID)
128
      return;
129
 
130
   /* decrement refcount on previously bound vertex program */
131
   if (ctx->VertexProgram.Current) {
132
      ctx->VertexProgram.Current->RefCount--;
133
      /* and delete if refcount goes below one */
134
      if (ctx->VertexProgram.Current->RefCount <= 0)
135
         _mesa_delete_program(ctx, ctx->VertexProgram.CurrentID);
136
   }
137
 
138
   /* NOTE: binding to a non-existant program is not an error.
139
    * That's supposed to be caught in glBegin.
140
    */
141
   vprog = (struct vp_program *)
142
      _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
143
 
144
   if (!vprog && id > 0){
145
      /* new program ID */
146
      vprog = CALLOC_STRUCT(vp_program);
147
      if (!vprog) {
148
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramNV");
149
         return;
150
      }
151
      vprog->Target = target;
152
      vprog->Resident = GL_TRUE;
153
      vprog->RefCount = 1;
154
      _mesa_HashInsert(ctx->Shared->VertexPrograms, id, vprog);
155
   }
156
 
157
   ctx->VertexProgram.CurrentID = id;
158
   ctx->VertexProgram.Current = vprog;
159
   if (vprog)
160
      vprog->RefCount++;
161
}
162
 
163
 
164
/**
165
 * Delete a list of programs.
166
 * \note Not compiled into display lists.
167
 * \note Called from the GL API dispatcher.
168
 */
169
void _mesa_DeleteProgramsNV(GLsizei n, const GLuint *ids)
170
{
171
   GLint i;
172
   GET_CURRENT_CONTEXT(ctx);
173
   ASSERT_OUTSIDE_BEGIN_END(ctx);
174
 
175
   if (n < 0) {
176
      _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
177
      return;
178
   }
179
 
180
   for (i = 0; i < n; i++) {
181
      if (ids[i] != 0) {
182
         struct vp_program *vprog = (struct vp_program *)
183
            _mesa_HashLookup(ctx->Shared->VertexPrograms, ids[i]);
184
         if (ctx->VertexProgram.CurrentID == ids[i]) {
185
            /* unbind this currently bound program */
186
            _mesa_BindProgramNV(vprog->Target, 0);
187
         }
188
         if (vprog) {
189
            vprog->RefCount--;
190
            if (vprog->RefCount <= 0) {
191
               _mesa_delete_program(ctx, ids[i]);
192
            }
193
         }
194
      }
195
   }
196
}
197
 
198
 
199
/**
200
 * Execute a vertex state program.
201
 * \note Called from the GL API dispatcher.
202
 */
203
void _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
204
{
205
   struct vp_program *vprog;
206
   GET_CURRENT_CONTEXT(ctx);
207
   ASSERT_OUTSIDE_BEGIN_END(ctx);
208
 
209
   if (target != GL_VERTEX_STATE_PROGRAM_NV) {
210
      _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV");
211
      return;
212
   }
213
 
214
   vprog = (struct vp_program *)
215
      _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
216
 
217
   if (!vprog || vprog->Target != GL_VERTEX_STATE_PROGRAM_NV) {
218
      _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV");
219
      return;
220
   }
221
 
222
   _mesa_init_vp_registers(ctx);
223
   _mesa_init_tracked_matrices(ctx);
224
   COPY_4V(ctx->VertexProgram.Machine.Registers[VP_INPUT_REG_START], params);
225
   _mesa_exec_program(ctx, vprog);
226
}
227
 
228
 
229
/**
230
 * Generate a list of new program identifiers.
231
 * \note Not compiled into display lists.
232
 * \note Called from the GL API dispatcher.
233
 */
234
void _mesa_GenProgramsNV(GLsizei n, GLuint *ids)
235
{
236
   GLuint first;
237
   GLuint i;
238
   GET_CURRENT_CONTEXT(ctx);
239
   ASSERT_OUTSIDE_BEGIN_END(ctx);
240
 
241
   if (n < 0) {
242
      _mesa_error(ctx, GL_INVALID_VALUE, "glGenProgramsNV");
243
      return;
244
   }
245
 
246
   if (!ids)
247
      return;
248
 
249
   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->VertexPrograms, n);
250
 
251
   for (i = 0; i < (GLuint) n; i++) {
252
      struct vp_program *vprog = CALLOC_STRUCT(vp_program);
253
      if (!vprog) {
254
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenProgramsNV");
255
         return;
256
      }
257
      vprog->RefCount = 1;
258
      _mesa_HashInsert(ctx->Shared->VertexPrograms, first + i, vprog);
259
   }
260
 
261
   /* Return the program names */
262
   for (i = 0; i < (GLuint) n; i++) {
263
      ids[i] = first + i;
264
   }
265
}
266
 
267
 
268
/**
269
 * Determine if a set of programs is resident in hardware.
270
 * \note Not compiled into display lists.
271
 * \note Called from the GL API dispatcher.
272
 */
273
GLboolean _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
274
                                      GLboolean *residences)
275
{
276
   GLint i;
277
   GLboolean retVal;
278
   GET_CURRENT_CONTEXT(ctx);
279
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
280
 
281
   if (n < 0) {
282
      _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)");
283
      return GL_FALSE;
284
   }
285
 
286
   retVal = GL_TRUE;
287
 
288
   for (i = 0; i < n; i++) {
289
      struct vp_program *vprog;
290
 
291
      if (ids[i] == 0) {
292
         _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(id)");
293
         return GL_FALSE;
294
      }
295
 
296
      vprog = (struct vp_program *)
297
         _mesa_HashLookup(ctx->Shared->VertexPrograms, ids[i]);
298
 
299
      if (!vprog) {
300
         _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(id)");
301
         return GL_FALSE;
302
      }
303
 
304
      *residences = vprog->Resident;
305
      if (!vprog->Resident)
306
         retVal = GL_FALSE;
307
   }
308
 
309
   return retVal;
310
}
311
 
312
 
313
/**
314
 * Request that a set of programs be resident in hardware.
315
 * \note Called from the GL API dispatcher.
316
 */
317
void _mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids)
318
{
319
   GLint i;
320
   GET_CURRENT_CONTEXT(ctx);
321
   ASSERT_OUTSIDE_BEGIN_END(ctx);
322
 
323
   if (n < 0) {
324
      _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)");
325
      return;
326
   }
327
 
328
   /* just error checking for now */
329
   for (i = 0; i < n; i++) {
330
      struct vp_program *vprog;
331
 
332
      if (ids[i] == 0) {
333
         _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
334
         return;
335
      }
336
 
337
      vprog = (struct vp_program *)
338
         _mesa_HashLookup(ctx->Shared->VertexPrograms, ids[i]);
339
 
340
      if (!vprog) {
341
         _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
342
         return;
343
      }
344
 
345
      vprog->Resident = GL_TRUE;
346
   }
347
}
348
 
349
 
350
/**
351
 * Get a program parameter register.
352
 * \note Not compiled into display lists.
353
 * \note Called from the GL API dispatcher.
354
 */
355
void _mesa_GetProgramParameterfvNV(GLenum target, GLuint index,
356
                                   GLenum pname, GLfloat *params)
357
{
358
   GET_CURRENT_CONTEXT(ctx);
359
   ASSERT_OUTSIDE_BEGIN_END(ctx);
360
 
361
   if (target != GL_VERTEX_PROGRAM_NV) {
362
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV");
363
      return;
364
   }
365
 
366
   if (index >= VP_NUM_PROG_REGS) {
367
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramParameterfvNV");
368
      return;
369
   }
370
 
371
   if (pname != GL_PROGRAM_PARAMETER_NV) {
372
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV");
373
      return;
374
   }
375
 
376
   index += VP_PROG_REG_START;
377
   COPY_4V(params, ctx->VertexProgram.Machine.Registers[index]);
378
}
379
 
380
 
381
/**
382
 * Get a program parameter register.
383
 * \note Not compiled into display lists.
384
 * \note Called from the GL API dispatcher.
385
 */
386
void _mesa_GetProgramParameterdvNV(GLenum target, GLuint index,
387
                                   GLenum pname, GLdouble *params)
388
{
389
   GET_CURRENT_CONTEXT(ctx);
390
   ASSERT_OUTSIDE_BEGIN_END(ctx);
391
 
392
   if (target != GL_VERTEX_PROGRAM_NV) {
393
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV");
394
      return;
395
   }
396
 
397
   if (index >= VP_NUM_PROG_REGS) {
398
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramParameterfvNV");
399
      return;
400
   }
401
 
402
   if (pname != GL_PROGRAM_PARAMETER_NV) {
403
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV");
404
      return;
405
   }
406
 
407
   index += VP_PROG_REG_START;
408
   COPY_4V(params, ctx->VertexProgram.Machine.Registers[index]);
409
}
410
 
411
 
412
/**
413
 * Get a program attribute.
414
 * \note Not compiled into display lists.
415
 * \note Called from the GL API dispatcher.
416
 */
417
void _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
418
{
419
   struct vp_program *vprog;
420
   GET_CURRENT_CONTEXT(ctx);
421
   ASSERT_OUTSIDE_BEGIN_END(ctx);
422
 
423
   vprog = (struct vp_program *)
424
      _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
425
 
426
   if (!vprog) {
427
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
428
      return;
429
   }
430
 
431
   switch (pname) {
432
      case GL_PROGRAM_TARGET_NV:
433
         *params = vprog->Target;
434
         return;
435
      case GL_PROGRAM_LENGTH_NV:
436
         *params = vprog->String ? _mesa_strlen((char *) vprog->String) : 0;
437
         return;
438
      case GL_PROGRAM_RESIDENT_NV:
439
         *params = vprog->Resident;
440
         return;
441
      default:
442
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
443
         return;
444
   }
445
}
446
 
447
 
448
/**
449
 * Get the program source code.
450
 * \note Not compiled into display lists.
451
 * \note Called from the GL API dispatcher.
452
 */
453
void _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
454
{
455
   struct vp_program *vprog;
456
   GET_CURRENT_CONTEXT(ctx);
457
   ASSERT_OUTSIDE_BEGIN_END(ctx);
458
 
459
   if (pname != GL_PROGRAM_STRING_NV) {
460
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
461
      return;
462
   }
463
 
464
   vprog = (struct vp_program *)
465
      _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
466
 
467
   if (!vprog) {
468
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
469
      return;
470
   }
471
 
472
   if (vprog->String) {
473
      MEMCPY(program, vprog->String, _mesa_strlen((char *) vprog->String));
474
   }
475
   else {
476
      program[0] = 0;
477
   }
478
}
479
 
480
 
481
/**
482
 * Get matrix tracking information.
483
 * \note Not compiled into display lists.
484
 * \note Called from the GL API dispatcher.
485
 */
486
void _mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
487
                              GLenum pname, GLint *params)
488
{
489
   GLuint i;
490
   GET_CURRENT_CONTEXT(ctx);
491
   ASSERT_OUTSIDE_BEGIN_END(ctx);
492
 
493
   if (target != GL_VERTEX_PROGRAM_NV) {
494
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
495
      return;
496
   }
497
 
498
   if ((address & 0x3) || address > VP_NUM_PROG_REGS) {
499
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)");
500
      return;
501
   }
502
 
503
   i = address / 4;
504
 
505
   switch (pname) {
506
      case GL_TRACK_MATRIX_NV:
507
         params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i];
508
         return;
509
      case GL_TRACK_MATRIX_TRANSFORM_NV:
510
         params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i];
511
         return;
512
      default:
513
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
514
         return;
515
   }
516
}
517
 
518
 
519
/**
520
 * Get a vertex (or vertex array) attribute.
521
 * \note Not compiled into display lists.
522
 * \note Called from the GL API dispatcher.
523
 */
524
void _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
525
{
526
   GET_CURRENT_CONTEXT(ctx);
527
   ASSERT_OUTSIDE_BEGIN_END(ctx);
528
 
529
   if (index == 0 || index >= VP_NUM_INPUT_REGS) {
530
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
531
      return;
532
   }
533
 
534
   switch (pname) {
535
      case GL_ATTRIB_ARRAY_SIZE_NV:
536
         params[0] = ctx->Array.VertexAttrib[index].Size;
537
         break;
538
      case GL_ATTRIB_ARRAY_STRIDE_NV:
539
         params[0] = ctx->Array.VertexAttrib[index].Stride;
540
         break;
541
      case GL_ATTRIB_ARRAY_TYPE_NV:
542
         params[0] = ctx->Array.VertexAttrib[index].Type;
543
         break;
544
      case GL_CURRENT_ATTRIB_NV:
545
         COPY_4V(params, ctx->Current.Attrib[index]);
546
         break;
547
      default:
548
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
549
         return;
550
   }
551
}
552
 
553
/**
554
 * Get a vertex (or vertex array) attribute.
555
 * \note Not compiled into display lists.
556
 * \note Called from the GL API dispatcher.
557
 */
558
void _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
559
{
560
   GET_CURRENT_CONTEXT(ctx);
561
   ASSERT_OUTSIDE_BEGIN_END(ctx);
562
 
563
   if (index == 0 || index >= VP_NUM_INPUT_REGS) {
564
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
565
      return;
566
   }
567
 
568
   switch (pname) {
569
      case GL_ATTRIB_ARRAY_SIZE_NV:
570
         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Size;
571
         break;
572
      case GL_ATTRIB_ARRAY_STRIDE_NV:
573
         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Stride;
574
         break;
575
      case GL_ATTRIB_ARRAY_TYPE_NV:
576
         params[0] = (GLfloat) ctx->Array.VertexAttrib[index].Type;
577
         break;
578
      case GL_CURRENT_ATTRIB_NV:
579
         COPY_4V(params, ctx->Current.Attrib[index]);
580
         break;
581
      default:
582
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
583
         return;
584
   }
585
}
586
 
587
/**
588
 * Get a vertex (or vertex array) attribute.
589
 * \note Not compiled into display lists.
590
 * \note Called from the GL API dispatcher.
591
 */
592
void _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
593
{
594
   GET_CURRENT_CONTEXT(ctx);
595
   ASSERT_OUTSIDE_BEGIN_END(ctx);
596
 
597
   if (index == 0 || index >= VP_NUM_INPUT_REGS) {
598
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
599
      return;
600
   }
601
 
602
   switch (pname) {
603
      case GL_ATTRIB_ARRAY_SIZE_NV:
604
         params[0] = ctx->Array.VertexAttrib[index].Size;
605
         break;
606
      case GL_ATTRIB_ARRAY_STRIDE_NV:
607
         params[0] = ctx->Array.VertexAttrib[index].Stride;
608
         break;
609
      case GL_ATTRIB_ARRAY_TYPE_NV:
610
         params[0] = ctx->Array.VertexAttrib[index].Type;
611
         break;
612
      case GL_CURRENT_ATTRIB_NV:
613
         COPY_4V_CAST(params, ctx->Current.Attrib[index], GLint);
614
         break;
615
      default:
616
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
617
         return;
618
   }
619
}
620
 
621
 
622
/**
623
 * Get a vertex array attribute pointer.
624
 * \note Not compiled into display lists.
625
 * \note Called from the GL API dispatcher.
626
 */
627
void _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
628
{
629
   GET_CURRENT_CONTEXT(ctx);
630
   ASSERT_OUTSIDE_BEGIN_END(ctx);
631
 
632
   if (index >= VP_NUM_PROG_REGS) {
633
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
634
      return;
635
   }
636
 
637
   if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
638
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
639
      return;
640
   }
641
 
642
   *pointer = ctx->Array.VertexAttrib[index].Ptr;;
643
}
644
 
645
 
646
/**
647
 * Determine if id names a program.
648
 * \note Not compiled into display lists.
649
 * \note Called from the GL API dispatcher.
650
 * \param id is the program identifier
651
 * \return GL_TRUE if id is a program, else GL_FALSE.
652
 */
653
GLboolean _mesa_IsProgramNV(GLuint id)
654
{
655
   struct vp_program *vprog;
656
   GET_CURRENT_CONTEXT(ctx);
657
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
658
 
659
   if (id == 0)
660
      return GL_FALSE;
661
 
662
   vprog = (struct vp_program *)
663
      _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
664
 
665
   if (vprog && vprog->Target)
666
      return GL_TRUE;
667
   else
668
      return GL_FALSE;
669
}
670
 
671
 
672
/**
673
 * Load a vertex program.
674
 * \note Called from the GL API dispatcher.
675
 */
676
void _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
677
                         const GLubyte *program)
678
{
679
   struct vp_program *vprog;
680
   GLboolean newProgram = GL_FALSE;
681
   GLubyte *programCopy;
682
   GET_CURRENT_CONTEXT(ctx);
683
   ASSERT_OUTSIDE_BEGIN_END(ctx);
684
 
685
   if (id == 0) {
686
      _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
687
      return;
688
   }
689
 
690
   vprog = (struct vp_program *)
691
      _mesa_HashLookup(ctx->Shared->VertexPrograms, id);
692
 
693
   if (vprog && vprog->Target != 0 && vprog->Target != target) {
694
      _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
695
      return;
696
   }
697
 
698
   /* make a copy of the program string so that we can null-terminate it */
699
   /* if we change the parser to stop after <len> characters, instead of */
700
   /* looking for '\0' we can eliminate this. */
701
   programCopy = (GLubyte *) MALLOC(len + 1);
702
   if (!programCopy) {
703
      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
704
      return;
705
   }
706
   MEMCPY(programCopy, program, len);
707
   programCopy[len] = 0;
708
 
709
   if (!vprog) {
710
      newProgram = GL_TRUE;
711
      vprog = CALLOC_STRUCT(vp_program);
712
      if (!vprog) {
713
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
714
         return;
715
      }
716
   }
717
 
718
   _mesa_parse_program(ctx, target, programCopy, vprog);
719
   if (ctx->VertexProgram.ErrorPos == -1) {
720
      /* loaded and parsed w/out errors */
721
      if (newProgram) {
722
         _mesa_HashInsert(ctx->Shared->VertexPrograms, id, vprog);
723
      }
724
      vprog->RefCount = 1;
725
      vprog->Resident = GL_TRUE;
726
   }
727
 
728
   FREE(programCopy);
729
}
730
 
731
 
732
 
733
/**
734
 * Set a program parameter register.
735
 * \note Called from the GL API dispatcher.
736
 */
737
void _mesa_ProgramParameter4dNV(GLenum target, GLuint index,
738
                                GLdouble x, GLdouble y, GLdouble z, GLdouble w)
739
{
740
   GET_CURRENT_CONTEXT(ctx);
741
   ASSERT_OUTSIDE_BEGIN_END(ctx);
742
 
743
   if (target != GL_VERTEX_PROGRAM_NV) {
744
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameter4dNV");
745
      return;
746
   }
747
 
748
   if (index >= VP_NUM_PROG_REGS) {
749
      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameter4dNV");
750
      return;
751
   }
752
 
753
   index += VP_PROG_REG_START;
754
   ASSIGN_4V(ctx->VertexProgram.Machine.Registers[index],
755
             (GLfloat)x, (GLfloat)y, (GLfloat)z, (GLfloat)w);
756
}
757
 
758
 
759
/**
760
 * Set a program parameter register.
761
 * \note Called from the GL API dispatcher.
762
 */
763
void _mesa_ProgramParameter4dvNV(GLenum target, GLuint index,
764
                                 const GLdouble *params)
765
{
766
   GET_CURRENT_CONTEXT(ctx);
767
   ASSERT_OUTSIDE_BEGIN_END(ctx);
768
 
769
   if (target != GL_VERTEX_PROGRAM_NV) {
770
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameter4dvNV");
771
      return;
772
   }
773
 
774
   if (index >= VP_NUM_PROG_REGS) {
775
      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameter4dvNV");
776
      return;
777
   }
778
 
779
   index += VP_PROG_REG_START;
780
   COPY_4V_CAST(ctx->VertexProgram.Machine.Registers[index], params, GLfloat);
781
}
782
 
783
 
784
/**
785
 * Set a program parameter register.
786
 * \note Called from the GL API dispatcher.
787
 */
788
void _mesa_ProgramParameter4fNV(GLenum target, GLuint index,
789
                                GLfloat x, GLfloat y, GLfloat z, GLfloat w)
790
{
791
   GET_CURRENT_CONTEXT(ctx);
792
   ASSERT_OUTSIDE_BEGIN_END(ctx);
793
 
794
   if (target != GL_VERTEX_PROGRAM_NV) {
795
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameter4fNV");
796
      return;
797
   }
798
 
799
   if (index >= VP_NUM_PROG_REGS) {
800
      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameter4fNV");
801
      return;
802
   }
803
 
804
   index += VP_PROG_REG_START;
805
   ASSIGN_4V(ctx->VertexProgram.Machine.Registers[index], x, y, z, w);
806
}
807
 
808
 
809
/**
810
 * Set a program parameter register.
811
 * \note Called from the GL API dispatcher.
812
 */
813
void _mesa_ProgramParameter4fvNV(GLenum target, GLuint index,
814
                                 const GLfloat *params)
815
{
816
   GET_CURRENT_CONTEXT(ctx);
817
   ASSERT_OUTSIDE_BEGIN_END(ctx);
818
 
819
   if (target != GL_VERTEX_PROGRAM_NV) {
820
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameter4fNV");
821
      return;
822
   }
823
 
824
   if (index >= VP_NUM_PROG_REGS) {
825
      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameter4fNV");
826
      return;
827
   }
828
 
829
   index += VP_PROG_REG_START;
830
   COPY_4V(ctx->VertexProgram.Machine.Registers[index], params);
831
}
832
 
833
 
834
/**
835
 * Set a sequence of program parameter registers.
836
 * \note Called from the GL API dispatcher.
837
 */
838
void _mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
839
                                  GLuint num, const GLdouble *params)
840
{
841
   GLuint i;
842
   GET_CURRENT_CONTEXT(ctx);
843
   ASSERT_OUTSIDE_BEGIN_END(ctx);
844
 
845
   if (target != GL_VERTEX_PROGRAM_NV) {
846
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
847
      return;
848
   }
849
 
850
   if (index + num > VP_NUM_PROG_REGS) {
851
      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
852
      return;
853
   }
854
 
855
   index += VP_PROG_REG_START;
856
   for (i = 0; i < num; i++) {
857
      COPY_4V_CAST(ctx->VertexProgram.Machine.Registers[index + i],
858
                   params, GLfloat);
859
      params += 4;
860
   };
861
}
862
 
863
 
864
/**
865
 * Set a sequence of program parameter registers.
866
 * \note Called from the GL API dispatcher.
867
 */
868
void _mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
869
                                  GLuint num, const GLfloat *params)
870
{
871
   GLuint i;
872
   GET_CURRENT_CONTEXT(ctx);
873
   ASSERT_OUTSIDE_BEGIN_END(ctx);
874
 
875
   if (target != GL_VERTEX_PROGRAM_NV) {
876
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
877
      return;
878
   }
879
 
880
   if (index + num > VP_NUM_PROG_REGS) {
881
      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
882
      return;
883
   }
884
 
885
   index += VP_PROG_REG_START;
886
   for (i = 0; i < num; i++) {
887
      COPY_4V(ctx->VertexProgram.Machine.Registers[index + i], params);
888
      params += 4;
889
   };
890
}
891
 
892
 
893
/**
894
 * Setup tracking of matrices into program parameter registers.
895
 * \note Called from the GL API dispatcher.
896
 */
897
void _mesa_TrackMatrixNV(GLenum target, GLuint address,
898
                         GLenum matrix, GLenum transform)
899
{
900
   GET_CURRENT_CONTEXT(ctx);
901
   ASSERT_OUTSIDE_BEGIN_END(ctx);
902
 
903
   if (target != GL_VERTEX_PROGRAM_NV) {
904
      _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
905
      return;
906
   }
907
 
908
   if (address & 0x3) {
909
      /* addr must be multiple of four */
910
      _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
911
      return;
912
   }
913
 
914
   switch (matrix) {
915
      case GL_NONE:
916
      case GL_MODELVIEW:
917
      case GL_PROJECTION:
918
      case GL_TEXTURE:
919
      case GL_COLOR:
920
      case GL_MODELVIEW_PROJECTION_NV:
921
      case GL_MATRIX0_NV:
922
      case GL_MATRIX1_NV:
923
      case GL_MATRIX2_NV:
924
      case GL_MATRIX3_NV:
925
      case GL_MATRIX4_NV:
926
      case GL_MATRIX5_NV:
927
      case GL_MATRIX6_NV:
928
      case GL_MATRIX7_NV:
929
         /* OK, fallthrough */
930
         break;
931
      default:
932
         _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
933
         return;
934
   }
935
 
936
   switch (transform) {
937
      case GL_IDENTITY_NV:
938
      case GL_INVERSE_NV:
939
      case GL_TRANSPOSE_NV:
940
      case GL_INVERSE_TRANSPOSE_NV:
941
         /* OK, fallthrough */
942
         break;
943
      default:
944
         _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
945
         return;
946
   }
947
 
948
   ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
949
   ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
950
}