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:  7.1
4
 *
5
 * Copyright (C) 1999-2007  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 prog_statevars.c
27
 * Program state variable management.
28
 * \author Brian Paul
29
 */
30
 
31
 
32
#include "main/glheader.h"
33
#include "main/context.h"
34
#include "main/imports.h"
35
#include "main/macros.h"
36
#include "main/mtypes.h"
37
#include "prog_statevars.h"
38
#include "prog_parameter.h"
39
 
40
 
41
/**
42
 * Use the list of tokens in the state[] array to find global GL state
43
 * and return it in .  Usually, four values are returned in 
44
 * but matrix queries may return as many as 16 values.
45
 * This function is used for ARB vertex/fragment programs.
46
 * The program parser will produce the state[] values.
47
 */
48
static void
49
_mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
50
                  GLfloat *value)
51
{
52
   switch (state[0]) {
53
   case STATE_MATERIAL:
54
      {
55
         /* state[1] is either 0=front or 1=back side */
56
         const GLuint face = (GLuint) state[1];
57
         const struct gl_material *mat = &ctx->Light.Material;
58
         ASSERT(face == 0 || face == 1);
59
         /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */
60
         ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT);
61
         /* XXX we could get rid of this switch entirely with a little
62
          * work in arbprogparse.c's parse_state_single_item().
63
          */
64
         /* state[2] is the material attribute */
65
         switch (state[2]) {
66
         case STATE_AMBIENT:
67
            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]);
68
            return;
69
         case STATE_DIFFUSE:
70
            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]);
71
            return;
72
         case STATE_SPECULAR:
73
            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]);
74
            return;
75
         case STATE_EMISSION:
76
            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]);
77
            return;
78
         case STATE_SHININESS:
79
            value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0];
80
            value[1] = 0.0F;
81
            value[2] = 0.0F;
82
            value[3] = 1.0F;
83
            return;
84
         default:
85
            _mesa_problem(ctx, "Invalid material state in fetch_state");
86
            return;
87
         }
88
      }
89
   case STATE_LIGHT:
90
      {
91
         /* state[1] is the light number */
92
         const GLuint ln = (GLuint) state[1];
93
         /* state[2] is the light attribute */
94
         switch (state[2]) {
95
         case STATE_AMBIENT:
96
            COPY_4V(value, ctx->Light.Light[ln].Ambient);
97
            return;
98
         case STATE_DIFFUSE:
99
            COPY_4V(value, ctx->Light.Light[ln].Diffuse);
100
            return;
101
         case STATE_SPECULAR:
102
            COPY_4V(value, ctx->Light.Light[ln].Specular);
103
            return;
104
         case STATE_POSITION:
105
            COPY_4V(value, ctx->Light.Light[ln].EyePosition);
106
            return;
107
         case STATE_ATTENUATION:
108
            value[0] = ctx->Light.Light[ln].ConstantAttenuation;
109
            value[1] = ctx->Light.Light[ln].LinearAttenuation;
110
            value[2] = ctx->Light.Light[ln].QuadraticAttenuation;
111
            value[3] = ctx->Light.Light[ln].SpotExponent;
112
            return;
113
         case STATE_SPOT_DIRECTION:
114
            COPY_3V(value, ctx->Light.Light[ln].SpotDirection);
115
            value[3] = ctx->Light.Light[ln]._CosCutoff;
116
            return;
117
         case STATE_SPOT_CUTOFF:
118
            value[0] = ctx->Light.Light[ln].SpotCutoff;
119
            return;
120
         case STATE_HALF_VECTOR:
121
            {
122
               static const GLfloat eye_z[] = {0, 0, 1};
123
               GLfloat p[3];
124
               /* Compute infinite half angle vector:
125
                *   halfVector = normalize(normalize(lightPos) + (0, 0, 1))
126
		* light.EyePosition.w should be 0 for infinite lights.
127
                */
128
               COPY_3V(p, ctx->Light.Light[ln].EyePosition);
129
               NORMALIZE_3FV(p);
130
	       ADD_3V(value, p, eye_z);
131
	       NORMALIZE_3FV(value);
132
	       value[3] = 1.0;
133
            }
134
            return;
135
         default:
136
            _mesa_problem(ctx, "Invalid light state in fetch_state");
137
            return;
138
         }
139
      }
140
   case STATE_LIGHTMODEL_AMBIENT:
141
      COPY_4V(value, ctx->Light.Model.Ambient);
142
      return;
143
   case STATE_LIGHTMODEL_SCENECOLOR:
144
      if (state[1] == 0) {
145
         /* front */
146
         GLint i;
147
         for (i = 0; i < 3; i++) {
148
            value[i] = ctx->Light.Model.Ambient[i]
149
               * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i]
150
               + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i];
151
         }
152
	 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
153
      }
154
      else {
155
         /* back */
156
         GLint i;
157
         for (i = 0; i < 3; i++) {
158
            value[i] = ctx->Light.Model.Ambient[i]
159
               * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i]
160
               + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i];
161
         }
162
	 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
163
      }
164
      return;
165
   case STATE_LIGHTPROD:
166
      {
167
         const GLuint ln = (GLuint) state[1];
168
         const GLuint face = (GLuint) state[2];
169
         GLint i;
170
         ASSERT(face == 0 || face == 1);
171
         switch (state[3]) {
172
            case STATE_AMBIENT:
173
               for (i = 0; i < 3; i++) {
174
                  value[i] = ctx->Light.Light[ln].Ambient[i] *
175
                     ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i];
176
               }
177
               /* [3] = material alpha */
178
               value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3];
