Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Mesa 3-D graphics library
3
 * Version:  6.5.2
4
 *
5
 * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6
 *
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 nvprogram.c
27
 * NVIDIA vertex/fragment program state management functions.
28
 * \author Brian Paul
29
 */
30
 
31
/*
32
 * Regarding GL_NV_fragment/vertex_program, GL_NV_vertex_program1_1, etc:
33
 *
34
 * Portions of this software may use or implement intellectual
35
 * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
36
 * any and all warranties with respect to such intellectual property,
37
 * including any use thereof or modifications thereto.
38
 */
39
 
40
#include "main/glheader.h"
41
#include "main/context.h"
42
#include "main/hash.h"
43
#include "main/imports.h"
44
#include "main/macros.h"
45
#include "main/nvprogram.h"
46
#include "program/arbprogparse.h"
47
#include "program/nvfragparse.h"
48
#include "program/nvvertparse.h"
49
#include "program/program.h"
50
#include "program/prog_instruction.h"
51
#include "program/prog_parameter.h"
52
 
53
 
54
 
55
/**
56
 * Execute a vertex state program.
57
 * \note Called from the GL API dispatcher.
58
 */
59
void GLAPIENTRY
60
_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params)
61
{
62
   struct gl_vertex_program *vprog;
63
   GET_CURRENT_CONTEXT(ctx);
64
   ASSERT_OUTSIDE_BEGIN_END(ctx);
65
 
66
   if (target != GL_VERTEX_STATE_PROGRAM_NV) {
67
      _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV");
68
      return;
69
   }
70
 
71
   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
72
 
73
   vprog = (struct gl_vertex_program *) _mesa_lookup_program(ctx, id);
74
 
75
   if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) {
76
      _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV");
77
      return;
78
   }
79
 
80
   _mesa_problem(ctx, "glExecuteProgramNV() not supported");
81
}
82
 
83
 
84
/**
85
 * Determine if a set of programs is resident in hardware.
86
 * \note Not compiled into display lists.
87
 * \note Called from the GL API dispatcher.
88
 */
89
GLboolean GLAPIENTRY
90
_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids,
91
                            GLboolean *residences)
92
{
93
   GLint i, j;
94
   GLboolean allResident = GL_TRUE;
95
   GET_CURRENT_CONTEXT(ctx);
96
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
97
 
98
   if (n < 0) {
99
      _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)");
100
      return GL_FALSE;
101
   }
102
 
103
   for (i = 0; i < n; i++) {
104
      const struct gl_program *prog;
105
      if (ids[i] == 0) {
106
         _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
107
         return GL_FALSE;
108
      }
109
      prog = _mesa_lookup_program(ctx, ids[i]);
110
      if (!prog) {
111
         _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV");
112
         return GL_FALSE;
113
      }
114
      if (prog->Resident) {
115
	 if (!allResident)
116
	    residences[i] = GL_TRUE;
117
      }
118
      else {
119
         if (allResident) {
120
	    allResident = GL_FALSE;
121
	    for (j = 0; j < i; j++)
122
	       residences[j] = GL_TRUE;
123
	 }
124
	 residences[i] = GL_FALSE;
125
      }
126
   }
127
 
128
   return allResident;
129
}
130
 
131
 
132
/**
133
 * Request that a set of programs be resident in hardware.
134
 * \note Called from the GL API dispatcher.
135
 */
136
void GLAPIENTRY
137
_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids)
138
{
139
   GLint i;
140
   GET_CURRENT_CONTEXT(ctx);
141
   ASSERT_OUTSIDE_BEGIN_END(ctx);
142
 
143
   if (n < 0) {
144
      _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)");
145
      return;
146
   }
147
 
148
   /* just error checking for now */
149
   for (i = 0; i < n; i++) {
150
      struct gl_program *prog;
151
 
152
      if (ids[i] == 0) {
153
         _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
154
         return;
155
      }
156
 
157
      prog = _mesa_lookup_program(ctx, ids[i]);
158
      if (!prog) {
159
         _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)");
160
         return;
161
      }
