Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
5564 serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included
14
 * in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 * 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 "main/glheader.h"
33
#include "main/context.h"
34
#include "main/hash.h"
35
#include "main/imports.h"
36
#include "main/macros.h"
37
#include "main/mtypes.h"
38
#include "main/arbprogram.h"
39
#include "program/arbprogparse.h"
40
#include "program/program.h"
41
#include "program/prog_print.h"
42
 
43
 
44
/**
45
 * Bind a program (make it current)
46
 * \note Called from the GL API dispatcher by both glBindProgramNV
47
 * and glBindProgramARB.
48
 */
49
void GLAPIENTRY
50
_mesa_BindProgramARB(GLenum target, GLuint id)
51
{
52
   struct gl_program *curProg, *newProg;
53
   GET_CURRENT_CONTEXT(ctx);
54
 
55
   /* Error-check target and get curProg */
56
   if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
57
      curProg = &ctx->VertexProgram.Current->Base;
58
   }
59
   else if (target == GL_FRAGMENT_PROGRAM_ARB
60
            && ctx->Extensions.ARB_fragment_program) {
61
      curProg = &ctx->FragmentProgram.Current->Base;
62
   }
63
   else {
64
      _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramARB(target)");
65
      return;
66
   }
67
 
68
   /*
69
    * Get pointer to new program to bind.
70
    * NOTE: binding to a non-existant program is not an error.
71
    * That's supposed to be caught in glBegin.
72
    */
73
   if (id == 0) {
74
      /* Bind a default program */
75
      newProg = NULL;
76
      if (target == GL_VERTEX_PROGRAM_ARB)
77
         newProg = &ctx->Shared->DefaultVertexProgram->Base;
78
      else
79
         newProg = &ctx->Shared->DefaultFragmentProgram->Base;
80
   }
81
   else {
82
      /* Bind a user program */
83
      newProg = _mesa_lookup_program(ctx, id);
84
      if (!newProg || newProg == &_mesa_DummyProgram) {
85
         /* allocate a new program now */
86
         newProg = ctx->Driver.NewProgram(ctx, target, id);
87
         if (!newProg) {
88
            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramARB");
89
            return;
90
         }
91
         _mesa_HashInsert(ctx->Shared->Programs, id, newProg);
92
      }
93
      else if (newProg->Target != target) {
94
         _mesa_error(ctx, GL_INVALID_OPERATION,
95
                     "glBindProgramARB(target mismatch)");
96
         return;
97
      }
98
   }
99
 
100
   /** All error checking is complete now **/
101
 
102
   if (curProg->Id == id) {
103
      /* binding same program - no change */
104
      return;
105
   }
106
 
107
   /* signal new program (and its new constants) */
108
   FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
109
 
110
   /* bind newProg */
111
   if (target == GL_VERTEX_PROGRAM_ARB) {
112
      _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current,
113
                               gl_vertex_program(newProg));
114
   }
115
   else if (target == GL_FRAGMENT_PROGRAM_ARB) {
116
      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current,
117
                               gl_fragment_program(newProg));
118
   }
119
 
120
   /* Never null pointers */
121
   assert(ctx->VertexProgram.Current);
122
   assert(ctx->FragmentProgram.Current);
123
 
124
   if (ctx->Driver.BindProgram)
125
      ctx->Driver.BindProgram(ctx, target, newProg);
126
}
127
 
128
 
129
/**
130
 * Delete a list of programs.
131
 * \note Not compiled into display lists.
132
 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB.
133
 */