179
               return;
180
            case STATE_DIFFUSE:
181
               for (i = 0; i < 3; i++) {
182
                  value[i] = ctx->Light.Light[ln].Diffuse[i] *
183
                     ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i];
184
               }
185
               /* [3] = material alpha */
186
               value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
187
               return;
188
            case STATE_SPECULAR:
189
               for (i = 0; i < 3; i++) {
190
                  value[i] = ctx->Light.Light[ln].Specular[i] *
191
                     ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i];
192
               }
193
               /* [3] = material alpha */
194
               value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3];
195
               return;
196
            default:
197
               _mesa_problem(ctx, "Invalid lightprod state in fetch_state");
198
               return;
199
         }
200
      }
201
   case STATE_TEXGEN:
202
      {
203
         /* state[1] is the texture unit */
204
         const GLuint unit = (GLuint) state[1];
205
         /* state[2] is the texgen attribute */
206
         switch (state[2]) {
207
         case STATE_TEXGEN_EYE_S:
208
            COPY_4V(value, ctx->Texture.Unit[unit].GenS.EyePlane);
209
            return;
210
         case STATE_TEXGEN_EYE_T:
211
            COPY_4V(value, ctx->Texture.Unit[unit].GenT.EyePlane);
212
            return;
213
         case STATE_TEXGEN_EYE_R:
214
            COPY_4V(value, ctx->Texture.Unit[unit].GenR.EyePlane);
215
            return;
216
         case STATE_TEXGEN_EYE_Q:
217
            COPY_4V(value, ctx->Texture.Unit[unit].GenQ.EyePlane);
218
            return;
219
         case STATE_TEXGEN_OBJECT_S:
220
            COPY_4V(value, ctx->Texture.Unit[unit].GenS.ObjectPlane);
221
            return;
222
         case STATE_TEXGEN_OBJECT_T:
223
            COPY_4V(value, ctx->Texture.Unit[unit].GenT.ObjectPlane);
224
            return;
225
         case STATE_TEXGEN_OBJECT_R:
226
            COPY_4V(value, ctx->Texture.Unit[unit].GenR.ObjectPlane);
227
            return;
228
         case STATE_TEXGEN_OBJECT_Q:
229
            COPY_4V(value, ctx->Texture.Unit[unit].GenQ.ObjectPlane);
230
            return;
231
         default:
232
            _mesa_problem(ctx, "Invalid texgen state in fetch_state");
233
            return;
234
         }
235
      }
236
   case STATE_TEXENV_COLOR:
237
      {
238
         /* state[1] is the texture unit */
239
         const GLuint unit = (GLuint) state[1];
240
         COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
241
      }
242
      return;
243
   case STATE_FOG_COLOR:
244
      COPY_4V(value, ctx->Fog.Color);
245
      return;
246
   case STATE_FOG_PARAMS:
247
      value[0] = ctx->Fog.Density;
248
      value[1] = ctx->Fog.Start;
249
      value[2] = ctx->Fog.End;
250
      value[3] = (ctx->Fog.End == ctx->Fog.Start)
251
         ? 1.0f : (GLfloat)(1.0 / (ctx->Fog.End - ctx->Fog.Start));
252
      return;
253
   case STATE_CLIPPLANE:
254
      {
255
         const GLuint plane = (GLuint) state[1];
256
         COPY_4V(value, ctx->Transform.EyeUserPlane[plane]);
257
      }
258
      return;
259
   case STATE_POINT_SIZE:
260
      value[0] = ctx->Point.Size;
261
      value[1] = ctx->Point.MinSize;
262
      value[2] = ctx->Point.MaxSize;
263
      value[3] = ctx->Point.Threshold;
264
      return;
265
   case STATE_POINT_ATTENUATION:
266
      value[0] = ctx->Point.Params[0];
267
      value[1] = ctx->Point.Params[1];
268
      value[2] = ctx->Point.Params[2];
269
      value[3] = 1.0F;
270
      return;
271
   case STATE_MODELVIEW_MATRIX:
272
   case STATE_PROJECTION_MATRIX:
273
   case STATE_MVP_MATRIX:
274
   case STATE_TEXTURE_MATRIX:
275
   case STATE_PROGRAM_MATRIX:
276
      {
277
         /* state[0] = modelview, projection, texture, etc. */
278
         /* state[1] = which texture matrix or program matrix */
279
         /* state[2] = first row to fetch */
280
         /* state[3] = last row to fetch */
281
         /* state[4] = transpose, inverse or invtrans */
282
         const GLmatrix *matrix;
283
         const gl_state_index mat = state[0];
284
         const GLuint index = (GLuint) state[1];
285
         const GLuint firstRow = (GLuint) state[2];
286
         const GLuint lastRow = (GLuint) state[3];
287
         const gl_state_index modifier = state[4];
288
         const GLfloat *m;
289
         GLuint row, i;
290
         ASSERT(firstRow >= 0);
291
         ASSERT(firstRow < 4);
292
         ASSERT(lastRow >= 0);
293
         ASSERT(lastRow < 4);
294
         if (mat == STATE_MODELVIEW_MATRIX) {
295
            matrix = ctx->ModelviewMatrixStack.Top;
296
         }
297
         else if (mat == STATE_PROJECTION_MATRIX) {
298
            matrix = ctx->ProjectionMatrixStack.Top;
299
         }
300
         else if (mat == STATE_MVP_MATRIX) {
301
            matrix = &ctx->_ModelProjectMatrix;
302
         }
303
         else if (mat == STATE_TEXTURE_MATRIX) {
304
            ASSERT(index < Elements(ctx->TextureMatrixStack));
305
            matrix = ctx->TextureMatrixStack[index].Top;
306
         }
307
         else if (mat == STATE_PROGRAM_MATRIX) {
308
            ASSERT(index < Elements(ctx->ProgramMatrixStack));
309
            matrix = ctx->ProgramMatrixStack[index].Top;
310
         }
311
         else {
312
            _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()");
313
            return;
314
         }
315
         if (modifier == STATE_MATRIX_INVERSE ||
316
             modifier == STATE_MATRIX_INVTRANS) {
317
            /* Be sure inverse is up to date:
318
	     */
319
            _math_matrix_alloc_inv( (GLmatrix *) matrix );
320
	    _math_matrix_analyse( (GLmatrix*) matrix );
321
            m = matrix->inv;
322
         }
323
         else {
324
            m = matrix->m;
325
         }
326
         if (modifier == STATE_MATRIX_TRANSPOSE ||
327
             modifier == STATE_MATRIX_INVTRANS) {
328
            for (i = 0, row = firstRow; row <= lastRow; row++) {
329
               value[i++] = m[row * 4 + 0];
330
               value[i++] = m[row * 4 + 1];
331
               value[i++] = m[row * 4 + 2];
332
               value[i++] = m[row * 4 + 3];
333
            }
334
         }
335
         else {
336
            for (i = 0, row = firstRow; row <= lastRow; row++) {
337
               value[i++] = m[row + 0];
338
               value[i++] = m[row + 4];
339
               value[i++] = m[row + 8];
340
               value[i++] = m[row + 12];
341
            }
342
         }
343
      }
344
      return;
345
   case STATE_DEPTH_RANGE:
346
      value[0] = ctx->Viewport.Near;                     /* near       */
347
      value[1] = ctx->Viewport.Far;                      /* far        */
348
      value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */
349
      value[3] = 1.0;
350
      return;
351
   case STATE_FRAGMENT_PROGRAM:
352
      {
353
         /* state[1] = {STATE_ENV, STATE_LOCAL} */
354
         /* state[2] = parameter index          */
355
         const int idx = (int) state[2];
356
         switch (state[1]) {
357
            case STATE_ENV:
358
               COPY_4V(value, ctx->FragmentProgram.Parameters[idx]);
359
               return;
360
            case STATE_LOCAL:
361
               COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]);
362
               return;
363
            default:
364
               _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
365
               return;
366
         }
367
      }
368
      return;
369
 
370
   case STATE_VERTEX_PROGRAM:
371
      {
372
         /* state[1] = {STATE_ENV, STATE_LOCAL} */
373
         /* state[2] = parameter index          */
374
         const int idx = (int) state[2];
375
         switch (state[1]) {
376
            case STATE_ENV:
377
               COPY_4V(value, ctx->VertexProgram.Parameters[idx]);
378
               return;
379
            case STATE_LOCAL:
380
               COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]);
381
               return;
382
            default:
383
               _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
384
               return;
385
         }
386
      }
387
      return;
388
 
389
   case STATE_NORMAL_SCALE:
390
      ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1);
391
      return;
392
 
393
   case STATE_INTERNAL:
394
      switch (state[1]) {
395
      case STATE_CURRENT_ATTRIB:
396
         {
397
            const GLuint idx = (GLuint) state[2];
398
            COPY_4V(value, ctx->Current.Attrib[idx]);
399
         }
400
         return;
401
 
402
      case STATE_NORMAL_SCALE:
403
         ASSIGN_4V(value,
404
                   ctx->_ModelViewInvScale,
405
                   ctx->_ModelViewInvScale,
406
                   ctx->_ModelViewInvScale,
407
                   1);
408
         return;
409
 
410
      case STATE_TEXRECT_SCALE:
411
         /* Value = { 1/texWidth, 1/texHeight, 0, 1 }.
412
          * Used to convert unnormalized texcoords to normalized texcoords.
413
          */
414
         {
415
            const int unit = (int) state[2];
416
            const struct gl_texture_object *texObj
417
               = ctx->Texture.Unit[unit]._Current;
418
            if (texObj) {
419
               struct gl_texture_image *texImage = texObj->Image[0][0];
420
               ASSIGN_4V(value,
421
                         (GLfloat) (1.0 / texImage->Width),
422
                         (GLfloat) (1.0 / texImage->Height),
423
                         0.0f, 1.0f);
424
            }
425
         }
426
         return;
427
 
428
      case STATE_FOG_PARAMS_OPTIMIZED:
429
         /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog)
430
          * might be more expensive than EX2 on some hw, plus it needs
431
          * another constant (e) anyway. Linear fog can now be done with a
432
          * single MAD.
433
          * linear: fogcoord * -1/(end-start) + end/(end-start)
434
          * exp: 2^-(density/ln(2) * fogcoord)
435
          * exp2: 2^-((density/(ln(2)^2) * fogcoord)^2)
436
          */
437
         value[0] = (ctx->Fog.End == ctx->Fog.Start)
438
            ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start));
439
         value[1] = ctx->Fog.End * -value[0];
440
         value[2] = (GLfloat)(ctx->Fog.Density * ONE_DIV_LN2);
441
         value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2);
442
         return;
443
 
444
      case STATE_POINT_SIZE_CLAMPED:
445
         {
446
           /* this includes implementation dependent limits, to avoid
447
            * another potentially necessary clamp.
448
            * Note: for sprites, point smooth (point AA) is ignored
449
            * and we'll clamp to MinPointSizeAA and MaxPointSize, because we
450
            * expect drivers will want to say their minimum for AA size is 0.0
451
            * but for non-AA it's 1.0 (because normal points with size below 1.0
452
            * need to get rounded up to 1.0, hence never disappear). GL does
453
            * not specify max clamp size for sprites, other than it needs to be
454
            * at least as large as max AA size, hence use non-AA size there.
455
            */
456
            GLfloat minImplSize;
457
            GLfloat maxImplSize;
458
            if (ctx->Point.PointSprite) {
459
               minImplSize = ctx->Const.MinPointSizeAA;
460
               maxImplSize = ctx->Const.MaxPointSize;
461
            }
462
            else if (ctx->Point.SmoothFlag || ctx->Multisample._Enabled) {
463
               minImplSize = ctx->Const.MinPointSizeAA;
464
               maxImplSize = ctx->Const.MaxPointSizeAA;
465
            }
466
            else {
467
               minImplSize = ctx->Const.MinPointSize;
468
               maxImplSize = ctx->Const.MaxPointSize;
469
            }
470
            value[0] = ctx->Point.Size;
471
            value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize;
472
            value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize;
473
            value[3] = ctx->Point.Threshold;
474
         }
475
         return;
476
      case STATE_POINT_SIZE_IMPL_CLAMP:
477
         {
478
           /* for implementation clamp only in vs */
479
            GLfloat minImplSize;
480
            GLfloat maxImplSize;
481
            if (ctx->Point.PointSprite) {
482
               minImplSize = ctx->Const.MinPointSizeAA;
483
               maxImplSize = ctx->Const.MaxPointSize;
484
            }
485
            else if (ctx->Point.SmoothFlag || ctx->Multisample._Enabled) {
486
               minImplSize = ctx->Const.MinPointSizeAA;
487
               maxImplSize = ctx->Const.MaxPointSizeAA;
488
            }
489
            else {
490
               minImplSize = ctx->Const.MinPointSize;
491
               maxImplSize = ctx->Const.MaxPointSize;
492
            }
493
            value[0] = ctx->Point.Size;
494
            value[1] = minImplSize;
495
            value[2] = maxImplSize;
496
            value[3] = ctx->Point.Threshold;
497
         }
498
         return;
499
      case STATE_LIGHT_SPOT_DIR_NORMALIZED:
500
         {
501
            /* here, state[2] is the light number */
502
            /* pre-normalize spot dir */
503
            const GLuint ln = (GLuint) state[2];
504
            COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection);
505
            value[3] = ctx->Light.Light[ln]._CosCutoff;
506
         }
507
         return;
508
 
509
      case STATE_LIGHT_POSITION:
510
         {
511
            const GLuint ln = (GLuint) state[2];
512
            COPY_4V(value, ctx->Light.Light[ln]._Position);
513
         }
514
         return;
515
 
516
      case STATE_LIGHT_POSITION_NORMALIZED:
517
         {
518
            const GLuint ln = (GLuint) state[2];
519
            COPY_4V(value, ctx->Light.Light[ln]._Position);
520
            NORMALIZE_3FV( value );
521
         }
522
         return;
523
 
524
      case STATE_LIGHT_HALF_VECTOR:
525
         {
526
            const GLuint ln = (GLuint) state[2];
527
            GLfloat p[3];
528
            /* Compute infinite half angle vector:
529
             *   halfVector = normalize(normalize(lightPos) + (0, 0, 1))
530
             * light.EyePosition.w should be 0 for infinite lights.
531
             */
532
            COPY_3V(p, ctx->Light.Light[ln]._Position);
533
            NORMALIZE_3FV(p);
534
            ADD_3V(value, p, ctx->_EyeZDir);
535
            NORMALIZE_3FV(value);
536
            value[3] = 1.0;
537
         }
538
         return;
539
 
540
      case STATE_PT_SCALE:
541
         value[0] = ctx->Pixel.RedScale;
542
         value[1] = ctx->Pixel.GreenScale;
543
         value[2] = ctx->Pixel.BlueScale;
544
         value[3] = ctx->Pixel.AlphaScale;
545
         return;
546
 
547
      case STATE_PT_BIAS:
548
         value[0] = ctx->Pixel.RedBias;
549
         value[1] = ctx->Pixel.GreenBias;
550
         value[2] = ctx->Pixel.BlueBias;
551
         value[3] = ctx->Pixel.AlphaBias;
552
         return;
553
 
554
      case STATE_SHADOW_AMBIENT:
555
         {
556
            const int unit = (int) state[2];
557
            const struct gl_texture_object *texObj
558
               = ctx->Texture.Unit[unit]._Current;
559
            if (texObj) {
560
               value[0] =
561
               value[1] =
562
               value[2] =
563
               value[3] = texObj->CompareFailValue;
564
            }
565
         }
566
         return;
567
 
568
      case STATE_FB_SIZE:
569
         value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1);
570
         value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1);
571
         value[2] = 0.0F;
572
         value[3] = 0.0F;
573
         return;
574
 
575
      case STATE_FB_WPOS_Y_TRANSFORM:
576
         /* A driver may negate this conditional by using ZW swizzle
577
          * instead of XY (based on e.g. some other state). */
578
         if (ctx->DrawBuffer->Name != 0) {
579
            /* Identity (XY) followed by flipping Y upside down (ZW). */
580
            value[0] = 1.0F;
581
            value[1] = 0.0F;
582
            value[2] = -1.0F;
583
            value[3] = (GLfloat) (ctx->DrawBuffer->Height - 1);
584
         } else {
585
            /* Flipping Y upside down (XY) followed by identity (ZW). */
586
            value[0] = -1.0F;
587
            value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1);