162
 
163
      /* XXX this is really a hardware thing we should hook out */
164
      prog->Resident = GL_TRUE;
165
   }
166
}
167
 
168
 
169
/**
170
 * Get a program parameter register.
171
 * \note Not compiled into display lists.
172
 * \note Called from the GL API dispatcher.
173
 */
174
void GLAPIENTRY
175
_mesa_GetProgramParameterfvNV(GLenum target, GLuint index,
176
                              GLenum pname, GLfloat *params)
177
{
178
   GET_CURRENT_CONTEXT(ctx);
179
   ASSERT_OUTSIDE_BEGIN_END(ctx);
180
 
181
   if (target == GL_VERTEX_PROGRAM_NV) {
182
      if (pname == GL_PROGRAM_PARAMETER_NV) {
183
         if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
184
            COPY_4V(params, ctx->VertexProgram.Parameters[index]);
185
         }
186
         else {
187
            _mesa_error(ctx, GL_INVALID_VALUE,
188
                        "glGetProgramParameterfvNV(index)");
189
            return;
190
         }
191
      }
192
      else {
193
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(pname)");
194
         return;
195
      }
196
   }
197
   else {
198
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(target)");
199
      return;
200
   }
201
}
202
 
203
 
204
/**
205
 * Get a program parameter register.
206
 * \note Not compiled into display lists.
207
 * \note Called from the GL API dispatcher.
208
 */
209
void GLAPIENTRY
210
_mesa_GetProgramParameterdvNV(GLenum target, GLuint index,
211
                              GLenum pname, GLdouble *params)
212
{
213
   GET_CURRENT_CONTEXT(ctx);
214
   ASSERT_OUTSIDE_BEGIN_END(ctx);
215
 
216
   if (target == GL_VERTEX_PROGRAM_NV) {
217
      if (pname == GL_PROGRAM_PARAMETER_NV) {
218
         if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) {
219
            COPY_4V(params, ctx->VertexProgram.Parameters[index]);
220
         }
221
         else {
222
            _mesa_error(ctx, GL_INVALID_VALUE,
223
                        "glGetProgramParameterdvNV(index)");
224
            return;
225
         }
226
      }
227
      else {
228
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(pname)");
229
         return;
230
      }
231
   }
232
   else {
233
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(target)");
234
      return;
235
   }
236
}
237
 
238
 
239
/**
240
 * Get a program attribute.
241
 * \note Not compiled into display lists.
242
 * \note Called from the GL API dispatcher.
243
 */
244
void GLAPIENTRY
245
_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params)
246
{
247
   struct gl_program *prog;
248
   GET_CURRENT_CONTEXT(ctx);
249
 
250
   ASSERT_OUTSIDE_BEGIN_END(ctx);
251
 
252
   prog = _mesa_lookup_program(ctx, id);
253
   if (!prog) {
254
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV");
255
      return;
256
   }
257
 
258
   switch (pname) {
259
      case GL_PROGRAM_TARGET_NV:
260
         *params = prog->Target;
261
         return;
262
      case GL_PROGRAM_LENGTH_NV:
263
         *params = prog->String ?(GLint) strlen((char *) prog->String) : 0;
264
         return;
265
      case GL_PROGRAM_RESIDENT_NV:
266
         *params = prog->Resident;
267
         return;
268
      default:
269
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)");
270
         return;
271
   }
272
}
273
 
274
 
275
/**
276
 * Get the program source code.
277
 * \note Not compiled into display lists.
278
 * \note Called from the GL API dispatcher.
279
 */
280
void GLAPIENTRY
281
_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program)
282
{
283
   struct gl_program *prog;
284
   GET_CURRENT_CONTEXT(ctx);
285
 
286
   ASSERT_OUTSIDE_BEGIN_END(ctx);
287
 
288
   if (pname != GL_PROGRAM_STRING_NV) {
289
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)");
290
      return;
291
   }