134
void GLAPIENTRY
135
_mesa_DeleteProgramsARB(GLsizei n, const GLuint *ids)
136
{
137
   GLint i;
138
   GET_CURRENT_CONTEXT(ctx);
139
 
140
   FLUSH_VERTICES(ctx, 0);
141
 
142
   if (n < 0) {
143
      _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" );
144
      return;
145
   }
146
 
147
   for (i = 0; i < n; i++) {
148
      if (ids[i] != 0) {
149
         struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]);
150
         if (prog == &_mesa_DummyProgram) {
151
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
152
         }
153
         else if (prog) {
154
            /* Unbind program if necessary */
155
            switch (prog->Target) {
156
            case GL_VERTEX_PROGRAM_ARB:
157
               if (ctx->VertexProgram.Current &&
158
                   ctx->VertexProgram.Current->Base.Id == ids[i]) {
159
                  /* unbind this currently bound program */
160
                  _mesa_BindProgramARB(prog->Target, 0);
161
               }
162
               break;
163
            case GL_FRAGMENT_PROGRAM_ARB:
164
               if (ctx->FragmentProgram.Current &&
165
                   ctx->FragmentProgram.Current->Base.Id == ids[i]) {
166
                  /* unbind this currently bound program */
167
                  _mesa_BindProgramARB(prog->Target, 0);
168
               }
169
               break;
170
            default:
171
               _mesa_problem(ctx, "bad target in glDeleteProgramsNV");
172
               return;
173
            }
174
            /* The ID is immediately available for re-use now */
175
            _mesa_HashRemove(ctx->Shared->Programs, ids[i]);
176
            _mesa_reference_program(ctx, &prog, NULL);
177
         }
178
      }
179
   }
180
}
181
 
182
 
183
/**
184
 * Generate a list of new program identifiers.
185
 * \note Not compiled into display lists.
186
 * \note Called by both glGenProgramsNV and glGenProgramsARB.
187
 */
188
void GLAPIENTRY
189
_mesa_GenProgramsARB(GLsizei n, GLuint *ids)
190
{
191
   GLuint first;
192
   GLuint i;
193
   GET_CURRENT_CONTEXT(ctx);
194
 
195
   if (n < 0) {
196
      _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms");
197
      return;
198
   }
199
 
200
   if (!ids)
201
      return;
202
 
203
   first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n);
204
 
205
   /* Insert pointer to dummy program as placeholder */
206
   for (i = 0; i < (GLuint) n; i++) {
207
      _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram);
208
   }
209
 
210
   /* Return the program names */
211
   for (i = 0; i < (GLuint) n; i++) {
212
      ids[i] = first + i;
213
   }
214
}
215
 
216
 
217
/**
218
 * Determine if id names a vertex or fragment program.
219
 * \note Not compiled into display lists.
220
 * \note Called from both glIsProgramNV and glIsProgramARB.
221
 * \param id is the program identifier
222
 * \return GL_TRUE if id is a program, else GL_FALSE.
223
 */
224
GLboolean GLAPIENTRY
225
_mesa_IsProgramARB(GLuint id)
226
{
227
   struct gl_program *prog = NULL;
228
   GET_CURRENT_CONTEXT(ctx);
229
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
230
 
231
   if (id == 0)
232
      return GL_FALSE;
233
 
234
   prog = _mesa_lookup_program(ctx, id);
235
   if (prog && (prog != &_mesa_DummyProgram))
236
      return GL_TRUE;
237
   else
238
      return GL_FALSE;
239
}
240
 
241
static GLboolean
242
get_local_param_pointer(struct gl_context *ctx, const char *func,
243
			GLenum target, GLuint index, GLfloat **param)
244
{
245
   struct gl_program *prog;
246
   GLuint maxParams;
247
 
248
   if (target == GL_VERTEX_PROGRAM_ARB
249
       && ctx->Extensions.ARB_vertex_program) {
250
      prog = &(ctx->VertexProgram.Current->Base);
251
      maxParams = ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams;
252
   }
253
   else if (target == GL_FRAGMENT_PROGRAM_ARB
254
            && ctx->Extensions.ARB_fragment_program) {
255
      prog = &(ctx->FragmentProgram.Current->Base);
256
      maxParams = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams;
257
   }
258
   else {
259
      _mesa_error(ctx, GL_INVALID_ENUM,
260
                  "%s(target)", func);
261
      return GL_FALSE;
262
   }
263
 
264
   if (index >= maxParams) {
265
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
266
      return GL_FALSE;
267
   }
268
 
269
   if (!prog->LocalParams) {
270
      prog->LocalParams = calloc(maxParams, sizeof(float[4]));
271
      if (!prog->LocalParams)
272
         return GL_FALSE;
273
   }
274
 
275
   *param = prog->LocalParams[index];
276
   return GL_TRUE;
277
}
278
 