588
            value[2] = 1.0F;
589
            value[3] = 0.0F;
590
         }
591
         return;
592
 
593
      case STATE_ROT_MATRIX_0:
594
         {
595
            const int unit = (int) state[2];
596
            GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
597
            value[0] = rotMat22[0];
598
            value[1] = rotMat22[2];
599
            value[2] = 0.0;
600
            value[3] = 0.0;
601
         }
602
         return;
603
 
604
      case STATE_ROT_MATRIX_1:
605
         {
606
            const int unit = (int) state[2];
607
            GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
608
            value[0] = rotMat22[1];
609
            value[1] = rotMat22[3];
610
            value[2] = 0.0;
611
            value[3] = 0.0;
612
         }
613
         return;
614
 
615
      /* XXX: make sure new tokens added here are also handled in the
616
       * _mesa_program_state_flags() switch, below.
617
       */
618
      default:
619
         /* Unknown state indexes are silently ignored here.
620
          * Drivers may do something special.
621
          */
622
         return;
623
      }
624
      return;
625
 
626
   default:
627
      _mesa_problem(ctx, "Invalid state in _mesa_fetch_state");
628
      return;
629
   }
630
}
631
 
632
 
633
/**
634
 * Return a bitmask of the Mesa state flags (_NEW_* values) which would
635
 * indicate that the given context state may have changed.
636
 * The bitmask is used during validation to determine if we need to update
637
 * vertex/fragment program parameters (like "state.material.color") when
638
 * some GL state has changed.
639
 */
640
GLbitfield
641
_mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
642
{
643
   switch (state[0]) {
644
   case STATE_MATERIAL:
645
   case STATE_LIGHT:
646
   case STATE_LIGHTMODEL_AMBIENT:
647
   case STATE_LIGHTMODEL_SCENECOLOR:
648
   case STATE_LIGHTPROD:
649
      return _NEW_LIGHT;
650
 
651
   case STATE_TEXGEN:
652
   case STATE_TEXENV_COLOR:
653
      return _NEW_TEXTURE;
654
 
655
   case STATE_FOG_COLOR:
656
   case STATE_FOG_PARAMS:
657
      return _NEW_FOG;
658
 
659
   case STATE_CLIPPLANE:
660
      return _NEW_TRANSFORM;
661
 
662
   case STATE_POINT_SIZE:
663
   case STATE_POINT_ATTENUATION:
664
      return _NEW_POINT;
665
 
666
   case STATE_MODELVIEW_MATRIX:
667
      return _NEW_MODELVIEW;
668
   case STATE_PROJECTION_MATRIX:
669
      return _NEW_PROJECTION;
670
   case STATE_MVP_MATRIX:
671
      return _NEW_MODELVIEW | _NEW_PROJECTION;
672
   case STATE_TEXTURE_MATRIX:
673
      return _NEW_TEXTURE_MATRIX;
674
   case STATE_PROGRAM_MATRIX:
675
      return _NEW_TRACK_MATRIX;
676
 
677
   case STATE_DEPTH_RANGE:
678
      return _NEW_VIEWPORT;
679
 
680
   case STATE_FRAGMENT_PROGRAM:
681
   case STATE_VERTEX_PROGRAM:
682
      return _NEW_PROGRAM;
683
 
684
   case STATE_NORMAL_SCALE:
685
      return _NEW_MODELVIEW;
686
 
687
   case STATE_INTERNAL:
688
      switch (state[1]) {
689
      case STATE_CURRENT_ATTRIB:
690
         return _NEW_CURRENT_ATTRIB;
691
 
692
      case STATE_NORMAL_SCALE:
693
         return _NEW_MODELVIEW;
694
 
695
      case STATE_TEXRECT_SCALE:
696
      case STATE_SHADOW_AMBIENT:
697
      case STATE_ROT_MATRIX_0:
698
      case STATE_ROT_MATRIX_1:
699
	 return _NEW_TEXTURE;
700
      case STATE_FOG_PARAMS_OPTIMIZED:
701
	 return _NEW_FOG;
702
      case STATE_POINT_SIZE_CLAMPED:
703
      case STATE_POINT_SIZE_IMPL_CLAMP:
704
         return _NEW_POINT | _NEW_MULTISAMPLE;
705
      case STATE_LIGHT_SPOT_DIR_NORMALIZED:
706
      case STATE_LIGHT_POSITION:
707
      case STATE_LIGHT_POSITION_NORMALIZED:
708
      case STATE_LIGHT_HALF_VECTOR:
709
         return _NEW_LIGHT;
710
 
711
      case STATE_PT_SCALE:
712
      case STATE_PT_BIAS:
713
         return _NEW_PIXEL;
714
 
715
      case STATE_FB_SIZE:
716
      case STATE_FB_WPOS_Y_TRANSFORM:
717
         return _NEW_BUFFERS;
718
 
719
      default:
720
         /* unknown state indexes are silently ignored and
721
         *  no flag set, since it is handled by the driver.
722
         */
723
	 return 0;
724
      }
725
 
726
   default:
727
      _mesa_problem(NULL, "unexpected state[0] in make_state_flags()");
728
      return 0;
729
   }
730
}
731
 
732
 
733
static void
734
append(char *dst, const char *src)
735
{
736
   while (*dst)
737
      dst++;
738
   while (*src)
739
     *dst++ = *src++;
740
   *dst = 0;
741
}
742
 