292
 
293
   prog = _mesa_lookup_program(ctx, id);
294
   if (!prog) {
295
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV");
296
      return;
297
   }
298
 
299
   if (prog->String) {
300
      memcpy(program, prog->String, strlen((char *) prog->String));
301
   }
302
   else {
303
      program[0] = 0;
304
   }
305
}
306
 
307
 
308
/**
309
 * Get matrix tracking information.
310
 * \note Not compiled into display lists.
311
 * \note Called from the GL API dispatcher.
312
 */
313
void GLAPIENTRY
314
_mesa_GetTrackMatrixivNV(GLenum target, GLuint address,
315
                         GLenum pname, GLint *params)
316
{
317
   GET_CURRENT_CONTEXT(ctx);
318
   ASSERT_OUTSIDE_BEGIN_END(ctx);
319
 
320
   if (target == GL_VERTEX_PROGRAM_NV
321
       && ctx->Extensions.NV_vertex_program) {
322
      GLuint i;
323
 
324
      if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) {
325
         _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)");
326
         return;
327
      }
328
 
329
      i = address / 4;
330
 
331
      switch (pname) {
332
         case GL_TRACK_MATRIX_NV:
333
            params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i];
334
            return;
335
         case GL_TRACK_MATRIX_TRANSFORM_NV:
336
            params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i];
337
            return;
338
         default:
339
            _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
340
            return;
341
      }
342
   }
343
   else {
344
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV");
345
      return;
346
   }
347
}
348
 
349
 
350
/**
351
 * Get a vertex (or vertex array) attribute.
352
 * \note Not compiled into display lists.
353
 * \note Called from the GL API dispatcher.
354
 */
355
void GLAPIENTRY
356
_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params)
357
{
358
   const struct gl_client_array *array;
359
   GET_CURRENT_CONTEXT(ctx);
360
   ASSERT_OUTSIDE_BEGIN_END(ctx);
361
 
362
   if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
363
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
364
      return;
365
   }
366
 
367
   array = &ctx->Array.ArrayObj->VertexAttrib[index];
368
 
369
   switch (pname) {
370
      case GL_ATTRIB_ARRAY_SIZE_NV:
371
         params[0] = array->Size;
372
         break;
373
      case GL_ATTRIB_ARRAY_STRIDE_NV:
374
         params[0] = array->Stride;
375
         break;
376
      case GL_ATTRIB_ARRAY_TYPE_NV:
377
         params[0] = array->Type;
378
         break;
379
      case GL_CURRENT_ATTRIB_NV:
380
         if (index == 0) {
381
            _mesa_error(ctx, GL_INVALID_OPERATION,
382
                        "glGetVertexAttribdvNV(index == 0)");
383
            return;
384
         }
385
	 FLUSH_CURRENT(ctx, 0);
386
         COPY_4V(params, ctx->Current.Attrib[index]);
387
         break;
388
      default:
389
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
390
         return;
391
   }
392
}
393
 
394
/**
395
 * Get a vertex (or vertex array) attribute.
396
 * \note Not compiled into display lists.
397
 * \note Called from the GL API dispatcher.
398
 */
399
void GLAPIENTRY
400
_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params)
401
{
402
   const struct gl_client_array *array;
403
   GET_CURRENT_CONTEXT(ctx);
404
   ASSERT_OUTSIDE_BEGIN_END(ctx);
405
 
406
   if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
407
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
408
      return;
409
   }
410
 
411
   array = &ctx->Array.ArrayObj->VertexAttrib[index];
412
 