279
 
280
static GLboolean
281
get_env_param_pointer(struct gl_context *ctx, const char *func,
282
		      GLenum target, GLuint index, GLfloat **param)
283
{
284
   if (target == GL_FRAGMENT_PROGRAM_ARB
285
       && ctx->Extensions.ARB_fragment_program) {
286
      if (index >= ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) {
287
         _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
288
         return GL_FALSE;
289
      }
290
      *param = ctx->FragmentProgram.Parameters[index];
291
      return GL_TRUE;
292
   }
293
   else if (target == GL_VERTEX_PROGRAM_ARB &&
294
            ctx->Extensions.ARB_vertex_program) {
295
      if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) {
296
         _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func);
297
         return GL_FALSE;
298
      }
299
      *param = ctx->VertexProgram.Parameters[index];
300
      return GL_TRUE;
301
   } else {
302
      _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
303
      return GL_FALSE;
304
   }
305
}
306
 
307
void GLAPIENTRY
308
_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
309
                       const GLvoid *string)
310
{
311
   struct gl_program *base;
312
   bool failed;
313
   GET_CURRENT_CONTEXT(ctx);
314
 
315
   FLUSH_VERTICES(ctx, _NEW_PROGRAM);
316
 
317
   if (!ctx->Extensions.ARB_vertex_program
318
       && !ctx->Extensions.ARB_fragment_program) {
319
      _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()");
320
      return;
321
   }
322
 
323
   if (format != GL_PROGRAM_FORMAT_ASCII_ARB) {
324
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)");
325
      return;
326
   }
327
 
328
   if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) {
329
      struct gl_vertex_program *prog = ctx->VertexProgram.Current;
330
      _mesa_parse_arb_vertex_program(ctx, target, string, len, prog);
331
 
332
      base = & prog->Base;
333
   }
334
   else if (target == GL_FRAGMENT_PROGRAM_ARB
335
            && ctx->Extensions.ARB_fragment_program) {
336
      struct gl_fragment_program *prog = ctx->FragmentProgram.Current;
337
      _mesa_parse_arb_fragment_program(ctx, target, string, len, prog);
338
 
339
      base = & prog->Base;
340
   }
341
   else {
342
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)");
343
      return;
344
   }
345
 
346
   failed = ctx->Program.ErrorPos != -1;
347
 
348
   if (!failed) {
349
      /* finally, give the program to the driver for translation/checking */
350
      if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) {
351
         failed = true;
352
         _mesa_error(ctx, GL_INVALID_OPERATION,
353
                     "glProgramStringARB(rejected by driver");
354
      }
355
   }
356
 
357
   if (ctx->_Shader->Flags & GLSL_DUMP) {
358
      const char *shader_type =
359
         target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex";
360
 
361
      fprintf(stderr, "ARB_%s_program source for program %d:\n",
362
              shader_type, base->Id);
363
      fprintf(stderr, "%s\n", (const char *) string);
364
 
365
      if (failed) {
366
         fprintf(stderr, "ARB_%s_program %d failed to compile.\n",
367
                 shader_type, base->Id);
368
      } else {
369
         fprintf(stderr, "Mesa IR for ARB_%s_program %d:\n",
370
                 shader_type, base->Id);
371
         _mesa_print_program(base);
372
         fprintf(stderr, "\n");
373
      }
374
      fflush(stderr);
375
   }
376
}
377
 
378
 
379
/**
380
 * Set a program env parameter register.
381
 * \note Called from the GL API dispatcher.
382
 */
383
void GLAPIENTRY
384
_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index,
385
                               GLdouble x, GLdouble y, GLdouble z, GLdouble w)
386
{
387
   _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
388
		                  (GLfloat) z, (GLfloat) w);
389
}
390
 
391
 
392
/**
393
 * Set a program env parameter register.
394
 * \note Called from the GL API dispatcher.
395
 */
396
void GLAPIENTRY
397
_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
398
                                const GLdouble *params)
399
{
400
   _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0],
401
	                          (GLfloat) params[1], (GLfloat) params[2],
402
				  (GLfloat) params[3]);
403
}
404
 
405
 