743
 
744
/**
745
 * Convert token 'k' to a string, append it onto 'dst' string.
746
 */
747
static void
748
append_token(char *dst, gl_state_index k)
749
{
750
   switch (k) {
751
   case STATE_MATERIAL:
752
      append(dst, "material");
753
      break;
754
   case STATE_LIGHT:
755
      append(dst, "light");
756
      break;
757
   case STATE_LIGHTMODEL_AMBIENT:
758
      append(dst, "lightmodel.ambient");
759
      break;
760
   case STATE_LIGHTMODEL_SCENECOLOR:
761
      break;
762
   case STATE_LIGHTPROD:
763
      append(dst, "lightprod");
764
      break;
765
   case STATE_TEXGEN:
766
      append(dst, "texgen");
767
      break;
768
   case STATE_FOG_COLOR:
769
      append(dst, "fog.color");
770
      break;
771
   case STATE_FOG_PARAMS:
772
      append(dst, "fog.params");
773
      break;
774
   case STATE_CLIPPLANE:
775
      append(dst, "clip");
776
      break;
777
   case STATE_POINT_SIZE:
778
      append(dst, "point.size");
779
      break;
780
   case STATE_POINT_ATTENUATION:
781
      append(dst, "point.attenuation");
782
      break;
783
   case STATE_MODELVIEW_MATRIX:
784
      append(dst, "matrix.modelview");
785
      break;
786
   case STATE_PROJECTION_MATRIX:
787
      append(dst, "matrix.projection");
788
      break;
789
   case STATE_MVP_MATRIX:
790
      append(dst, "matrix.mvp");
791
      break;
792
   case STATE_TEXTURE_MATRIX:
793
      append(dst, "matrix.texture");
794
      break;
795
   case STATE_PROGRAM_MATRIX:
796
      append(dst, "matrix.program");
797
      break;
798
   case STATE_MATRIX_INVERSE:
799
      append(dst, ".inverse");
800
      break;
801
   case STATE_MATRIX_TRANSPOSE:
802
      append(dst, ".transpose");
803
      break;
804
   case STATE_MATRIX_INVTRANS:
805
      append(dst, ".invtrans");
806
      break;
807
   case STATE_AMBIENT:
808
      append(dst, ".ambient");
809
      break;
810
   case STATE_DIFFUSE:
811
      append(dst, ".diffuse");
812
      break;
813
   case STATE_SPECULAR:
814
      append(dst, ".specular");
815
      break;
816
   case STATE_EMISSION:
817
      append(dst, ".emission");
818
      break;
819
   case STATE_SHININESS:
820
      append(dst, "lshininess");
821
      break;
822
   case STATE_HALF_VECTOR:
823
      append(dst, ".half");
824
      break;
825
   case STATE_POSITION:
826
      append(dst, ".position");
827
      break;
828
   case STATE_ATTENUATION:
829
      append(dst, ".attenuation");
830
      break;
831
   case STATE_SPOT_DIRECTION:
832
      append(dst, ".spot.direction");
833
      break;
834
   case STATE_SPOT_CUTOFF:
835
      append(dst, ".spot.cutoff");
836
      break;
837
   case STATE_TEXGEN_EYE_S:
838
      append(dst, ".eye.s");
839
      break;
840
   case STATE_TEXGEN_EYE_T:
841
      append(dst, ".eye.t");
842
      break;
843
   case STATE_TEXGEN_EYE_R:
844
      append(dst, ".eye.r");
845
      break;
846
   case STATE_TEXGEN_EYE_Q:
847
      append(dst, ".eye.q");
848
      break;
849
   case STATE_TEXGEN_OBJECT_S:
850
      append(dst, ".object.s");
851
      break;
852
   case STATE_TEXGEN_OBJECT_T:
853
      append(dst, ".object.t");
854
      break;
855
   case STATE_TEXGEN_OBJECT_R:
856
      append(dst, ".object.r");
857
      break;
858
   case STATE_TEXGEN_OBJECT_Q:
859
      append(dst, ".object.q");
860
      break;
861
   case STATE_TEXENV_COLOR:
862
      append(dst, "texenv");
863
      break;
864
   case STATE_DEPTH_RANGE:
865
      append(dst, "depth.range");
866
      break;
867
   case STATE_VERTEX_PROGRAM:
868
   case STATE_FRAGMENT_PROGRAM:
869
      break;
870
   case STATE_ENV:
871
      append(dst, "env");
872
      break;
873
   case STATE_LOCAL:
874
      append(dst, "local");
875
      break;
876
   /* BEGIN internal state vars */
877
   case STATE_INTERNAL:
878
      append(dst, ".internal.");
879
      break;
880
   case STATE_CURRENT_ATTRIB:
881
      append(dst, "current");
882
      break;
883
   case STATE_NORMAL_SCALE:
884
      append(dst, "normalScale");
885
      break;
886
   case STATE_TEXRECT_SCALE:
887
      append(dst, "texrectScale");
888
      break;
889
   case STATE_FOG_PARAMS_OPTIMIZED:
890
      append(dst, "fogParamsOptimized");
891
      break;
892
   case STATE_POINT_SIZE_CLAMPED:
893
      append(dst, "pointSizeClamped");
894
      break;
895
   case STATE_POINT_SIZE_IMPL_CLAMP:
896
      append(dst, "pointSizeImplClamp");
897
      break;
898
   case STATE_LIGHT_SPOT_DIR_NORMALIZED:
899
      append(dst, "lightSpotDirNormalized");
900
      break;
901
   case STATE_LIGHT_POSITION:
902
      append(dst, "lightPosition");
903
      break;
904
   case STATE_LIGHT_POSITION_NORMALIZED:
905
      append(dst, "light.position.normalized");
906
      break;
907
   case STATE_LIGHT_HALF_VECTOR:
908
      append(dst, "lightHalfVector");
909
      break;
910
   case STATE_PT_SCALE:
911
      append(dst, "PTscale");
912
      break;
913
   case STATE_PT_BIAS:
914
      append(dst, "PTbias");
915
      break;
916
   case STATE_SHADOW_AMBIENT:
917
      append(dst, "CompareFailValue");
918
      break;
919
   case STATE_FB_SIZE:
920
      append(dst, "FbSize");
921
      break;
922
   case STATE_FB_WPOS_Y_TRANSFORM:
923
      append(dst, "FbWposYTransform");
924
      break;
925
   case STATE_ROT_MATRIX_0:
926
      append(dst, "rotMatrixRow0");
927
      break;
928
   case STATE_ROT_MATRIX_1:
929
      append(dst, "rotMatrixRow1");
930
      break;
931
   default:
932
      /* probably STATE_INTERNAL_DRIVER+i (driver private state) */
933
      append(dst, "driverState");
934
   }
935
}
936
 
