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 <stddef.h>
34 #include "main/glheader.h"
35 #include "main/context.h"
36 #include "main/blend.h"
37
38 #include "main/macros.h"
39 #include "main/fbobject.h"
40 #include "prog_statevars.h"
41 #include "prog_parameter.h"
42 #include "main/samplerobj.h"
43 #include "main/framebuffer.h"
44
45
46 #define ONE_DIV_SQRT_LN2 (1.201122408786449815)
47
48 static ALWAYS_INLINE void
copy_matrix(float * value,const float * m,unsigned firstRow,unsigned lastRow)49 copy_matrix(float *value, const float *m, unsigned firstRow, unsigned lastRow)
50 {
51 unsigned i, row;
52
53 assert(firstRow < 4);
54 assert(lastRow < 4);
55
56 for (i = 0, row = firstRow; row <= lastRow; row++) {
57 value[i++] = m[row + 0];
58 value[i++] = m[row + 4];
59 value[i++] = m[row + 8];
60 value[i++] = m[row + 12];
61 }
62 }
63
64 static ALWAYS_INLINE void
copy_matrix_transposed(float * value,const float * m,unsigned firstRow,unsigned lastRow)65 copy_matrix_transposed(float *value, const float *m, unsigned firstRow, unsigned lastRow)
66 {
67 assert(firstRow < 4);
68 assert(lastRow < 4);
69
70 memcpy(value, &m[firstRow * 4],
71 (lastRow - firstRow + 1) * 4 * sizeof(GLfloat));
72 }
73
74 /**
75 * Use the list of tokens in the state[] array to find global GL state
76 * and return it in <value>. Usually, four values are returned in <value>
77 * but matrix queries may return as many as 16 values.
78 * This function is used for ARB vertex/fragment programs.
79 * The program parser will produce the state[] values.
80 */
81 static void
fetch_state(struct gl_context * ctx,const gl_state_index16 state[],gl_constant_value * val)82 fetch_state(struct gl_context *ctx, const gl_state_index16 state[],
83 gl_constant_value *val)
84 {
85 GLfloat *value = &val->f;
86
87 switch (state[0]) {
88 case STATE_MATERIAL:
89 {
90 /* state[1] is MAT_ATTRIB_FRONT_* */
91 const GLuint index = (GLuint) state[1];
92 const struct gl_material *mat = &ctx->Light.Material;
93 assert(index >= MAT_ATTRIB_FRONT_AMBIENT &&
94 index <= MAT_ATTRIB_BACK_SHININESS);
95 if (index >= MAT_ATTRIB_FRONT_SHININESS) {
96 value[0] = mat->Attrib[index][0];
97 value[1] = 0.0F;
98 value[2] = 0.0F;
99 value[3] = 1.0F;
100 } else {
101 COPY_4V(value, mat->Attrib[index]);
102 }
103 return;
104 }
105 case STATE_LIGHT:
106 {
107 /* state[1] is the light number */
108 const GLuint ln = (GLuint) state[1];
109 /* state[2] is the light attribute */
110 const unsigned index = state[2] - STATE_AMBIENT;
111 assert(index < 8);
112 if (index != STATE_SPOT_CUTOFF)
113 COPY_4V(value, (float*)&ctx->Light.LightSource[ln] + index * 4);
114 else
115 value[0] = ctx->Light.LightSource[ln].SpotCutoff;
116 return;
117 }
118 case STATE_LIGHT_ARRAY: {
119 /* This must be exact because it must match the gl_LightSource layout
120 * in GLSL.
121 */
122 STATIC_ASSERT(sizeof(struct gl_light_uniforms) == 29 * 4);
123 STATIC_ASSERT(ARRAY_SIZE(ctx->Light.LightSourceData) == 29 * MAX_LIGHTS);
124 /* state[1] is the index of the first value */
125 /* state[2] is the number of values */
126 assert(state[1] + state[2] <= ARRAY_SIZE(ctx->Light.LightSourceData));
127 memcpy(value, &ctx->Light.LightSourceData[state[1]],
128 state[2] * sizeof(float));
129 return;
130 }
131 case STATE_LIGHT_ATTENUATION_ARRAY: {
132 const unsigned first = state[1];
133 const unsigned num_lights = state[2];
134 for (unsigned i = 0; i < num_lights; i++) {
135 COPY_4V(value,
136 &ctx->Light.LightSource[first + i].ConstantAttenuation);
137 value += 4;
138 }
139 return;
140 }
141 case STATE_LIGHTMODEL_AMBIENT:
142 COPY_4V(value, ctx->Light.Model.Ambient);
143 return;
144 case STATE_LIGHTMODEL_SCENECOLOR:
145 if (state[1] == 0) {
146 /* front */
147 GLint i;
148 for (i = 0; i < 3; i++) {
149 value[i] = ctx->Light.Model.Ambient[i]
150 * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i]
151 + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i];
152 }
153 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
154 }
155 else {
156 /* back */
157 GLint i;
158 for (i = 0; i < 3; i++) {
159 value[i] = ctx->Light.Model.Ambient[i]
160 * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i]
161 + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i];
162 }
163 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
164 }
165 return;
166 case STATE_LIGHTPROD:
167 {
168 const GLuint ln = (GLuint) state[1];
169 const GLuint index = (GLuint) state[2];
170 const GLuint attr = (index / 2) * 4;
171 assert(index >= MAT_ATTRIB_FRONT_AMBIENT &&
172 index <= MAT_ATTRIB_BACK_SPECULAR);
173 for (int i = 0; i < 3; i++) {
174 /* We want attr to access out of bounds into the following Diffuse
175 * and Specular fields. This is guaranteed to work because
176 * STATE_LIGHT and STATE_LIGHT_ARRAY also rely on this memory
177 * layout.
178 */
179 STATIC_ASSERT(offsetof(struct gl_light_uniforms, Ambient) + 16 ==
180 offsetof(struct gl_light_uniforms, Diffuse));
181 STATIC_ASSERT(offsetof(struct gl_light_uniforms, Diffuse) + 16 ==
182 offsetof(struct gl_light_uniforms, Specular));
183 value[i] = ctx->Light.LightSource[ln].Ambient[attr + i] *
184 ctx->Light.Material.Attrib[index][i];
185 }
186 /* [3] = material alpha */
187 value[3] = ctx->Light.Material.Attrib[index][3];
188 return;
189 }
190 case STATE_LIGHTPROD_ARRAY_FRONT: {
191 const unsigned first_light = state[1];
192 const unsigned num_lights = state[2];
193
194 for (unsigned i = 0; i < num_lights; i++) {
195 unsigned light = first_light + i;
196
197 for (unsigned attrib = MAT_ATTRIB_FRONT_AMBIENT;
198 attrib <= MAT_ATTRIB_FRONT_SPECULAR; attrib += 2) {
199 for (int chan = 0; chan < 3; chan++) {
200 /* We want offset to access out of bounds into the following
201 * Diffuse and Specular fields. This is guaranteed to work
202 * because STATE_LIGHT and STATE_LIGHT_ATTRIBS also rely
203 * on this memory layout.
204 */
205 unsigned offset = (attrib / 2) * 4 + chan;
206 *value++ =
207 (&ctx->Light.LightSource[light].Ambient[0])[offset] *
208 ctx->Light.Material.Attrib[attrib][chan];
209 }
210 /* [3] = material alpha */
211 *value++ = ctx->Light.Material.Attrib[attrib][3];
212 }
213 }
214 return;
215 }
216 case STATE_LIGHTPROD_ARRAY_BACK: {
217 const unsigned first_light = state[1];
218 const unsigned num_lights = state[2];
219
220 for (unsigned i = 0; i < num_lights; i++) {
221 unsigned light = first_light + i;
222
223 for (unsigned attrib = MAT_ATTRIB_BACK_AMBIENT;
224 attrib <= MAT_ATTRIB_BACK_SPECULAR; attrib += 2) {
225 for (int chan = 0; chan < 3; chan++) {
226 /* We want offset to access out of bounds into the following
227 * Diffuse and Specular fields. This is guaranteed to work
228 * because STATE_LIGHT and STATE_LIGHT_ATTRIBS also rely
229 * on this memory layout.
230 */
231 unsigned offset = (attrib / 2) * 4 + chan;
232 *value++ =
233 (&ctx->Light.LightSource[light].Ambient[0])[offset] *
234 ctx->Light.Material.Attrib[attrib][chan];
235 }
236 /* [3] = material alpha */
237 *value++ = ctx->Light.Material.Attrib[attrib][3];
238 }
239 }
240 return;
241 }
242 case STATE_LIGHTPROD_ARRAY_TWOSIDE: {
243 const unsigned first_light = state[1];
244 const unsigned num_lights = state[2];
245
246 for (unsigned i = 0; i < num_lights; i++) {
247 unsigned light = first_light + i;
248
249 for (unsigned attrib = MAT_ATTRIB_FRONT_AMBIENT;
250 attrib <= MAT_ATTRIB_BACK_SPECULAR; attrib++) {
251 for (int chan = 0; chan < 3; chan++) {
252 /* We want offset to access out of bounds into the following
253 * Diffuse and Specular fields. This is guaranteed to work
254 * because STATE_LIGHT and STATE_LIGHT_ATTRIBS also rely
255 * on this memory layout.
256 */
257 unsigned offset = (attrib / 2) * 4 + chan;
258 *value++ =
259 (&ctx->Light.LightSource[light].Ambient[0])[offset] *
260 ctx->Light.Material.Attrib[attrib][chan];
261 }
262 /* [3] = material alpha */
263 *value++ = ctx->Light.Material.Attrib[attrib][3];
264 }
265 }
266 return;
267 }
268 case STATE_TEXGEN:
269 {
270 /* state[1] is the texture unit */
271 const GLuint unit = (GLuint) state[1];
272 /* state[2] is the texgen attribute */
273 /* Assertions for the expected memory layout. */
274 #define MEMBER_SIZEOF(type, member) sizeof(((type *)0)->member)
275 STATIC_ASSERT(MEMBER_SIZEOF(struct gl_fixedfunc_texture_unit,
276 EyePlane[0]) == 4 * sizeof(float));
277 STATIC_ASSERT(MEMBER_SIZEOF(struct gl_fixedfunc_texture_unit,
278 ObjectPlane[0]) == 4 * sizeof(float));
279 #undef MEMBER_SIZEOF
280 STATIC_ASSERT(STATE_TEXGEN_EYE_T - STATE_TEXGEN_EYE_S == GEN_T - GEN_S);
281 STATIC_ASSERT(STATE_TEXGEN_EYE_R - STATE_TEXGEN_EYE_S == GEN_R - GEN_S);
282 STATIC_ASSERT(STATE_TEXGEN_EYE_Q - STATE_TEXGEN_EYE_S == GEN_Q - GEN_S);
283 STATIC_ASSERT(offsetof(struct gl_fixedfunc_texture_unit, ObjectPlane) -
284 offsetof(struct gl_fixedfunc_texture_unit, EyePlane) ==
285 (STATE_TEXGEN_OBJECT_S - STATE_TEXGEN_EYE_S) * 4 * sizeof(float));
286 STATIC_ASSERT(STATE_TEXGEN_OBJECT_T - STATE_TEXGEN_OBJECT_S == GEN_T - GEN_S);
287 STATIC_ASSERT(STATE_TEXGEN_OBJECT_R - STATE_TEXGEN_OBJECT_S == GEN_R - GEN_S);
288 STATIC_ASSERT(STATE_TEXGEN_OBJECT_Q - STATE_TEXGEN_OBJECT_S == GEN_Q - GEN_S);
289
290 const float *attr = (float*)ctx->Texture.FixedFuncUnit[unit].EyePlane +
291 (state[2] - STATE_TEXGEN_EYE_S) * 4;
292 COPY_4V(value, attr);
293 return;
294 }
295 case STATE_TEXENV_COLOR:
296 {
297 /* state[1] is the texture unit */
298 const GLuint unit = (GLuint) state[1];
299 if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
300 COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColor);
301 else
302 COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColorUnclamped);
303 }
304 return;
305 case STATE_FOG_COLOR:
306 if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer))
307 COPY_4V(value, ctx->Fog.Color);
308 else
309 COPY_4V(value, ctx->Fog.ColorUnclamped);
310 return;
311 case STATE_FOG_PARAMS:
312 value[0] = ctx->Fog.Density;
313 value[1] = ctx->Fog.Start;
314 value[2] = ctx->Fog.End;
315 value[3] = 1.0f / (ctx->Fog.End - ctx->Fog.Start);
316 return;
317 case STATE_CLIPPLANE:
318 {
319 const GLuint plane = (GLuint) state[1];
320 COPY_4V(value, ctx->Transform.EyeUserPlane[plane]);
321 }
322 return;
323 case STATE_POINT_SIZE:
324 value[0] = ctx->Point.Size;
325 value[1] = ctx->Point.MinSize;
326 value[2] = ctx->Point.MaxSize;
327 value[3] = ctx->Point.Threshold;
328 return;
329 case STATE_POINT_ATTENUATION:
330 value[0] = ctx->Point.Params[0];
331 value[1] = ctx->Point.Params[1];
332 value[2] = ctx->Point.Params[2];
333 value[3] = 1.0F;
334 return;
335 /* state[0] = modelview, projection, texture, etc. */
336 /* state[1] = which texture matrix or program matrix */
337 /* state[2] = first row to fetch */
338 /* state[3] = last row to fetch */
339 case STATE_MODELVIEW_MATRIX: {
340 const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top;
341 copy_matrix(value, matrix->m, state[2], state[3]);
342 return;
343 }
344 case STATE_MODELVIEW_MATRIX_INVERSE: {
345 const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top;
346 copy_matrix(value, matrix->inv, state[2], state[3]);
347 return;
348 }
349 case STATE_MODELVIEW_MATRIX_TRANSPOSE: {
350 const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top;
351 copy_matrix_transposed(value, matrix->m, state[2], state[3]);
352 return;
353 }
354 case STATE_MODELVIEW_MATRIX_INVTRANS: {
355 const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top;
356 copy_matrix_transposed(value, matrix->inv, state[2], state[3]);
357 return;
358 }
359 case STATE_PROJECTION_MATRIX: {
360 const GLmatrix *matrix = ctx->ProjectionMatrixStack.Top;
361 copy_matrix(value, matrix->m, state[2], state[3]);
362 return;
363 }
364 case STATE_PROJECTION_MATRIX_INVERSE: {
365 GLmatrix *matrix = ctx->ProjectionMatrixStack.Top;
366 _math_matrix_analyse(matrix); /* make sure the inverse is up to date */
367 copy_matrix(value, matrix->inv, state[2], state[3]);
368 return;
369 }
370 case STATE_PROJECTION_MATRIX_TRANSPOSE: {
371 const GLmatrix *matrix = ctx->ProjectionMatrixStack.Top;
372 copy_matrix_transposed(value, matrix->m, state[2], state[3]);
373 return;
374 }
375 case STATE_PROJECTION_MATRIX_INVTRANS: {
376 GLmatrix *matrix = ctx->ProjectionMatrixStack.Top;
377 _math_matrix_analyse(matrix); /* make sure the inverse is up to date */
378 copy_matrix_transposed(value, matrix->inv, state[2], state[3]);
379 return;
380 }
381 case STATE_MVP_MATRIX: {
382 const GLmatrix *matrix = &ctx->_ModelProjectMatrix;
383 copy_matrix(value, matrix->m, state[2], state[3]);
384 return;
385 }
386 case STATE_MVP_MATRIX_INVERSE: {
387 GLmatrix *matrix = &ctx->_ModelProjectMatrix;
388 _math_matrix_analyse(matrix); /* make sure the inverse is up to date */
389 copy_matrix(value, matrix->inv, state[2], state[3]);
390 return;
391 }
392 case STATE_MVP_MATRIX_TRANSPOSE: {
393 const GLmatrix *matrix = &ctx->_ModelProjectMatrix;
394 copy_matrix_transposed(value, matrix->m, state[2], state[3]);
395 return;
396 }
397 case STATE_MVP_MATRIX_INVTRANS: {
398 GLmatrix *matrix = &ctx->_ModelProjectMatrix;
399 _math_matrix_analyse(matrix); /* make sure the inverse is up to date */
400 copy_matrix_transposed(value, matrix->inv, state[2], state[3]);
401 return;
402 }
403 case STATE_TEXTURE_MATRIX: {
404 const GLuint index = (GLuint) state[1];
405 assert(index < ARRAY_SIZE(ctx->TextureMatrixStack));
406 const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top;
407 copy_matrix(value, matrix->m, state[2], state[3]);
408 return;
409 }
410 case STATE_TEXTURE_MATRIX_INVERSE: {
411 const GLuint index = (GLuint) state[1];
412 assert(index < ARRAY_SIZE(ctx->TextureMatrixStack));
413 const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top;
414 copy_matrix(value, matrix->inv, state[2], state[3]);
415 return;
416 }
417 case STATE_TEXTURE_MATRIX_TRANSPOSE: {
418 const GLuint index = (GLuint) state[1];
419 assert(index < ARRAY_SIZE(ctx->TextureMatrixStack));
420 const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top;
421 copy_matrix_transposed(value, matrix->m, state[2], state[3]);
422 return;
423 }
424 case STATE_TEXTURE_MATRIX_INVTRANS: {
425 const GLuint index = (GLuint) state[1];
426 assert(index < ARRAY_SIZE(ctx->TextureMatrixStack));
427 const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top;
428 copy_matrix_transposed(value, matrix->inv, state[2], state[3]);
429 return;
430 }
431 case STATE_PROGRAM_MATRIX: {
432 const GLuint index = (GLuint) state[1];
433 assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack));
434 const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top;
435 copy_matrix(value, matrix->m, state[2], state[3]);
436 return;
437 }
438 case STATE_PROGRAM_MATRIX_INVERSE: {
439 const GLuint index = (GLuint) state[1];
440 assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack));
441 const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top;
442 _math_matrix_analyse((GLmatrix*)matrix); /* Be sure inverse is up to date: */
443 copy_matrix(value, matrix->inv, state[2], state[3]);
444 return;
445 }
446 case STATE_PROGRAM_MATRIX_TRANSPOSE: {
447 const GLuint index = (GLuint) state[1];
448 assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack));
449 const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top;
450 copy_matrix_transposed(value, matrix->m, state[2], state[3]);
451 return;
452 }
453 case STATE_PROGRAM_MATRIX_INVTRANS: {
454 const GLuint index = (GLuint) state[1];
455 assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack));
456 const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top;
457 _math_matrix_analyse((GLmatrix*)matrix); /* Be sure inverse is up to date: */
458 copy_matrix_transposed(value, matrix->inv, state[2], state[3]);
459 return;
460 }
461 case STATE_NUM_SAMPLES:
462 val[0].i = MAX2(1, _mesa_geometric_samples(ctx->DrawBuffer));
463 return;
464 case STATE_DEPTH_RANGE:
465 value[0] = ctx->ViewportArray[0].Near; /* near */
466 value[1] = ctx->ViewportArray[0].Far; /* far */
467 value[2] = ctx->ViewportArray[0].Far - ctx->ViewportArray[0].Near; /* far - near */
468 value[3] = 1.0;
469 return;
470 case STATE_FRAGMENT_PROGRAM_ENV: {
471 const int idx = (int) state[1];
472 COPY_4V(value, ctx->FragmentProgram.Parameters[idx]);
473 return;
474 }
475 case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: {
476 const unsigned idx = state[1];
477 const unsigned bytes = state[2] * 16;
478 memcpy(value, ctx->FragmentProgram.Parameters[idx], bytes);
479 return;
480 }
481 case STATE_FRAGMENT_PROGRAM_LOCAL: {
482 float (*params)[4] = ctx->FragmentProgram.Current->arb.LocalParams;
483 if (unlikely(!params)) {
484 /* Local parameters haven't been allocated yet.
485 * ARB_fragment_program says that local parameters are
486 * "initially set to (0,0,0,0)." Return that.
487 */
488 memset(value, 0, sizeof(float) * 4);
489 return;
490 }
491
492 const int idx = (int) state[1];
493 COPY_4V(value, params[idx]);
494 return;
495 }
496 case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: {
497 const unsigned idx = state[1];
498 const unsigned bytes = state[2] * 16;
499 float (*params)[4] = ctx->FragmentProgram.Current->arb.LocalParams;
500 if (!params) {
501 /* Local parameters haven't been allocated yet.
502 * ARB_fragment_program says that local parameters are
503 * "initially set to (0,0,0,0)." Return that.
504 */
505 memset(value, 0, bytes);
506 return;
507 }
508 memcpy(value, params[idx], bytes);
509 return;
510 }
511 case STATE_VERTEX_PROGRAM_ENV: {
512 const int idx = (int) state[1];
513 COPY_4V(value, ctx->VertexProgram.Parameters[idx]);
514 return;
515 }
516 case STATE_VERTEX_PROGRAM_ENV_ARRAY: {
517 const unsigned idx = state[1];
518 const unsigned bytes = state[2] * 16;
519 memcpy(value, ctx->VertexProgram.Parameters[idx], bytes);
520 return;
521 }
522 case STATE_VERTEX_PROGRAM_LOCAL: {
523 float (*params)[4] = ctx->VertexProgram.Current->arb.LocalParams;
524 if (unlikely(!params)) {
525 /* Local parameters haven't been allocated yet.
526 * ARB_vertex_program says that local parameters are
527 * "initially set to (0,0,0,0)." Return that.
528 */
529 memset(value, 0, sizeof(float) * 4);
530 return;
531 }
532
533 const int idx = (int) state[1];
534 COPY_4V(value, params[idx]);
535 return;
536 }
537 case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: {
538 const unsigned idx = state[1];
539 const unsigned bytes = state[2] * 16;
540 float (*params)[4] = ctx->VertexProgram.Current->arb.LocalParams;
541 if (!params) {
542 /* Local parameters haven't been allocated yet.
543 * ARB_vertex_program says that local parameters are
544 * "initially set to (0,0,0,0)." Return that.
545 */
546 memset(value, 0, bytes);
547 return;
548 }
549 memcpy(value, params[idx], bytes);
550 return;
551 }
552
553 case STATE_NORMAL_SCALE_EYESPACE:
554 ASSIGN_4V(value, ctx->_ModelViewInvScaleEyespace, 0, 0, 1);
555 return;
556
557 case STATE_CURRENT_ATTRIB:
558 {
559 const GLuint idx = (GLuint) state[1];
560 COPY_4V(value, ctx->Current.Attrib[idx]);
561 }
562 return;
563
564 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
565 {
566 const GLuint idx = (GLuint) state[1];
567 if(ctx->Light._ClampVertexColor &&
568 (idx == VERT_ATTRIB_COLOR0 ||
569 idx == VERT_ATTRIB_COLOR1)) {
570 value[0] = SATURATE(ctx->Current.Attrib[idx][0]);
571 value[1] = SATURATE(ctx->Current.Attrib[idx][1]);
572 value[2] = SATURATE(ctx->Current.Attrib[idx][2]);
573 value[3] = SATURATE(ctx->Current.Attrib[idx][3]);
574 }
575 else
576 COPY_4V(value, ctx->Current.Attrib[idx]);
577 }
578 return;
579
580 case STATE_NORMAL_SCALE:
581 ASSIGN_4V(value,
582 ctx->_ModelViewInvScale,
583 ctx->_ModelViewInvScale,
584 ctx->_ModelViewInvScale,
585 1);
586 return;
587
588 case STATE_FOG_PARAMS_OPTIMIZED: {
589 /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog)
590 * might be more expensive than EX2 on some hw, plus it needs
591 * another constant (e) anyway. Linear fog can now be done with a
592 * single MAD.
593 * linear: fogcoord * -1/(end-start) + end/(end-start)
594 * exp: 2^-(density/ln(2) * fogcoord)
595 * exp2: 2^-((density/(sqrt(ln(2))) * fogcoord)^2)
596 */
597 float val = (ctx->Fog.End == ctx->Fog.Start)
598 ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start));
599 value[0] = val;
600 value[1] = ctx->Fog.End * -val;
601 value[2] = (GLfloat)(ctx->Fog.Density * M_LOG2E); /* M_LOG2E == 1/ln(2) */
602 value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2);
603 return;
604 }
605
606 case STATE_POINT_SIZE_CLAMPED:
607 {
608 /* this includes implementation dependent limits, to avoid
609 * another potentially necessary clamp.
610 * Note: for sprites, point smooth (point AA) is ignored
611 * and we'll clamp to MinPointSizeAA and MaxPointSize, because we
612 * expect drivers will want to say their minimum for AA size is 0.0
613 * but for non-AA it's 1.0 (because normal points with size below 1.0
614 * need to get rounded up to 1.0, hence never disappear). GL does
615 * not specify max clamp size for sprites, other than it needs to be
616 * at least as large as max AA size, hence use non-AA size there.
617 */
618 GLfloat minImplSize;
619 GLfloat maxImplSize;
620 if (ctx->Point.PointSprite) {
621 minImplSize = ctx->Const.MinPointSizeAA;
622 maxImplSize = ctx->Const.MaxPointSize;
623 }
624 else if (ctx->Point.SmoothFlag || _mesa_is_multisample_enabled(ctx)) {
625 minImplSize = ctx->Const.MinPointSizeAA;
626 maxImplSize = ctx->Const.MaxPointSizeAA;
627 }
628 else {
629 minImplSize = ctx->Const.MinPointSize;
630 maxImplSize = ctx->Const.MaxPointSize;
631 }
632 value[0] = ctx->Point.Size;
633 value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize;
634 value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize;
635 value[3] = ctx->Point.Threshold;
636 }
637 return;
638 case STATE_LIGHT_SPOT_DIR_NORMALIZED:
639 {
640 /* here, state[1] is the light number */
641 /* pre-normalize spot dir */
642 const GLuint ln = (GLuint) state[1];
643 COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection);
644 value[3] = ctx->Light.LightSource[ln]._CosCutoff;
645 }
646 return;
647
648 case STATE_LIGHT_POSITION:
649 {
650 const GLuint ln = (GLuint) state[1];
651 COPY_4V(value, ctx->Light.Light[ln]._Position);
652 }
653 return;
654
655 case STATE_LIGHT_POSITION_ARRAY: {
656 const unsigned first = state[1];
657 const unsigned num_lights = state[2];
658 for (unsigned i = 0; i < num_lights; i++) {
659 COPY_4V(value, ctx->Light.Light[first + i]._Position);
660 value += 4;
661 }
662 return;
663 }
664
665 case STATE_LIGHT_POSITION_NORMALIZED:
666 {
667 const GLuint ln = (GLuint) state[1];
668 float p[4];
669 COPY_4V(p, ctx->Light.Light[ln]._Position);
670 NORMALIZE_3FV(p);
671 COPY_4V(value, p);
672 }
673 return;
674
675 case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: {
676 const unsigned first = state[1];
677 const unsigned num_lights = state[2];
678 for (unsigned i = 0; i < num_lights; i++) {
679 float p[4];
680 COPY_4V(p, ctx->Light.Light[first + i]._Position);
681 NORMALIZE_3FV(p);
682 COPY_4V(value, p);
683 value += 4;
684 }
685 return;
686 }
687
688 case STATE_LIGHT_HALF_VECTOR:
689 {
690 const GLuint ln = (GLuint) state[1];
691 GLfloat p[3];
692 /* Compute infinite half angle vector:
693 * halfVector = normalize(normalize(lightPos) + (0, 0, 1))
694 * light.EyePosition.w should be 0 for infinite lights.
695 */
696 COPY_3V(p, ctx->Light.Light[ln]._Position);
697 NORMALIZE_3FV(p);
698 ADD_3V(p, p, ctx->_EyeZDir);
699 NORMALIZE_3FV(p);
700 COPY_3V(value, p);
701 value[3] = 1.0;
702 }
703 return;
704
705 case STATE_PT_SCALE:
706 value[0] = ctx->Pixel.RedScale;
707 value[1] = ctx->Pixel.GreenScale;
708 value[2] = ctx->Pixel.BlueScale;
709 value[3] = ctx->Pixel.AlphaScale;
710 return;
711
712 case STATE_PT_BIAS:
713 value[0] = ctx->Pixel.RedBias;
714 value[1] = ctx->Pixel.GreenBias;
715 value[2] = ctx->Pixel.BlueBias;
716 value[3] = ctx->Pixel.AlphaBias;
717 return;
718
719 case STATE_FB_SIZE:
720 value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1);
721 value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1);
722 value[2] = 0.0F;
723 value[3] = 0.0F;
724 return;
725
726 case STATE_FB_WPOS_Y_TRANSFORM:
727 /* A driver may negate this conditional by using ZW swizzle
728 * instead of XY (based on e.g. some other state). */
729 if (!ctx->DrawBuffer->FlipY) {
730 /* Identity (XY) followed by flipping Y upside down (ZW). */
731 value[0] = 1.0F;
732 value[1] = 0.0F;
733 value[2] = -1.0F;
734 value[3] = _mesa_geometric_height(ctx->DrawBuffer);
735 } else {
736 /* Flipping Y upside down (XY) followed by identity (ZW). */
737 value[0] = -1.0F;
738 value[1] = _mesa_geometric_height(ctx->DrawBuffer);
739 value[2] = 1.0F;
740 value[3] = 0.0F;
741 }
742 return;
743
744 case STATE_FB_PNTC_Y_TRANSFORM:
745 {
746 bool flip_y = (ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^
747 (ctx->Const.PointCoordOriginUpperLeft) ^
748 (ctx->DrawBuffer->FlipY);
749
750 value[0] = flip_y ? -1.0F : 1.0F;
751 value[1] = flip_y ? 1.0F : 0.0F;
752 value[2] = 0.0F;
753 value[3] = 0.0F;
754 }
755 return;
756
757 case STATE_TCS_PATCH_VERTICES_IN:
758 val[0].i = ctx->TessCtrlProgram.patch_vertices;
759 return;
760
761 case STATE_TES_PATCH_VERTICES_IN:
762 if (ctx->TessCtrlProgram._Current)
763 val[0].i = ctx->TessCtrlProgram._Current->info.tess.tcs_vertices_out;
764 else
765 val[0].i = ctx->TessCtrlProgram.patch_vertices;
766 return;
767
768 case STATE_ADVANCED_BLENDING_MODE:
769 val[0].i = _mesa_get_advanced_blend_sh_constant(
770 ctx->Color.BlendEnabled, ctx->Color._AdvancedBlendMode);
771 return;
772
773 case STATE_ALPHA_REF:
774 value[0] = ctx->Color.AlphaRefUnclamped;
775 return;
776
777 case STATE_CLIP_INTERNAL:
778 {
779 const GLuint plane = (GLuint) state[1];
780 COPY_4V(value, ctx->Transform._ClipUserPlane[plane]);
781 }
782 return;
783
784 case STATE_ATOMIC_COUNTER_OFFSET:
785 {
786 const GLuint counter = (GLuint) state[1];
787 val[0].i = ctx->AtomicBufferBindings[counter].Offset % ctx->Const.ShaderStorageBufferOffsetAlignment;
788 }
789 return;
790 }
791 }
792
793 unsigned
_mesa_program_state_value_size(const gl_state_index16 state[STATE_LENGTH])794 _mesa_program_state_value_size(const gl_state_index16 state[STATE_LENGTH])
795 {
796 if (state[0] == STATE_LIGHT && state[2] == STATE_SPOT_CUTOFF)
797 return 1;
798
799 /* Everything else is packed into vec4s */
800 return 4;
801 }
802
803 /**
804 * Return a bitmask of the Mesa state flags (_NEW_* values) which would
805 * indicate that the given context state may have changed.
806 * The bitmask is used during validation to determine if we need to update
807 * vertex/fragment program parameters (like "state.material.color") when
808 * some GL state has changed.
809 */
810 GLbitfield
_mesa_program_state_flags(const gl_state_index16 state[STATE_LENGTH])811 _mesa_program_state_flags(const gl_state_index16 state[STATE_LENGTH])
812 {
813 switch (state[0]) {
814 case STATE_MATERIAL:
815 return _NEW_MATERIAL;
816
817 case STATE_LIGHTPROD:
818 case STATE_LIGHTPROD_ARRAY_FRONT:
819 case STATE_LIGHTPROD_ARRAY_BACK:
820 case STATE_LIGHTPROD_ARRAY_TWOSIDE:
821 case STATE_LIGHTMODEL_SCENECOLOR:
822 return _NEW_LIGHT_CONSTANTS | _NEW_MATERIAL;
823
824 case STATE_LIGHT:
825 case STATE_LIGHT_ARRAY:
826 case STATE_LIGHT_ATTENUATION_ARRAY:
827 case STATE_LIGHTMODEL_AMBIENT:
828 case STATE_LIGHT_SPOT_DIR_NORMALIZED:
829 case STATE_LIGHT_POSITION:
830 case STATE_LIGHT_POSITION_ARRAY:
831 case STATE_LIGHT_POSITION_NORMALIZED:
832 case STATE_LIGHT_POSITION_NORMALIZED_ARRAY:
833 case STATE_LIGHT_HALF_VECTOR:
834 return _NEW_LIGHT_CONSTANTS;
835
836 case STATE_TEXGEN:
837 return _NEW_TEXTURE_STATE;
838 case STATE_TEXENV_COLOR:
839 return _NEW_TEXTURE_STATE | _NEW_BUFFERS | _NEW_FRAG_CLAMP;
840
841 case STATE_FOG_COLOR:
842 return _NEW_FOG | _NEW_BUFFERS | _NEW_FRAG_CLAMP;
843 case STATE_FOG_PARAMS:
844 case STATE_FOG_PARAMS_OPTIMIZED:
845 return _NEW_FOG;
846
847 case STATE_CLIPPLANE:
848 return _NEW_TRANSFORM;
849
850 case STATE_POINT_SIZE:
851 case STATE_POINT_ATTENUATION:
852 return _NEW_POINT;
853
854 case STATE_MODELVIEW_MATRIX:
855 case STATE_MODELVIEW_MATRIX_INVERSE:
856 case STATE_MODELVIEW_MATRIX_TRANSPOSE:
857 case STATE_MODELVIEW_MATRIX_INVTRANS:
858 case STATE_NORMAL_SCALE_EYESPACE:
859 case STATE_NORMAL_SCALE:
860 return _NEW_MODELVIEW;
861
862 case STATE_PROJECTION_MATRIX:
863 case STATE_PROJECTION_MATRIX_INVERSE:
864 case STATE_PROJECTION_MATRIX_TRANSPOSE:
865 case STATE_PROJECTION_MATRIX_INVTRANS:
866 return _NEW_PROJECTION;
867 case STATE_MVP_MATRIX:
868 case STATE_MVP_MATRIX_INVERSE:
869 case STATE_MVP_MATRIX_TRANSPOSE:
870 case STATE_MVP_MATRIX_INVTRANS:
871 return _NEW_MODELVIEW | _NEW_PROJECTION;
872 case STATE_TEXTURE_MATRIX:
873 case STATE_TEXTURE_MATRIX_INVERSE:
874 case STATE_TEXTURE_MATRIX_TRANSPOSE:
875 case STATE_TEXTURE_MATRIX_INVTRANS:
876 return _NEW_TEXTURE_MATRIX;
877 case STATE_PROGRAM_MATRIX:
878 case STATE_PROGRAM_MATRIX_INVERSE:
879 case STATE_PROGRAM_MATRIX_TRANSPOSE:
880 case STATE_PROGRAM_MATRIX_INVTRANS:
881 return _NEW_TRACK_MATRIX;
882
883 case STATE_NUM_SAMPLES:
884 case STATE_FB_SIZE:
885 case STATE_FB_WPOS_Y_TRANSFORM:
886 return _NEW_BUFFERS;
887
888 case STATE_FB_PNTC_Y_TRANSFORM:
889 return _NEW_BUFFERS | _NEW_POINT;
890
891 case STATE_DEPTH_RANGE:
892 return _NEW_VIEWPORT;
893
894 case STATE_FRAGMENT_PROGRAM_ENV:
895 case STATE_FRAGMENT_PROGRAM_ENV_ARRAY:
896 case STATE_FRAGMENT_PROGRAM_LOCAL:
897 case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY:
898 case STATE_VERTEX_PROGRAM_ENV:
899 case STATE_VERTEX_PROGRAM_ENV_ARRAY:
900 case STATE_VERTEX_PROGRAM_LOCAL:
901 case STATE_VERTEX_PROGRAM_LOCAL_ARRAY:
902 return _NEW_PROGRAM;
903
904 case STATE_CURRENT_ATTRIB:
905 return _NEW_CURRENT_ATTRIB;
906 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
907 return _NEW_CURRENT_ATTRIB | _NEW_LIGHT_STATE | _NEW_BUFFERS;
908
909 case STATE_POINT_SIZE_CLAMPED:
910 return _NEW_POINT | _NEW_MULTISAMPLE;
911
912 case STATE_PT_SCALE:
913 case STATE_PT_BIAS:
914 return _NEW_PIXEL;
915
916 case STATE_ADVANCED_BLENDING_MODE:
917 case STATE_ALPHA_REF:
918 return _NEW_COLOR;
919
920 case STATE_CLIP_INTERNAL:
921 return _NEW_TRANSFORM | _NEW_PROJECTION;
922
923 /* Needs to return any nonzero value to trigger constant updating */
924 case STATE_ATOMIC_COUNTER_OFFSET:
925 return _NEW_PROGRAM_CONSTANTS;
926
927 case STATE_TCS_PATCH_VERTICES_IN:
928 case STATE_TES_PATCH_VERTICES_IN:
929 case STATE_INTERNAL_DRIVER:
930 return 0; /* internal driver state */
931
932 case STATE_NOT_STATE_VAR:
933 return 0;
934
935 default:
936 _mesa_problem(NULL, "unexpected state[0] in make_state_flags()");
937 return 0;
938 }
939 }
940
941
942 static void
append(char * dst,const char * src)943 append(char *dst, const char *src)
944 {
945 while (*dst)
946 dst++;
947 while (*src)
948 *dst++ = *src++;
949 *dst = 0;
950 }
951
952
953 /**
954 * Convert token 'k' to a string, append it onto 'dst' string.
955 */
956 static void
append_token(char * dst,gl_state_index k)957 append_token(char *dst, gl_state_index k)
958 {
959 switch (k) {
960 case STATE_MATERIAL:
961 append(dst, "material");
962 break;
963 case STATE_LIGHT:
964 append(dst, "light");
965 break;
966 case STATE_LIGHT_ARRAY:
967 append(dst, "light.array");
968 break;
969 case STATE_LIGHT_ATTENUATION_ARRAY:
970 append(dst, "light.attenuation");
971 break;
972 case STATE_LIGHTMODEL_AMBIENT:
973 append(dst, "lightmodel.ambient");
974 break;
975 case STATE_LIGHTMODEL_SCENECOLOR:
976 break;
977 case STATE_LIGHTPROD:
978 append(dst, "lightprod");
979 break;
980 case STATE_LIGHTPROD_ARRAY_FRONT:
981 append(dst, "lightprod.array.front");
982 break;
983 case STATE_LIGHTPROD_ARRAY_BACK:
984 append(dst, "lightprod.array.back");
985 break;
986 case STATE_LIGHTPROD_ARRAY_TWOSIDE:
987 append(dst, "lightprod.array.twoside");
988 break;
989 case STATE_TEXGEN:
990 append(dst, "texgen");
991 break;
992 case STATE_FOG_COLOR:
993 append(dst, "fog.color");
994 break;
995 case STATE_FOG_PARAMS:
996 append(dst, "fog.params");
997 break;
998 case STATE_CLIPPLANE:
999 append(dst, "clip");
1000 break;
1001 case STATE_POINT_SIZE:
1002 append(dst, "point.size");
1003 break;
1004 case STATE_POINT_ATTENUATION:
1005 append(dst, "point.attenuation");
1006 break;
1007 case STATE_MODELVIEW_MATRIX:
1008 append(dst, "matrix.modelview.");
1009 break;
1010 case STATE_MODELVIEW_MATRIX_INVERSE:
1011 append(dst, "matrix.modelview.inverse.");
1012 break;
1013 case STATE_MODELVIEW_MATRIX_TRANSPOSE:
1014 append(dst, "matrix.modelview.transpose.");
1015 break;
1016 case STATE_MODELVIEW_MATRIX_INVTRANS:
1017 append(dst, "matrix.modelview.invtrans.");
1018 break;
1019 case STATE_PROJECTION_MATRIX:
1020 append(dst, "matrix.projection.");
1021 break;
1022 case STATE_PROJECTION_MATRIX_INVERSE:
1023 append(dst, "matrix.projection.inverse.");
1024 break;
1025 case STATE_PROJECTION_MATRIX_TRANSPOSE:
1026 append(dst, "matrix.projection.transpose.");
1027 break;
1028 case STATE_PROJECTION_MATRIX_INVTRANS:
1029 append(dst, "matrix.projection.invtrans.");
1030 break;
1031 case STATE_MVP_MATRIX:
1032 append(dst, "matrix.mvp.");
1033 break;
1034 case STATE_MVP_MATRIX_INVERSE:
1035 append(dst, "matrix.mvp.inverse.");
1036 break;
1037 case STATE_MVP_MATRIX_TRANSPOSE:
1038 append(dst, "matrix.mvp.transpose.");
1039 break;
1040 case STATE_MVP_MATRIX_INVTRANS:
1041 append(dst, "matrix.mvp.invtrans.");
1042 break;
1043 case STATE_TEXTURE_MATRIX:
1044 append(dst, "matrix.texture");
1045 break;
1046 case STATE_TEXTURE_MATRIX_INVERSE:
1047 append(dst, "matrix.texture.inverse");
1048 break;
1049 case STATE_TEXTURE_MATRIX_TRANSPOSE:
1050 append(dst, "matrix.texture.transpose");
1051 break;
1052 case STATE_TEXTURE_MATRIX_INVTRANS:
1053 append(dst, "matrix.texture.invtrans");
1054 break;
1055 case STATE_PROGRAM_MATRIX:
1056 append(dst, "matrix.program");
1057 break;
1058 case STATE_PROGRAM_MATRIX_INVERSE:
1059 append(dst, "matrix.program.inverse");
1060 break;
1061 case STATE_PROGRAM_MATRIX_TRANSPOSE:
1062 append(dst, "matrix.program.transpose");
1063 break;
1064 case STATE_PROGRAM_MATRIX_INVTRANS:
1065 append(dst, "matrix.program.invtrans");
1066 break;
1067 break;
1068 case STATE_AMBIENT:
1069 append(dst, "ambient");
1070 break;
1071 case STATE_DIFFUSE:
1072 append(dst, "diffuse");
1073 break;
1074 case STATE_SPECULAR:
1075 append(dst, "specular");
1076 break;
1077 case STATE_EMISSION:
1078 append(dst, "emission");
1079 break;
1080 case STATE_SHININESS:
1081 append(dst, "shininess");
1082 break;
1083 case STATE_HALF_VECTOR:
1084 append(dst, "half");
1085 break;
1086 case STATE_POSITION:
1087 append(dst, "position");
1088 break;
1089 case STATE_ATTENUATION:
1090 append(dst, "attenuation");
1091 break;
1092 case STATE_SPOT_DIRECTION:
1093 append(dst, "spot.direction");
1094 break;
1095 case STATE_SPOT_CUTOFF:
1096 append(dst, "spot.cutoff");
1097 break;
1098 case STATE_TEXGEN_EYE_S:
1099 append(dst, "eye.s");
1100 break;
1101 case STATE_TEXGEN_EYE_T:
1102 append(dst, "eye.t");
1103 break;
1104 case STATE_TEXGEN_EYE_R:
1105 append(dst, "eye.r");
1106 break;
1107 case STATE_TEXGEN_EYE_Q:
1108 append(dst, "eye.q");
1109 break;
1110 case STATE_TEXGEN_OBJECT_S:
1111 append(dst, "object.s");
1112 break;
1113 case STATE_TEXGEN_OBJECT_T:
1114 append(dst, "object.t");
1115 break;
1116 case STATE_TEXGEN_OBJECT_R:
1117 append(dst, "object.r");
1118 break;
1119 case STATE_TEXGEN_OBJECT_Q:
1120 append(dst, "object.q");
1121 break;
1122 case STATE_TEXENV_COLOR:
1123 append(dst, "texenv");
1124 break;
1125 case STATE_NUM_SAMPLES:
1126 append(dst, "numsamples");
1127 break;
1128 case STATE_DEPTH_RANGE:
1129 append(dst, "depth.range");
1130 break;
1131 case STATE_VERTEX_PROGRAM_ENV:
1132 case STATE_FRAGMENT_PROGRAM_ENV:
1133 append(dst, "env");
1134 break;
1135 case STATE_VERTEX_PROGRAM_ENV_ARRAY:
1136 case STATE_FRAGMENT_PROGRAM_ENV_ARRAY:
1137 append(dst, "env.range");
1138 break;
1139 case STATE_VERTEX_PROGRAM_LOCAL:
1140 case STATE_FRAGMENT_PROGRAM_LOCAL:
1141 append(dst, "local");
1142 break;
1143 case STATE_VERTEX_PROGRAM_LOCAL_ARRAY:
1144 case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY:
1145 append(dst, "local.range");
1146 break;
1147 case STATE_CURRENT_ATTRIB:
1148 append(dst, "current");
1149 break;
1150 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
1151 append(dst, "currentAttribMaybeVPClamped");
1152 break;
1153 case STATE_NORMAL_SCALE_EYESPACE:
1154 append(dst, "normalScaleEyeSpace");
1155 break;
1156 case STATE_NORMAL_SCALE:
1157 append(dst, "normalScale");
1158 break;
1159 case STATE_FOG_PARAMS_OPTIMIZED:
1160 append(dst, "fogParamsOptimized");
1161 break;
1162 case STATE_POINT_SIZE_CLAMPED:
1163 append(dst, "pointSizeClamped");
1164 break;
1165 case STATE_LIGHT_SPOT_DIR_NORMALIZED:
1166 append(dst, "lightSpotDirNormalized");
1167 break;
1168 case STATE_LIGHT_POSITION:
1169 append(dst, "light.position");
1170 break;
1171 case STATE_LIGHT_POSITION_ARRAY:
1172 append(dst, "light.position.array");
1173 break;
1174 case STATE_LIGHT_POSITION_NORMALIZED:
1175 append(dst, "light.position.normalized");
1176 break;
1177 case STATE_LIGHT_POSITION_NORMALIZED_ARRAY:
1178 append(dst, "light.position.normalized.array");
1179 break;
1180 case STATE_LIGHT_HALF_VECTOR:
1181 append(dst, "lightHalfVector");
1182 break;
1183 case STATE_PT_SCALE:
1184 append(dst, "PTscale");
1185 break;
1186 case STATE_PT_BIAS:
1187 append(dst, "PTbias");
1188 break;
1189 case STATE_FB_SIZE:
1190 append(dst, "FbSize");
1191 break;
1192 case STATE_FB_WPOS_Y_TRANSFORM:
1193 append(dst, "FbWposYTransform");
1194 break;
1195 case STATE_FB_PNTC_Y_TRANSFORM:
1196 append(dst, "PntcYTransform");
1197 break;
1198 case STATE_ADVANCED_BLENDING_MODE:
1199 append(dst, "AdvancedBlendingMode");
1200 break;
1201 case STATE_ALPHA_REF:
1202 append(dst, "alphaRef");
1203 break;
1204 case STATE_CLIP_INTERNAL:
1205 append(dst, "clipInternal");
1206 break;
1207 case STATE_ATOMIC_COUNTER_OFFSET:
1208 append(dst, "counterOffset");
1209 break;
1210 default:
1211 /* probably STATE_INTERNAL_DRIVER+i (driver private state) */
1212 append(dst, "driverState");
1213 }
1214 }
1215
1216 static void
append_index(char * dst,GLint index,bool structure)1217 append_index(char *dst, GLint index, bool structure)
1218 {
1219 char s[20];
1220 sprintf(s, "[%d]%s", index, structure ? "." : "");
1221 append(dst, s);
1222 }
1223
1224 /**
1225 * Make a string from the given state vector.
1226 * For example, return "state.matrix.texture[2].inverse".
1227 * Use free() to deallocate the string.
1228 */
1229 char *
_mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH])1230 _mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH])
1231 {
1232 char str[1000] = "";
1233 char tmp[30];
1234
1235 append(str, "state.");
1236 append_token(str, state[0]);
1237
1238 switch (state[0]) {
1239 case STATE_LIGHT:
1240 append_index(str, state[1], true); /* light number [i]. */
1241 append_token(str, state[2]); /* coefficients */
1242 break;
1243 case STATE_LIGHTMODEL_AMBIENT:
1244 break;
1245 case STATE_LIGHTMODEL_SCENECOLOR:
1246 if (state[1] == 0) {
1247 append(str, "lightmodel.front.scenecolor");
1248 }
1249 else {
1250 append(str, "lightmodel.back.scenecolor");
1251 }
1252 break;
1253 case STATE_LIGHTPROD:
1254 append_index(str, state[1], false); /* light number [i] */
1255 append_index(str, state[2], false);
1256 break;
1257 case STATE_TEXGEN:
1258 append_index(str, state[1], true); /* tex unit [i] */
1259 append_token(str, state[2]); /* plane coef */
1260 break;
1261 case STATE_TEXENV_COLOR:
1262 append_index(str, state[1], true); /* tex unit [i] */
1263 append(str, "color");
1264 break;
1265 case STATE_CLIPPLANE:
1266 append_index(str, state[1], true); /* plane [i] */
1267 append(str, "plane");
1268 break;
1269 case STATE_MODELVIEW_MATRIX:
1270 case STATE_MODELVIEW_MATRIX_INVERSE:
1271 case STATE_MODELVIEW_MATRIX_TRANSPOSE:
1272 case STATE_MODELVIEW_MATRIX_INVTRANS:
1273 case STATE_PROJECTION_MATRIX:
1274 case STATE_PROJECTION_MATRIX_INVERSE:
1275 case STATE_PROJECTION_MATRIX_TRANSPOSE:
1276 case STATE_PROJECTION_MATRIX_INVTRANS:
1277 case STATE_MVP_MATRIX:
1278 case STATE_MVP_MATRIX_INVERSE:
1279 case STATE_MVP_MATRIX_TRANSPOSE:
1280 case STATE_MVP_MATRIX_INVTRANS:
1281 case STATE_TEXTURE_MATRIX:
1282 case STATE_TEXTURE_MATRIX_INVERSE:
1283 case STATE_TEXTURE_MATRIX_TRANSPOSE:
1284 case STATE_TEXTURE_MATRIX_INVTRANS:
1285 case STATE_PROGRAM_MATRIX:
1286 case STATE_PROGRAM_MATRIX_INVERSE:
1287 case STATE_PROGRAM_MATRIX_TRANSPOSE:
1288 case STATE_PROGRAM_MATRIX_INVTRANS:
1289 {
1290 /* state[0] = modelview, projection, texture, etc. */
1291 /* state[1] = which texture matrix or program matrix */
1292 /* state[2] = first row to fetch */
1293 /* state[3] = last row to fetch */
1294 const gl_state_index mat = state[0];
1295 const GLuint index = (GLuint) state[1];
1296 const GLuint firstRow = (GLuint) state[2];
1297 const GLuint lastRow = (GLuint) state[3];
1298 if (index ||
1299 (mat >= STATE_TEXTURE_MATRIX &&
1300 mat <= STATE_PROGRAM_MATRIX_INVTRANS))
1301 append_index(str, index, true);
1302 if (firstRow == lastRow)
1303 sprintf(tmp, "row[%d]", firstRow);
1304 else
1305 sprintf(tmp, "row[%d..%d]", firstRow, lastRow);
1306 append(str, tmp);
1307 }
1308 break;
1309 case STATE_LIGHT_ARRAY:
1310 case STATE_LIGHT_ATTENUATION_ARRAY:
1311 case STATE_FRAGMENT_PROGRAM_ENV_ARRAY:
1312 case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY:
1313 case STATE_VERTEX_PROGRAM_ENV_ARRAY:
1314 case STATE_VERTEX_PROGRAM_LOCAL_ARRAY:
1315 case STATE_LIGHTPROD_ARRAY_FRONT:
1316 case STATE_LIGHTPROD_ARRAY_BACK:
1317 case STATE_LIGHTPROD_ARRAY_TWOSIDE:
1318 case STATE_LIGHT_POSITION_ARRAY:
1319 case STATE_LIGHT_POSITION_NORMALIZED_ARRAY:
1320 sprintf(tmp, "[%d..%d]", state[1], state[1] + state[2] - 1);
1321 append(str, tmp);
1322 break;
1323 case STATE_MATERIAL:
1324 case STATE_FRAGMENT_PROGRAM_ENV:
1325 case STATE_FRAGMENT_PROGRAM_LOCAL:
1326 case STATE_VERTEX_PROGRAM_ENV:
1327 case STATE_VERTEX_PROGRAM_LOCAL:
1328 case STATE_CURRENT_ATTRIB:
1329 case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED:
1330 case STATE_LIGHT_SPOT_DIR_NORMALIZED:
1331 case STATE_LIGHT_POSITION:
1332 case STATE_LIGHT_POSITION_NORMALIZED:
1333 case STATE_LIGHT_HALF_VECTOR:
1334 case STATE_CLIP_INTERNAL:
1335 case STATE_ATOMIC_COUNTER_OFFSET:
1336 append_index(str, state[1], false);
1337 break;
1338 case STATE_POINT_SIZE:
1339 case STATE_POINT_ATTENUATION:
1340 case STATE_FOG_PARAMS:
1341 case STATE_FOG_COLOR:
1342 case STATE_NUM_SAMPLES:
1343 case STATE_DEPTH_RANGE:
1344 case STATE_NORMAL_SCALE_EYESPACE:
1345 case STATE_NORMAL_SCALE:
1346 case STATE_FOG_PARAMS_OPTIMIZED:
1347 case STATE_POINT_SIZE_CLAMPED:
1348 case STATE_PT_SCALE:
1349 case STATE_PT_BIAS:
1350 case STATE_FB_SIZE:
1351 case STATE_FB_WPOS_Y_TRANSFORM:
1352 case STATE_FB_PNTC_Y_TRANSFORM:
1353 case STATE_TCS_PATCH_VERTICES_IN:
1354 case STATE_TES_PATCH_VERTICES_IN:
1355 case STATE_ADVANCED_BLENDING_MODE:
1356 case STATE_ALPHA_REF:
1357 break;
1358 case STATE_NOT_STATE_VAR:
1359 append(str, "not_state");
1360 break;
1361 default:
1362 _mesa_problem(NULL, "Invalid state in _mesa_program_state_string: %d", state[0]);
1363 break;
1364 }
1365
1366 return strdup(str);
1367 }
1368
1369
1370 /**
1371 * Loop over all the parameters in a parameter list. If the parameter
1372 * is a GL state reference, look up the current value of that state
1373 * variable and put it into the parameter's Value[4] array.
1374 * Other parameter types never change or are explicitly set by the user
1375 * with glUniform() or glProgramParameter(), etc.
1376 * This would be called at glBegin time.
1377 */
1378 void
_mesa_load_state_parameters(struct gl_context * ctx,struct gl_program_parameter_list * paramList)1379 _mesa_load_state_parameters(struct gl_context *ctx,
1380 struct gl_program_parameter_list *paramList)
1381 {
1382 if (!paramList)
1383 return;
1384
1385 int last = paramList->LastStateVarIndex;
1386
1387 for (int i = paramList->FirstStateVarIndex; i <= last; i++) {
1388 unsigned pvo = paramList->Parameters[i].ValueOffset;
1389 fetch_state(ctx, paramList->Parameters[i].StateIndexes,
1390 paramList->ParameterValues + pvo);
1391 }
1392 }
1393
1394 void
_mesa_upload_state_parameters(struct gl_context * ctx,struct gl_program_parameter_list * paramList,uint32_t * dst)1395 _mesa_upload_state_parameters(struct gl_context *ctx,
1396 struct gl_program_parameter_list *paramList,
1397 uint32_t *dst)
1398 {
1399 int last = paramList->LastStateVarIndex;
1400
1401 for (int i = paramList->FirstStateVarIndex; i <= last; i++) {
1402 unsigned pvo = paramList->Parameters[i].ValueOffset;
1403 fetch_state(ctx, paramList->Parameters[i].StateIndexes,
1404 (gl_constant_value*)(dst + pvo));
1405 }
1406 }
1407
1408 /* Merge consecutive state vars into one for the state vars that allow
1409 * multiple vec4s.
1410 *
1411 * This should be done after shader compilation, so that drivers don't
1412 * have to deal with multi-slot state parameters in their backends.
1413 * It's only meant to optimize _mesa_load/upload_state_parameters.
1414 */
1415 void
_mesa_optimize_state_parameters(struct gl_constants * consts,struct gl_program_parameter_list * list)1416 _mesa_optimize_state_parameters(struct gl_constants *consts,
1417 struct gl_program_parameter_list *list)
1418 {
1419 for (int first_param = list->FirstStateVarIndex;
1420 first_param < (int)list->NumParameters; first_param++) {
1421 int last_param = first_param;
1422 int param_diff = 0;
1423
1424 switch (list->Parameters[first_param].StateIndexes[0]) {
1425 case STATE_MODELVIEW_MATRIX:
1426 case STATE_MODELVIEW_MATRIX_INVERSE:
1427 case STATE_MODELVIEW_MATRIX_TRANSPOSE:
1428 case STATE_MODELVIEW_MATRIX_INVTRANS:
1429 case STATE_PROJECTION_MATRIX:
1430 case STATE_PROJECTION_MATRIX_INVERSE:
1431 case STATE_PROJECTION_MATRIX_TRANSPOSE:
1432 case STATE_PROJECTION_MATRIX_INVTRANS:
1433 case STATE_MVP_MATRIX:
1434 case STATE_MVP_MATRIX_INVERSE:
1435 case STATE_MVP_MATRIX_TRANSPOSE:
1436 case STATE_MVP_MATRIX_INVTRANS:
1437 case STATE_TEXTURE_MATRIX:
1438 case STATE_TEXTURE_MATRIX_INVERSE:
1439 case STATE_TEXTURE_MATRIX_TRANSPOSE:
1440 case STATE_TEXTURE_MATRIX_INVTRANS:
1441 case STATE_PROGRAM_MATRIX:
1442 case STATE_PROGRAM_MATRIX_INVERSE:
1443 case STATE_PROGRAM_MATRIX_TRANSPOSE:
1444 case STATE_PROGRAM_MATRIX_INVTRANS:
1445 /* Skip unaligned state vars. */
1446 if (list->Parameters[first_param].Size % 4)
1447 break;
1448
1449 /* Search for adjacent state vars that refer to adjacent rows. */
1450 for (int i = first_param + 1; i < (int)list->NumParameters; i++) {
1451 if (list->Parameters[i].StateIndexes[0] ==
1452 list->Parameters[i - 1].StateIndexes[0] &&
1453 list->Parameters[i].StateIndexes[1] ==
1454 list->Parameters[i - 1].StateIndexes[1] &&
1455 list->Parameters[i].StateIndexes[2] == /* FirstRow */
1456 list->Parameters[i - 1].StateIndexes[3] + 1 && /* LastRow + 1 */
1457 list->Parameters[i].Size == 4) {
1458 last_param = i;
1459 continue;
1460 }
1461 break; /* The adjacent state var is incompatible. */
1462 }
1463 if (last_param > first_param) {
1464 int first_vec = list->Parameters[first_param].StateIndexes[2];
1465 int last_vec = list->Parameters[last_param].StateIndexes[3];
1466
1467 assert(first_vec < last_vec);
1468 assert(last_vec - first_vec == last_param - first_param);
1469
1470 /* Update LastRow. */
1471 list->Parameters[first_param].StateIndexes[3] = last_vec;
1472 list->Parameters[first_param].Size = (last_vec - first_vec + 1) * 4;
1473
1474 param_diff = last_param - first_param;
1475 }
1476 break;
1477
1478 case STATE_LIGHT:
1479 /* Skip trimmed state vars. (this shouldn't occur though) */
1480 if (list->Parameters[first_param].Size !=
1481 _mesa_program_state_value_size(list->Parameters[first_param].StateIndexes))
1482 break;
1483
1484 /* Search for light attributes that are adjacent in memory. */
1485 for (int i = first_param + 1; i < (int)list->NumParameters; i++) {
1486 if (list->Parameters[i].StateIndexes[0] == STATE_LIGHT &&
1487 /* Consecutive attributes of the same light: */
1488 ((list->Parameters[i].StateIndexes[1] ==
1489 list->Parameters[i - 1].StateIndexes[1] &&
1490 list->Parameters[i].StateIndexes[2] ==
1491 list->Parameters[i - 1].StateIndexes[2] + 1) ||
1492 /* Consecutive attributes between 2 lights: */
1493 /* SPOT_CUTOFF should have only 1 component, which isn't true
1494 * with unpacked uniform storage. */
1495 (consts->PackedDriverUniformStorage &&
1496 list->Parameters[i].StateIndexes[1] ==
1497 list->Parameters[i - 1].StateIndexes[1] + 1 &&
1498 list->Parameters[i].StateIndexes[2] == STATE_AMBIENT &&
1499 list->Parameters[i - 1].StateIndexes[2] == STATE_SPOT_CUTOFF))) {
1500 last_param = i;
1501 continue;
1502 }
1503 break; /* The adjacent state var is incompatible. */
1504 }
1505 if (last_param > first_param) {
1506 /* Convert the state var to STATE_LIGHT_ARRAY. */
1507 list->Parameters[first_param].StateIndexes[0] = STATE_LIGHT_ARRAY;
1508 /* Set the offset in floats. */
1509 list->Parameters[first_param].StateIndexes[1] =
1510 list->Parameters[first_param].StateIndexes[1] * /* light index */
1511 sizeof(struct gl_light_uniforms) / 4 +
1512 (list->Parameters[first_param].StateIndexes[2] - STATE_AMBIENT) * 4;
1513
1514 /* Set the real size in floats that we will upload (memcpy). */
1515 list->Parameters[first_param].StateIndexes[2] =
1516 _mesa_program_state_value_size(list->Parameters[last_param].StateIndexes) +
1517 list->Parameters[last_param].ValueOffset -
1518 list->Parameters[first_param].ValueOffset;
1519
1520 /* Set the allocated size, which can be aligned to 4 components. */
1521 list->Parameters[first_param].Size =
1522 list->Parameters[last_param].Size +
1523 list->Parameters[last_param].ValueOffset -
1524 list->Parameters[first_param].ValueOffset;
1525
1526 param_diff = last_param - first_param;
1527 break; /* all done */
1528 }
1529
1530 /* We were not able to convert light attributes to STATE_LIGHT_ARRAY.
1531 * Another occuring pattern is light attentuation vectors placed back
1532 * to back. Find them.
1533 */
1534 if (list->Parameters[first_param].StateIndexes[2] == STATE_ATTENUATION) {
1535 for (int i = first_param + 1; i < (int)list->NumParameters; i++) {
1536 if (list->Parameters[i].StateIndexes[0] == STATE_LIGHT &&
1537 /* Consecutive light: */
1538 list->Parameters[i].StateIndexes[1] ==
1539 list->Parameters[i - 1].StateIndexes[1] + 1 &&
1540 /* Same attribute: */
1541 list->Parameters[i].StateIndexes[2] ==
1542 list->Parameters[i - 1].StateIndexes[2]) {
1543 last_param = i;
1544 continue;
1545 }
1546 break; /* The adjacent state var is incompatible. */
1547 }
1548 if (last_param > first_param) {
1549 param_diff = last_param - first_param;
1550
1551 /* Convert the state var to STATE_LIGHT_ATTENUATION_ARRAY. */
1552 list->Parameters[first_param].StateIndexes[0] =
1553 STATE_LIGHT_ATTENUATION_ARRAY;
1554 /* Keep the light index the same. */
1555 /* Set the number of lights. */
1556 unsigned size = param_diff + 1;
1557 list->Parameters[first_param].StateIndexes[2] = size;
1558 list->Parameters[first_param].Size = size * 4;
1559 break; /* all done */
1560 }
1561 }
1562 break;
1563
1564 case STATE_VERTEX_PROGRAM_ENV:
1565 case STATE_VERTEX_PROGRAM_LOCAL:
1566 case STATE_FRAGMENT_PROGRAM_ENV:
1567 case STATE_FRAGMENT_PROGRAM_LOCAL:
1568 if (list->Parameters[first_param].Size != 4)
1569 break;
1570
1571 /* Search for adjacent mergeable state vars. */
1572 for (int i = first_param + 1; i < (int)list->NumParameters; i++) {
1573 if (list->Parameters[i].StateIndexes[0] ==
1574 list->Parameters[i - 1].StateIndexes[0] &&
1575 list->Parameters[i].StateIndexes[1] ==
1576 list->Parameters[i - 1].StateIndexes[1] + 1 &&
1577 list->Parameters[i].Size == 4) {
1578 last_param = i;
1579 continue;
1580 }
1581 break; /* The adjacent state var is incompatible. */
1582 }
1583 if (last_param > first_param) {
1584 /* Set STATE_xxx_RANGE. */
1585 STATIC_ASSERT(STATE_VERTEX_PROGRAM_ENV + 1 ==
1586 STATE_VERTEX_PROGRAM_ENV_ARRAY);
1587 STATIC_ASSERT(STATE_VERTEX_PROGRAM_LOCAL + 1 ==
1588 STATE_VERTEX_PROGRAM_LOCAL_ARRAY);
1589 STATIC_ASSERT(STATE_FRAGMENT_PROGRAM_ENV + 1 ==
1590 STATE_FRAGMENT_PROGRAM_ENV_ARRAY);
1591 STATIC_ASSERT(STATE_FRAGMENT_PROGRAM_LOCAL + 1 ==
1592 STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY);
1593 list->Parameters[first_param].StateIndexes[0]++;
1594
1595 param_diff = last_param - first_param;
1596
1597 /* Set the size. */
1598 unsigned size = param_diff + 1;
1599 list->Parameters[first_param].StateIndexes[2] = size;
1600 list->Parameters[first_param].Size = size * 4;
1601 }
1602 break;
1603
1604 case STATE_LIGHTPROD: {
1605 if (list->Parameters[first_param].Size != 4)
1606 break;
1607
1608 gl_state_index16 state = STATE_NOT_STATE_VAR;
1609 unsigned num_lights = 0;
1610
1611 for (unsigned state_iter = STATE_LIGHTPROD_ARRAY_FRONT;
1612 state_iter <= STATE_LIGHTPROD_ARRAY_TWOSIDE; state_iter++) {
1613 unsigned num_attribs, base_attrib, attrib_incr;
1614
1615 if (state_iter == STATE_LIGHTPROD_ARRAY_FRONT) {
1616 num_attribs = 3;
1617 base_attrib = MAT_ATTRIB_FRONT_AMBIENT;
1618 attrib_incr = 2;
1619 } else if (state_iter == STATE_LIGHTPROD_ARRAY_BACK) {
1620 num_attribs = 3;
1621 base_attrib = MAT_ATTRIB_BACK_AMBIENT;
1622 attrib_incr = 2;
1623 } else if (state_iter == STATE_LIGHTPROD_ARRAY_TWOSIDE) {
1624 num_attribs = 6;
1625 base_attrib = MAT_ATTRIB_FRONT_AMBIENT;
1626 attrib_incr = 1;
1627 }
1628
1629 /* Find all attributes for one light. */
1630 while (first_param + (num_lights + 1) * num_attribs <=
1631 list->NumParameters &&
1632 (state == STATE_NOT_STATE_VAR || state == state_iter)) {
1633 unsigned i = 0, base = first_param + num_lights * num_attribs;
1634
1635 /* Consecutive light indices: */
1636 if (list->Parameters[first_param].StateIndexes[1] + num_lights ==
1637 list->Parameters[base].StateIndexes[1]) {
1638 for (i = 0; i < num_attribs; i++) {
1639 if (list->Parameters[base + i].StateIndexes[0] ==
1640 STATE_LIGHTPROD &&
1641 list->Parameters[base + i].Size == 4 &&
1642 /* Equal light indices: */
1643 list->Parameters[base + i].StateIndexes[1] ==
1644 list->Parameters[base + 0].StateIndexes[1] &&
1645 /* Consecutive attributes: */
1646 list->Parameters[base + i].StateIndexes[2] ==
1647 base_attrib + i * attrib_incr)
1648 continue;
1649 break;
1650 }
1651 }
1652 if (i == num_attribs) {
1653 /* Accept all parameters for merging. */
1654 state = state_iter;
1655 last_param = base + num_attribs - 1;
1656 num_lights++;
1657 } else {
1658 break;
1659 }
1660 }
1661 }
1662
1663 if (last_param > first_param) {
1664 param_diff = last_param - first_param;
1665
1666 list->Parameters[first_param].StateIndexes[0] = state;
1667 list->Parameters[first_param].StateIndexes[2] = num_lights;
1668 list->Parameters[first_param].Size = (param_diff + 1) * 4;
1669 }
1670 break;
1671 }
1672
1673 case STATE_LIGHT_POSITION:
1674 case STATE_LIGHT_POSITION_NORMALIZED:
1675 if (list->Parameters[first_param].Size != 4)
1676 break;
1677
1678 for (int i = first_param + 1; i < (int)list->NumParameters; i++) {
1679 if (list->Parameters[i].StateIndexes[0] ==
1680 list->Parameters[i - 1].StateIndexes[0] &&
1681 /* Consecutive light: */
1682 list->Parameters[i].StateIndexes[1] ==
1683 list->Parameters[i - 1].StateIndexes[1] + 1) {
1684 last_param = i;
1685 continue;
1686 }
1687 break; /* The adjacent state var is incompatible. */
1688 }
1689 if (last_param > first_param) {
1690 param_diff = last_param - first_param;
1691
1692 /* Convert the state var to STATE_LIGHT_POSITION_*ARRAY. */
1693 STATIC_ASSERT(STATE_LIGHT_POSITION + 1 ==
1694 STATE_LIGHT_POSITION_ARRAY);
1695 STATIC_ASSERT(STATE_LIGHT_POSITION_NORMALIZED + 1 ==
1696 STATE_LIGHT_POSITION_NORMALIZED_ARRAY);
1697 list->Parameters[first_param].StateIndexes[0]++;
1698 /* Keep the light index the same. */
1699 unsigned size = param_diff + 1;
1700 /* Set the number of lights. */
1701 list->Parameters[first_param].StateIndexes[2] = size;
1702 list->Parameters[first_param].Size = size * 4;
1703 }
1704 }
1705
1706 if (param_diff) {
1707 /* Update the name. */
1708 free((void*)list->Parameters[first_param].Name);
1709 list->Parameters[first_param].Name =
1710 _mesa_program_state_string(list->Parameters[first_param].StateIndexes);
1711
1712 /* Free names that we are going to overwrite. */
1713 for (int i = first_param + 1; i <= last_param; i++)
1714 free((char*)list->Parameters[i].Name);
1715
1716 /* Remove the merged state vars. */
1717 if (last_param + 1 < list->NumParameters) {
1718 memmove(&list->Parameters[first_param + 1],
1719 &list->Parameters[last_param + 1],
1720 sizeof(list->Parameters[0]) *
1721 (list->NumParameters - last_param - 1));
1722 }
1723 list->NumParameters -= param_diff;
1724 }
1725 }
1726
1727 _mesa_recompute_parameter_bounds(list);
1728 }
1729