406
/**
407
 * Set a program env parameter register.
408
 * \note Called from the GL API dispatcher.
409
 */
410
void GLAPIENTRY
411
_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index,
412
                               GLfloat x, GLfloat y, GLfloat z, GLfloat w)
413
{
414
   GLfloat *param;
415
 
416
   GET_CURRENT_CONTEXT(ctx);
417
 
418
   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
419
 
420
   if (get_env_param_pointer(ctx, "glProgramEnvParameter",
421
			     target, index, ¶m)) {
422
      ASSIGN_4V(param, x, y, z, w);
423
   }
424
}
425
 
426
 
427
 
428
/**
429
 * Set a program env parameter register.
430
 * \note Called from the GL API dispatcher.
431
 */
432
void GLAPIENTRY
433
_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
434
                                const GLfloat *params)
435
{
436
   GLfloat *param;
437
 
438
   GET_CURRENT_CONTEXT(ctx);
439
 
440
   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
441
 
442
   if (get_env_param_pointer(ctx, "glProgramEnvParameter4fv",
443
			      target, index, ¶m)) {
444
      memcpy(param, params, 4 * sizeof(GLfloat));
445
   }
446
}
447
 
448
 
449
void GLAPIENTRY
450
_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
451
				 const GLfloat *params)
452
{
453
   GET_CURRENT_CONTEXT(ctx);
454
   GLfloat * dest;
455
 
456
   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
457
 
458
   if (count <= 0) {
459
      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)");
460
   }
461
 
462
   if (target == GL_FRAGMENT_PROGRAM_ARB
463
       && ctx->Extensions.ARB_fragment_program) {
464
      if ((index + count) > ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) {
465
         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
466
         return;
467
      }
468
      dest = ctx->FragmentProgram.Parameters[index];
469
   }
470
   else if (target == GL_VERTEX_PROGRAM_ARB
471
       && ctx->Extensions.ARB_vertex_program) {
472
      if ((index + count) > ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) {
473
         _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)");
474
         return;
475
      }
476
      dest = ctx->VertexProgram.Parameters[index];
477
   }
478
   else {
479
      _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)");
480
      return;
481
   }
482
 
483
   memcpy(dest, params, count * 4 * sizeof(GLfloat));
484
}
485
 
486
 
487
void GLAPIENTRY
488
_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index,
489
                                  GLdouble *params)
490
{
491
   GET_CURRENT_CONTEXT(ctx);
492
   GLfloat *fparam;
493
 
494
   if (get_env_param_pointer(ctx, "glGetProgramEnvParameterdv",
495
			     target, index, &fparam)) {
496
      COPY_4V(params, fparam);
497
   }
498
}
499
 
500
 
501
void GLAPIENTRY
502
_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index,
503
                                  GLfloat *params)
504
{
505
   GLfloat *param;
506
 
507
   GET_CURRENT_CONTEXT(ctx);
508
 
509
   if (get_env_param_pointer(ctx, "glGetProgramEnvParameterfv",
510
			      target, index, ¶m)) {
511
      COPY_4V(params, param);
512
   }
513
}
514
 
515
 
516
void GLAPIENTRY
517
_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index,
518
                                 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
519
{
520
   GET_CURRENT_CONTEXT(ctx);
521
   GLfloat *param;
522
 
523
   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
524
 
525
   if (get_local_param_pointer(ctx, "glProgramLocalParameterARB",
526
			       target, index, ¶m)) {
527
      assert(index < MAX_PROGRAM_LOCAL_PARAMS);
528
      ASSIGN_4V(param, x, y, z, w);
529
   }
530
}
531
 
532
 
533
void GLAPIENTRY
534
_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
535
                                  const GLfloat *params)
536
{
537
   _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1],
538
                                    params[2], params[3]);
539
}
540
 
541
 
542
void GLAPIENTRY
543
_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
544
				   const GLfloat *params)
545
{
546
   GET_CURRENT_CONTEXT(ctx);
547
   GLfloat *dest;
548
 
549
   FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
550
 
551
   if (count <= 0) {
552
      _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)");
553
   }
554
 
555
   if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