937
static void
938
append_face(char *dst, GLint face)
939
{
940
   if (face == 0)
941
      append(dst, "front.");
942
   else
943
      append(dst, "back.");
944
}
945
 
946
static void
947
append_index(char *dst, GLint index)
948
{
949
   char s[20];
950
   sprintf(s, "[%d]", index);
951
   append(dst, s);
952
}
953
 
954
/**
955
 * Make a string from the given state vector.
956
 * For example, return "state.matrix.texture[2].inverse".
957
 * Use free() to deallocate the string.
958
 */
959
char *
960
_mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
961
{
962
   char str[1000] = "";
963
   char tmp[30];
964
 
965
   append(str, "state.");
966
   append_token(str, state[0]);
967
 
968
   switch (state[0]) {
969
   case STATE_MATERIAL:
970
      append_face(str, state[1]);
971
      append_token(str, state[2]);
972
      break;
973
   case STATE_LIGHT:
974
      append_index(str, state[1]); /* light number [i]. */
975
      append_token(str, state[2]); /* coefficients */
976
      break;
977
   case STATE_LIGHTMODEL_AMBIENT:
978
      append(str, "lightmodel.ambient");
979
      break;
980
   case STATE_LIGHTMODEL_SCENECOLOR:
981
      if (state[1] == 0) {
982
         append(str, "lightmodel.front.scenecolor");
983
      }
984
      else {
985
         append(str, "lightmodel.back.scenecolor");
986
      }
987
      break;
988
   case STATE_LIGHTPROD:
989
      append_index(str, state[1]); /* light number [i]. */
990
      append_face(str, state[2]);
991
      append_token(str, state[3]);
992
      break;
993
   case STATE_TEXGEN:
994
      append_index(str, state[1]); /* tex unit [i] */
995
      append_token(str, state[2]); /* plane coef */
996
      break;
997
   case STATE_TEXENV_COLOR:
998
      append_index(str, state[1]); /* tex unit [i] */
999
      append(str, "color");
1000
      break;
1001
   case STATE_CLIPPLANE:
1002
      append_index(str, state[1]); /* plane [i] */
1003
      append(str, ".plane");
1004
      break;
1005
   case STATE_MODELVIEW_MATRIX:
1006
   case STATE_PROJECTION_MATRIX:
1007
   case STATE_MVP_MATRIX:
1008
   case STATE_TEXTURE_MATRIX:
1009
   case STATE_PROGRAM_MATRIX:
1010
      {
1011
         /* state[0] = modelview, projection, texture, etc. */
1012
         /* state[1] = which texture matrix or program matrix */
1013
         /* state[2] = first row to fetch */
1014
         /* state[3] = last row to fetch */
1015
         /* state[4] = transpose, inverse or invtrans */
1016
         const gl_state_index mat = state[0];
1017
         const GLuint index = (GLuint) state[1];
1018
         const GLuint firstRow = (GLuint) state[2];
1019
         const GLuint lastRow = (GLuint) state[3];
1020
         const gl_state_index modifier = state[4];
1021
         if (index ||
1022
             mat == STATE_TEXTURE_MATRIX ||
1023
             mat == STATE_PROGRAM_MATRIX)
1024
            append_index(str, index);
1025
         if (modifier)
1026
            append_token(str, modifier);
1027
         if (firstRow == lastRow)
1028
            sprintf(tmp, ".row[%d]", firstRow);
1029
         else
1030
            sprintf(tmp, ".row[%d..%d]", firstRow, lastRow);
1031
         append(str, tmp);
1032
      }
1033
      break;
1034
   case STATE_POINT_SIZE:
1035
      break;
1036
   case STATE_POINT_ATTENUATION:
1037
      break;
1038
   case STATE_FOG_PARAMS:
1039
      break;
1040
   case STATE_FOG_COLOR:
1041
      break;
1042
   case STATE_DEPTH_RANGE:
1043
      break;
1044
   case STATE_FRAGMENT_PROGRAM:
1045
   case STATE_VERTEX_PROGRAM:
1046
      /* state[1] = {STATE_ENV, STATE_LOCAL} */
1047
      /* state[2] = parameter index          */
1048
      append_token(str, state[1]);
1049
      append_index(str, state[2]);
1050
      break;
1051
   case STATE_NORMAL_SCALE:
1052
      break;
1053
   case STATE_INTERNAL:
1054
      append_token(str, state[1]);
1055
      if (state[1] == STATE_CURRENT_ATTRIB)
1056
         append_index(str, state[2]);
1057
       break;
1058
   default:
1059
      _mesa_problem(NULL, "Invalid state in _mesa_program_state_string");
1060
      break;
1061
   }
1062
 
1063
   return _mesa_strdup(str);
1064
}
1065
 