413
   switch (pname) {
414
      case GL_ATTRIB_ARRAY_SIZE_NV:
415
         params[0] = (GLfloat) array->Size;
416
         break;
417
      case GL_ATTRIB_ARRAY_STRIDE_NV:
418
         params[0] = (GLfloat) array->Stride;
419
         break;
420
      case GL_ATTRIB_ARRAY_TYPE_NV:
421
         params[0] = (GLfloat) array->Type;
422
         break;
423
      case GL_CURRENT_ATTRIB_NV:
424
         if (index == 0) {
425
            _mesa_error(ctx, GL_INVALID_OPERATION,
426
                        "glGetVertexAttribfvNV(index == 0)");
427
            return;
428
         }
429
	 FLUSH_CURRENT(ctx, 0);
430
         COPY_4V(params, ctx->Current.Attrib[index]);
431
         break;
432
      default:
433
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
434
         return;
435
   }
436
}
437
 
438
/**
439
 * Get a vertex (or vertex array) attribute.
440
 * \note Not compiled into display lists.
441
 * \note Called from the GL API dispatcher.
442
 */
443
void GLAPIENTRY
444
_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params)
445
{
446
   const struct gl_client_array *array;
447
   GET_CURRENT_CONTEXT(ctx);
448
   ASSERT_OUTSIDE_BEGIN_END(ctx);
449
 
450
   if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
451
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)");
452
      return;
453
   }
454
 
455
   array = &ctx->Array.ArrayObj->VertexAttrib[index];
456
 
457
   switch (pname) {
458
      case GL_ATTRIB_ARRAY_SIZE_NV:
459
         params[0] = array->Size;
460
         break;
461
      case GL_ATTRIB_ARRAY_STRIDE_NV:
462
         params[0] = array->Stride;
463
         break;
464
      case GL_ATTRIB_ARRAY_TYPE_NV:
465
         params[0] = array->Type;
466
         break;
467
      case GL_CURRENT_ATTRIB_NV:
468
         if (index == 0) {
469
            _mesa_error(ctx, GL_INVALID_OPERATION,
470
                        "glGetVertexAttribivNV(index == 0)");
471
            return;
472
         }
473
	 FLUSH_CURRENT(ctx, 0);
474
         params[0] = (GLint) ctx->Current.Attrib[index][0];
475
         params[1] = (GLint) ctx->Current.Attrib[index][1];
476
         params[2] = (GLint) ctx->Current.Attrib[index][2];
477
         params[3] = (GLint) ctx->Current.Attrib[index][3];
478
         break;
479
      case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
480
         params[0] = array->BufferObj->Name;
481
         break;
482
      default:
483
         _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV");
484
         return;
485
   }
486
}
487
 
488
 
489
/**
490
 * Get a vertex array attribute pointer.
491
 * \note Not compiled into display lists.
492
 * \note Called from the GL API dispatcher.
493
 */
494
void GLAPIENTRY
495
_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer)
496
{
497
   GET_CURRENT_CONTEXT(ctx);
498
   ASSERT_OUTSIDE_BEGIN_END(ctx);
499
 
500
   if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
501
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)");
502
      return;
503
   }
504
 
505
   if (pname != GL_ATTRIB_ARRAY_POINTER_NV) {
506
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)");
507
      return;
508
   }
509
 
510
   *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
511
}
512
 
513
void
514
_mesa_emit_nv_temp_initialization(struct gl_context *ctx,
515
				  struct gl_program *program)
516
{
517
   struct prog_instruction *inst;
518
   GLuint i;
519
   struct gl_shader_compiler_options* options =
520
         &ctx->ShaderCompilerOptions[_mesa_program_target_to_index(program->Target)];
521
 
522
   if (!options->EmitNVTempInitialization)
523
      return;
524
 
525
   /* We'll swizzle up a zero temporary so we can use it for the
526
    * ARL.
527
    */
528
   if (program->NumTemporaries == 0)
529
      program->NumTemporaries = 1;
530
 
531
   _mesa_insert_instructions(program, 0, program->NumTemporaries + 1);
532
 
533
   for (i = 0; i < program->NumTemporaries; i++) {
534
      struct prog_instruction *inst = &program->Instructions[i];
535
 
536
      inst->Opcode = OPCODE_SWZ;
537
      inst->DstReg.File = PROGRAM_TEMPORARY;
538
      inst->DstReg.Index = i;
539
      inst->DstReg.WriteMask = WRITEMASK_XYZW;
540
      inst->SrcReg[0].File = PROGRAM_TEMPORARY;
541
      inst->SrcReg[0].Index = 0;
542
      inst->SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO,
543
					      SWIZZLE_ZERO,
544
					      SWIZZLE_ZERO,
545
					      SWIZZLE_ZERO);
546
   }
