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