556
                               target, index, &dest)) {
557
      GLuint maxParams = target == GL_FRAGMENT_PROGRAM_ARB ?
558
         ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams :
559
         ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams;
560
 
561
      if ((index + count) > maxParams) {
562
         _mesa_error(ctx, GL_INVALID_VALUE,
563
                     "glProgramLocalParameters4fvEXT(index + count)");
564
         return;
565
      }
566
 
567
      memcpy(dest, params, count * 4 * sizeof(GLfloat));
568
   }
569
}
570
 
571
 
572
void GLAPIENTRY
573
_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index,
574
                                 GLdouble x, GLdouble y,
575
                                 GLdouble z, GLdouble w)
576
{
577
   _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y,
578
                                    (GLfloat) z, (GLfloat) w);
579
}
580
 
581
 
582
void GLAPIENTRY
583
_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
584
                                  const GLdouble *params)
585
{
586
   _mesa_ProgramLocalParameter4fARB(target, index,
587
                                    (GLfloat) params[0], (GLfloat) params[1],
588
                                    (GLfloat) params[2], (GLfloat) params[3]);
589
}
590
 
591
 
592
void GLAPIENTRY
593
_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index,
594
                                    GLfloat *params)
595
{
596
   GLfloat *param;
597
   GET_CURRENT_CONTEXT(ctx);
598
 
599
   if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
600
				target, index, ¶m)) {
601
      COPY_4V(params, param);
602
   }
603
}
604
 
605
 
606
void GLAPIENTRY
607
_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index,
608
                                    GLdouble *params)
609
{
610
   GLfloat *param;
611
   GET_CURRENT_CONTEXT(ctx);
612
 
613
   if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT",
614
				target, index, ¶m)) {
615
      COPY_4V(params, param);
616
   }
617
}
618
 
619
 
620
void GLAPIENTRY
621
_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params)
622
{
623
   const struct gl_program_constants *limits;
624
   struct gl_program *prog;
625
   GET_CURRENT_CONTEXT(ctx);
626
 
627
   if (target == GL_VERTEX_PROGRAM_ARB
628
       && ctx->Extensions.ARB_vertex_program) {
629
      prog = &(ctx->VertexProgram.Current->Base);
630
      limits = &ctx->Const.Program[MESA_SHADER_VERTEX];
631
   }
632
   else if (target == GL_FRAGMENT_PROGRAM_ARB
633
            && ctx->Extensions.ARB_fragment_program) {
634
      prog = &(ctx->FragmentProgram.Current->Base);
635
      limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT];
636
   }
637
   else {
638
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)");
639
      return;
640
   }
641
 
642
   assert(prog);
643
   assert(limits);
644
 
645
   /* Queries supported for both vertex and fragment programs */