547
 
548
   inst = &program->Instructions[i];
549
   inst->Opcode = OPCODE_ARL;
550
   inst->DstReg.File = PROGRAM_ADDRESS;
551
   inst->DstReg.Index = 0;
552
   inst->DstReg.WriteMask = WRITEMASK_XYZW;
553
   inst->SrcReg[0].File = PROGRAM_TEMPORARY;
554
   inst->SrcReg[0].Index = 0;
555
   inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;
556
 
557
   if (program->NumAddressRegs == 0)
558
      program->NumAddressRegs = 1;
559
}
560
 
561
void
562
_mesa_setup_nv_temporary_count(struct gl_context *ctx, struct gl_program *program)
563
{
564
   GLuint i;
565
 
566
   program->NumTemporaries = 0;
567
   for (i = 0; i < program->NumInstructions; i++) {
568
      struct prog_instruction *inst = &program->Instructions[i];
569
 
570
      if (inst->DstReg.File == PROGRAM_TEMPORARY) {
571
	 program->NumTemporaries = MAX2(program->NumTemporaries,
572
					inst->DstReg.Index + 1);
573
      }
574
      if (inst->SrcReg[0].File == PROGRAM_TEMPORARY) {
575
	 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
576
					inst->SrcReg[0].Index + 1);
577
      }
578
      if (inst->SrcReg[1].File == PROGRAM_TEMPORARY) {
579
	 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
580
					inst->SrcReg[1].Index + 1);
581
      }
582
      if (inst->SrcReg[2].File == PROGRAM_TEMPORARY) {
583
	 program->NumTemporaries = MAX2((GLint)program->NumTemporaries,
584
					inst->SrcReg[2].Index + 1);
585
      }
586
   }
587
}
588
 
589
/**
590
 * Load/parse/compile a program.
591
 * \note Called from the GL API dispatcher.
592
 */
593
void GLAPIENTRY
594
_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len,
595
                    const GLubyte *program)
596
{
597
   struct gl_program *prog;
598
   GET_CURRENT_CONTEXT(ctx);
599
   ASSERT_OUTSIDE_BEGIN_END(ctx);
600
 
601
   if (!ctx->Extensions.NV_vertex_program
602
       && !ctx->Extensions.NV_fragment_program) {
603
      _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV()");
604
      return;
605
   }
606
 
607
   if (id == 0) {
608
      _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)");
609
      return;
610
   }
611
 
612
   if (len < 0) {
613
      _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)");
614
      return;
615
   }
616
 
617
   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
618
 
619
   prog = _mesa_lookup_program(ctx, id);
620
 
621
   if (prog && prog->Target != 0 && prog->Target != target) {
622
      _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)");
623
      return;
624
   }
625
 
626
   if ((target == GL_VERTEX_PROGRAM_NV ||
627
        target == GL_VERTEX_STATE_PROGRAM_NV)
628
       && ctx->Extensions.NV_vertex_program) {
629
      struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog;
630
      if (!vprog || prog == &_mesa_DummyProgram) {
631
         vprog = (struct gl_vertex_program *)
632
            ctx->Driver.NewProgram(ctx, target, id);
633
         if (!vprog) {
634
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
635
            return;
636
         }
637
         _mesa_HashInsert(ctx->Shared->Programs, id, vprog);
638
      }
639
 
640
      if (ctx->Extensions.ARB_vertex_program
641
	  && (strncmp((char *) program, "!!ARB", 5) == 0)) {
642
	 _mesa_parse_arb_vertex_program(ctx, target, program, len, vprog);
643
      } else {
644
	 _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog);
645
      }
