1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg/** 26848b8605Smrg * \file prog_statevars.c 27848b8605Smrg * Program state variable management. 28848b8605Smrg * \author Brian Paul 29848b8605Smrg */ 30848b8605Smrg 31848b8605Smrg 32b8e80941Smrg#include <stdio.h> 33848b8605Smrg#include "main/glheader.h" 34848b8605Smrg#include "main/context.h" 35848b8605Smrg#include "main/blend.h" 36848b8605Smrg#include "main/imports.h" 37848b8605Smrg#include "main/macros.h" 38848b8605Smrg#include "main/mtypes.h" 39848b8605Smrg#include "main/fbobject.h" 40848b8605Smrg#include "prog_statevars.h" 41848b8605Smrg#include "prog_parameter.h" 42848b8605Smrg#include "main/samplerobj.h" 43b8e80941Smrg#include "main/framebuffer.h" 44b8e80941Smrg 45b8e80941Smrg 46b8e80941Smrg#define ONE_DIV_SQRT_LN2 (1.201122408786449815) 47848b8605Smrg 48848b8605Smrg 49848b8605Smrg/** 50848b8605Smrg * Use the list of tokens in the state[] array to find global GL state 51848b8605Smrg * and return it in <value>. Usually, four values are returned in <value> 52848b8605Smrg * but matrix queries may return as many as 16 values. 53848b8605Smrg * This function is used for ARB vertex/fragment programs. 54848b8605Smrg * The program parser will produce the state[] values. 55848b8605Smrg */ 56848b8605Smrgstatic void 57b8e80941Smrg_mesa_fetch_state(struct gl_context *ctx, const gl_state_index16 state[], 58b8e80941Smrg gl_constant_value *val) 59848b8605Smrg{ 60b8e80941Smrg GLfloat *value = &val->f; 61b8e80941Smrg 62848b8605Smrg switch (state[0]) { 63848b8605Smrg case STATE_MATERIAL: 64848b8605Smrg { 65848b8605Smrg /* state[1] is either 0=front or 1=back side */ 66848b8605Smrg const GLuint face = (GLuint) state[1]; 67848b8605Smrg const struct gl_material *mat = &ctx->Light.Material; 68b8e80941Smrg assert(face == 0 || face == 1); 69848b8605Smrg /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */ 70b8e80941Smrg assert(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT); 71848b8605Smrg /* XXX we could get rid of this switch entirely with a little 72848b8605Smrg * work in arbprogparse.c's parse_state_single_item(). 73848b8605Smrg */ 74848b8605Smrg /* state[2] is the material attribute */ 75848b8605Smrg switch (state[2]) { 76848b8605Smrg case STATE_AMBIENT: 77848b8605Smrg COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]); 78848b8605Smrg return; 79848b8605Smrg case STATE_DIFFUSE: 80848b8605Smrg COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]); 81848b8605Smrg return; 82848b8605Smrg case STATE_SPECULAR: 83848b8605Smrg COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]); 84848b8605Smrg return; 85848b8605Smrg case STATE_EMISSION: 86848b8605Smrg COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]); 87848b8605Smrg return; 88848b8605Smrg case STATE_SHININESS: 89848b8605Smrg value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0]; 90848b8605Smrg value[1] = 0.0F; 91848b8605Smrg value[2] = 0.0F; 92848b8605Smrg value[3] = 1.0F; 93848b8605Smrg return; 94848b8605Smrg default: 95848b8605Smrg _mesa_problem(ctx, "Invalid material state in fetch_state"); 96848b8605Smrg return; 97848b8605Smrg } 98848b8605Smrg } 99848b8605Smrg case STATE_LIGHT: 100848b8605Smrg { 101848b8605Smrg /* state[1] is the light number */ 102848b8605Smrg const GLuint ln = (GLuint) state[1]; 103848b8605Smrg /* state[2] is the light attribute */ 104848b8605Smrg switch (state[2]) { 105848b8605Smrg case STATE_AMBIENT: 106848b8605Smrg COPY_4V(value, ctx->Light.Light[ln].Ambient); 107848b8605Smrg return; 108848b8605Smrg case STATE_DIFFUSE: 109848b8605Smrg COPY_4V(value, ctx->Light.Light[ln].Diffuse); 110848b8605Smrg return; 111848b8605Smrg case STATE_SPECULAR: 112848b8605Smrg COPY_4V(value, ctx->Light.Light[ln].Specular); 113848b8605Smrg return; 114848b8605Smrg case STATE_POSITION: 115848b8605Smrg COPY_4V(value, ctx->Light.Light[ln].EyePosition); 116848b8605Smrg return; 117848b8605Smrg case STATE_ATTENUATION: 118848b8605Smrg value[0] = ctx->Light.Light[ln].ConstantAttenuation; 119848b8605Smrg value[1] = ctx->Light.Light[ln].LinearAttenuation; 120848b8605Smrg value[2] = ctx->Light.Light[ln].QuadraticAttenuation; 121848b8605Smrg value[3] = ctx->Light.Light[ln].SpotExponent; 122848b8605Smrg return; 123848b8605Smrg case STATE_SPOT_DIRECTION: 124848b8605Smrg COPY_3V(value, ctx->Light.Light[ln].SpotDirection); 125848b8605Smrg value[3] = ctx->Light.Light[ln]._CosCutoff; 126848b8605Smrg return; 127848b8605Smrg case STATE_SPOT_CUTOFF: 128848b8605Smrg value[0] = ctx->Light.Light[ln].SpotCutoff; 129848b8605Smrg return; 130848b8605Smrg case STATE_HALF_VECTOR: 131848b8605Smrg { 132848b8605Smrg static const GLfloat eye_z[] = {0, 0, 1}; 133848b8605Smrg GLfloat p[3]; 134848b8605Smrg /* Compute infinite half angle vector: 135848b8605Smrg * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) 136848b8605Smrg * light.EyePosition.w should be 0 for infinite lights. 137848b8605Smrg */ 138848b8605Smrg COPY_3V(p, ctx->Light.Light[ln].EyePosition); 139848b8605Smrg NORMALIZE_3FV(p); 140848b8605Smrg ADD_3V(value, p, eye_z); 141848b8605Smrg NORMALIZE_3FV(value); 142848b8605Smrg value[3] = 1.0; 143848b8605Smrg } 144848b8605Smrg return; 145848b8605Smrg default: 146848b8605Smrg _mesa_problem(ctx, "Invalid light state in fetch_state"); 147848b8605Smrg return; 148848b8605Smrg } 149848b8605Smrg } 150848b8605Smrg case STATE_LIGHTMODEL_AMBIENT: 151848b8605Smrg COPY_4V(value, ctx->Light.Model.Ambient); 152848b8605Smrg return; 153848b8605Smrg case STATE_LIGHTMODEL_SCENECOLOR: 154848b8605Smrg if (state[1] == 0) { 155848b8605Smrg /* front */ 156848b8605Smrg GLint i; 157848b8605Smrg for (i = 0; i < 3; i++) { 158848b8605Smrg value[i] = ctx->Light.Model.Ambient[i] 159848b8605Smrg * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] 160848b8605Smrg + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; 161848b8605Smrg } 162848b8605Smrg value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; 163848b8605Smrg } 164848b8605Smrg else { 165848b8605Smrg /* back */ 166848b8605Smrg GLint i; 167848b8605Smrg for (i = 0; i < 3; i++) { 168848b8605Smrg value[i] = ctx->Light.Model.Ambient[i] 169848b8605Smrg * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] 170848b8605Smrg + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; 171848b8605Smrg } 172848b8605Smrg value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; 173848b8605Smrg } 174848b8605Smrg return; 175848b8605Smrg case STATE_LIGHTPROD: 176848b8605Smrg { 177848b8605Smrg const GLuint ln = (GLuint) state[1]; 178848b8605Smrg const GLuint face = (GLuint) state[2]; 179848b8605Smrg GLint i; 180b8e80941Smrg assert(face == 0 || face == 1); 181848b8605Smrg switch (state[3]) { 182848b8605Smrg case STATE_AMBIENT: 183848b8605Smrg for (i = 0; i < 3; i++) { 184848b8605Smrg value[i] = ctx->Light.Light[ln].Ambient[i] * 185848b8605Smrg ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i]; 186848b8605Smrg } 187848b8605Smrg /* [3] = material alpha */ 188848b8605Smrg value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][3]; 189848b8605Smrg return; 190848b8605Smrg case STATE_DIFFUSE: 191848b8605Smrg for (i = 0; i < 3; i++) { 192848b8605Smrg value[i] = ctx->Light.Light[ln].Diffuse[i] * 193848b8605Smrg ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i]; 194848b8605Smrg } 195848b8605Smrg /* [3] = material alpha */ 196848b8605Smrg value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; 197848b8605Smrg return; 198848b8605Smrg case STATE_SPECULAR: 199848b8605Smrg for (i = 0; i < 3; i++) { 200848b8605Smrg value[i] = ctx->Light.Light[ln].Specular[i] * 201848b8605Smrg ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i]; 202848b8605Smrg } 203848b8605Smrg /* [3] = material alpha */ 204848b8605Smrg value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][3]; 205848b8605Smrg return; 206848b8605Smrg default: 207848b8605Smrg _mesa_problem(ctx, "Invalid lightprod state in fetch_state"); 208848b8605Smrg return; 209848b8605Smrg } 210848b8605Smrg } 211848b8605Smrg case STATE_TEXGEN: 212848b8605Smrg { 213848b8605Smrg /* state[1] is the texture unit */ 214848b8605Smrg const GLuint unit = (GLuint) state[1]; 215848b8605Smrg /* state[2] is the texgen attribute */ 216848b8605Smrg switch (state[2]) { 217848b8605Smrg case STATE_TEXGEN_EYE_S: 218b8e80941Smrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenS.EyePlane); 219848b8605Smrg return; 220848b8605Smrg case STATE_TEXGEN_EYE_T: 221b8e80941Smrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenT.EyePlane); 222848b8605Smrg return; 223848b8605Smrg case STATE_TEXGEN_EYE_R: 224b8e80941Smrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenR.EyePlane); 225848b8605Smrg return; 226848b8605Smrg case STATE_TEXGEN_EYE_Q: 227b8e80941Smrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenQ.EyePlane); 228848b8605Smrg return; 229848b8605Smrg case STATE_TEXGEN_OBJECT_S: 230b8e80941Smrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenS.ObjectPlane); 231848b8605Smrg return; 232848b8605Smrg case STATE_TEXGEN_OBJECT_T: 233b8e80941Smrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenT.ObjectPlane); 234848b8605Smrg return; 235848b8605Smrg case STATE_TEXGEN_OBJECT_R: 236b8e80941Smrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenR.ObjectPlane); 237848b8605Smrg return; 238848b8605Smrg case STATE_TEXGEN_OBJECT_Q: 239b8e80941Smrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].GenQ.ObjectPlane); 240848b8605Smrg return; 241848b8605Smrg default: 242848b8605Smrg _mesa_problem(ctx, "Invalid texgen state in fetch_state"); 243848b8605Smrg return; 244848b8605Smrg } 245848b8605Smrg } 246848b8605Smrg case STATE_TEXENV_COLOR: 247848b8605Smrg { 248848b8605Smrg /* state[1] is the texture unit */ 249848b8605Smrg const GLuint unit = (GLuint) state[1]; 250b8e80941Smrg if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) 251b8e80941Smrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColor); 252848b8605Smrg else 253b8e80941Smrg COPY_4V(value, ctx->Texture.FixedFuncUnit[unit].EnvColorUnclamped); 254848b8605Smrg } 255848b8605Smrg return; 256848b8605Smrg case STATE_FOG_COLOR: 257b8e80941Smrg if (_mesa_get_clamp_fragment_color(ctx, ctx->DrawBuffer)) 258848b8605Smrg COPY_4V(value, ctx->Fog.Color); 259848b8605Smrg else 260848b8605Smrg COPY_4V(value, ctx->Fog.ColorUnclamped); 261848b8605Smrg return; 262848b8605Smrg case STATE_FOG_PARAMS: 263848b8605Smrg value[0] = ctx->Fog.Density; 264848b8605Smrg value[1] = ctx->Fog.Start; 265848b8605Smrg value[2] = ctx->Fog.End; 266848b8605Smrg value[3] = 1.0f / (ctx->Fog.End - ctx->Fog.Start); 267848b8605Smrg return; 268848b8605Smrg case STATE_CLIPPLANE: 269848b8605Smrg { 270848b8605Smrg const GLuint plane = (GLuint) state[1]; 271848b8605Smrg COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); 272848b8605Smrg } 273848b8605Smrg return; 274848b8605Smrg case STATE_POINT_SIZE: 275848b8605Smrg value[0] = ctx->Point.Size; 276848b8605Smrg value[1] = ctx->Point.MinSize; 277848b8605Smrg value[2] = ctx->Point.MaxSize; 278848b8605Smrg value[3] = ctx->Point.Threshold; 279848b8605Smrg return; 280848b8605Smrg case STATE_POINT_ATTENUATION: 281848b8605Smrg value[0] = ctx->Point.Params[0]; 282848b8605Smrg value[1] = ctx->Point.Params[1]; 283848b8605Smrg value[2] = ctx->Point.Params[2]; 284848b8605Smrg value[3] = 1.0F; 285848b8605Smrg return; 286848b8605Smrg case STATE_MODELVIEW_MATRIX: 287848b8605Smrg case STATE_PROJECTION_MATRIX: 288848b8605Smrg case STATE_MVP_MATRIX: 289848b8605Smrg case STATE_TEXTURE_MATRIX: 290848b8605Smrg case STATE_PROGRAM_MATRIX: 291848b8605Smrg { 292848b8605Smrg /* state[0] = modelview, projection, texture, etc. */ 293848b8605Smrg /* state[1] = which texture matrix or program matrix */ 294848b8605Smrg /* state[2] = first row to fetch */ 295848b8605Smrg /* state[3] = last row to fetch */ 296848b8605Smrg /* state[4] = transpose, inverse or invtrans */ 297848b8605Smrg const GLmatrix *matrix; 298848b8605Smrg const gl_state_index mat = state[0]; 299848b8605Smrg const GLuint index = (GLuint) state[1]; 300848b8605Smrg const GLuint firstRow = (GLuint) state[2]; 301848b8605Smrg const GLuint lastRow = (GLuint) state[3]; 302848b8605Smrg const gl_state_index modifier = state[4]; 303848b8605Smrg const GLfloat *m; 304848b8605Smrg GLuint row, i; 305b8e80941Smrg assert(firstRow < 4); 306b8e80941Smrg assert(lastRow < 4); 307848b8605Smrg if (mat == STATE_MODELVIEW_MATRIX) { 308848b8605Smrg matrix = ctx->ModelviewMatrixStack.Top; 309848b8605Smrg } 310848b8605Smrg else if (mat == STATE_PROJECTION_MATRIX) { 311848b8605Smrg matrix = ctx->ProjectionMatrixStack.Top; 312848b8605Smrg } 313848b8605Smrg else if (mat == STATE_MVP_MATRIX) { 314848b8605Smrg matrix = &ctx->_ModelProjectMatrix; 315848b8605Smrg } 316848b8605Smrg else if (mat == STATE_TEXTURE_MATRIX) { 317b8e80941Smrg assert(index < ARRAY_SIZE(ctx->TextureMatrixStack)); 318848b8605Smrg matrix = ctx->TextureMatrixStack[index].Top; 319848b8605Smrg } 320848b8605Smrg else if (mat == STATE_PROGRAM_MATRIX) { 321b8e80941Smrg assert(index < ARRAY_SIZE(ctx->ProgramMatrixStack)); 322848b8605Smrg matrix = ctx->ProgramMatrixStack[index].Top; 323848b8605Smrg } 324848b8605Smrg else { 325848b8605Smrg _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()"); 326848b8605Smrg return; 327848b8605Smrg } 328848b8605Smrg if (modifier == STATE_MATRIX_INVERSE || 329848b8605Smrg modifier == STATE_MATRIX_INVTRANS) { 330848b8605Smrg /* Be sure inverse is up to date: 331848b8605Smrg */ 332848b8605Smrg _math_matrix_analyse( (GLmatrix*) matrix ); 333848b8605Smrg m = matrix->inv; 334848b8605Smrg } 335848b8605Smrg else { 336848b8605Smrg m = matrix->m; 337848b8605Smrg } 338848b8605Smrg if (modifier == STATE_MATRIX_TRANSPOSE || 339848b8605Smrg modifier == STATE_MATRIX_INVTRANS) { 340848b8605Smrg for (i = 0, row = firstRow; row <= lastRow; row++) { 341848b8605Smrg value[i++] = m[row * 4 + 0]; 342848b8605Smrg value[i++] = m[row * 4 + 1]; 343848b8605Smrg value[i++] = m[row * 4 + 2]; 344848b8605Smrg value[i++] = m[row * 4 + 3]; 345848b8605Smrg } 346848b8605Smrg } 347848b8605Smrg else { 348848b8605Smrg for (i = 0, row = firstRow; row <= lastRow; row++) { 349848b8605Smrg value[i++] = m[row + 0]; 350848b8605Smrg value[i++] = m[row + 4]; 351848b8605Smrg value[i++] = m[row + 8]; 352848b8605Smrg value[i++] = m[row + 12]; 353848b8605Smrg } 354848b8605Smrg } 355848b8605Smrg } 356848b8605Smrg return; 357848b8605Smrg case STATE_NUM_SAMPLES: 358b8e80941Smrg val[0].i = MAX2(1, _mesa_geometric_samples(ctx->DrawBuffer)); 359848b8605Smrg return; 360848b8605Smrg case STATE_DEPTH_RANGE: 361848b8605Smrg value[0] = ctx->ViewportArray[0].Near; /* near */ 362848b8605Smrg value[1] = ctx->ViewportArray[0].Far; /* far */ 363848b8605Smrg value[2] = ctx->ViewportArray[0].Far - ctx->ViewportArray[0].Near; /* far - near */ 364848b8605Smrg value[3] = 1.0; 365848b8605Smrg return; 366848b8605Smrg case STATE_FRAGMENT_PROGRAM: 367848b8605Smrg { 368848b8605Smrg /* state[1] = {STATE_ENV, STATE_LOCAL} */ 369848b8605Smrg /* state[2] = parameter index */ 370848b8605Smrg const int idx = (int) state[2]; 371848b8605Smrg switch (state[1]) { 372848b8605Smrg case STATE_ENV: 373848b8605Smrg COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); 374848b8605Smrg return; 375848b8605Smrg case STATE_LOCAL: 376b8e80941Smrg if (!ctx->FragmentProgram.Current->arb.LocalParams) { 377b8e80941Smrg ctx->FragmentProgram.Current->arb.LocalParams = 378b8e80941Smrg rzalloc_array_size(ctx->FragmentProgram.Current, 379b8e80941Smrg sizeof(float[4]), 380b8e80941Smrg MAX_PROGRAM_LOCAL_PARAMS); 381b8e80941Smrg if (!ctx->FragmentProgram.Current->arb.LocalParams) 382848b8605Smrg return; 383848b8605Smrg } 384848b8605Smrg 385b8e80941Smrg COPY_4V(value, 386b8e80941Smrg ctx->FragmentProgram.Current->arb.LocalParams[idx]); 387848b8605Smrg return; 388848b8605Smrg default: 389848b8605Smrg _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); 390848b8605Smrg return; 391848b8605Smrg } 392848b8605Smrg } 393848b8605Smrg return; 394848b8605Smrg 395848b8605Smrg case STATE_VERTEX_PROGRAM: 396848b8605Smrg { 397848b8605Smrg /* state[1] = {STATE_ENV, STATE_LOCAL} */ 398848b8605Smrg /* state[2] = parameter index */ 399848b8605Smrg const int idx = (int) state[2]; 400848b8605Smrg switch (state[1]) { 401848b8605Smrg case STATE_ENV: 402848b8605Smrg COPY_4V(value, ctx->VertexProgram.Parameters[idx]); 403848b8605Smrg return; 404848b8605Smrg case STATE_LOCAL: 405b8e80941Smrg if (!ctx->VertexProgram.Current->arb.LocalParams) { 406b8e80941Smrg ctx->VertexProgram.Current->arb.LocalParams = 407b8e80941Smrg rzalloc_array_size(ctx->VertexProgram.Current, 408b8e80941Smrg sizeof(float[4]), 409b8e80941Smrg MAX_PROGRAM_LOCAL_PARAMS); 410b8e80941Smrg if (!ctx->VertexProgram.Current->arb.LocalParams) 411848b8605Smrg return; 412848b8605Smrg } 413848b8605Smrg 414b8e80941Smrg COPY_4V(value, 415b8e80941Smrg ctx->VertexProgram.Current->arb.LocalParams[idx]); 416848b8605Smrg return; 417848b8605Smrg default: 418848b8605Smrg _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); 419848b8605Smrg return; 420848b8605Smrg } 421848b8605Smrg } 422848b8605Smrg return; 423848b8605Smrg 424848b8605Smrg case STATE_NORMAL_SCALE: 425b8e80941Smrg ASSIGN_4V(value, ctx->_ModelViewInvScaleEyespace, 0, 0, 1); 426848b8605Smrg return; 427848b8605Smrg 428848b8605Smrg case STATE_INTERNAL: 429848b8605Smrg switch (state[1]) { 430848b8605Smrg case STATE_CURRENT_ATTRIB: 431848b8605Smrg { 432848b8605Smrg const GLuint idx = (GLuint) state[2]; 433848b8605Smrg COPY_4V(value, ctx->Current.Attrib[idx]); 434848b8605Smrg } 435848b8605Smrg return; 436848b8605Smrg 437848b8605Smrg case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 438848b8605Smrg { 439848b8605Smrg const GLuint idx = (GLuint) state[2]; 440848b8605Smrg if(ctx->Light._ClampVertexColor && 441848b8605Smrg (idx == VERT_ATTRIB_COLOR0 || 442848b8605Smrg idx == VERT_ATTRIB_COLOR1)) { 443848b8605Smrg value[0] = CLAMP(ctx->Current.Attrib[idx][0], 0.0f, 1.0f); 444848b8605Smrg value[1] = CLAMP(ctx->Current.Attrib[idx][1], 0.0f, 1.0f); 445848b8605Smrg value[2] = CLAMP(ctx->Current.Attrib[idx][2], 0.0f, 1.0f); 446848b8605Smrg value[3] = CLAMP(ctx->Current.Attrib[idx][3], 0.0f, 1.0f); 447848b8605Smrg } 448848b8605Smrg else 449848b8605Smrg COPY_4V(value, ctx->Current.Attrib[idx]); 450848b8605Smrg } 451848b8605Smrg return; 452848b8605Smrg 453848b8605Smrg case STATE_NORMAL_SCALE: 454848b8605Smrg ASSIGN_4V(value, 455848b8605Smrg ctx->_ModelViewInvScale, 456848b8605Smrg ctx->_ModelViewInvScale, 457848b8605Smrg ctx->_ModelViewInvScale, 458848b8605Smrg 1); 459848b8605Smrg return; 460848b8605Smrg 461848b8605Smrg case STATE_FOG_PARAMS_OPTIMIZED: 462848b8605Smrg /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog) 463848b8605Smrg * might be more expensive than EX2 on some hw, plus it needs 464848b8605Smrg * another constant (e) anyway. Linear fog can now be done with a 465848b8605Smrg * single MAD. 466848b8605Smrg * linear: fogcoord * -1/(end-start) + end/(end-start) 467848b8605Smrg * exp: 2^-(density/ln(2) * fogcoord) 468b8e80941Smrg * exp2: 2^-((density/(sqrt(ln(2))) * fogcoord)^2) 469848b8605Smrg */ 470848b8605Smrg value[0] = (ctx->Fog.End == ctx->Fog.Start) 471848b8605Smrg ? 1.0f : (GLfloat)(-1.0F / (ctx->Fog.End - ctx->Fog.Start)); 472848b8605Smrg value[1] = ctx->Fog.End * -value[0]; 473848b8605Smrg value[2] = (GLfloat)(ctx->Fog.Density * M_LOG2E); /* M_LOG2E == 1/ln(2) */ 474848b8605Smrg value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2); 475848b8605Smrg return; 476848b8605Smrg 477848b8605Smrg case STATE_POINT_SIZE_CLAMPED: 478848b8605Smrg { 479848b8605Smrg /* this includes implementation dependent limits, to avoid 480848b8605Smrg * another potentially necessary clamp. 481848b8605Smrg * Note: for sprites, point smooth (point AA) is ignored 482848b8605Smrg * and we'll clamp to MinPointSizeAA and MaxPointSize, because we 483848b8605Smrg * expect drivers will want to say their minimum for AA size is 0.0 484848b8605Smrg * but for non-AA it's 1.0 (because normal points with size below 1.0 485848b8605Smrg * need to get rounded up to 1.0, hence never disappear). GL does 486848b8605Smrg * not specify max clamp size for sprites, other than it needs to be 487848b8605Smrg * at least as large as max AA size, hence use non-AA size there. 488848b8605Smrg */ 489848b8605Smrg GLfloat minImplSize; 490848b8605Smrg GLfloat maxImplSize; 491848b8605Smrg if (ctx->Point.PointSprite) { 492848b8605Smrg minImplSize = ctx->Const.MinPointSizeAA; 493848b8605Smrg maxImplSize = ctx->Const.MaxPointSize; 494848b8605Smrg } 495b8e80941Smrg else if (ctx->Point.SmoothFlag || _mesa_is_multisample_enabled(ctx)) { 496848b8605Smrg minImplSize = ctx->Const.MinPointSizeAA; 497848b8605Smrg maxImplSize = ctx->Const.MaxPointSizeAA; 498848b8605Smrg } 499848b8605Smrg else { 500848b8605Smrg minImplSize = ctx->Const.MinPointSize; 501848b8605Smrg maxImplSize = ctx->Const.MaxPointSize; 502848b8605Smrg } 503848b8605Smrg value[0] = ctx->Point.Size; 504848b8605Smrg value[1] = ctx->Point.MinSize >= minImplSize ? ctx->Point.MinSize : minImplSize; 505848b8605Smrg value[2] = ctx->Point.MaxSize <= maxImplSize ? ctx->Point.MaxSize : maxImplSize; 506848b8605Smrg value[3] = ctx->Point.Threshold; 507848b8605Smrg } 508848b8605Smrg return; 509848b8605Smrg case STATE_LIGHT_SPOT_DIR_NORMALIZED: 510848b8605Smrg { 511848b8605Smrg /* here, state[2] is the light number */ 512848b8605Smrg /* pre-normalize spot dir */ 513848b8605Smrg const GLuint ln = (GLuint) state[2]; 514848b8605Smrg COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection); 515848b8605Smrg value[3] = ctx->Light.Light[ln]._CosCutoff; 516848b8605Smrg } 517848b8605Smrg return; 518848b8605Smrg 519848b8605Smrg case STATE_LIGHT_POSITION: 520848b8605Smrg { 521848b8605Smrg const GLuint ln = (GLuint) state[2]; 522848b8605Smrg COPY_4V(value, ctx->Light.Light[ln]._Position); 523848b8605Smrg } 524848b8605Smrg return; 525848b8605Smrg 526848b8605Smrg case STATE_LIGHT_POSITION_NORMALIZED: 527848b8605Smrg { 528848b8605Smrg const GLuint ln = (GLuint) state[2]; 529848b8605Smrg COPY_4V(value, ctx->Light.Light[ln]._Position); 530848b8605Smrg NORMALIZE_3FV( value ); 531848b8605Smrg } 532848b8605Smrg return; 533848b8605Smrg 534848b8605Smrg case STATE_LIGHT_HALF_VECTOR: 535848b8605Smrg { 536848b8605Smrg const GLuint ln = (GLuint) state[2]; 537848b8605Smrg GLfloat p[3]; 538848b8605Smrg /* Compute infinite half angle vector: 539848b8605Smrg * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) 540848b8605Smrg * light.EyePosition.w should be 0 for infinite lights. 541848b8605Smrg */ 542848b8605Smrg COPY_3V(p, ctx->Light.Light[ln]._Position); 543848b8605Smrg NORMALIZE_3FV(p); 544848b8605Smrg ADD_3V(value, p, ctx->_EyeZDir); 545848b8605Smrg NORMALIZE_3FV(value); 546848b8605Smrg value[3] = 1.0; 547848b8605Smrg } 548848b8605Smrg return; 549848b8605Smrg 550848b8605Smrg case STATE_PT_SCALE: 551848b8605Smrg value[0] = ctx->Pixel.RedScale; 552848b8605Smrg value[1] = ctx->Pixel.GreenScale; 553848b8605Smrg value[2] = ctx->Pixel.BlueScale; 554848b8605Smrg value[3] = ctx->Pixel.AlphaScale; 555848b8605Smrg return; 556848b8605Smrg 557848b8605Smrg case STATE_PT_BIAS: 558848b8605Smrg value[0] = ctx->Pixel.RedBias; 559848b8605Smrg value[1] = ctx->Pixel.GreenBias; 560848b8605Smrg value[2] = ctx->Pixel.BlueBias; 561848b8605Smrg value[3] = ctx->Pixel.AlphaBias; 562848b8605Smrg return; 563848b8605Smrg 564848b8605Smrg case STATE_FB_SIZE: 565848b8605Smrg value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1); 566848b8605Smrg value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); 567848b8605Smrg value[2] = 0.0F; 568848b8605Smrg value[3] = 0.0F; 569848b8605Smrg return; 570848b8605Smrg 571848b8605Smrg case STATE_FB_WPOS_Y_TRANSFORM: 572848b8605Smrg /* A driver may negate this conditional by using ZW swizzle 573848b8605Smrg * instead of XY (based on e.g. some other state). */ 574b8e80941Smrg if (!ctx->DrawBuffer->FlipY) { 575848b8605Smrg /* Identity (XY) followed by flipping Y upside down (ZW). */ 576848b8605Smrg value[0] = 1.0F; 577848b8605Smrg value[1] = 0.0F; 578848b8605Smrg value[2] = -1.0F; 579848b8605Smrg value[3] = (GLfloat) ctx->DrawBuffer->Height; 580848b8605Smrg } else { 581848b8605Smrg /* Flipping Y upside down (XY) followed by identity (ZW). */ 582848b8605Smrg value[0] = -1.0F; 583848b8605Smrg value[1] = (GLfloat) ctx->DrawBuffer->Height; 584848b8605Smrg value[2] = 1.0F; 585848b8605Smrg value[3] = 0.0F; 586848b8605Smrg } 587848b8605Smrg return; 588848b8605Smrg 589b8e80941Smrg case STATE_TCS_PATCH_VERTICES_IN: 590b8e80941Smrg val[0].i = ctx->TessCtrlProgram.patch_vertices; 591b8e80941Smrg return; 592b8e80941Smrg 593b8e80941Smrg case STATE_TES_PATCH_VERTICES_IN: 594b8e80941Smrg if (ctx->TessCtrlProgram._Current) 595b8e80941Smrg val[0].i = ctx->TessCtrlProgram._Current->info.tess.tcs_vertices_out; 596b8e80941Smrg else 597b8e80941Smrg val[0].i = ctx->TessCtrlProgram.patch_vertices; 598b8e80941Smrg return; 599b8e80941Smrg 600b8e80941Smrg case STATE_ADVANCED_BLENDING_MODE: 601b8e80941Smrg val[0].i = _mesa_get_advanced_blend_sh_constant( 602b8e80941Smrg ctx->Color.BlendEnabled, ctx->Color._AdvancedBlendMode); 603b8e80941Smrg return; 604b8e80941Smrg 605848b8605Smrg /* XXX: make sure new tokens added here are also handled in the 606848b8605Smrg * _mesa_program_state_flags() switch, below. 607848b8605Smrg */ 608848b8605Smrg default: 609848b8605Smrg /* Unknown state indexes are silently ignored here. 610848b8605Smrg * Drivers may do something special. 611848b8605Smrg */ 612848b8605Smrg return; 613848b8605Smrg } 614848b8605Smrg return; 615848b8605Smrg 616848b8605Smrg default: 617848b8605Smrg _mesa_problem(ctx, "Invalid state in _mesa_fetch_state"); 618848b8605Smrg return; 619848b8605Smrg } 620848b8605Smrg} 621848b8605Smrg 622848b8605Smrg 623848b8605Smrg/** 624848b8605Smrg * Return a bitmask of the Mesa state flags (_NEW_* values) which would 625848b8605Smrg * indicate that the given context state may have changed. 626848b8605Smrg * The bitmask is used during validation to determine if we need to update 627848b8605Smrg * vertex/fragment program parameters (like "state.material.color") when 628848b8605Smrg * some GL state has changed. 629848b8605Smrg */ 630848b8605SmrgGLbitfield 631b8e80941Smrg_mesa_program_state_flags(const gl_state_index16 state[STATE_LENGTH]) 632848b8605Smrg{ 633848b8605Smrg switch (state[0]) { 634848b8605Smrg case STATE_MATERIAL: 635848b8605Smrg case STATE_LIGHTPROD: 636848b8605Smrg case STATE_LIGHTMODEL_SCENECOLOR: 637848b8605Smrg /* these can be effected by glColor when colormaterial mode is used */ 638848b8605Smrg return _NEW_LIGHT | _NEW_CURRENT_ATTRIB; 639848b8605Smrg 640848b8605Smrg case STATE_LIGHT: 641848b8605Smrg case STATE_LIGHTMODEL_AMBIENT: 642848b8605Smrg return _NEW_LIGHT; 643848b8605Smrg 644848b8605Smrg case STATE_TEXGEN: 645b8e80941Smrg return _NEW_TEXTURE_STATE; 646848b8605Smrg case STATE_TEXENV_COLOR: 647b8e80941Smrg return _NEW_TEXTURE_STATE | _NEW_BUFFERS | _NEW_FRAG_CLAMP; 648848b8605Smrg 649848b8605Smrg case STATE_FOG_COLOR: 650848b8605Smrg return _NEW_FOG | _NEW_BUFFERS | _NEW_FRAG_CLAMP; 651848b8605Smrg case STATE_FOG_PARAMS: 652848b8605Smrg return _NEW_FOG; 653848b8605Smrg 654848b8605Smrg case STATE_CLIPPLANE: 655848b8605Smrg return _NEW_TRANSFORM; 656848b8605Smrg 657848b8605Smrg case STATE_POINT_SIZE: 658848b8605Smrg case STATE_POINT_ATTENUATION: 659848b8605Smrg return _NEW_POINT; 660848b8605Smrg 661848b8605Smrg case STATE_MODELVIEW_MATRIX: 662848b8605Smrg return _NEW_MODELVIEW; 663848b8605Smrg case STATE_PROJECTION_MATRIX: 664848b8605Smrg return _NEW_PROJECTION; 665848b8605Smrg case STATE_MVP_MATRIX: 666848b8605Smrg return _NEW_MODELVIEW | _NEW_PROJECTION; 667848b8605Smrg case STATE_TEXTURE_MATRIX: 668848b8605Smrg return _NEW_TEXTURE_MATRIX; 669848b8605Smrg case STATE_PROGRAM_MATRIX: 670848b8605Smrg return _NEW_TRACK_MATRIX; 671848b8605Smrg 672848b8605Smrg case STATE_NUM_SAMPLES: 673848b8605Smrg return _NEW_BUFFERS; 674848b8605Smrg 675848b8605Smrg case STATE_DEPTH_RANGE: 676848b8605Smrg return _NEW_VIEWPORT; 677848b8605Smrg 678848b8605Smrg case STATE_FRAGMENT_PROGRAM: 679848b8605Smrg case STATE_VERTEX_PROGRAM: 680848b8605Smrg return _NEW_PROGRAM; 681848b8605Smrg 682848b8605Smrg case STATE_NORMAL_SCALE: 683848b8605Smrg return _NEW_MODELVIEW; 684848b8605Smrg 685848b8605Smrg case STATE_INTERNAL: 686848b8605Smrg switch (state[1]) { 687848b8605Smrg case STATE_CURRENT_ATTRIB: 688848b8605Smrg return _NEW_CURRENT_ATTRIB; 689848b8605Smrg case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 690848b8605Smrg return _NEW_CURRENT_ATTRIB | _NEW_LIGHT | _NEW_BUFFERS; 691848b8605Smrg 692848b8605Smrg case STATE_NORMAL_SCALE: 693848b8605Smrg return _NEW_MODELVIEW; 694848b8605Smrg 695848b8605Smrg case STATE_FOG_PARAMS_OPTIMIZED: 696848b8605Smrg return _NEW_FOG; 697848b8605Smrg case STATE_POINT_SIZE_CLAMPED: 698848b8605Smrg return _NEW_POINT | _NEW_MULTISAMPLE; 699848b8605Smrg case STATE_LIGHT_SPOT_DIR_NORMALIZED: 700848b8605Smrg case STATE_LIGHT_POSITION: 701848b8605Smrg case STATE_LIGHT_POSITION_NORMALIZED: 702848b8605Smrg case STATE_LIGHT_HALF_VECTOR: 703848b8605Smrg return _NEW_LIGHT; 704848b8605Smrg 705848b8605Smrg case STATE_PT_SCALE: 706848b8605Smrg case STATE_PT_BIAS: 707848b8605Smrg return _NEW_PIXEL; 708848b8605Smrg 709848b8605Smrg case STATE_FB_SIZE: 710848b8605Smrg case STATE_FB_WPOS_Y_TRANSFORM: 711848b8605Smrg return _NEW_BUFFERS; 712848b8605Smrg 713b8e80941Smrg case STATE_ADVANCED_BLENDING_MODE: 714b8e80941Smrg return _NEW_COLOR; 715b8e80941Smrg 716848b8605Smrg default: 717848b8605Smrg /* unknown state indexes are silently ignored and 718848b8605Smrg * no flag set, since it is handled by the driver. 719848b8605Smrg */ 720848b8605Smrg return 0; 721848b8605Smrg } 722848b8605Smrg 723848b8605Smrg default: 724848b8605Smrg _mesa_problem(NULL, "unexpected state[0] in make_state_flags()"); 725848b8605Smrg return 0; 726848b8605Smrg } 727848b8605Smrg} 728848b8605Smrg 729848b8605Smrg 730848b8605Smrgstatic void 731848b8605Smrgappend(char *dst, const char *src) 732848b8605Smrg{ 733848b8605Smrg while (*dst) 734848b8605Smrg dst++; 735848b8605Smrg while (*src) 736848b8605Smrg *dst++ = *src++; 737848b8605Smrg *dst = 0; 738848b8605Smrg} 739848b8605Smrg 740848b8605Smrg 741848b8605Smrg/** 742848b8605Smrg * Convert token 'k' to a string, append it onto 'dst' string. 743848b8605Smrg */ 744848b8605Smrgstatic void 745848b8605Smrgappend_token(char *dst, gl_state_index k) 746848b8605Smrg{ 747848b8605Smrg switch (k) { 748848b8605Smrg case STATE_MATERIAL: 749848b8605Smrg append(dst, "material"); 750848b8605Smrg break; 751848b8605Smrg case STATE_LIGHT: 752848b8605Smrg append(dst, "light"); 753848b8605Smrg break; 754848b8605Smrg case STATE_LIGHTMODEL_AMBIENT: 755848b8605Smrg append(dst, "lightmodel.ambient"); 756848b8605Smrg break; 757848b8605Smrg case STATE_LIGHTMODEL_SCENECOLOR: 758848b8605Smrg break; 759848b8605Smrg case STATE_LIGHTPROD: 760848b8605Smrg append(dst, "lightprod"); 761848b8605Smrg break; 762848b8605Smrg case STATE_TEXGEN: 763848b8605Smrg append(dst, "texgen"); 764848b8605Smrg break; 765848b8605Smrg case STATE_FOG_COLOR: 766848b8605Smrg append(dst, "fog.color"); 767848b8605Smrg break; 768848b8605Smrg case STATE_FOG_PARAMS: 769848b8605Smrg append(dst, "fog.params"); 770848b8605Smrg break; 771848b8605Smrg case STATE_CLIPPLANE: 772848b8605Smrg append(dst, "clip"); 773848b8605Smrg break; 774848b8605Smrg case STATE_POINT_SIZE: 775848b8605Smrg append(dst, "point.size"); 776848b8605Smrg break; 777848b8605Smrg case STATE_POINT_ATTENUATION: 778848b8605Smrg append(dst, "point.attenuation"); 779848b8605Smrg break; 780848b8605Smrg case STATE_MODELVIEW_MATRIX: 781848b8605Smrg append(dst, "matrix.modelview"); 782848b8605Smrg break; 783848b8605Smrg case STATE_PROJECTION_MATRIX: 784848b8605Smrg append(dst, "matrix.projection"); 785848b8605Smrg break; 786848b8605Smrg case STATE_MVP_MATRIX: 787848b8605Smrg append(dst, "matrix.mvp"); 788848b8605Smrg break; 789848b8605Smrg case STATE_TEXTURE_MATRIX: 790848b8605Smrg append(dst, "matrix.texture"); 791848b8605Smrg break; 792848b8605Smrg case STATE_PROGRAM_MATRIX: 793848b8605Smrg append(dst, "matrix.program"); 794848b8605Smrg break; 795848b8605Smrg case STATE_MATRIX_INVERSE: 796848b8605Smrg append(dst, ".inverse"); 797848b8605Smrg break; 798848b8605Smrg case STATE_MATRIX_TRANSPOSE: 799848b8605Smrg append(dst, ".transpose"); 800848b8605Smrg break; 801848b8605Smrg case STATE_MATRIX_INVTRANS: 802848b8605Smrg append(dst, ".invtrans"); 803848b8605Smrg break; 804848b8605Smrg case STATE_AMBIENT: 805848b8605Smrg append(dst, ".ambient"); 806848b8605Smrg break; 807848b8605Smrg case STATE_DIFFUSE: 808848b8605Smrg append(dst, ".diffuse"); 809848b8605Smrg break; 810848b8605Smrg case STATE_SPECULAR: 811848b8605Smrg append(dst, ".specular"); 812848b8605Smrg break; 813848b8605Smrg case STATE_EMISSION: 814848b8605Smrg append(dst, ".emission"); 815848b8605Smrg break; 816848b8605Smrg case STATE_SHININESS: 817848b8605Smrg append(dst, "lshininess"); 818848b8605Smrg break; 819848b8605Smrg case STATE_HALF_VECTOR: 820848b8605Smrg append(dst, ".half"); 821848b8605Smrg break; 822848b8605Smrg case STATE_POSITION: 823848b8605Smrg append(dst, ".position"); 824848b8605Smrg break; 825848b8605Smrg case STATE_ATTENUATION: 826848b8605Smrg append(dst, ".attenuation"); 827848b8605Smrg break; 828848b8605Smrg case STATE_SPOT_DIRECTION: 829848b8605Smrg append(dst, ".spot.direction"); 830848b8605Smrg break; 831848b8605Smrg case STATE_SPOT_CUTOFF: 832848b8605Smrg append(dst, ".spot.cutoff"); 833848b8605Smrg break; 834848b8605Smrg case STATE_TEXGEN_EYE_S: 835848b8605Smrg append(dst, ".eye.s"); 836848b8605Smrg break; 837848b8605Smrg case STATE_TEXGEN_EYE_T: 838848b8605Smrg append(dst, ".eye.t"); 839848b8605Smrg break; 840848b8605Smrg case STATE_TEXGEN_EYE_R: 841848b8605Smrg append(dst, ".eye.r"); 842848b8605Smrg break; 843848b8605Smrg case STATE_TEXGEN_EYE_Q: 844848b8605Smrg append(dst, ".eye.q"); 845848b8605Smrg break; 846848b8605Smrg case STATE_TEXGEN_OBJECT_S: 847848b8605Smrg append(dst, ".object.s"); 848848b8605Smrg break; 849848b8605Smrg case STATE_TEXGEN_OBJECT_T: 850848b8605Smrg append(dst, ".object.t"); 851848b8605Smrg break; 852848b8605Smrg case STATE_TEXGEN_OBJECT_R: 853848b8605Smrg append(dst, ".object.r"); 854848b8605Smrg break; 855848b8605Smrg case STATE_TEXGEN_OBJECT_Q: 856848b8605Smrg append(dst, ".object.q"); 857848b8605Smrg break; 858848b8605Smrg case STATE_TEXENV_COLOR: 859848b8605Smrg append(dst, "texenv"); 860848b8605Smrg break; 861848b8605Smrg case STATE_NUM_SAMPLES: 862848b8605Smrg append(dst, "numsamples"); 863848b8605Smrg break; 864848b8605Smrg case STATE_DEPTH_RANGE: 865848b8605Smrg append(dst, "depth.range"); 866848b8605Smrg break; 867848b8605Smrg case STATE_VERTEX_PROGRAM: 868848b8605Smrg case STATE_FRAGMENT_PROGRAM: 869848b8605Smrg break; 870848b8605Smrg case STATE_ENV: 871848b8605Smrg append(dst, "env"); 872848b8605Smrg break; 873848b8605Smrg case STATE_LOCAL: 874848b8605Smrg append(dst, "local"); 875848b8605Smrg break; 876848b8605Smrg /* BEGIN internal state vars */ 877848b8605Smrg case STATE_INTERNAL: 878848b8605Smrg append(dst, ".internal."); 879848b8605Smrg break; 880848b8605Smrg case STATE_CURRENT_ATTRIB: 881848b8605Smrg append(dst, "current"); 882848b8605Smrg break; 883848b8605Smrg case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: 884848b8605Smrg append(dst, "currentAttribMaybeVPClamped"); 885848b8605Smrg break; 886848b8605Smrg case STATE_NORMAL_SCALE: 887848b8605Smrg append(dst, "normalScale"); 888848b8605Smrg break; 889848b8605Smrg case STATE_FOG_PARAMS_OPTIMIZED: 890848b8605Smrg append(dst, "fogParamsOptimized"); 891848b8605Smrg break; 892848b8605Smrg case STATE_POINT_SIZE_CLAMPED: 893848b8605Smrg append(dst, "pointSizeClamped"); 894848b8605Smrg break; 895848b8605Smrg case STATE_LIGHT_SPOT_DIR_NORMALIZED: 896848b8605Smrg append(dst, "lightSpotDirNormalized"); 897848b8605Smrg break; 898848b8605Smrg case STATE_LIGHT_POSITION: 899848b8605Smrg append(dst, "lightPosition"); 900848b8605Smrg break; 901848b8605Smrg case STATE_LIGHT_POSITION_NORMALIZED: 902848b8605Smrg append(dst, "light.position.normalized"); 903848b8605Smrg break; 904848b8605Smrg case STATE_LIGHT_HALF_VECTOR: 905848b8605Smrg append(dst, "lightHalfVector"); 906848b8605Smrg break; 907848b8605Smrg case STATE_PT_SCALE: 908848b8605Smrg append(dst, "PTscale"); 909848b8605Smrg break; 910848b8605Smrg case STATE_PT_BIAS: 911848b8605Smrg append(dst, "PTbias"); 912848b8605Smrg break; 913848b8605Smrg case STATE_FB_SIZE: 914848b8605Smrg append(dst, "FbSize"); 915848b8605Smrg break; 916848b8605Smrg case STATE_FB_WPOS_Y_TRANSFORM: 917848b8605Smrg append(dst, "FbWposYTransform"); 918848b8605Smrg break; 919b8e80941Smrg case STATE_ADVANCED_BLENDING_MODE: 920b8e80941Smrg append(dst, "AdvancedBlendingMode"); 921b8e80941Smrg break; 922848b8605Smrg default: 923848b8605Smrg /* probably STATE_INTERNAL_DRIVER+i (driver private state) */ 924848b8605Smrg append(dst, "driverState"); 925848b8605Smrg } 926848b8605Smrg} 927848b8605Smrg 928848b8605Smrgstatic void 929848b8605Smrgappend_face(char *dst, GLint face) 930848b8605Smrg{ 931848b8605Smrg if (face == 0) 932848b8605Smrg append(dst, "front."); 933848b8605Smrg else 934848b8605Smrg append(dst, "back."); 935848b8605Smrg} 936848b8605Smrg 937848b8605Smrgstatic void 938848b8605Smrgappend_index(char *dst, GLint index) 939848b8605Smrg{ 940848b8605Smrg char s[20]; 941848b8605Smrg sprintf(s, "[%d]", index); 942848b8605Smrg append(dst, s); 943848b8605Smrg} 944848b8605Smrg 945848b8605Smrg/** 946848b8605Smrg * Make a string from the given state vector. 947848b8605Smrg * For example, return "state.matrix.texture[2].inverse". 948848b8605Smrg * Use free() to deallocate the string. 949848b8605Smrg */ 950848b8605Smrgchar * 951b8e80941Smrg_mesa_program_state_string(const gl_state_index16 state[STATE_LENGTH]) 952848b8605Smrg{ 953848b8605Smrg char str[1000] = ""; 954848b8605Smrg char tmp[30]; 955848b8605Smrg 956848b8605Smrg append(str, "state."); 957848b8605Smrg append_token(str, state[0]); 958848b8605Smrg 959848b8605Smrg switch (state[0]) { 960848b8605Smrg case STATE_MATERIAL: 961848b8605Smrg append_face(str, state[1]); 962848b8605Smrg append_token(str, state[2]); 963848b8605Smrg break; 964848b8605Smrg case STATE_LIGHT: 965848b8605Smrg append_index(str, state[1]); /* light number [i]. */ 966848b8605Smrg append_token(str, state[2]); /* coefficients */ 967848b8605Smrg break; 968848b8605Smrg case STATE_LIGHTMODEL_AMBIENT: 969848b8605Smrg append(str, "lightmodel.ambient"); 970848b8605Smrg break; 971848b8605Smrg case STATE_LIGHTMODEL_SCENECOLOR: 972848b8605Smrg if (state[1] == 0) { 973848b8605Smrg append(str, "lightmodel.front.scenecolor"); 974848b8605Smrg } 975848b8605Smrg else { 976848b8605Smrg append(str, "lightmodel.back.scenecolor"); 977848b8605Smrg } 978848b8605Smrg break; 979848b8605Smrg case STATE_LIGHTPROD: 980848b8605Smrg append_index(str, state[1]); /* light number [i]. */ 981848b8605Smrg append_face(str, state[2]); 982848b8605Smrg append_token(str, state[3]); 983848b8605Smrg break; 984848b8605Smrg case STATE_TEXGEN: 985848b8605Smrg append_index(str, state[1]); /* tex unit [i] */ 986848b8605Smrg append_token(str, state[2]); /* plane coef */ 987848b8605Smrg break; 988848b8605Smrg case STATE_TEXENV_COLOR: 989848b8605Smrg append_index(str, state[1]); /* tex unit [i] */ 990848b8605Smrg append(str, "color"); 991848b8605Smrg break; 992848b8605Smrg case STATE_CLIPPLANE: 993848b8605Smrg append_index(str, state[1]); /* plane [i] */ 994848b8605Smrg append(str, ".plane"); 995848b8605Smrg break; 996848b8605Smrg case STATE_MODELVIEW_MATRIX: 997848b8605Smrg case STATE_PROJECTION_MATRIX: 998848b8605Smrg case STATE_MVP_MATRIX: 999848b8605Smrg case STATE_TEXTURE_MATRIX: 1000848b8605Smrg case STATE_PROGRAM_MATRIX: 1001848b8605Smrg { 1002848b8605Smrg /* state[0] = modelview, projection, texture, etc. */ 1003848b8605Smrg /* state[1] = which texture matrix or program matrix */ 1004848b8605Smrg /* state[2] = first row to fetch */ 1005848b8605Smrg /* state[3] = last row to fetch */ 1006848b8605Smrg /* state[4] = transpose, inverse or invtrans */ 1007848b8605Smrg const gl_state_index mat = state[0]; 1008848b8605Smrg const GLuint index = (GLuint) state[1]; 1009848b8605Smrg const GLuint firstRow = (GLuint) state[2]; 1010848b8605Smrg const GLuint lastRow = (GLuint) state[3]; 1011848b8605Smrg const gl_state_index modifier = state[4]; 1012848b8605Smrg if (index || 1013848b8605Smrg mat == STATE_TEXTURE_MATRIX || 1014848b8605Smrg mat == STATE_PROGRAM_MATRIX) 1015848b8605Smrg append_index(str, index); 1016848b8605Smrg if (modifier) 1017848b8605Smrg append_token(str, modifier); 1018848b8605Smrg if (firstRow == lastRow) 1019848b8605Smrg sprintf(tmp, ".row[%d]", firstRow); 1020848b8605Smrg else 1021848b8605Smrg sprintf(tmp, ".row[%d..%d]", firstRow, lastRow); 1022848b8605Smrg append(str, tmp); 1023848b8605Smrg } 1024848b8605Smrg break; 1025848b8605Smrg case STATE_POINT_SIZE: 1026848b8605Smrg break; 1027848b8605Smrg case STATE_POINT_ATTENUATION: 1028848b8605Smrg break; 1029848b8605Smrg case STATE_FOG_PARAMS: 1030848b8605Smrg break; 1031848b8605Smrg case STATE_FOG_COLOR: 1032848b8605Smrg break; 1033848b8605Smrg case STATE_NUM_SAMPLES: 1034848b8605Smrg break; 1035848b8605Smrg case STATE_DEPTH_RANGE: 1036848b8605Smrg break; 1037848b8605Smrg case STATE_FRAGMENT_PROGRAM: 1038848b8605Smrg case STATE_VERTEX_PROGRAM: 1039848b8605Smrg /* state[1] = {STATE_ENV, STATE_LOCAL} */ 1040848b8605Smrg /* state[2] = parameter index */ 1041848b8605Smrg append_token(str, state[1]); 1042848b8605Smrg append_index(str, state[2]); 1043848b8605Smrg break; 1044848b8605Smrg case STATE_NORMAL_SCALE: 1045848b8605Smrg break; 1046848b8605Smrg case STATE_INTERNAL: 1047848b8605Smrg append_token(str, state[1]); 1048848b8605Smrg if (state[1] == STATE_CURRENT_ATTRIB) 1049848b8605Smrg append_index(str, state[2]); 1050848b8605Smrg break; 1051848b8605Smrg default: 1052848b8605Smrg _mesa_problem(NULL, "Invalid state in _mesa_program_state_string"); 1053848b8605Smrg break; 1054848b8605Smrg } 1055848b8605Smrg 1056b8e80941Smrg return strdup(str); 1057848b8605Smrg} 1058848b8605Smrg 1059848b8605Smrg 1060848b8605Smrg/** 1061848b8605Smrg * Loop over all the parameters in a parameter list. If the parameter 1062848b8605Smrg * is a GL state reference, look up the current value of that state 1063848b8605Smrg * variable and put it into the parameter's Value[4] array. 1064848b8605Smrg * Other parameter types never change or are explicitly set by the user 1065848b8605Smrg * with glUniform() or glProgramParameter(), etc. 1066848b8605Smrg * This would be called at glBegin time. 1067848b8605Smrg */ 1068848b8605Smrgvoid 1069848b8605Smrg_mesa_load_state_parameters(struct gl_context *ctx, 1070848b8605Smrg struct gl_program_parameter_list *paramList) 1071848b8605Smrg{ 1072848b8605Smrg GLuint i; 1073848b8605Smrg 1074848b8605Smrg if (!paramList) 1075848b8605Smrg return; 1076848b8605Smrg 1077848b8605Smrg for (i = 0; i < paramList->NumParameters; i++) { 1078848b8605Smrg if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { 1079b8e80941Smrg unsigned pvo = paramList->ParameterValueOffset[i]; 1080848b8605Smrg _mesa_fetch_state(ctx, 1081848b8605Smrg paramList->Parameters[i].StateIndexes, 1082b8e80941Smrg paramList->ParameterValues + pvo); 1083848b8605Smrg } 1084848b8605Smrg } 1085848b8605Smrg} 1086