646
   switch (pname) {
647
      case GL_PROGRAM_LENGTH_ARB:
648
         *params
649
            = prog->String ? (GLint) strlen((char *) prog->String) : 0;
650
         return;
651
      case GL_PROGRAM_FORMAT_ARB:
652
         *params = prog->Format;
653
         return;
654
      case GL_PROGRAM_BINDING_ARB:
655
         *params = prog->Id;
656
         return;
657
      case GL_PROGRAM_INSTRUCTIONS_ARB:
658
         *params = prog->NumInstructions;
659
         return;
660
      case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
661
         *params = limits->MaxInstructions;
662
         return;
663
      case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
664
         *params = prog->NumNativeInstructions;
665
         return;
666
      case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
667
         *params = limits->MaxNativeInstructions;
668
         return;
669
      case GL_PROGRAM_TEMPORARIES_ARB:
670
         *params = prog->NumTemporaries;
671
         return;
672
      case GL_MAX_PROGRAM_TEMPORARIES_ARB:
673
         *params = limits->MaxTemps;
674
         return;
675
      case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
676
         *params = prog->NumNativeTemporaries;
677
         return;
678
      case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
679
         *params = limits->MaxNativeTemps;
680
         return;
681
      case GL_PROGRAM_PARAMETERS_ARB:
682
         *params = prog->NumParameters;
683
         return;
684
      case GL_MAX_PROGRAM_PARAMETERS_ARB:
685
         *params = limits->MaxParameters;
686
         return;
687
      case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
688
         *params = prog->NumNativeParameters;
689
         return;
690
      case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
691
         *params = limits->MaxNativeParameters;
692
         return;
693
      case GL_PROGRAM_ATTRIBS_ARB:
694
         *params = prog->NumAttributes;
695
         return;
696
      case GL_MAX_PROGRAM_ATTRIBS_ARB:
697
         *params = limits->MaxAttribs;
698
         return;
699
      case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
700
         *params = prog->NumNativeAttributes;
701
         return;
702
      case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
703
         *params = limits->MaxNativeAttribs;
704
         return;
705
      case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
706
         *params = prog->NumAddressRegs;
707
         return;
708
      case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
709
         *params = limits->MaxAddressRegs;
710
         return;
711
      case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
712
         *params = prog->NumNativeAddressRegs;
713
         return;
714
      case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
715
         *params = limits->MaxNativeAddressRegs;
716
         return;
717
      case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
718
         *params = limits->MaxLocalParams;
719
         return;
720
      case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
721
         *params = limits->MaxEnvParams;
722
         return;
723
      case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
724
         /*
725
          * XXX we may not really need a driver callback here.
726
          * If the number of native instructions, registers, etc. used
727
          * are all below the maximums, we could return true.
728
          * The spec says that even if this query returns true, there's
729
          * no guarantee that the program will run in hardware.
730
          */
731
         if (prog->Id == 0) {
732
            /* default/null program */
733
            *params = GL_FALSE;
734
         }
735
	 else if (ctx->Driver.IsProgramNative) {
736
            /* ask the driver */
737
	    *params = ctx->Driver.IsProgramNative( ctx, target, prog );
738
         }
739
	 else {
740
            /* probably running in software */
741
	    *params = GL_TRUE;
742
         }
743
         return;
744
      default:
745
         /* continue with fragment-program only queries below */
746
         break;
747
   }
748
 
749
   /*
750
    * The following apply to fragment programs only (at this time)
751
    */
752
   if (target == GL_FRAGMENT_PROGRAM_ARB) {
753
      const struct gl_fragment_program *fp = ctx->FragmentProgram.Current;
754
      switch (pname) {
755
         case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
756
            *params = fp->Base.NumNativeAluInstructions;
757
            return;
758
         case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
759
            *params = fp->Base.NumAluInstructions;
760
            return;
761
         case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
762
            *params = fp->Base.NumTexInstructions;
763
            return;
764
         case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
765
            *params = fp->Base.NumNativeTexInstructions;
766
            return;
767
         case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
768
            *params = fp->Base.NumTexIndirections;
769
            return;
770
         case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
771
            *params = fp->Base.NumNativeTexIndirections;
772
            return;
773
         case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
774
            *params = limits->MaxAluInstructions;
775
            return;
776
         case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
777
            *params = limits->MaxNativeAluInstructions;
778
            return;
779
         case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
780
            *params = limits->MaxTexInstructions;
781
            return;
782
         case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
783
            *params = limits->MaxNativeTexInstructions;
784
            return;
785
         case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
786
            *params = limits->MaxTexIndirections;
787
            return;
788
         case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
789
            *params = limits->MaxNativeTexIndirections;
790
            return;
791
         default:
792
            _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
793
            return;
794
      }
795
   } else {
796
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)");
797
      return;
798
   }
799
}
800
 
801
 
802
void GLAPIENTRY
803
_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string)
804
{
805
   const struct gl_program *prog;
806
   char *dst = (char *) string;
807
   GET_CURRENT_CONTEXT(ctx);
808
 
809
   if (target == GL_VERTEX_PROGRAM_ARB) {
810
      prog = &(ctx->VertexProgram.Current->Base);
811
   }
812
   else if (target == GL_FRAGMENT_PROGRAM_ARB) {
813
      prog = &(ctx->FragmentProgram.Current->Base);
814
   }
815
   else {
816
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)");
817
      return;
818
   }
819
 
820
   assert(prog);
821
 
822
   if (pname != GL_PROGRAM_STRING_ARB) {
823
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)");
824
      return;
825
   }
826
 
827
   if (prog->String)
828
      memcpy(dst, prog->String, strlen((char *) prog->String));
829
   else
830
      *dst = '\0';
831
}