646
   }
647
   else if (target == GL_FRAGMENT_PROGRAM_NV
648
            && ctx->Extensions.NV_fragment_program) {
649
      struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
650
      if (!fprog || prog == &_mesa_DummyProgram) {
651
         fprog = (struct gl_fragment_program *)
652
            ctx->Driver.NewProgram(ctx, target, id);
653
         if (!fprog) {
654
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
655
            return;
656
         }
657
         _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
658
      }
659
      _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog);
660
   }
661
   else if (target == GL_FRAGMENT_PROGRAM_ARB
662
            && ctx->Extensions.ARB_fragment_program) {
663
      struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog;
664
      if (!fprog || prog == &_mesa_DummyProgram) {
665
         fprog = (struct gl_fragment_program *)
666
            ctx->Driver.NewProgram(ctx, target, id);
667
         if (!fprog) {
668
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
669
            return;
670
         }
671
         _mesa_HashInsert(ctx->Shared->Programs, id, fprog);
672
      }
673
      _mesa_parse_arb_fragment_program(ctx, target, program, len, fprog);
674
   }
675
   else {
676
      _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)");
677
   }
678
}
679
 
680
 
681
 
682
/**
683
 * Set a sequence of program parameter registers.
684
 * \note Called from the GL API dispatcher.
685
 */
686
void GLAPIENTRY
687
_mesa_ProgramParameters4dvNV(GLenum target, GLuint index,
688
                             GLsizei num, const GLdouble *params)
689
{
690
   GET_CURRENT_CONTEXT(ctx);
691
   ASSERT_OUTSIDE_BEGIN_END(ctx);
692
 
693
   if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
694
      GLint i;
695
      if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
696
         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV");
697
         return;
698
      }
699
      for (i = 0; i < num; i++) {
700
         ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0];
701
         ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1];
702
         ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2];
703
         ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3];
704
         params += 4;
705
      };
706
   }
707
   else {
708
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV");
709
      return;
710
   }
711
}
712
 
713
 
714
/**
715
 * Set a sequence of program parameter registers.
716
 * \note Called from the GL API dispatcher.
717
 */
718
void GLAPIENTRY
719
_mesa_ProgramParameters4fvNV(GLenum target, GLuint index,
720
                             GLsizei num, const GLfloat *params)
721
{
722
   GET_CURRENT_CONTEXT(ctx);
723
   ASSERT_OUTSIDE_BEGIN_END(ctx);
724
 
725
   if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
726
      GLint i;
727
      if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) {
728
         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV");
729
         return;
730
      }
731
      for (i = 0; i < num; i++) {
732
         COPY_4V(ctx->VertexProgram.Parameters[index + i], params);
733
         params += 4;
734
      }
735
   }
736
   else {
737
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV");
738
      return;
739
   }
740
}
741
 
742
 
743
 
744
/**
745
 * Setup tracking of matrices into program parameter registers.
746
 * \note Called from the GL API dispatcher.
747
 */
748
void GLAPIENTRY
749
_mesa_TrackMatrixNV(GLenum target, GLuint address,
750
                    GLenum matrix, GLenum transform)
751
{
752
   GET_CURRENT_CONTEXT(ctx);
753
   ASSERT_OUTSIDE_BEGIN_END(ctx);
754
 
755
   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
756
 
757
   if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) {
758
      if (address & 0x3) {
759
         /* addr must be multiple of four */
760
         _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)");
761
         return;
762
      }
763
 