1066
 
1067
/**
1068
 * Loop over all the parameters in a parameter list.  If the parameter
1069
 * is a GL state reference, look up the current value of that state
1070
 * variable and put it into the parameter's Value[4] array.
1071
 * Other parameter types never change or are explicitly set by the user
1072
 * with glUniform() or glProgramParameter(), etc.
1073
 * This would be called at glBegin time.
1074
 */
1075
void
1076
_mesa_load_state_parameters(struct gl_context *ctx,
1077
                            struct gl_program_parameter_list *paramList)
1078
{
1079
   GLuint i;
1080
 
1081
   if (!paramList)
1082
      return;
1083
 
1084
   for (i = 0; i < paramList->NumParameters; i++) {
1085
      if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
1086
         _mesa_fetch_state(ctx,
1087
			   paramList->Parameters[i].StateIndexes,
1088
                           paramList->ParameterValues[i]);
1089
      }
1090
   }
1091
}
1092
 
1093
 
1094
/**
1095
 * Copy the 16 elements of a matrix into four consecutive program
1096
 * registers starting at 'pos'.
1097
 */
1098
static void
1099
load_matrix(GLfloat registers[][4], GLuint pos, const GLfloat mat[16])
1100
{
1101
   GLuint i;
1102
   for (i = 0; i < 4; i++) {
1103
      registers[pos + i][0] = mat[0 + i];
1104
      registers[pos + i][1] = mat[4 + i];
1105
      registers[pos + i][2] = mat[8 + i];
1106
      registers[pos + i][3] = mat[12 + i];
1107
   }
1108
}
1109
 
1110
 
1111
/**
1112
 * As above, but transpose the matrix.
1113
 */
1114
static void
1115
load_transpose_matrix(GLfloat registers[][4], GLuint pos,
1116
                      const GLfloat mat[16])
1117
{
1118
   memcpy(registers[pos], mat, 16 * sizeof(GLfloat));
1119
}
1120
 
1121
 
1122
/**
1123
 * Load current vertex program's parameter registers with tracked
1124
 * matrices (if NV program).  This only needs to be done per
1125
 * glBegin/glEnd, not per-vertex.
1126
 */
1127
void
1128
_mesa_load_tracked_matrices(struct gl_context *ctx)
1129
{
1130
   GLuint i;
1131
 
1132
   for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS / 4; i++) {
1133
      /* point 'mat' at source matrix */
1134
      GLmatrix *mat;
1135
      if (ctx->VertexProgram.TrackMatrix[i] == GL_MODELVIEW) {
1136
         mat = ctx->ModelviewMatrixStack.Top;
1137
      }
1138
      else if (ctx->VertexProgram.TrackMatrix[i] == GL_PROJECTION) {
1139
         mat = ctx->ProjectionMatrixStack.Top;
1140
      }
1141
      else if (ctx->VertexProgram.TrackMatrix[i] == GL_TEXTURE) {
1142
         GLuint unit = MIN2(ctx->Texture.CurrentUnit,
1143
                            Elements(ctx->TextureMatrixStack) - 1);
1144
         mat = ctx->TextureMatrixStack[unit].Top;
1145
      }
1146
      else if (ctx->VertexProgram.TrackMatrix[i]==GL_MODELVIEW_PROJECTION_NV) {
1147
         /* XXX verify the combined matrix is up to date */
1148
         mat = &ctx->_ModelProjectMatrix;
1149
      }
1150
      else if (ctx->VertexProgram.TrackMatrix[i] >= GL_MATRIX0_NV &&
1151
               ctx->VertexProgram.TrackMatrix[i] <= GL_MATRIX7_NV) {
1152
         GLuint n = ctx->VertexProgram.TrackMatrix[i] - GL_MATRIX0_NV;
1153
         ASSERT(n < Elements(ctx->ProgramMatrixStack));
1154
         mat = ctx->ProgramMatrixStack[n].Top;
1155
      }
1156
      else {
1157
         /* no matrix is tracked, but we leave the register values as-is */
1158
         assert(ctx->VertexProgram.TrackMatrix[i] == GL_NONE);
1159
         continue;
1160
      }
1161
 
1162
      /* load the matrix values into sequential registers */
1163
      if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_IDENTITY_NV) {
1164
         load_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
1165
      }
1166
      else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_INVERSE_NV) {
1167
         _math_matrix_analyse(mat); /* update the inverse */
1168
         ASSERT(!_math_matrix_is_dirty(mat));
1169
         load_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
1170
      }
1171
      else if (ctx->VertexProgram.TrackMatrixTransform[i] == GL_TRANSPOSE_NV) {
1172
         load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->m);
1173
      }
1174
      else {
1175
         assert(ctx->VertexProgram.TrackMatrixTransform[i]
1176
                == GL_INVERSE_TRANSPOSE_NV);
1177
         _math_matrix_analyse(mat); /* update the inverse */
1178
         ASSERT(!_math_matrix_is_dirty(mat));
1179
         load_transpose_matrix(ctx->VertexProgram.Parameters, i*4, mat->inv);
1180
      }
1181
   }
1182
}