13464ebd5Sriastradh/* 23464ebd5Sriastradh * Mesa 3-D graphics library 33464ebd5Sriastradh * 43464ebd5Sriastradh * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 53464ebd5Sriastradh * 63464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a 73464ebd5Sriastradh * copy of this software and associated documentation files (the "Software"), 83464ebd5Sriastradh * to deal in the Software without restriction, including without limitation 93464ebd5Sriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 103464ebd5Sriastradh * and/or sell copies of the Software, and to permit persons to whom the 113464ebd5Sriastradh * Software is furnished to do so, subject to the following conditions: 123464ebd5Sriastradh * 133464ebd5Sriastradh * The above copyright notice and this permission notice shall be included 143464ebd5Sriastradh * in all copies or substantial portions of the Software. 153464ebd5Sriastradh * 163464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 173464ebd5Sriastradh * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 183464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 233464ebd5Sriastradh */ 243464ebd5Sriastradh 253464ebd5Sriastradh/** 263464ebd5Sriastradh * \file prog_statevars.c 273464ebd5Sriastradh * Program state variable management. 283464ebd5Sriastradh * \author Brian Paul 293464ebd5Sriastradh */ 303464ebd5Sriastradh 313464ebd5Sriastradh 3201e04c3fSmrg#include <stdio.h> 337ec681f3Smrg#include <stddef.h> 343464ebd5Sriastradh#include "main/glheader.h" 353464ebd5Sriastradh#include "main/context.h" 36af69d88dSmrg#include "main/blend.h" 377ec681f3Smrg 383464ebd5Sriastradh#include "main/macros.h" 393464ebd5Sriastradh#include "main/mtypes.h" 40af69d88dSmrg#include "main/fbobject.h" 413464ebd5Sriastradh#include "prog_statevars.h" 423464ebd5Sriastradh#include "prog_parameter.h" 43af69d88dSmrg#include "main/samplerobj.h" 4401e04c3fSmrg#include "main/framebuffer.h" 4501e04c3fSmrg 4601e04c3fSmrg 4701e04c3fSmrg#define ONE_DIV_SQRT_LN2 (1.201122408786449815) 483464ebd5Sriastradh 497ec681f3Smrgstatic ALWAYS_INLINE void 507ec681f3Smrgcopy_matrix(float *value, const float *m, unsigned firstRow, unsigned lastRow) 517ec681f3Smrg{ 527ec681f3Smrg unsigned i, row; 537ec681f3Smrg 547ec681f3Smrg assert(firstRow < 4); 557ec681f3Smrg assert(lastRow < 4); 567ec681f3Smrg 577ec681f3Smrg for (i = 0, row = firstRow; row <= lastRow; row++) { 587ec681f3Smrg value[i++] = m[row + 0]; 597ec681f3Smrg value[i++] = m[row + 4]; 607ec681f3Smrg value[i++] = m[row + 8]; 617ec681f3Smrg value[i++] = m[row + 12]; 627ec681f3Smrg } 637ec681f3Smrg} 647ec681f3Smrg 657ec681f3Smrgstatic ALWAYS_INLINE void 667ec681f3Smrgcopy_matrix_transposed(float *value, const float *m, unsigned firstRow, unsigned lastRow) 677ec681f3Smrg{ 687ec681f3Smrg assert(firstRow < 4); 697ec681f3Smrg assert(lastRow < 4); 707ec681f3Smrg 717ec681f3Smrg memcpy(value, &m[firstRow * 4], 727ec681f3Smrg (lastRow - firstRow + 1) * 4 * sizeof(GLfloat)); 737ec681f3Smrg} 743464ebd5Sriastradh 753464ebd5Sriastradh/** 763464ebd5Sriastradh * Use the list of tokens in the state[] array to find global GL state 773464ebd5Sriastradh * and return it in <value>. Usually, four values are returned in <value> 783464ebd5Sriastradh * but matrix queries may return as many as 16 values. 793464ebd5Sriastradh * This function is used for ARB vertex/fragment programs. 803464ebd5Sriastradh * The program parser will produce the state[] values. 813464ebd5Sriastradh */ 823464ebd5Sriastradhstatic void 837ec681f3Smrgfetch_state(struct gl_context *ctx, const gl_state_index16 state[], 847ec681f3Smrg gl_constant_value *val) 853464ebd5Sriastradh{ 8601e04c3fSmrg GLfloat *value = &val->f; 8701e04c3fSmrg 883464ebd5Sriastradh switch (state[0]) { 893464ebd5Sriastradh case STATE_MATERIAL: 903464ebd5Sriastradh { 917ec681f3Smrg /* state[1] is MAT_ATTRIB_FRONT_* */ 927ec681f3Smrg const GLuint index = (GLuint) state[1]; 933464ebd5Sriastradh const struct gl_material *mat = &ctx->Light.Material; 947ec681f3Smrg assert(index >= MAT_ATTRIB_FRONT_AMBIENT && 957ec681f3Smrg index <= MAT_ATTRIB_BACK_SHININESS); 967ec681f3Smrg if (index >= MAT_ATTRIB_FRONT_SHININESS) { 977ec681f3Smrg value[0] = mat->Attrib[index][0]; 983464ebd5Sriastradh value[1] = 0.0F; 993464ebd5Sriastradh value[2] = 0.0F; 1003464ebd5Sriastradh value[3] = 1.0F; 1017ec681f3Smrg } else { 1027ec681f3Smrg COPY_4V(value, mat->Attrib[index]); 1033464ebd5Sriastradh } 1047ec681f3Smrg return; 1053464ebd5Sriastradh } 1063464ebd5Sriastradh case STATE_LIGHT: 1073464ebd5Sriastradh { 1083464ebd5Sriastradh /* state[1] is the light number */ 1093464ebd5Sriastradh const GLuint ln = (GLuint) state[1]; 1103464ebd5Sriastradh /* state[2] is the light attribute */ 1117ec681f3Smrg const unsigned index = state[2] - STATE_AMBIENT; 1127ec681f3Smrg assert(index < 8); 1137ec681f3Smrg if (index != STATE_SPOT_CUTOFF) 1147ec681f3Smrg COPY_4V(value, (float*)&ctx->Light.LightSource[ln] + index * 4); 1157ec681f3Smrg else 1167ec681f3Smrg value[0] = ctx->Light.LightSource[ln].SpotCutoff; 1177ec681f3Smrg return; 1183464ebd5Sriastradh } 1197ec681f3Smrg case STATE_LIGHT_ARRAY: { 1207ec681f3Smrg /* This must be exact because it must match the gl_LightSource layout 1217ec681f3Smrg * in GLSL. 1227ec681f3Smrg */ 1237ec681f3Smrg STATIC_ASSERT(sizeof(struct gl_light_uniforms) == 29 * 4); 1247ec681f3Smrg STATIC_ASSERT(ARRAY_SIZE(ctx->Light.LightSourceData) == 29 * MAX_LIGHTS); 1257ec681f3Smrg /* state[1] is the index of the first value */ 1267ec681f3Smrg /* state[2] is the number of values */ 1277ec681f3Smrg assert(state[1] + state[2] <= ARRAY_SIZE(ctx->Light.LightSourceData)); 1287ec681f3Smrg memcpy(value, &ctx->Light.LightSourceData[state[1]], 1297ec681f3Smrg state[2] * sizeof(float)); 1307ec681f3Smrg return; 1317ec681f3Smrg } 1327ec681f3Smrg case STATE_LIGHT_ATTENUATION_ARRAY: { 1337ec681f3Smrg const unsigned first = state[1]; 1347ec681f3Smrg const unsigned num_lights = state[2]; 1357ec681f3Smrg for (unsigned i = 0; i < num_lights; i++) { 1367ec681f3Smrg COPY_4V(value, 1377ec681f3Smrg &ctx->Light.LightSource[first + i].ConstantAttenuation); 1387ec681f3Smrg value += 4; 1397ec681f3Smrg } 1407ec681f3Smrg return; 1417ec681f3Smrg } 1423464ebd5Sriastradh case STATE_LIGHTMODEL_AMBIENT: 1433464ebd5Sriastradh COPY_4V(value, ctx->Light.Model.Ambient); 1443464ebd5Sriastradh return; 1453464ebd5Sriastradh case STATE_LIGHTMODEL_SCENECOLOR: 1463464ebd5Sriastradh if (state[1] == 0) { 1473464ebd5Sriastradh /* front */ 1483464ebd5Sriastradh GLint i; 1493464ebd5Sriastradh for (i = 0; i < 3; i++) { 1503464ebd5Sriastradh value[i] = ctx->Light.Model.Ambient[i] 1513464ebd5Sriastradh * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] 1523464ebd5Sriastradh + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; 1533464ebd5Sriastradh } 1543464ebd5Sriastradh value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 1553464ebd5Sriastradh } 1563464ebd5Sriastradh else { 1573464ebd5Sriastradh /* back */ 1583464ebd5Sriastradh GLint i; 1593464ebd5Sriastradh for (i = 0; i < 3; i++) { 1603464ebd5Sriastradh value[i] = ctx->Light.Model.Ambient[i] 1613464ebd5Sriastradh * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] 1623464ebd5Sriastradh + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; 1633464ebd5Sriastradh } 1643464ebd5Sriastradh value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 1653464ebd5Sriastradh } 1663464ebd5Sriastradh return; 1673464ebd5Sriastradh case STATE_LIGHTPROD: 1683464ebd5Sriastradh { 1693464ebd5Sriastradh const GLuint ln = (GLuint) state[1]; 1707ec681f3Smrg const GLuint index = (GLuint) state[2]; 1717ec681f3Smrg const GLuint attr = (index / 2) * 4; 1727ec681f3Smrg assert(index >= MAT_ATTRIB_FRONT_AMBIENT && 1737ec681f3Smrg index <= MAT_ATTRIB_BACK_SPECULAR); 1747ec681f3Smrg for (int i = 0; i < 3; i++) { 1757ec681f3Smrg /* We want attr to access out of bounds into the following Diffuse 1767ec681f3Smrg * and Specular fields. This is guaranteed to work because 1777ec681f3Smrg * STATE_LIGHT and STATE_LIGHT_ARRAY also rely on this memory 1787ec681f3Smrg * layout. 1797ec681f3Smrg */ 1807ec681f3Smrg STATIC_ASSERT(offsetof(struct gl_light_uniforms, Ambient) + 16 == 1817ec681f3Smrg offsetof(struct gl_light_uniforms, Diffuse)); 1827ec681f3Smrg STATIC_ASSERT(offsetof(struct gl_light_uniforms, Diffuse) + 16 == 1837ec681f3Smrg offsetof(struct gl_light_uniforms, Specular)); 1847ec681f3Smrg value[i] = ctx->Light.LightSource[ln].Ambient[attr + i] * 1857ec681f3Smrg ctx->Light.Material.Attrib[index][i]; 1867ec681f3Smrg } 1877ec681f3Smrg /* [3] = material alpha */ 1887ec681f3Smrg value[3] = ctx->Light.Material.Attrib[index][3]; 1897ec681f3Smrg return; 1907ec681f3Smrg } 1917ec681f3Smrg case STATE_LIGHTPROD_ARRAY_FRONT: { 1927ec681f3Smrg const unsigned first_light = state[1]; 1937ec681f3Smrg const unsigned num_lights = state[2]; 1947ec681f3Smrg 1957ec681f3Smrg for (unsigned i = 0; i < num_lights; i++) { 1967ec681f3Smrg unsigned light = first_light + i; 1977ec681f3Smrg 1987ec681f3Smrg for (unsigned attrib = MAT_ATTRIB_FRONT_AMBIENT; 1997ec681f3Smrg attrib <= MAT_ATTRIB_FRONT_SPECULAR; attrib += 2) { 2007ec681f3Smrg for (int chan = 0; chan < 3; chan++) { 2017ec681f3Smrg /* We want offset to access out of bounds into the following 2027ec681f3Smrg * Diffuse and Specular fields. This is guaranteed to work 2037ec681f3Smrg * because STATE_LIGHT and STATE_LIGHT_ATTRIBS also rely 2047ec681f3Smrg * on this memory layout. 2057ec681f3Smrg */ 2067ec681f3Smrg unsigned offset = (attrib / 2) * 4 + chan; 2077ec681f3Smrg *value++ = 2087ec681f3Smrg (&ctx->Light.LightSource[light].Ambient[0])[offset] * 2097ec681f3Smrg ctx->Light.Material.Attrib[attrib][chan]; 2107ec681f3Smrg } 2117ec681f3Smrg /* [3] = material alpha */ 2127ec681f3Smrg *value++ = ctx->Light.Material.Attrib[attrib][3]; 2133464ebd5Sriastradh } 2143464ebd5Sriastradh } 2157ec681f3Smrg return; 2167ec681f3Smrg } 2177ec681f3Smrg case STATE_LIGHTPROD_ARRAY_BACK: { 2187ec681f3Smrg const unsigned first_light = state[1]; 2197ec681f3Smrg const unsigned num_lights = state[2]; 2207ec681f3Smrg 2217ec681f3Smrg for (unsigned i = 0; i < num_lights; i++) { 2227ec681f3Smrg unsigned light = first_light + i; 2237ec681f3Smrg 2247ec681f3Smrg for (unsigned attrib = MAT_ATTRIB_BACK_AMBIENT; 2257ec681f3Smrg attrib <= MAT_ATTRIB_BACK_SPECULAR; attrib += 2) { 2267ec681f3Smrg for (int chan = 0; chan < 3; chan++) { 2277ec681f3Smrg /* We want offset to access out of bounds into the following 2287ec681f3Smrg * Diffuse and Specular fields. This is guaranteed to work 2297ec681f3Smrg * because STATE_LIGHT and STATE_LIGHT_ATTRIBS also rely 2307ec681f3Smrg * on this memory layout. 2317ec681f3Smrg */ 2327ec681f3Smrg unsigned offset = (attrib / 2) * 4 + chan; 2337ec681f3Smrg *value++ = 2347ec681f3Smrg (&ctx->Light.LightSource[light].Ambient[0])[offset] * 2357ec681f3Smrg ctx->Light.Material.Attrib[attrib][chan]; 2367ec681f3Smrg } 2377ec681f3Smrg /* [3] = material alpha */ 2387ec681f3Smrg *value++ = ctx->Light.Material.Attrib[attrib][3]; 2397ec681f3Smrg } 2407ec681f3Smrg } 2417ec681f3Smrg return; 2427ec681f3Smrg } 2437ec681f3Smrg case STATE_LIGHTPROD_ARRAY_TWOSIDE: { 2447ec681f3Smrg const unsigned first_light = state[1]; 2457ec681f3Smrg const unsigned num_lights = state[2]; 2467ec681f3Smrg 2477ec681f3Smrg for (unsigned i = 0; i < num_lights; i++) { 2487ec681f3Smrg unsigned light = first_light + i; 2497ec681f3Smrg 2507ec681f3Smrg for (unsigned attrib = MAT_ATTRIB_FRONT_AMBIENT; 2517ec681f3Smrg attrib <= MAT_ATTRIB_BACK_SPECULAR; attrib++) { 2527ec681f3Smrg for (int chan = 0; chan < 3; chan++) { 2537ec681f3Smrg /* We want offset to access out of bounds into the following 2547ec681f3Smrg * Diffuse and Specular fields. This is guaranteed to work 2557ec681f3Smrg * because STATE_LIGHT and STATE_LIGHT_ATTRIBS also rely 2567ec681f3Smrg * on this memory layout. 2577ec681f3Smrg */ 2587ec681f3Smrg unsigned offset = (attrib / 2) * 4 + chan; 2597ec681f3Smrg *value++ = 2607ec681f3Smrg (&ctx->Light.LightSource[light].Ambient[0])[offset] * 2617ec681f3Smrg ctx->Light.Material.Attrib[attrib][chan]; 2627ec681f3Smrg } 2637ec681f3Smrg /* [3] = material alpha */ 2647ec681f3Smrg *value++ = ctx->Light.Material.Attrib[attrib][3]; 2657ec681f3Smrg } 2667ec681f3Smrg } 2677ec681f3Smrg return; 2687ec681f3Smrg } 2693464ebd5Sriastradh case STATE_TEXGEN: 2703464ebd5Sriastradh { 2713464ebd5Sriastradh /* state[1] is the texture unit */ 2723464ebd5Sriastradh const GLuint unit = (GLuint) state[1]; 2733464ebd5Sriastradh /* state[2] is the texgen attribute */ 2747ec681f3Smrg /* Assertions for the expected memory layout. */ 2757ec681f3Smrg#define MEMBER_SIZEOF(type, member) sizeof(((type *)0)->member) 2767ec681f3Smrg STATIC_ASSERT(MEMBER_SIZEOF(struct gl_fixedfunc_texture_unit, 2777ec681f3Smrg EyePlane[0]) == 4 * sizeof(float)); 2787ec681f3Smrg STATIC_ASSERT(MEMBER_SIZEOF(struct gl_fixedfunc_texture_unit, 2797ec681f3Smrg ObjectPlane[0]) == 4 * sizeof(float)); 2807ec681f3Smrg#undef MEMBER_SIZEOF 2817ec681f3Smrg STATIC_ASSERT(STATE_TEXGEN_EYE_T - STATE_TEXGEN_EYE_S == GEN_T - GEN_S); 2827ec681f3Smrg STATIC_ASSERT(STATE_TEXGEN_EYE_R - STATE_TEXGEN_EYE_S == GEN_R - GEN_S); 2837ec681f3Smrg STATIC_ASSERT(STATE_TEXGEN_EYE_Q - STATE_TEXGEN_EYE_S == GEN_Q - GEN_S); 2847ec681f3Smrg STATIC_ASSERT(offsetof(struct gl_fixedfunc_texture_unit, ObjectPlane) - 2857ec681f3Smrg offsetof(struct gl_fixedfunc_texture_unit, EyePlane) == 2867ec681f3Smrg (STATE_TEXGEN_OBJECT_S - STATE_TEXGEN_EYE_S) * 4 * sizeof(float)); 2877ec681f3Smrg STATIC_ASSERT(STATE_TEXGEN_OBJECT_T - STATE_TEXGEN_OBJECT_S == GEN_T - GEN_S); 2887ec681f3Smrg STATIC_ASSERT(STATE_TEXGEN_OBJECT_R - STATE_TEXGEN_OBJECT_S == GEN_R - GEN_S); 2897ec681f3Smrg STATIC_ASSERT(STATE_TEXGEN_OBJECT_Q - STATE_TEXGEN_OBJECT_S == GEN_Q - GEN_S); 2907ec681f3Smrg 2917ec681f3Smrg const float *attr = (float*)ctx->Texture.FixedFuncUnit[unit].EyePlane + 2927ec681f3Smrg (state[2] - STATE_TEXGEN_EYE_S) * 4; 2937ec681f3Smrg COPY_4V(value, attr); 2947ec681f3Smrg return; 2953464ebd5Sriastradh } 2963464ebd5Sriastradh case STATE_TEXENV_COLOR: 2973464ebd5Sriastradh { 2983464ebd5Sriastradh /* state[1] is the texture unit */ 2993464ebd5Sriastradh const GLuint unit = (GLuint) state[1]; 30001e04c3fSmrg if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) 30101e04c3fSmrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColor); 3023464ebd5Sriastradh else 30301e04c3fSmrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColorUnclamped); 3043464ebd5Sriastradh } 3053464ebd5Sriastradh return; 3063464ebd5Sriastradh case STATE_FOG_COLOR: 30701e04c3fSmrg if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) 3083464ebd5Sriastradh COPY_4V(value, ctx->Fog.Color); 3093464ebd5Sriastradh else 3103464ebd5Sriastradh COPY_4V(value, ctx->Fog.ColorUnclamped); 3113464ebd5Sriastradh return; 3123464ebd5Sriastradh case STATE_FOG_PARAMS: 3133464ebd5Sriastradh value[0] = ctx->Fog.Density; 3143464ebd5Sriastradh value[1] = ctx->Fog.Start; 3153464ebd5Sriastradh value[2] = ctx->Fog.End; 316af69d88dSmrg value[3] = 1.0f / (ctx->Fog.End - ctx->Fog.Start); 3173464ebd5Sriastradh return; 3183464ebd5Sriastradh case STATE_CLIPPLANE: 3193464ebd5Sriastradh { 3203464ebd5Sriastradh const GLuint plane = (GLuint) state[1]; 3213464ebd5Sriastradh COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); 3223464ebd5Sriastradh } 3233464ebd5Sriastradh return; 3243464ebd5Sriastradh case STATE_POINT_SIZE: 3253464ebd5Sriastradh value[0] = ctx->Point.Size; 3263464ebd5Sriastradh value[1] = ctx->Point.MinSize; 3273464ebd5Sriastradh value[2] = ctx->Point.MaxSize; 3283464ebd5Sriastradh value[3] = ctx->Point.Threshold; 3293464ebd5Sriastradh return; 3303464ebd5Sriastradh case STATE_POINT_ATTENUATION: 3313464ebd5Sriastradh value[0] = ctx->Point.Params[0]; 3323464ebd5Sriastradh value[1] = ctx->Point.Params[1]; 3333464ebd5Sriastradh value[2] = ctx->Point.Params[2]; 3343464ebd5Sriastradh value[3] = 1.0F; 3353464ebd5Sriastradh return; 3367ec681f3Smrg /* state[0] = modelview, projection, texture, etc. */ 3377ec681f3Smrg /* state[1] = which texture matrix or program matrix */ 3387ec681f3Smrg /* state[2] = first row to fetch */ 3397ec681f3Smrg /* state[3] = last row to fetch */ 3407ec681f3Smrg case STATE_MODELVIEW_MATRIX: { 3417ec681f3Smrg const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top; 3427ec681f3Smrg copy_matrix(value, matrix->m, state[2], state[3]); 3437ec681f3Smrg return; 3447ec681f3Smrg } 3457ec681f3Smrg case STATE_MODELVIEW_MATRIX_INVERSE: { 3467ec681f3Smrg const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top; 3477ec681f3Smrg copy_matrix(value, matrix->inv, state[2], state[3]); 3487ec681f3Smrg return; 3497ec681f3Smrg } 3507ec681f3Smrg case STATE_MODELVIEW_MATRIX_TRANSPOSE: { 3517ec681f3Smrg const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top; 3527ec681f3Smrg copy_matrix_transposed(value, matrix->m, state[2], state[3]); 3537ec681f3Smrg return; 3547ec681f3Smrg } 3557ec681f3Smrg case STATE_MODELVIEW_MATRIX_INVTRANS: { 3567ec681f3Smrg const GLmatrix *matrix = ctx->ModelviewMatrixStack.Top; 3577ec681f3Smrg copy_matrix_transposed(value, matrix->inv, state[2], state[3]); 3587ec681f3Smrg return; 3597ec681f3Smrg } 3607ec681f3Smrg case STATE_PROJECTION_MATRIX: { 3617ec681f3Smrg const GLmatrix *matrix = ctx->ProjectionMatrixStack.Top; 3627ec681f3Smrg copy_matrix(value, matrix->m, state[2], state[3]); 3637ec681f3Smrg return; 3647ec681f3Smrg } 3657ec681f3Smrg case STATE_PROJECTION_MATRIX_INVERSE: { 3667ec681f3Smrg GLmatrix *matrix = ctx->ProjectionMatrixStack.Top; 3677ec681f3Smrg _math_matrix_analyse(matrix); /* make sure the inverse is up to date */ 3687ec681f3Smrg copy_matrix(value, matrix->inv, state[2], state[3]); 3697ec681f3Smrg return; 3707ec681f3Smrg } 3717ec681f3Smrg case STATE_PROJECTION_MATRIX_TRANSPOSE: { 3727ec681f3Smrg const GLmatrix *matrix = ctx->ProjectionMatrixStack.Top; 3737ec681f3Smrg copy_matrix_transposed(value, matrix->m, state[2], state[3]); 3747ec681f3Smrg return; 3757ec681f3Smrg } 3767ec681f3Smrg case STATE_PROJECTION_MATRIX_INVTRANS: { 3777ec681f3Smrg GLmatrix *matrix = ctx->ProjectionMatrixStack.Top; 3787ec681f3Smrg _math_matrix_analyse(matrix); /* make sure the inverse is up to date */ 3797ec681f3Smrg copy_matrix_transposed(value, matrix->inv, state[2], state[3]); 3807ec681f3Smrg return; 3817ec681f3Smrg } 3827ec681f3Smrg case STATE_MVP_MATRIX: { 3837ec681f3Smrg const GLmatrix *matrix = &ctx->_ModelProjectMatrix; 3847ec681f3Smrg copy_matrix(value, matrix->m, state[2], state[3]); 3857ec681f3Smrg return; 3867ec681f3Smrg } 3877ec681f3Smrg case STATE_MVP_MATRIX_INVERSE: { 3887ec681f3Smrg GLmatrix *matrix = &ctx->_ModelProjectMatrix; 3897ec681f3Smrg _math_matrix_analyse(matrix); /* make sure the inverse is up to date */ 3907ec681f3Smrg copy_matrix(value, matrix->inv, state[2], state[3]); 3917ec681f3Smrg return; 3927ec681f3Smrg } 3937ec681f3Smrg case STATE_MVP_MATRIX_TRANSPOSE: { 3947ec681f3Smrg const GLmatrix *matrix = &ctx->_ModelProjectMatrix; 3957ec681f3Smrg copy_matrix_transposed(value, matrix->m, state[2], state[3]); 3963464ebd5Sriastradh return; 3977ec681f3Smrg } 3987ec681f3Smrg case STATE_MVP_MATRIX_INVTRANS: { 3997ec681f3Smrg GLmatrix *matrix = &ctx->_ModelProjectMatrix; 4007ec681f3Smrg _math_matrix_analyse(matrix); /* make sure the inverse is up to date */ 4017ec681f3Smrg copy_matrix_transposed(value, matrix->inv, state[2], state[3]); 4027ec681f3Smrg return; 4037ec681f3Smrg } 4047ec681f3Smrg case STATE_TEXTURE_MATRIX: { 4057ec681f3Smrg const GLuint index = (GLuint) state[1]; 4067ec681f3Smrg assert(index < ARRAY_SIZE(ctx->TextureMatrixStack)); 4077ec681f3Smrg const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top; 4087ec681f3Smrg copy_matrix(value, matrix->m, state[2], state[3]); 4097ec681f3Smrg return; 4107ec681f3Smrg } 4117ec681f3Smrg case STATE_TEXTURE_MATRIX_INVERSE: { 4127ec681f3Smrg const GLuint index = (GLuint) state[1]; 4137ec681f3Smrg assert(index < ARRAY_SIZE(ctx->TextureMatrixStack)); 4147ec681f3Smrg const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top; 4157ec681f3Smrg copy_matrix(value, matrix->inv, state[2], state[3]); 4167ec681f3Smrg return; 4177ec681f3Smrg } 4187ec681f3Smrg case STATE_TEXTURE_MATRIX_TRANSPOSE: { 4197ec681f3Smrg const GLuint index = (GLuint) state[1]; 4207ec681f3Smrg assert(index < ARRAY_SIZE(ctx->TextureMatrixStack)); 4217ec681f3Smrg const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top; 4227ec681f3Smrg copy_matrix_transposed(value, matrix->m, state[2], state[3]); 4237ec681f3Smrg return; 4247ec681f3Smrg } 4257ec681f3Smrg case STATE_TEXTURE_MATRIX_INVTRANS: { 4267ec681f3Smrg const GLuint index = (GLuint) state[1]; 4277ec681f3Smrg assert(index < ARRAY_SIZE(ctx->TextureMatrixStack)); 4287ec681f3Smrg const GLmatrix *matrix = ctx->TextureMatrixStack[index].Top; 4297ec681f3Smrg copy_matrix_transposed(value, matrix->inv, state[2], state[3]); 4307ec681f3Smrg return; 4317ec681f3Smrg } 4327ec681f3Smrg case STATE_PROGRAM_MATRIX: { 4337ec681f3Smrg const GLuint index = (GLuint) state[1]; 4347ec681f3Smrg assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack)); 4357ec681f3Smrg const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top; 4367ec681f3Smrg copy_matrix(value, matrix->m, state[2], state[3]); 4377ec681f3Smrg return; 4387ec681f3Smrg } 4397ec681f3Smrg case STATE_PROGRAM_MATRIX_INVERSE: { 4407ec681f3Smrg const GLuint index = (GLuint) state[1]; 4417ec681f3Smrg assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack)); 4427ec681f3Smrg const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top; 4437ec681f3Smrg _math_matrix_analyse((GLmatrix*)matrix); /* Be sure inverse is up to date: */ 4447ec681f3Smrg copy_matrix(value, matrix->inv, state[2], state[3]); 4457ec681f3Smrg return; 4467ec681f3Smrg } 4477ec681f3Smrg case STATE_PROGRAM_MATRIX_TRANSPOSE: { 4487ec681f3Smrg const GLuint index = (GLuint) state[1]; 4497ec681f3Smrg assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack)); 4507ec681f3Smrg const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top; 4517ec681f3Smrg copy_matrix_transposed(value, matrix->m, state[2], state[3]); 4527ec681f3Smrg return; 4537ec681f3Smrg } 4547ec681f3Smrg case STATE_PROGRAM_MATRIX_INVTRANS: { 4557ec681f3Smrg const GLuint index = (GLuint) state[1]; 4567ec681f3Smrg assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack)); 4577ec681f3Smrg const GLmatrix *matrix = ctx->ProgramMatrixStack[index].Top; 4587ec681f3Smrg _math_matrix_analyse((GLmatrix*)matrix); /* Be sure inverse is up to date: */ 4597ec681f3Smrg copy_matrix_transposed(value, matrix->inv, state[2], state[3]); 4607ec681f3Smrg return; 4617ec681f3Smrg } 462af69d88dSmrg case STATE_NUM_SAMPLES: 46301e04c3fSmrg val[0].i = MAX2(1, _mesa_geometric_samples(ctx->DrawBuffer)); 464af69d88dSmrg return; 4653464ebd5Sriastradh case STATE_DEPTH_RANGE: 466af69d88dSmrg value[0] = ctx->ViewportArray[0].Near; /* near */ 467af69d88dSmrg value[1] = ctx->ViewportArray[0].Far; /* far */ 468af69d88dSmrg value[2] = ctx->ViewportArray[0].Far - ctx->ViewportArray[0].Near; /* far - near */ 4693464ebd5Sriastradh value[3] = 1.0; 4703464ebd5Sriastradh return; 4717ec681f3Smrg case STATE_FRAGMENT_PROGRAM_ENV: { 4727ec681f3Smrg const int idx = (int) state[1]; 4737ec681f3Smrg COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); 4747ec681f3Smrg return; 4757ec681f3Smrg } 4767ec681f3Smrg case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: { 4777ec681f3Smrg const unsigned idx = state[1]; 4787ec681f3Smrg const unsigned bytes = state[2] * 16; 4797ec681f3Smrg memcpy(value, ctx->FragmentProgram.Parameters[idx], bytes); 4807ec681f3Smrg return; 4817ec681f3Smrg } 4827ec681f3Smrg case STATE_FRAGMENT_PROGRAM_LOCAL: { 4837ec681f3Smrg float (*params)[4] = ctx->FragmentProgram.Current->arb.LocalParams; 4847ec681f3Smrg if (unlikely(!params)) { 4857ec681f3Smrg /* Local parameters haven't been allocated yet. 4867ec681f3Smrg * ARB_fragment_program says that local parameters are 4877ec681f3Smrg * "initially set to (0,0,0,0)." Return that. 4887ec681f3Smrg */ 4897ec681f3Smrg memset(value, 0, sizeof(float) * 4); 4907ec681f3Smrg return; 4917ec681f3Smrg } 492af69d88dSmrg 4937ec681f3Smrg const int idx = (int) state[1]; 4947ec681f3Smrg COPY_4V(value, params[idx]); 4957ec681f3Smrg return; 4967ec681f3Smrg } 4977ec681f3Smrg case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: { 4987ec681f3Smrg const unsigned idx = state[1]; 4997ec681f3Smrg const unsigned bytes = state[2] * 16; 5007ec681f3Smrg float (*params)[4] = ctx->FragmentProgram.Current->arb.LocalParams; 5017ec681f3Smrg if (!params) { 5027ec681f3Smrg /* Local parameters haven't been allocated yet. 5037ec681f3Smrg * ARB_fragment_program says that local parameters are 5047ec681f3Smrg * "initially set to (0,0,0,0)." Return that. 5057ec681f3Smrg */ 5067ec681f3Smrg memset(value, 0, bytes); 5077ec681f3Smrg return; 5083464ebd5Sriastradh } 5097ec681f3Smrg memcpy(value, params[idx], bytes); 5107ec681f3Smrg return; 5117ec681f3Smrg } 5127ec681f3Smrg case STATE_VERTEX_PROGRAM_ENV: { 5137ec681f3Smrg const int idx = (int) state[1]; 5147ec681f3Smrg COPY_4V(value, ctx->VertexProgram.Parameters[idx]); 5157ec681f3Smrg return; 5167ec681f3Smrg } 5177ec681f3Smrg case STATE_VERTEX_PROGRAM_ENV_ARRAY: { 5187ec681f3Smrg const unsigned idx = state[1]; 5197ec681f3Smrg const unsigned bytes = state[2] * 16; 5207ec681f3Smrg memcpy(value, ctx->VertexProgram.Parameters[idx], bytes); 5213464ebd5Sriastradh return; 5227ec681f3Smrg } 5237ec681f3Smrg case STATE_VERTEX_PROGRAM_LOCAL: { 5247ec681f3Smrg float (*params)[4] = ctx->VertexProgram.Current->arb.LocalParams; 5257ec681f3Smrg if (unlikely(!params)) { 5267ec681f3Smrg /* Local parameters haven't been allocated yet. 5277ec681f3Smrg * ARB_vertex_program says that local parameters are 5287ec681f3Smrg * "initially set to (0,0,0,0)." Return that. 5297ec681f3Smrg */ 5307ec681f3Smrg memset(value, 0, sizeof(float) * 4); 5317ec681f3Smrg return; 5327ec681f3Smrg } 5333464ebd5Sriastradh 5347ec681f3Smrg const int idx = (int) state[1]; 5357ec681f3Smrg COPY_4V(value, params[idx]); 5367ec681f3Smrg return; 5377ec681f3Smrg } 5387ec681f3Smrg case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: { 5397ec681f3Smrg const unsigned idx = state[1]; 5407ec681f3Smrg const unsigned bytes = state[2] * 16; 5417ec681f3Smrg float (*params)[4] = ctx->VertexProgram.Current->arb.LocalParams; 5427ec681f3Smrg if (!params) { 5437ec681f3Smrg /* Local parameters haven't been allocated yet. 5447ec681f3Smrg * ARB_vertex_program says that local parameters are 5457ec681f3Smrg * "initially set to (0,0,0,0)." Return that. 5467ec681f3Smrg */ 5477ec681f3Smrg memset(value, 0, bytes); 5487ec681f3Smrg return; 5497ec681f3Smrg } 5507ec681f3Smrg memcpy(value, params[idx], bytes); 5517ec681f3Smrg return; 5527ec681f3Smrg } 5537ec681f3Smrg 5547ec681f3Smrg case STATE_NORMAL_SCALE_EYESPACE: 5557ec681f3Smrg ASSIGN_4V(value, ctx->_ModelViewInvScaleEyespace, 0, 0, 1); 5567ec681f3Smrg return; 5577ec681f3Smrg 5587ec681f3Smrg case STATE_CURRENT_ATTRIB: 5593464ebd5Sriastradh { 5607ec681f3Smrg const GLuint idx = (GLuint) state[1]; 5617ec681f3Smrg COPY_4V(value, ctx->Current.Attrib[idx]); 5627ec681f3Smrg } 5637ec681f3Smrg return; 564af69d88dSmrg 5657ec681f3Smrg case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 5667ec681f3Smrg { 5677ec681f3Smrg const GLuint idx = (GLuint) state[1]; 5687ec681f3Smrg if(ctx->Light._ClampVertexColor && 5697ec681f3Smrg (idx == VERT_ATTRIB_COLOR0 || 5707ec681f3Smrg idx == VERT_ATTRIB_COLOR1)) { 5717ec681f3Smrg value[0] = SATURATE(ctx->Current.Attrib[idx][0]); 5727ec681f3Smrg value[1] = SATURATE(ctx->Current.Attrib[idx][1]); 5737ec681f3Smrg value[2] = SATURATE(ctx->Current.Attrib[idx][2]); 5747ec681f3Smrg value[3] = SATURATE(ctx->Current.Attrib[idx][3]); 5753464ebd5Sriastradh } 5767ec681f3Smrg else 5777ec681f3Smrg COPY_4V(value, ctx->Current.Attrib[idx]); 5783464ebd5Sriastradh } 5793464ebd5Sriastradh return; 5803464ebd5Sriastradh 5813464ebd5Sriastradh case STATE_NORMAL_SCALE: 5827ec681f3Smrg ASSIGN_4V(value, 5837ec681f3Smrg ctx->_ModelViewInvScale, 5847ec681f3Smrg ctx->_ModelViewInvScale, 5857ec681f3Smrg ctx->_ModelViewInvScale, 5867ec681f3Smrg 1); 5873464ebd5Sriastradh return; 5883464ebd5Sriastradh 5897ec681f3Smrg case STATE_FOG_PARAMS_OPTIMIZED: { 5907ec681f3Smrg /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog) 5917ec681f3Smrg * might be more expensive than EX2 on some hw, plus it needs 5927ec681f3Smrg * another constant (e) anyway. Linear fog can now be done with a 5937ec681f3Smrg * single MAD. 5947ec681f3Smrg * linear: fogcoord * -1/(end-start) + end/(end-start) 5957ec681f3Smrg * exp: 2^-(density/ln(2) * fogcoord) 5967ec681f3Smrg * exp2: 2^-((density/(sqrt(ln(2))) * fogcoord)^2) 5977ec681f3Smrg */ 5987ec681f3Smrg float val = (ctx->Fog.End == ctx->Fog.Start) 5997ec681f3Smrg ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start)); 6007ec681f3Smrg value[0] = val; 6017ec681f3Smrg value[1] = ctx->Fog.End * -val; 6027ec681f3Smrg value[2] = (GLfloat)(ctx->Fog.Density * M_LOG2E); /* M_LOG2E == 1/ln(2) */ 6037ec681f3Smrg value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2); 6047ec681f3Smrg return; 6057ec681f3Smrg } 6063464ebd5Sriastradh 6077ec681f3Smrg case STATE_POINT_SIZE_CLAMPED: 6087ec681f3Smrg { 6097ec681f3Smrg /* this includes implementation dependent limits, to avoid 6107ec681f3Smrg * another potentially necessary clamp. 6117ec681f3Smrg * Note: for sprites, point smooth (point AA) is ignored 6127ec681f3Smrg * and we'll clamp to MinPointSizeAA and MaxPointSize, because we 6137ec681f3Smrg * expect drivers will want to say their minimum for AA size is 0.0 6147ec681f3Smrg * but for non-AA it's 1.0 (because normal points with size below 1.0 6157ec681f3Smrg * need to get rounded up to 1.0, hence never disappear). GL does 6167ec681f3Smrg * not specify max clamp size for sprites, other than it needs to be 6177ec681f3Smrg * at least as large as max AA size, hence use non-AA size there. 6187ec681f3Smrg */ 6197ec681f3Smrg GLfloat minImplSize; 6207ec681f3Smrg GLfloat maxImplSize; 6217ec681f3Smrg if (ctx->Point.PointSprite) { 6227ec681f3Smrg minImplSize = ctx->Const.MinPointSizeAA; 6237ec681f3Smrg maxImplSize = ctx->Const.MaxPointSize; 6243464ebd5Sriastradh } 6257ec681f3Smrg else if (ctx->Point.SmoothFlag || _mesa_is_multisample_enabled(ctx)) { 6267ec681f3Smrg minImplSize = ctx->Const.MinPointSizeAA; 6277ec681f3Smrg maxImplSize = ctx->Const.MaxPointSizeAA; 6287ec681f3Smrg } 6297ec681f3Smrg else { 6307ec681f3Smrg minImplSize = ctx->Const.MinPointSize; 6317ec681f3Smrg maxImplSize = ctx->Const.MaxPointSize; 6327ec681f3Smrg } 6337ec681f3Smrg value[0] = ctx->Point.Size; 6347ec681f3Smrg value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize; 6357ec681f3Smrg value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize; 6367ec681f3Smrg value[3] = ctx->Point.Threshold; 6377ec681f3Smrg } 6387ec681f3Smrg return; 6397ec681f3Smrg case STATE_LIGHT_SPOT_DIR_NORMALIZED: 6407ec681f3Smrg { 6417ec681f3Smrg /* here, state[1] is the light number */ 6427ec681f3Smrg /* pre-normalize spot dir */ 6437ec681f3Smrg const GLuint ln = (GLuint) state[1]; 6447ec681f3Smrg COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection); 6457ec681f3Smrg value[3] = ctx->Light.LightSource[ln]._CosCutoff; 6467ec681f3Smrg } 6477ec681f3Smrg return; 6483464ebd5Sriastradh 6497ec681f3Smrg case STATE_LIGHT_POSITION: 6507ec681f3Smrg { 6517ec681f3Smrg const GLuint ln = (GLuint) state[1]; 6527ec681f3Smrg COPY_4V(value, ctx->Light.Light[ln]._Position); 6537ec681f3Smrg } 6547ec681f3Smrg return; 6553464ebd5Sriastradh 6567ec681f3Smrg case STATE_LIGHT_POSITION_ARRAY: { 6577ec681f3Smrg const unsigned first = state[1]; 6587ec681f3Smrg const unsigned num_lights = state[2]; 6597ec681f3Smrg for (unsigned i = 0; i < num_lights; i++) { 6607ec681f3Smrg COPY_4V(value, ctx->Light.Light[first + i]._Position); 6617ec681f3Smrg value += 4; 6627ec681f3Smrg } 6637ec681f3Smrg return; 6647ec681f3Smrg } 6653464ebd5Sriastradh 6667ec681f3Smrg case STATE_LIGHT_POSITION_NORMALIZED: 6677ec681f3Smrg { 6687ec681f3Smrg const GLuint ln = (GLuint) state[1]; 6697ec681f3Smrg float p[4]; 6707ec681f3Smrg COPY_4V(p, ctx->Light.Light[ln]._Position); 6717ec681f3Smrg NORMALIZE_3FV(p); 6727ec681f3Smrg COPY_4V(value, p); 6737ec681f3Smrg } 6747ec681f3Smrg return; 6753464ebd5Sriastradh 6767ec681f3Smrg case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: { 6777ec681f3Smrg const unsigned first = state[1]; 6787ec681f3Smrg const unsigned num_lights = state[2]; 6797ec681f3Smrg for (unsigned i = 0; i < num_lights; i++) { 6807ec681f3Smrg float p[4]; 6817ec681f3Smrg COPY_4V(p, ctx->Light.Light[first + i]._Position); 6827ec681f3Smrg NORMALIZE_3FV(p); 6837ec681f3Smrg COPY_4V(value, p); 6847ec681f3Smrg value += 4; 6857ec681f3Smrg } 6867ec681f3Smrg return; 6877ec681f3Smrg } 6883464ebd5Sriastradh 6897ec681f3Smrg case STATE_LIGHT_HALF_VECTOR: 6907ec681f3Smrg { 6917ec681f3Smrg const GLuint ln = (GLuint) state[1]; 6927ec681f3Smrg GLfloat p[3]; 6937ec681f3Smrg /* Compute infinite half angle vector: 6947ec681f3Smrg * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) 6957ec681f3Smrg * light.EyePosition.w should be 0 for infinite lights. 6967ec681f3Smrg */ 6977ec681f3Smrg COPY_3V(p, ctx->Light.Light[ln]._Position); 6987ec681f3Smrg NORMALIZE_3FV(p); 6997ec681f3Smrg ADD_3V(p, p, ctx->_EyeZDir); 7007ec681f3Smrg NORMALIZE_3FV(p); 7017ec681f3Smrg COPY_3V(value, p); 7027ec681f3Smrg value[3] = 1.0; 7037ec681f3Smrg } 7047ec681f3Smrg return; 7053464ebd5Sriastradh 7067ec681f3Smrg case STATE_PT_SCALE: 7077ec681f3Smrg value[0] = ctx->Pixel.RedScale; 7087ec681f3Smrg value[1] = ctx->Pixel.GreenScale; 7097ec681f3Smrg value[2] = ctx->Pixel.BlueScale; 7107ec681f3Smrg value[3] = ctx->Pixel.AlphaScale; 7117ec681f3Smrg return; 7123464ebd5Sriastradh 7137ec681f3Smrg case STATE_PT_BIAS: 7147ec681f3Smrg value[0] = ctx->Pixel.RedBias; 7157ec681f3Smrg value[1] = ctx->Pixel.GreenBias; 7167ec681f3Smrg value[2] = ctx->Pixel.BlueBias; 7177ec681f3Smrg value[3] = ctx->Pixel.AlphaBias; 7187ec681f3Smrg return; 7193464ebd5Sriastradh 7207ec681f3Smrg case STATE_FB_SIZE: 7217ec681f3Smrg value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1); 7227ec681f3Smrg value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); 7237ec681f3Smrg value[2] = 0.0F; 7247ec681f3Smrg value[3] = 0.0F; 7257ec681f3Smrg return; 7267ec681f3Smrg 7277ec681f3Smrg case STATE_FB_WPOS_Y_TRANSFORM: 7287ec681f3Smrg /* A driver may negate this conditional by using ZW swizzle 7297ec681f3Smrg * instead of XY (based on e.g. some other state). */ 7307ec681f3Smrg if (!ctx->DrawBuffer->FlipY) { 7317ec681f3Smrg /* Identity (XY) followed by flipping Y upside down (ZW). */ 7327ec681f3Smrg value[0] = 1.0F; 7337ec681f3Smrg value[1] = 0.0F; 7347ec681f3Smrg value[2] = -1.0F; 7357ec681f3Smrg value[3] = _mesa_geometric_height(ctx->DrawBuffer); 7367ec681f3Smrg } else { 7377ec681f3Smrg /* Flipping Y upside down (XY) followed by identity (ZW). */ 7387ec681f3Smrg value[0] = -1.0F; 7397ec681f3Smrg value[1] = _mesa_geometric_height(ctx->DrawBuffer); 7407ec681f3Smrg value[2] = 1.0F; 7417ec681f3Smrg value[3] = 0.0F; 7427ec681f3Smrg } 7437ec681f3Smrg return; 7447ec681f3Smrg 7457ec681f3Smrg case STATE_FB_PNTC_Y_TRANSFORM: 7467ec681f3Smrg { 7477ec681f3Smrg bool flip_y = (ctx->Point.SpriteOrigin == GL_LOWER_LEFT) ^ 7487ec681f3Smrg (ctx->DrawBuffer->FlipY); 7493464ebd5Sriastradh 7507ec681f3Smrg value[0] = flip_y ? -1.0F : 1.0F; 7517ec681f3Smrg value[1] = flip_y ? 1.0F : 0.0F; 7523464ebd5Sriastradh value[2] = 0.0F; 7533464ebd5Sriastradh value[3] = 0.0F; 7547ec681f3Smrg } 7557ec681f3Smrg return; 7563464ebd5Sriastradh 7577ec681f3Smrg case STATE_TCS_PATCH_VERTICES_IN: 7587ec681f3Smrg val[0].i = ctx->TessCtrlProgram.patch_vertices; 7597ec681f3Smrg return; 7603464ebd5Sriastradh 7617ec681f3Smrg case STATE_TES_PATCH_VERTICES_IN: 7627ec681f3Smrg if (ctx->TessCtrlProgram._Current) 7637ec681f3Smrg val[0].i = ctx->TessCtrlProgram._Current->info.tess.tcs_vertices_out; 7647ec681f3Smrg else 76501e04c3fSmrg val[0].i = ctx->TessCtrlProgram.patch_vertices; 7667ec681f3Smrg return; 76701e04c3fSmrg 7687ec681f3Smrg case STATE_ADVANCED_BLENDING_MODE: 7697ec681f3Smrg val[0].i = _mesa_get_advanced_blend_sh_constant( 7707ec681f3Smrg ctx->Color.BlendEnabled, ctx->Color._AdvancedBlendMode); 7717ec681f3Smrg return; 77201e04c3fSmrg 7737ec681f3Smrg case STATE_ALPHA_REF: 7747ec681f3Smrg value[0] = ctx->Color.AlphaRefUnclamped; 7753464ebd5Sriastradh return; 7763464ebd5Sriastradh 7777ec681f3Smrg case STATE_CLIP_INTERNAL: 7787ec681f3Smrg { 7797ec681f3Smrg const GLuint plane = (GLuint) state[1]; 7807ec681f3Smrg COPY_4V(value, ctx->Transform._ClipUserPlane[plane]); 7817ec681f3Smrg } 7823464ebd5Sriastradh return; 7833464ebd5Sriastradh } 7843464ebd5Sriastradh} 7853464ebd5Sriastradh 7867ec681f3Smrgunsigned 7877ec681f3Smrg_mesa_program_state_value_size(const gl_state_index16 state[STATE_LENGTH]) 7887ec681f3Smrg{ 7897ec681f3Smrg if (state[0] == STATE_LIGHT && state[2] == STATE_SPOT_CUTOFF) 7907ec681f3Smrg return 1; 7917ec681f3Smrg 7927ec681f3Smrg /* Everything else is packed into vec4s */ 7937ec681f3Smrg return 4; 7947ec681f3Smrg} 7953464ebd5Sriastradh 7963464ebd5Sriastradh/** 7973464ebd5Sriastradh * Return a bitmask of the Mesa state flags (_NEW_* values) which would 7983464ebd5Sriastradh * indicate that the given context state may have changed. 7993464ebd5Sriastradh * The bitmask is used during validation to determine if we need to update 8003464ebd5Sriastradh * vertex/fragment program parameters (like "state.material.color") when 8013464ebd5Sriastradh * some GL state has changed. 8023464ebd5Sriastradh */ 8033464ebd5SriastradhGLbitfield 80401e04c3fSmrg_mesa_program_state_flags(const gl_state_index16 state[STATE_LENGTH]) 8053464ebd5Sriastradh{ 8063464ebd5Sriastradh switch (state[0]) { 8073464ebd5Sriastradh case STATE_MATERIAL: 8087ec681f3Smrg return _NEW_MATERIAL; 8097ec681f3Smrg 8103464ebd5Sriastradh case STATE_LIGHTPROD: 8117ec681f3Smrg case STATE_LIGHTPROD_ARRAY_FRONT: 8127ec681f3Smrg case STATE_LIGHTPROD_ARRAY_BACK: 8137ec681f3Smrg case STATE_LIGHTPROD_ARRAY_TWOSIDE: 8143464ebd5Sriastradh case STATE_LIGHTMODEL_SCENECOLOR: 8157ec681f3Smrg return _NEW_LIGHT_CONSTANTS | _NEW_MATERIAL; 8163464ebd5Sriastradh 8173464ebd5Sriastradh case STATE_LIGHT: 8187ec681f3Smrg case STATE_LIGHT_ARRAY: 8197ec681f3Smrg case STATE_LIGHT_ATTENUATION_ARRAY: 8203464ebd5Sriastradh case STATE_LIGHTMODEL_AMBIENT: 8217ec681f3Smrg case STATE_LIGHT_SPOT_DIR_NORMALIZED: 8227ec681f3Smrg case STATE_LIGHT_POSITION: 8237ec681f3Smrg case STATE_LIGHT_POSITION_ARRAY: 8247ec681f3Smrg case STATE_LIGHT_POSITION_NORMALIZED: 8257ec681f3Smrg case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: 8267ec681f3Smrg case STATE_LIGHT_HALF_VECTOR: 8277ec681f3Smrg return _NEW_LIGHT_CONSTANTS; 8283464ebd5Sriastradh 8293464ebd5Sriastradh case STATE_TEXGEN: 83001e04c3fSmrg return _NEW_TEXTURE_STATE; 8313464ebd5Sriastradh case STATE_TEXENV_COLOR: 83201e04c3fSmrg return _NEW_TEXTURE_STATE | _NEW_BUFFERS | _NEW_FRAG_CLAMP; 8333464ebd5Sriastradh 8343464ebd5Sriastradh case STATE_FOG_COLOR: 8353464ebd5Sriastradh return _NEW_FOG | _NEW_BUFFERS | _NEW_FRAG_CLAMP; 8363464ebd5Sriastradh case STATE_FOG_PARAMS: 8377ec681f3Smrg case STATE_FOG_PARAMS_OPTIMIZED: 8383464ebd5Sriastradh return _NEW_FOG; 8393464ebd5Sriastradh 8403464ebd5Sriastradh case STATE_CLIPPLANE: 8413464ebd5Sriastradh return _NEW_TRANSFORM; 8423464ebd5Sriastradh 8433464ebd5Sriastradh case STATE_POINT_SIZE: 8443464ebd5Sriastradh case STATE_POINT_ATTENUATION: 8453464ebd5Sriastradh return _NEW_POINT; 8463464ebd5Sriastradh 8473464ebd5Sriastradh case STATE_MODELVIEW_MATRIX: 8487ec681f3Smrg case STATE_MODELVIEW_MATRIX_INVERSE: 8497ec681f3Smrg case STATE_MODELVIEW_MATRIX_TRANSPOSE: 8507ec681f3Smrg case STATE_MODELVIEW_MATRIX_INVTRANS: 8517ec681f3Smrg case STATE_NORMAL_SCALE_EYESPACE: 8527ec681f3Smrg case STATE_NORMAL_SCALE: 8533464ebd5Sriastradh return _NEW_MODELVIEW; 8547ec681f3Smrg 8553464ebd5Sriastradh case STATE_PROJECTION_MATRIX: 8567ec681f3Smrg case STATE_PROJECTION_MATRIX_INVERSE: 8577ec681f3Smrg case STATE_PROJECTION_MATRIX_TRANSPOSE: 8587ec681f3Smrg case STATE_PROJECTION_MATRIX_INVTRANS: 8593464ebd5Sriastradh return _NEW_PROJECTION; 8603464ebd5Sriastradh case STATE_MVP_MATRIX: 8617ec681f3Smrg case STATE_MVP_MATRIX_INVERSE: 8627ec681f3Smrg case STATE_MVP_MATRIX_TRANSPOSE: 8637ec681f3Smrg case STATE_MVP_MATRIX_INVTRANS: 8643464ebd5Sriastradh return _NEW_MODELVIEW | _NEW_PROJECTION; 8653464ebd5Sriastradh case STATE_TEXTURE_MATRIX: 8667ec681f3Smrg case STATE_TEXTURE_MATRIX_INVERSE: 8677ec681f3Smrg case STATE_TEXTURE_MATRIX_TRANSPOSE: 8687ec681f3Smrg case STATE_TEXTURE_MATRIX_INVTRANS: 8693464ebd5Sriastradh return _NEW_TEXTURE_MATRIX; 8703464ebd5Sriastradh case STATE_PROGRAM_MATRIX: 8717ec681f3Smrg case STATE_PROGRAM_MATRIX_INVERSE: 8727ec681f3Smrg case STATE_PROGRAM_MATRIX_TRANSPOSE: 8737ec681f3Smrg case STATE_PROGRAM_MATRIX_INVTRANS: 8743464ebd5Sriastradh return _NEW_TRACK_MATRIX; 8753464ebd5Sriastradh 876af69d88dSmrg case STATE_NUM_SAMPLES: 8777ec681f3Smrg case STATE_FB_SIZE: 8787ec681f3Smrg case STATE_FB_WPOS_Y_TRANSFORM: 879af69d88dSmrg return _NEW_BUFFERS; 880af69d88dSmrg 8817ec681f3Smrg case STATE_FB_PNTC_Y_TRANSFORM: 8827ec681f3Smrg return _NEW_BUFFERS | _NEW_POINT; 8837ec681f3Smrg 8843464ebd5Sriastradh case STATE_DEPTH_RANGE: 8853464ebd5Sriastradh return _NEW_VIEWPORT; 8863464ebd5Sriastradh 8877ec681f3Smrg case STATE_FRAGMENT_PROGRAM_ENV: 8887ec681f3Smrg case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: 8897ec681f3Smrg case STATE_FRAGMENT_PROGRAM_LOCAL: 8907ec681f3Smrg case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: 8917ec681f3Smrg case STATE_VERTEX_PROGRAM_ENV: 8927ec681f3Smrg case STATE_VERTEX_PROGRAM_ENV_ARRAY: 8937ec681f3Smrg case STATE_VERTEX_PROGRAM_LOCAL: 8947ec681f3Smrg case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: 8953464ebd5Sriastradh return _NEW_PROGRAM; 8963464ebd5Sriastradh 8977ec681f3Smrg case STATE_CURRENT_ATTRIB: 8987ec681f3Smrg return _NEW_CURRENT_ATTRIB; 8997ec681f3Smrg case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 9007ec681f3Smrg return _NEW_CURRENT_ATTRIB | _NEW_LIGHT_STATE | _NEW_BUFFERS; 9013464ebd5Sriastradh 9027ec681f3Smrg case STATE_POINT_SIZE_CLAMPED: 9037ec681f3Smrg return _NEW_POINT | _NEW_MULTISAMPLE; 9043464ebd5Sriastradh 9057ec681f3Smrg case STATE_PT_SCALE: 9067ec681f3Smrg case STATE_PT_BIAS: 9077ec681f3Smrg return _NEW_PIXEL; 9083464ebd5Sriastradh 9097ec681f3Smrg case STATE_ADVANCED_BLENDING_MODE: 9107ec681f3Smrg case STATE_ALPHA_REF: 9117ec681f3Smrg return _NEW_COLOR; 9123464ebd5Sriastradh 9137ec681f3Smrg case STATE_CLIP_INTERNAL: 9147ec681f3Smrg return _NEW_TRANSFORM | _NEW_PROJECTION; 91501e04c3fSmrg 9167ec681f3Smrg case STATE_TCS_PATCH_VERTICES_IN: 9177ec681f3Smrg case STATE_TES_PATCH_VERTICES_IN: 9187ec681f3Smrg case STATE_INTERNAL_DRIVER: 9197ec681f3Smrg return 0; /* internal driver state */ 9207ec681f3Smrg 9217ec681f3Smrg case STATE_NOT_STATE_VAR: 9227ec681f3Smrg return 0; 9233464ebd5Sriastradh 9243464ebd5Sriastradh default: 9253464ebd5Sriastradh _mesa_problem(NULL, "unexpected state[0] in make_state_flags()"); 9263464ebd5Sriastradh return 0; 9273464ebd5Sriastradh } 9283464ebd5Sriastradh} 9293464ebd5Sriastradh 9303464ebd5Sriastradh 9313464ebd5Sriastradhstatic void 9323464ebd5Sriastradhappend(char *dst, const char *src) 9333464ebd5Sriastradh{ 9343464ebd5Sriastradh while (*dst) 9353464ebd5Sriastradh dst++; 9363464ebd5Sriastradh while (*src) 9373464ebd5Sriastradh *dst++ = *src++; 9383464ebd5Sriastradh *dst = 0; 9393464ebd5Sriastradh} 9403464ebd5Sriastradh 9413464ebd5Sriastradh 9423464ebd5Sriastradh/** 9433464ebd5Sriastradh * Convert token 'k' to a string, append it onto 'dst' string. 9443464ebd5Sriastradh */ 9453464ebd5Sriastradhstatic void 9463464ebd5Sriastradhappend_token(char *dst, gl_state_index k) 9473464ebd5Sriastradh{ 9483464ebd5Sriastradh switch (k) { 9493464ebd5Sriastradh case STATE_MATERIAL: 9503464ebd5Sriastradh append(dst, "material"); 9513464ebd5Sriastradh break; 9523464ebd5Sriastradh case STATE_LIGHT: 9533464ebd5Sriastradh append(dst, "light"); 9543464ebd5Sriastradh break; 9557ec681f3Smrg case STATE_LIGHT_ARRAY: 9567ec681f3Smrg append(dst, "light.array"); 9577ec681f3Smrg break; 9587ec681f3Smrg case STATE_LIGHT_ATTENUATION_ARRAY: 9597ec681f3Smrg append(dst, "light.attenuation"); 9607ec681f3Smrg break; 9613464ebd5Sriastradh case STATE_LIGHTMODEL_AMBIENT: 9623464ebd5Sriastradh append(dst, "lightmodel.ambient"); 9633464ebd5Sriastradh break; 9643464ebd5Sriastradh case STATE_LIGHTMODEL_SCENECOLOR: 9653464ebd5Sriastradh break; 9663464ebd5Sriastradh case STATE_LIGHTPROD: 9673464ebd5Sriastradh append(dst, "lightprod"); 9683464ebd5Sriastradh break; 9697ec681f3Smrg case STATE_LIGHTPROD_ARRAY_FRONT: 9707ec681f3Smrg append(dst, "lightprod.array.front"); 9717ec681f3Smrg break; 9727ec681f3Smrg case STATE_LIGHTPROD_ARRAY_BACK: 9737ec681f3Smrg append(dst, "lightprod.array.back"); 9747ec681f3Smrg break; 9757ec681f3Smrg case STATE_LIGHTPROD_ARRAY_TWOSIDE: 9767ec681f3Smrg append(dst, "lightprod.array.twoside"); 9777ec681f3Smrg break; 9783464ebd5Sriastradh case STATE_TEXGEN: 9793464ebd5Sriastradh append(dst, "texgen"); 9803464ebd5Sriastradh break; 9813464ebd5Sriastradh case STATE_FOG_COLOR: 9823464ebd5Sriastradh append(dst, "fog.color"); 9833464ebd5Sriastradh break; 9843464ebd5Sriastradh case STATE_FOG_PARAMS: 9853464ebd5Sriastradh append(dst, "fog.params"); 9863464ebd5Sriastradh break; 9873464ebd5Sriastradh case STATE_CLIPPLANE: 9883464ebd5Sriastradh append(dst, "clip"); 9893464ebd5Sriastradh break; 9903464ebd5Sriastradh case STATE_POINT_SIZE: 9913464ebd5Sriastradh append(dst, "point.size"); 9923464ebd5Sriastradh break; 9933464ebd5Sriastradh case STATE_POINT_ATTENUATION: 9943464ebd5Sriastradh append(dst, "point.attenuation"); 9953464ebd5Sriastradh break; 9963464ebd5Sriastradh case STATE_MODELVIEW_MATRIX: 9977ec681f3Smrg append(dst, "matrix.modelview."); 9987ec681f3Smrg break; 9997ec681f3Smrg case STATE_MODELVIEW_MATRIX_INVERSE: 10007ec681f3Smrg append(dst, "matrix.modelview.inverse."); 10017ec681f3Smrg break; 10027ec681f3Smrg case STATE_MODELVIEW_MATRIX_TRANSPOSE: 10037ec681f3Smrg append(dst, "matrix.modelview.transpose."); 10047ec681f3Smrg break; 10057ec681f3Smrg case STATE_MODELVIEW_MATRIX_INVTRANS: 10067ec681f3Smrg append(dst, "matrix.modelview.invtrans."); 10073464ebd5Sriastradh break; 10083464ebd5Sriastradh case STATE_PROJECTION_MATRIX: 10097ec681f3Smrg append(dst, "matrix.projection."); 10107ec681f3Smrg break; 10117ec681f3Smrg case STATE_PROJECTION_MATRIX_INVERSE: 10127ec681f3Smrg append(dst, "matrix.projection.inverse."); 10137ec681f3Smrg break; 10147ec681f3Smrg case STATE_PROJECTION_MATRIX_TRANSPOSE: 10157ec681f3Smrg append(dst, "matrix.projection.transpose."); 10167ec681f3Smrg break; 10177ec681f3Smrg case STATE_PROJECTION_MATRIX_INVTRANS: 10187ec681f3Smrg append(dst, "matrix.projection.invtrans."); 10193464ebd5Sriastradh break; 10203464ebd5Sriastradh case STATE_MVP_MATRIX: 10217ec681f3Smrg append(dst, "matrix.mvp."); 10227ec681f3Smrg break; 10237ec681f3Smrg case STATE_MVP_MATRIX_INVERSE: 10247ec681f3Smrg append(dst, "matrix.mvp.inverse."); 10257ec681f3Smrg break; 10267ec681f3Smrg case STATE_MVP_MATRIX_TRANSPOSE: 10277ec681f3Smrg append(dst, "matrix.mvp.transpose."); 10287ec681f3Smrg break; 10297ec681f3Smrg case STATE_MVP_MATRIX_INVTRANS: 10307ec681f3Smrg append(dst, "matrix.mvp.invtrans."); 10313464ebd5Sriastradh break; 10323464ebd5Sriastradh case STATE_TEXTURE_MATRIX: 10333464ebd5Sriastradh append(dst, "matrix.texture"); 10343464ebd5Sriastradh break; 10357ec681f3Smrg case STATE_TEXTURE_MATRIX_INVERSE: 10367ec681f3Smrg append(dst, "matrix.texture.inverse"); 10377ec681f3Smrg break; 10387ec681f3Smrg case STATE_TEXTURE_MATRIX_TRANSPOSE: 10397ec681f3Smrg append(dst, "matrix.texture.transpose"); 10407ec681f3Smrg break; 10417ec681f3Smrg case STATE_TEXTURE_MATRIX_INVTRANS: 10427ec681f3Smrg append(dst, "matrix.texture.invtrans"); 10437ec681f3Smrg break; 10443464ebd5Sriastradh case STATE_PROGRAM_MATRIX: 10453464ebd5Sriastradh append(dst, "matrix.program"); 10463464ebd5Sriastradh break; 10477ec681f3Smrg case STATE_PROGRAM_MATRIX_INVERSE: 10487ec681f3Smrg append(dst, "matrix.program.inverse"); 10493464ebd5Sriastradh break; 10507ec681f3Smrg case STATE_PROGRAM_MATRIX_TRANSPOSE: 10517ec681f3Smrg append(dst, "matrix.program.transpose"); 10527ec681f3Smrg break; 10537ec681f3Smrg case STATE_PROGRAM_MATRIX_INVTRANS: 10547ec681f3Smrg append(dst, "matrix.program.invtrans"); 10553464ebd5Sriastradh break; 10563464ebd5Sriastradh break; 10573464ebd5Sriastradh case STATE_AMBIENT: 10587ec681f3Smrg append(dst, "ambient"); 10593464ebd5Sriastradh break; 10603464ebd5Sriastradh case STATE_DIFFUSE: 10617ec681f3Smrg append(dst, "diffuse"); 10623464ebd5Sriastradh break; 10633464ebd5Sriastradh case STATE_SPECULAR: 10647ec681f3Smrg append(dst, "specular"); 10653464ebd5Sriastradh break; 10663464ebd5Sriastradh case STATE_EMISSION: 10677ec681f3Smrg append(dst, "emission"); 10683464ebd5Sriastradh break; 10693464ebd5Sriastradh case STATE_SHININESS: 10707ec681f3Smrg append(dst, "shininess"); 10713464ebd5Sriastradh break; 10723464ebd5Sriastradh case STATE_HALF_VECTOR: 10737ec681f3Smrg append(dst, "half"); 10743464ebd5Sriastradh break; 10753464ebd5Sriastradh case STATE_POSITION: 10767ec681f3Smrg append(dst, "position"); 10773464ebd5Sriastradh break; 10783464ebd5Sriastradh case STATE_ATTENUATION: 10797ec681f3Smrg append(dst, "attenuation"); 10803464ebd5Sriastradh break; 10813464ebd5Sriastradh case STATE_SPOT_DIRECTION: 10827ec681f3Smrg append(dst, "spot.direction"); 10833464ebd5Sriastradh break; 10843464ebd5Sriastradh case STATE_SPOT_CUTOFF: 10857ec681f3Smrg append(dst, "spot.cutoff"); 10863464ebd5Sriastradh break; 10873464ebd5Sriastradh case STATE_TEXGEN_EYE_S: 10887ec681f3Smrg append(dst, "eye.s"); 10893464ebd5Sriastradh break; 10903464ebd5Sriastradh case STATE_TEXGEN_EYE_T: 10917ec681f3Smrg append(dst, "eye.t"); 10923464ebd5Sriastradh break; 10933464ebd5Sriastradh case STATE_TEXGEN_EYE_R: 10947ec681f3Smrg append(dst, "eye.r"); 10953464ebd5Sriastradh break; 10963464ebd5Sriastradh case STATE_TEXGEN_EYE_Q: 10977ec681f3Smrg append(dst, "eye.q"); 10983464ebd5Sriastradh break; 10993464ebd5Sriastradh case STATE_TEXGEN_OBJECT_S: 11007ec681f3Smrg append(dst, "object.s"); 11013464ebd5Sriastradh break; 11023464ebd5Sriastradh case STATE_TEXGEN_OBJECT_T: 11037ec681f3Smrg append(dst, "object.t"); 11043464ebd5Sriastradh break; 11053464ebd5Sriastradh case STATE_TEXGEN_OBJECT_R: 11067ec681f3Smrg append(dst, "object.r"); 11073464ebd5Sriastradh break; 11083464ebd5Sriastradh case STATE_TEXGEN_OBJECT_Q: 11097ec681f3Smrg append(dst, "object.q"); 11103464ebd5Sriastradh break; 11113464ebd5Sriastradh case STATE_TEXENV_COLOR: 11123464ebd5Sriastradh append(dst, "texenv"); 11133464ebd5Sriastradh break; 1114af69d88dSmrg case STATE_NUM_SAMPLES: 1115af69d88dSmrg append(dst, "numsamples"); 1116af69d88dSmrg break; 11173464ebd5Sriastradh case STATE_DEPTH_RANGE: 11183464ebd5Sriastradh append(dst, "depth.range"); 11193464ebd5Sriastradh break; 11207ec681f3Smrg case STATE_VERTEX_PROGRAM_ENV: 11217ec681f3Smrg case STATE_FRAGMENT_PROGRAM_ENV: 11223464ebd5Sriastradh append(dst, "env"); 11233464ebd5Sriastradh break; 11247ec681f3Smrg case STATE_VERTEX_PROGRAM_ENV_ARRAY: 11257ec681f3Smrg case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: 11267ec681f3Smrg append(dst, "env.range"); 11277ec681f3Smrg break; 11287ec681f3Smrg case STATE_VERTEX_PROGRAM_LOCAL: 11297ec681f3Smrg case STATE_FRAGMENT_PROGRAM_LOCAL: 11303464ebd5Sriastradh append(dst, "local"); 11313464ebd5Sriastradh break; 11327ec681f3Smrg case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: 11337ec681f3Smrg case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: 11347ec681f3Smrg append(dst, "local.range"); 11353464ebd5Sriastradh break; 11363464ebd5Sriastradh case STATE_CURRENT_ATTRIB: 11373464ebd5Sriastradh append(dst, "current"); 11383464ebd5Sriastradh break; 1139af69d88dSmrg case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 1140af69d88dSmrg append(dst, "currentAttribMaybeVPClamped"); 1141af69d88dSmrg break; 11427ec681f3Smrg case STATE_NORMAL_SCALE_EYESPACE: 11437ec681f3Smrg append(dst, "normalScaleEyeSpace"); 11447ec681f3Smrg break; 11453464ebd5Sriastradh case STATE_NORMAL_SCALE: 11463464ebd5Sriastradh append(dst, "normalScale"); 11473464ebd5Sriastradh break; 11483464ebd5Sriastradh case STATE_FOG_PARAMS_OPTIMIZED: 11493464ebd5Sriastradh append(dst, "fogParamsOptimized"); 11503464ebd5Sriastradh break; 11513464ebd5Sriastradh case STATE_POINT_SIZE_CLAMPED: 11523464ebd5Sriastradh append(dst, "pointSizeClamped"); 11533464ebd5Sriastradh break; 11543464ebd5Sriastradh case STATE_LIGHT_SPOT_DIR_NORMALIZED: 11553464ebd5Sriastradh append(dst, "lightSpotDirNormalized"); 11563464ebd5Sriastradh break; 11573464ebd5Sriastradh case STATE_LIGHT_POSITION: 11587ec681f3Smrg append(dst, "light.position"); 11597ec681f3Smrg break; 11607ec681f3Smrg case STATE_LIGHT_POSITION_ARRAY: 11617ec681f3Smrg append(dst, "light.position.array"); 11623464ebd5Sriastradh break; 11633464ebd5Sriastradh case STATE_LIGHT_POSITION_NORMALIZED: 11643464ebd5Sriastradh append(dst, "light.position.normalized"); 11653464ebd5Sriastradh break; 11667ec681f3Smrg case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: 11677ec681f3Smrg append(dst, "light.position.normalized.array"); 11687ec681f3Smrg break; 11693464ebd5Sriastradh case STATE_LIGHT_HALF_VECTOR: 11703464ebd5Sriastradh append(dst, "lightHalfVector"); 11713464ebd5Sriastradh break; 11723464ebd5Sriastradh case STATE_PT_SCALE: 11733464ebd5Sriastradh append(dst, "PTscale"); 11743464ebd5Sriastradh break; 11753464ebd5Sriastradh case STATE_PT_BIAS: 11763464ebd5Sriastradh append(dst, "PTbias"); 11773464ebd5Sriastradh break; 11783464ebd5Sriastradh case STATE_FB_SIZE: 11793464ebd5Sriastradh append(dst, "FbSize"); 11803464ebd5Sriastradh break; 11813464ebd5Sriastradh case STATE_FB_WPOS_Y_TRANSFORM: 11823464ebd5Sriastradh append(dst, "FbWposYTransform"); 11833464ebd5Sriastradh break; 11847ec681f3Smrg case STATE_FB_PNTC_Y_TRANSFORM: 11857ec681f3Smrg append(dst, "PntcYTransform"); 11867ec681f3Smrg break; 118701e04c3fSmrg case STATE_ADVANCED_BLENDING_MODE: 118801e04c3fSmrg append(dst, "AdvancedBlendingMode"); 118901e04c3fSmrg break; 11907ec681f3Smrg case STATE_ALPHA_REF: 11917ec681f3Smrg append(dst, "alphaRef"); 11927ec681f3Smrg break; 11937ec681f3Smrg case STATE_CLIP_INTERNAL: 11947ec681f3Smrg append(dst, "clipInternal"); 11957ec681f3Smrg break; 11963464ebd5Sriastradh default: 11973464ebd5Sriastradh /* probably STATE_INTERNAL_DRIVER+i (driver private state) */ 11983464ebd5Sriastradh append(dst, "driverState"); 11993464ebd5Sriastradh } 12003464ebd5Sriastradh} 12013464ebd5Sriastradh 12023464ebd5Sriastradhstatic void 12037ec681f3Smrgappend_index(char *dst, GLint index, bool structure) 12043464ebd5Sriastradh{ 12053464ebd5Sriastradh char s[20]; 12067ec681f3Smrg sprintf(s, "[%d]%s", index, structure ? "." : ""); 12073464ebd5Sriastradh append(dst, s); 12083464ebd5Sriastradh} 12093464ebd5Sriastradh 12103464ebd5Sriastradh/** 12113464ebd5Sriastradh * Make a string from the given state vector. 12123464ebd5Sriastradh * For example, return "state.matrix.texture[2].inverse". 12133464ebd5Sriastradh * Use free() to deallocate the string. 12143464ebd5Sriastradh */ 12153464ebd5Sriastradhchar * 121601e04c3fSmrg_mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH]) 12173464ebd5Sriastradh{ 12183464ebd5Sriastradh char str[1000] = ""; 12193464ebd5Sriastradh char tmp[30]; 12203464ebd5Sriastradh 12213464ebd5Sriastradh append(str, "state."); 12223464ebd5Sriastradh append_token(str, state[0]); 12233464ebd5Sriastradh 12243464ebd5Sriastradh switch (state[0]) { 12253464ebd5Sriastradh case STATE_LIGHT: 12267ec681f3Smrg append_index(str, state[1], true); /* light number [i]. */ 12273464ebd5Sriastradh append_token(str, state[2]); /* coefficients */ 12283464ebd5Sriastradh break; 12293464ebd5Sriastradh case STATE_LIGHTMODEL_AMBIENT: 12303464ebd5Sriastradh break; 12313464ebd5Sriastradh case STATE_LIGHTMODEL_SCENECOLOR: 12323464ebd5Sriastradh if (state[1] == 0) { 12333464ebd5Sriastradh append(str, "lightmodel.front.scenecolor"); 12343464ebd5Sriastradh } 12353464ebd5Sriastradh else { 12363464ebd5Sriastradh append(str, "lightmodel.back.scenecolor"); 12373464ebd5Sriastradh } 12383464ebd5Sriastradh break; 12393464ebd5Sriastradh case STATE_LIGHTPROD: 12407ec681f3Smrg append_index(str, state[1], false); /* light number [i] */ 12417ec681f3Smrg append_index(str, state[2], false); 12423464ebd5Sriastradh break; 12433464ebd5Sriastradh case STATE_TEXGEN: 12447ec681f3Smrg append_index(str, state[1], true); /* tex unit [i] */ 12453464ebd5Sriastradh append_token(str, state[2]); /* plane coef */ 12463464ebd5Sriastradh break; 12473464ebd5Sriastradh case STATE_TEXENV_COLOR: 12487ec681f3Smrg append_index(str, state[1], true); /* tex unit [i] */ 12493464ebd5Sriastradh append(str, "color"); 12503464ebd5Sriastradh break; 12513464ebd5Sriastradh case STATE_CLIPPLANE: 12527ec681f3Smrg append_index(str, state[1], true); /* plane [i] */ 12537ec681f3Smrg append(str, "plane"); 12543464ebd5Sriastradh break; 12553464ebd5Sriastradh case STATE_MODELVIEW_MATRIX: 12567ec681f3Smrg case STATE_MODELVIEW_MATRIX_INVERSE: 12577ec681f3Smrg case STATE_MODELVIEW_MATRIX_TRANSPOSE: 12587ec681f3Smrg case STATE_MODELVIEW_MATRIX_INVTRANS: 12593464ebd5Sriastradh case STATE_PROJECTION_MATRIX: 12607ec681f3Smrg case STATE_PROJECTION_MATRIX_INVERSE: 12617ec681f3Smrg case STATE_PROJECTION_MATRIX_TRANSPOSE: 12627ec681f3Smrg case STATE_PROJECTION_MATRIX_INVTRANS: 12633464ebd5Sriastradh case STATE_MVP_MATRIX: 12647ec681f3Smrg case STATE_MVP_MATRIX_INVERSE: 12657ec681f3Smrg case STATE_MVP_MATRIX_TRANSPOSE: 12667ec681f3Smrg case STATE_MVP_MATRIX_INVTRANS: 12673464ebd5Sriastradh case STATE_TEXTURE_MATRIX: 12687ec681f3Smrg case STATE_TEXTURE_MATRIX_INVERSE: 12697ec681f3Smrg case STATE_TEXTURE_MATRIX_TRANSPOSE: 12707ec681f3Smrg case STATE_TEXTURE_MATRIX_INVTRANS: 12713464ebd5Sriastradh case STATE_PROGRAM_MATRIX: 12727ec681f3Smrg case STATE_PROGRAM_MATRIX_INVERSE: 12737ec681f3Smrg case STATE_PROGRAM_MATRIX_TRANSPOSE: 12747ec681f3Smrg case STATE_PROGRAM_MATRIX_INVTRANS: 12753464ebd5Sriastradh { 12763464ebd5Sriastradh /* state[0] = modelview, projection, texture, etc. */ 12773464ebd5Sriastradh /* state[1] = which texture matrix or program matrix */ 12783464ebd5Sriastradh /* state[2] = first row to fetch */ 12793464ebd5Sriastradh /* state[3] = last row to fetch */ 12803464ebd5Sriastradh const gl_state_index mat = state[0]; 12813464ebd5Sriastradh const GLuint index = (GLuint) state[1]; 12823464ebd5Sriastradh const GLuint firstRow = (GLuint) state[2]; 12833464ebd5Sriastradh const GLuint lastRow = (GLuint) state[3]; 12843464ebd5Sriastradh if (index || 12857ec681f3Smrg (mat >= STATE_TEXTURE_MATRIX && 12867ec681f3Smrg mat <= STATE_PROGRAM_MATRIX_INVTRANS)) 12877ec681f3Smrg append_index(str, index, true); 12883464ebd5Sriastradh if (firstRow == lastRow) 12897ec681f3Smrg sprintf(tmp, "row[%d]", firstRow); 12903464ebd5Sriastradh else 12917ec681f3Smrg sprintf(tmp, "row[%d..%d]", firstRow, lastRow); 12923464ebd5Sriastradh append(str, tmp); 12933464ebd5Sriastradh } 12943464ebd5Sriastradh break; 12957ec681f3Smrg case STATE_LIGHT_ARRAY: 12967ec681f3Smrg case STATE_LIGHT_ATTENUATION_ARRAY: 12977ec681f3Smrg case STATE_FRAGMENT_PROGRAM_ENV_ARRAY: 12987ec681f3Smrg case STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY: 12997ec681f3Smrg case STATE_VERTEX_PROGRAM_ENV_ARRAY: 13007ec681f3Smrg case STATE_VERTEX_PROGRAM_LOCAL_ARRAY: 13017ec681f3Smrg case STATE_LIGHTPROD_ARRAY_FRONT: 13027ec681f3Smrg case STATE_LIGHTPROD_ARRAY_BACK: 13037ec681f3Smrg case STATE_LIGHTPROD_ARRAY_TWOSIDE: 13047ec681f3Smrg case STATE_LIGHT_POSITION_ARRAY: 13057ec681f3Smrg case STATE_LIGHT_POSITION_NORMALIZED_ARRAY: 13067ec681f3Smrg sprintf(tmp, "[%d..%d]", state[1], state[1] + state[2] - 1); 13077ec681f3Smrg append(str, tmp); 13083464ebd5Sriastradh break; 13097ec681f3Smrg case STATE_MATERIAL: 13107ec681f3Smrg case STATE_FRAGMENT_PROGRAM_ENV: 13117ec681f3Smrg case STATE_FRAGMENT_PROGRAM_LOCAL: 13127ec681f3Smrg case STATE_VERTEX_PROGRAM_ENV: 13137ec681f3Smrg case STATE_VERTEX_PROGRAM_LOCAL: 13147ec681f3Smrg case STATE_CURRENT_ATTRIB: 13157ec681f3Smrg case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 13167ec681f3Smrg case STATE_LIGHT_SPOT_DIR_NORMALIZED: 13177ec681f3Smrg case STATE_LIGHT_POSITION: 13187ec681f3Smrg case STATE_LIGHT_POSITION_NORMALIZED: 13197ec681f3Smrg case STATE_LIGHT_HALF_VECTOR: 13207ec681f3Smrg case STATE_CLIP_INTERNAL: 13217ec681f3Smrg append_index(str, state[1], false); 13223464ebd5Sriastradh break; 13237ec681f3Smrg case STATE_POINT_SIZE: 13247ec681f3Smrg case STATE_POINT_ATTENUATION: 13253464ebd5Sriastradh case STATE_FOG_PARAMS: 13263464ebd5Sriastradh case STATE_FOG_COLOR: 1327af69d88dSmrg case STATE_NUM_SAMPLES: 13283464ebd5Sriastradh case STATE_DEPTH_RANGE: 13297ec681f3Smrg case STATE_NORMAL_SCALE_EYESPACE: 13303464ebd5Sriastradh case STATE_NORMAL_SCALE: 13317ec681f3Smrg case STATE_FOG_PARAMS_OPTIMIZED: 13327ec681f3Smrg case STATE_POINT_SIZE_CLAMPED: 13337ec681f3Smrg case STATE_PT_SCALE: 13347ec681f3Smrg case STATE_PT_BIAS: 13357ec681f3Smrg case STATE_FB_SIZE: 13367ec681f3Smrg case STATE_FB_WPOS_Y_TRANSFORM: 13377ec681f3Smrg case STATE_TCS_PATCH_VERTICES_IN: 13387ec681f3Smrg case STATE_TES_PATCH_VERTICES_IN: 13397ec681f3Smrg case STATE_ADVANCED_BLENDING_MODE: 13407ec681f3Smrg case STATE_ALPHA_REF: 13417ec681f3Smrg break; 13427ec681f3Smrg case STATE_NOT_STATE_VAR: 13437ec681f3Smrg append(str, "not_state"); 13443464ebd5Sriastradh break; 13453464ebd5Sriastradh default: 13463464ebd5Sriastradh _mesa_problem(NULL, "Invalid state in _mesa_program_state_string"); 13473464ebd5Sriastradh break; 13483464ebd5Sriastradh } 13493464ebd5Sriastradh 135001e04c3fSmrg return strdup(str); 13513464ebd5Sriastradh} 13523464ebd5Sriastradh 13533464ebd5Sriastradh 13543464ebd5Sriastradh/** 13553464ebd5Sriastradh * Loop over all the parameters in a parameter list. If the parameter 13563464ebd5Sriastradh * is a GL state reference, look up the current value of that state 13573464ebd5Sriastradh * variable and put it into the parameter's Value[4] array. 13583464ebd5Sriastradh * Other parameter types never change or are explicitly set by the user 13593464ebd5Sriastradh * with glUniform() or glProgramParameter(), etc. 13603464ebd5Sriastradh * This would be called at glBegin time. 13613464ebd5Sriastradh */ 13623464ebd5Sriastradhvoid 13633464ebd5Sriastradh_mesa_load_state_parameters(struct gl_context *ctx, 13643464ebd5Sriastradh struct gl_program_parameter_list *paramList) 13653464ebd5Sriastradh{ 13663464ebd5Sriastradh if (!paramList) 13673464ebd5Sriastradh return; 13683464ebd5Sriastradh 13697ec681f3Smrg int last = paramList->LastStateVarIndex; 13707ec681f3Smrg 13717ec681f3Smrg for (int i = paramList->FirstStateVarIndex; i <= last; i++) { 13727ec681f3Smrg unsigned pvo = paramList->Parameters[i].ValueOffset; 13737ec681f3Smrg fetch_state(ctx, paramList->Parameters[i].StateIndexes, 13747ec681f3Smrg paramList->ParameterValues + pvo); 13757ec681f3Smrg } 13767ec681f3Smrg} 13777ec681f3Smrg 13787ec681f3Smrgvoid 13797ec681f3Smrg_mesa_upload_state_parameters(struct gl_context *ctx, 13807ec681f3Smrg struct gl_program_parameter_list *paramList, 13817ec681f3Smrg uint32_t *dst) 13827ec681f3Smrg{ 13837ec681f3Smrg int last = paramList->LastStateVarIndex; 13847ec681f3Smrg 13857ec681f3Smrg for (int i = paramList->FirstStateVarIndex; i <= last; i++) { 13867ec681f3Smrg unsigned pvo = paramList->Parameters[i].ValueOffset; 13877ec681f3Smrg fetch_state(ctx, paramList->Parameters[i].StateIndexes, 13887ec681f3Smrg (gl_constant_value*)(dst + pvo)); 13897ec681f3Smrg } 13907ec681f3Smrg} 13917ec681f3Smrg 13927ec681f3Smrg/* Merge consecutive state vars into one for the state vars that allow 13937ec681f3Smrg * multiple vec4s. 13947ec681f3Smrg * 13957ec681f3Smrg * This should be done after shader compilation, so that drivers don't 13967ec681f3Smrg * have to deal with multi-slot state parameters in their backends. 13977ec681f3Smrg * It's only meant to optimize _mesa_load/upload_state_parameters. 13987ec681f3Smrg */ 13997ec681f3Smrgvoid 14007ec681f3Smrg_mesa_optimize_state_parameters(struct gl_constants *consts, 14017ec681f3Smrg struct gl_program_parameter_list *list) 14027ec681f3Smrg{ 14037ec681f3Smrg for (int first_param = list->FirstStateVarIndex; 14047ec681f3Smrg first_param < (int)list->NumParameters; first_param++) { 14057ec681f3Smrg int last_param = first_param; 14067ec681f3Smrg int param_diff = 0; 14077ec681f3Smrg 14087ec681f3Smrg switch (list->Parameters[first_param].StateIndexes[0]) { 14097ec681f3Smrg case STATE_MODELVIEW_MATRIX: 14107ec681f3Smrg case STATE_MODELVIEW_MATRIX_INVERSE: 14117ec681f3Smrg case STATE_MODELVIEW_MATRIX_TRANSPOSE: 14127ec681f3Smrg case STATE_MODELVIEW_MATRIX_INVTRANS: 14137ec681f3Smrg case STATE_PROJECTION_MATRIX: 14147ec681f3Smrg case STATE_PROJECTION_MATRIX_INVERSE: 14157ec681f3Smrg case STATE_PROJECTION_MATRIX_TRANSPOSE: 14167ec681f3Smrg case STATE_PROJECTION_MATRIX_INVTRANS: 14177ec681f3Smrg case STATE_MVP_MATRIX: 14187ec681f3Smrg case STATE_MVP_MATRIX_INVERSE: 14197ec681f3Smrg case STATE_MVP_MATRIX_TRANSPOSE: 14207ec681f3Smrg case STATE_MVP_MATRIX_INVTRANS: 14217ec681f3Smrg case STATE_TEXTURE_MATRIX: 14227ec681f3Smrg case STATE_TEXTURE_MATRIX_INVERSE: 14237ec681f3Smrg case STATE_TEXTURE_MATRIX_TRANSPOSE: 14247ec681f3Smrg case STATE_TEXTURE_MATRIX_INVTRANS: 14257ec681f3Smrg case STATE_PROGRAM_MATRIX: 14267ec681f3Smrg case STATE_PROGRAM_MATRIX_INVERSE: 14277ec681f3Smrg case STATE_PROGRAM_MATRIX_TRANSPOSE: 14287ec681f3Smrg case STATE_PROGRAM_MATRIX_INVTRANS: 14297ec681f3Smrg /* Skip unaligned state vars. */ 14307ec681f3Smrg if (list->Parameters[first_param].Size % 4) 14317ec681f3Smrg break; 14327ec681f3Smrg 14337ec681f3Smrg /* Search for adjacent state vars that refer to adjacent rows. */ 14347ec681f3Smrg for (int i = first_param + 1; i < (int)list->NumParameters; i++) { 14357ec681f3Smrg if (list->Parameters[i].StateIndexes[0] == 14367ec681f3Smrg list->Parameters[i - 1].StateIndexes[0] && 14377ec681f3Smrg list->Parameters[i].StateIndexes[1] == 14387ec681f3Smrg list->Parameters[i - 1].StateIndexes[1] && 14397ec681f3Smrg list->Parameters[i].StateIndexes[2] == /* FirstRow */ 14407ec681f3Smrg list->Parameters[i - 1].StateIndexes[3] + 1 && /* LastRow + 1 */ 14417ec681f3Smrg list->Parameters[i].Size == 4) { 14427ec681f3Smrg last_param = i; 14437ec681f3Smrg continue; 14447ec681f3Smrg } 14457ec681f3Smrg break; /* The adjacent state var is incompatible. */ 14467ec681f3Smrg } 14477ec681f3Smrg if (last_param > first_param) { 14487ec681f3Smrg int first_vec = list->Parameters[first_param].StateIndexes[2]; 14497ec681f3Smrg int last_vec = list->Parameters[last_param].StateIndexes[3]; 14507ec681f3Smrg 14517ec681f3Smrg assert(first_vec < last_vec); 14527ec681f3Smrg assert(last_vec - first_vec == last_param - first_param); 14537ec681f3Smrg 14547ec681f3Smrg /* Update LastRow. */ 14557ec681f3Smrg list->Parameters[first_param].StateIndexes[3] = last_vec; 14567ec681f3Smrg list->Parameters[first_param].Size = (last_vec - first_vec + 1) * 4; 14577ec681f3Smrg 14587ec681f3Smrg param_diff = last_param - first_param; 14597ec681f3Smrg } 14607ec681f3Smrg break; 14617ec681f3Smrg 14627ec681f3Smrg case STATE_LIGHT: 14637ec681f3Smrg /* Skip trimmed state vars. (this shouldn't occur though) */ 14647ec681f3Smrg if (list->Parameters[first_param].Size != 14657ec681f3Smrg _mesa_program_state_value_size(list->Parameters[first_param].StateIndexes)) 14667ec681f3Smrg break; 14677ec681f3Smrg 14687ec681f3Smrg /* Search for light attributes that are adjacent in memory. */ 14697ec681f3Smrg for (int i = first_param + 1; i < (int)list->NumParameters; i++) { 14707ec681f3Smrg if (list->Parameters[i].StateIndexes[0] == STATE_LIGHT && 14717ec681f3Smrg /* Consecutive attributes of the same light: */ 14727ec681f3Smrg ((list->Parameters[i].StateIndexes[1] == 14737ec681f3Smrg list->Parameters[i - 1].StateIndexes[1] && 14747ec681f3Smrg list->Parameters[i].StateIndexes[2] == 14757ec681f3Smrg list->Parameters[i - 1].StateIndexes[2] + 1) || 14767ec681f3Smrg /* Consecutive attributes between 2 lights: */ 14777ec681f3Smrg /* SPOT_CUTOFF should have only 1 component, which isn't true 14787ec681f3Smrg * with unpacked uniform storage. */ 14797ec681f3Smrg (consts->PackedDriverUniformStorage && 14807ec681f3Smrg list->Parameters[i].StateIndexes[1] == 14817ec681f3Smrg list->Parameters[i - 1].StateIndexes[1] + 1 && 14827ec681f3Smrg list->Parameters[i].StateIndexes[2] == STATE_AMBIENT && 14837ec681f3Smrg list->Parameters[i - 1].StateIndexes[2] == STATE_SPOT_CUTOFF))) { 14847ec681f3Smrg last_param = i; 14857ec681f3Smrg continue; 14867ec681f3Smrg } 14877ec681f3Smrg break; /* The adjacent state var is incompatible. */ 14887ec681f3Smrg } 14897ec681f3Smrg if (last_param > first_param) { 14907ec681f3Smrg /* Convert the state var to STATE_LIGHT_ARRAY. */ 14917ec681f3Smrg list->Parameters[first_param].StateIndexes[0] = STATE_LIGHT_ARRAY; 14927ec681f3Smrg /* Set the offset in floats. */ 14937ec681f3Smrg list->Parameters[first_param].StateIndexes[1] = 14947ec681f3Smrg list->Parameters[first_param].StateIndexes[1] * /* light index */ 14957ec681f3Smrg sizeof(struct gl_light_uniforms) / 4 + 14967ec681f3Smrg (list->Parameters[first_param].StateIndexes[2] - STATE_AMBIENT) * 4; 14977ec681f3Smrg 14987ec681f3Smrg /* Set the real size in floats that we will upload (memcpy). */ 14997ec681f3Smrg list->Parameters[first_param].StateIndexes[2] = 15007ec681f3Smrg _mesa_program_state_value_size(list->Parameters[last_param].StateIndexes) + 15017ec681f3Smrg list->Parameters[last_param].ValueOffset - 15027ec681f3Smrg list->Parameters[first_param].ValueOffset; 15037ec681f3Smrg 15047ec681f3Smrg /* Set the allocated size, which can be aligned to 4 components. */ 15057ec681f3Smrg list->Parameters[first_param].Size = 15067ec681f3Smrg list->Parameters[last_param].Size + 15077ec681f3Smrg list->Parameters[last_param].ValueOffset - 15087ec681f3Smrg list->Parameters[first_param].ValueOffset; 15097ec681f3Smrg 15107ec681f3Smrg param_diff = last_param - first_param; 15117ec681f3Smrg break; /* all done */ 15127ec681f3Smrg } 15137ec681f3Smrg 15147ec681f3Smrg /* We were not able to convert light attributes to STATE_LIGHT_ARRAY. 15157ec681f3Smrg * Another occuring pattern is light attentuation vectors placed back 15167ec681f3Smrg * to back. Find them. 15177ec681f3Smrg */ 15187ec681f3Smrg if (list->Parameters[first_param].StateIndexes[2] == STATE_ATTENUATION) { 15197ec681f3Smrg for (int i = first_param + 1; i < (int)list->NumParameters; i++) { 15207ec681f3Smrg if (list->Parameters[i].StateIndexes[0] == STATE_LIGHT && 15217ec681f3Smrg /* Consecutive light: */ 15227ec681f3Smrg list->Parameters[i].StateIndexes[1] == 15237ec681f3Smrg list->Parameters[i - 1].StateIndexes[1] + 1 && 15247ec681f3Smrg /* Same attribute: */ 15257ec681f3Smrg list->Parameters[i].StateIndexes[2] == 15267ec681f3Smrg list->Parameters[i - 1].StateIndexes[2]) { 15277ec681f3Smrg last_param = i; 15287ec681f3Smrg continue; 15297ec681f3Smrg } 15307ec681f3Smrg break; /* The adjacent state var is incompatible. */ 15317ec681f3Smrg } 15327ec681f3Smrg if (last_param > first_param) { 15337ec681f3Smrg param_diff = last_param - first_param; 15347ec681f3Smrg 15357ec681f3Smrg /* Convert the state var to STATE_LIGHT_ATTENUATION_ARRAY. */ 15367ec681f3Smrg list->Parameters[first_param].StateIndexes[0] = 15377ec681f3Smrg STATE_LIGHT_ATTENUATION_ARRAY; 15387ec681f3Smrg /* Keep the light index the same. */ 15397ec681f3Smrg /* Set the number of lights. */ 15407ec681f3Smrg unsigned size = param_diff + 1; 15417ec681f3Smrg list->Parameters[first_param].StateIndexes[2] = size; 15427ec681f3Smrg list->Parameters[first_param].Size = size * 4; 15437ec681f3Smrg break; /* all done */ 15447ec681f3Smrg } 15457ec681f3Smrg } 15467ec681f3Smrg break; 15477ec681f3Smrg 15487ec681f3Smrg case STATE_VERTEX_PROGRAM_ENV: 15497ec681f3Smrg case STATE_VERTEX_PROGRAM_LOCAL: 15507ec681f3Smrg case STATE_FRAGMENT_PROGRAM_ENV: 15517ec681f3Smrg case STATE_FRAGMENT_PROGRAM_LOCAL: 15527ec681f3Smrg if (list->Parameters[first_param].Size != 4) 15537ec681f3Smrg break; 15547ec681f3Smrg 15557ec681f3Smrg /* Search for adjacent mergeable state vars. */ 15567ec681f3Smrg for (int i = first_param + 1; i < (int)list->NumParameters; i++) { 15577ec681f3Smrg if (list->Parameters[i].StateIndexes[0] == 15587ec681f3Smrg list->Parameters[i - 1].StateIndexes[0] && 15597ec681f3Smrg list->Parameters[i].StateIndexes[1] == 15607ec681f3Smrg list->Parameters[i - 1].StateIndexes[1] + 1 && 15617ec681f3Smrg list->Parameters[i].Size == 4) { 15627ec681f3Smrg last_param = i; 15637ec681f3Smrg continue; 15647ec681f3Smrg } 15657ec681f3Smrg break; /* The adjacent state var is incompatible. */ 15667ec681f3Smrg } 15677ec681f3Smrg if (last_param > first_param) { 15687ec681f3Smrg /* Set STATE_xxx_RANGE. */ 15697ec681f3Smrg STATIC_ASSERT(STATE_VERTEX_PROGRAM_ENV + 1 == 15707ec681f3Smrg STATE_VERTEX_PROGRAM_ENV_ARRAY); 15717ec681f3Smrg STATIC_ASSERT(STATE_VERTEX_PROGRAM_LOCAL + 1 == 15727ec681f3Smrg STATE_VERTEX_PROGRAM_LOCAL_ARRAY); 15737ec681f3Smrg STATIC_ASSERT(STATE_FRAGMENT_PROGRAM_ENV + 1 == 15747ec681f3Smrg STATE_FRAGMENT_PROGRAM_ENV_ARRAY); 15757ec681f3Smrg STATIC_ASSERT(STATE_FRAGMENT_PROGRAM_LOCAL + 1 == 15767ec681f3Smrg STATE_FRAGMENT_PROGRAM_LOCAL_ARRAY); 15777ec681f3Smrg list->Parameters[first_param].StateIndexes[0]++; 15787ec681f3Smrg 15797ec681f3Smrg param_diff = last_param - first_param; 15807ec681f3Smrg 15817ec681f3Smrg /* Set the size. */ 15827ec681f3Smrg unsigned size = param_diff + 1; 15837ec681f3Smrg list->Parameters[first_param].StateIndexes[2] = size; 15847ec681f3Smrg list->Parameters[first_param].Size = size * 4; 15857ec681f3Smrg } 15867ec681f3Smrg break; 15877ec681f3Smrg 15887ec681f3Smrg case STATE_LIGHTPROD: { 15897ec681f3Smrg if (list->Parameters[first_param].Size != 4) 15907ec681f3Smrg break; 15917ec681f3Smrg 15927ec681f3Smrg gl_state_index16 state = STATE_NOT_STATE_VAR; 15937ec681f3Smrg unsigned num_lights = 0; 15947ec681f3Smrg 15957ec681f3Smrg for (unsigned state_iter = STATE_LIGHTPROD_ARRAY_FRONT; 15967ec681f3Smrg state_iter <= STATE_LIGHTPROD_ARRAY_TWOSIDE; state_iter++) { 15977ec681f3Smrg unsigned num_attribs, base_attrib, attrib_incr; 15987ec681f3Smrg 15997ec681f3Smrg if (state_iter == STATE_LIGHTPROD_ARRAY_FRONT) { 16007ec681f3Smrg num_attribs = 3; 16017ec681f3Smrg base_attrib = MAT_ATTRIB_FRONT_AMBIENT; 16027ec681f3Smrg attrib_incr = 2; 16037ec681f3Smrg } else if (state_iter == STATE_LIGHTPROD_ARRAY_BACK) { 16047ec681f3Smrg num_attribs = 3; 16057ec681f3Smrg base_attrib = MAT_ATTRIB_BACK_AMBIENT; 16067ec681f3Smrg attrib_incr = 2; 16077ec681f3Smrg } else if (state_iter == STATE_LIGHTPROD_ARRAY_TWOSIDE) { 16087ec681f3Smrg num_attribs = 6; 16097ec681f3Smrg base_attrib = MAT_ATTRIB_FRONT_AMBIENT; 16107ec681f3Smrg attrib_incr = 1; 16117ec681f3Smrg } 16127ec681f3Smrg 16137ec681f3Smrg /* Find all attributes for one light. */ 16147ec681f3Smrg while (first_param + (num_lights + 1) * num_attribs <= 16157ec681f3Smrg list->NumParameters && 16167ec681f3Smrg (state == STATE_NOT_STATE_VAR || state == state_iter)) { 16177ec681f3Smrg unsigned i = 0, base = first_param + num_lights * num_attribs; 16187ec681f3Smrg 16197ec681f3Smrg /* Consecutive light indices: */ 16207ec681f3Smrg if (list->Parameters[first_param].StateIndexes[1] + num_lights == 16217ec681f3Smrg list->Parameters[base].StateIndexes[1]) { 16227ec681f3Smrg for (i = 0; i < num_attribs; i++) { 16237ec681f3Smrg if (list->Parameters[base + i].StateIndexes[0] == 16247ec681f3Smrg STATE_LIGHTPROD && 16257ec681f3Smrg list->Parameters[base + i].Size == 4 && 16267ec681f3Smrg /* Equal light indices: */ 16277ec681f3Smrg list->Parameters[base + i].StateIndexes[1] == 16287ec681f3Smrg list->Parameters[base + 0].StateIndexes[1] && 16297ec681f3Smrg /* Consecutive attributes: */ 16307ec681f3Smrg list->Parameters[base + i].StateIndexes[2] == 16317ec681f3Smrg base_attrib + i * attrib_incr) 16327ec681f3Smrg continue; 16337ec681f3Smrg break; 16347ec681f3Smrg } 16357ec681f3Smrg } 16367ec681f3Smrg if (i == num_attribs) { 16377ec681f3Smrg /* Accept all parameters for merging. */ 16387ec681f3Smrg state = state_iter; 16397ec681f3Smrg last_param = base + num_attribs - 1; 16407ec681f3Smrg num_lights++; 16417ec681f3Smrg } else { 16427ec681f3Smrg break; 16437ec681f3Smrg } 16447ec681f3Smrg } 16457ec681f3Smrg } 16467ec681f3Smrg 16477ec681f3Smrg if (last_param > first_param) { 16487ec681f3Smrg param_diff = last_param - first_param; 16497ec681f3Smrg 16507ec681f3Smrg list->Parameters[first_param].StateIndexes[0] = state; 16517ec681f3Smrg list->Parameters[first_param].StateIndexes[2] = num_lights; 16527ec681f3Smrg list->Parameters[first_param].Size = (param_diff + 1) * 4; 16537ec681f3Smrg } 16547ec681f3Smrg break; 16557ec681f3Smrg } 16567ec681f3Smrg 16577ec681f3Smrg case STATE_LIGHT_POSITION: 16587ec681f3Smrg case STATE_LIGHT_POSITION_NORMALIZED: 16597ec681f3Smrg if (list->Parameters[first_param].Size != 4) 16607ec681f3Smrg break; 16617ec681f3Smrg 16627ec681f3Smrg for (int i = first_param + 1; i < (int)list->NumParameters; i++) { 16637ec681f3Smrg if (list->Parameters[i].StateIndexes[0] == 16647ec681f3Smrg list->Parameters[i - 1].StateIndexes[0] && 16657ec681f3Smrg /* Consecutive light: */ 16667ec681f3Smrg list->Parameters[i].StateIndexes[1] == 16677ec681f3Smrg list->Parameters[i - 1].StateIndexes[1] + 1) { 16687ec681f3Smrg last_param = i; 16697ec681f3Smrg continue; 16707ec681f3Smrg } 16717ec681f3Smrg break; /* The adjacent state var is incompatible. */ 16727ec681f3Smrg } 16737ec681f3Smrg if (last_param > first_param) { 16747ec681f3Smrg param_diff = last_param - first_param; 16757ec681f3Smrg 16767ec681f3Smrg /* Convert the state var to STATE_LIGHT_POSITION_*ARRAY. */ 16777ec681f3Smrg STATIC_ASSERT(STATE_LIGHT_POSITION + 1 == 16787ec681f3Smrg STATE_LIGHT_POSITION_ARRAY); 16797ec681f3Smrg STATIC_ASSERT(STATE_LIGHT_POSITION_NORMALIZED + 1 == 16807ec681f3Smrg STATE_LIGHT_POSITION_NORMALIZED_ARRAY); 16817ec681f3Smrg list->Parameters[first_param].StateIndexes[0]++; 16827ec681f3Smrg /* Keep the light index the same. */ 16837ec681f3Smrg unsigned size = param_diff + 1; 16847ec681f3Smrg /* Set the number of lights. */ 16857ec681f3Smrg list->Parameters[first_param].StateIndexes[2] = size; 16867ec681f3Smrg list->Parameters[first_param].Size = size * 4; 16877ec681f3Smrg } 16887ec681f3Smrg } 16897ec681f3Smrg 16907ec681f3Smrg if (param_diff) { 16917ec681f3Smrg /* Update the name. */ 16927ec681f3Smrg free((void*)list->Parameters[first_param].Name); 16937ec681f3Smrg list->Parameters[first_param].Name = 16947ec681f3Smrg _mesa_program_state_string(list->Parameters[first_param].StateIndexes); 16957ec681f3Smrg 16967ec681f3Smrg /* Free names that we are going to overwrite. */ 16977ec681f3Smrg for (int i = first_param + 1; i <= last_param; i++) 16987ec681f3Smrg free((char*)list->Parameters[i].Name); 16997ec681f3Smrg 17007ec681f3Smrg /* Remove the merged state vars. */ 17017ec681f3Smrg if (last_param + 1 < list->NumParameters) { 17027ec681f3Smrg memmove(&list->Parameters[first_param + 1], 17037ec681f3Smrg &list->Parameters[last_param + 1], 17047ec681f3Smrg sizeof(list->Parameters[0]) * 17057ec681f3Smrg (list->NumParameters - last_param - 1)); 17067ec681f3Smrg } 17077ec681f3Smrg list->NumParameters -= param_diff; 17083464ebd5Sriastradh } 17093464ebd5Sriastradh } 17107ec681f3Smrg 17117ec681f3Smrg _mesa_recompute_parameter_bounds(list); 17123464ebd5Sriastradh} 1713