764
      switch (matrix) {
765
         case GL_NONE:
766
         case GL_MODELVIEW:
767
         case GL_PROJECTION:
768
         case GL_TEXTURE:
769
         case GL_COLOR:
770
         case GL_MODELVIEW_PROJECTION_NV:
771
         case GL_MATRIX0_NV:
772
         case GL_MATRIX1_NV:
773
         case GL_MATRIX2_NV:
774
         case GL_MATRIX3_NV:
775
         case GL_MATRIX4_NV:
776
         case GL_MATRIX5_NV:
777
         case GL_MATRIX6_NV:
778
         case GL_MATRIX7_NV:
779
            /* OK, fallthrough */
780
            break;
781
         default:
782
            _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)");
783
            return;
784
      }
785
 
786
      switch (transform) {
787
         case GL_IDENTITY_NV:
788
         case GL_INVERSE_NV:
789
         case GL_TRANSPOSE_NV:
790
         case GL_INVERSE_TRANSPOSE_NV:
791
            /* OK, fallthrough */
792
            break;
793
         default:
794
            _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)");
795
            return;
796
      }
797
 
798
      ctx->VertexProgram.TrackMatrix[address / 4] = matrix;
799
      ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform;
800
   }
801
   else {
802
      _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)");
803
      return;
804
   }
805
}
806
 
807
 
808
void GLAPIENTRY
809
_mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
810
                                GLfloat x, GLfloat y, GLfloat z, GLfloat w)
811
{
812
   struct gl_program *prog;
813
   struct gl_fragment_program *fragProg;
814
   GLfloat *v;
815
 
816
   GET_CURRENT_CONTEXT(ctx);
817
   ASSERT_OUTSIDE_BEGIN_END(ctx);
818
 
819
   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
820
 
821
   prog = _mesa_lookup_program(ctx, id);
822
   if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
823
      _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV");
824
      return;
825
   }
826
 
827
   if (len <= 0) {
828
      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)");
829
      return;
830
   }
831
 
832
   fragProg = (struct gl_fragment_program *) prog;
833
   v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len,
834
                                    (char *) name);
835
   if (v) {
836
      v[0] = x;
837
      v[1] = y;
838
      v[2] = z;
839
      v[3] = w;
840
      return;
841
   }
842
 
843
   _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)");
844
}
845
 
846
 
847
void GLAPIENTRY
848
_mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name,
849
                                 const float v[])
850
{
851
   _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]);
852
}
853
 
854
 
855
void GLAPIENTRY
856
_mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name,
857
                                GLdouble x, GLdouble y, GLdouble z, GLdouble w)
858
{
859
   _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y,
860
                                   (GLfloat)z, (GLfloat)w);
861
}
862
 
863
 
864
void GLAPIENTRY
865
_mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name,
866
                                 const double v[])
867
{
868
   _mesa_ProgramNamedParameter4fNV(id, len, name,
869
                                   (GLfloat)v[0], (GLfloat)v[1],
870
                                   (GLfloat)v[2], (GLfloat)v[3]);
871
}
872
 
873
 
874
void GLAPIENTRY
875
_mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
876
                                   GLfloat *params)
877
{
878
   struct gl_program *prog;
879
   struct gl_fragment_program *fragProg;
880
   const GLfloat *v;
881
 
882
   GET_CURRENT_CONTEXT(ctx);
883
 
884
   ASSERT_OUTSIDE_BEGIN_END(ctx);
885
 
886
   prog = _mesa_lookup_program(ctx, id);
887
   if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) {
888
      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV");
889
      return;
890
   }
891
 
892
   if (len <= 0) {
893
      _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
894
      return;
895
   }
896
 
897
   fragProg = (struct gl_fragment_program *) prog;
898
   v = _mesa_lookup_parameter_value(fragProg->Base.Parameters,
899
                                    len, (char *) name);
900
   if (v) {
901
      params[0] = v[0];
902
      params[1] = v[1];
903
      params[2] = v[2];
904
      params[3] = v[3];
905
      return;
906
   }
907
 
908
   _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
909
}
910
 
911
 
912
void GLAPIENTRY
913
_mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name,
914
                                   GLdouble *params)
915
{
916
   GLfloat floatParams[4];
917
   _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams);
918
   COPY_4V(params, floatParams);
919
}